kernel/eka/drivers/locmedia/locmedia.cpp
changeset 109 b3a1d9898418
parent 90 947f0dc9f7a8
child 152 657f875b013e
equal deleted inserted replaced
102:ef2a444a7410 109:b3a1d9898418
    69 TPasswordStore* ThePasswordStore=NULL;
    69 TPasswordStore* ThePasswordStore=NULL;
    70 
    70 
    71 class DPrimaryMediaBase::DBody : public DBase
    71 class DPrimaryMediaBase::DBody : public DBase
    72 	{
    72 	{
    73 public:
    73 public:
       
    74 	DBody(DPrimaryMediaBase& aPrimaryMediaBase);
       
    75 public:
       
    76 	DPrimaryMediaBase& iPrimaryMediaBase;	// ptr to parent
    74 	TInt iPhysDevIndex;
    77 	TInt iPhysDevIndex;
    75 	TInt iRequestCount;
    78 	TInt iRequestCount;
    76 #ifdef __DEMAND_PAGING__
    79 #ifdef __DEMAND_PAGING__
    77 	DMediaPagingDevice* iPagingDevice;
    80 	DMediaPagingDevice* iPagingDevice;
    78 	TInt iPageSizeMsk;			// Mask of page size (e.g. 4096-1 -> 4095)
    81 	TInt iPageSizeMsk;			// Mask of page size (e.g. 4096-1 -> 4095)
    79 	TInt iMediaChanges;
    82 	TInt iMediaChanges;
    80 #endif
    83 #endif
       
    84 
       
    85 	// This bit mask indicates which local drives the media is attached to
       
    86 	TUint32 iRegisteredDriveMask;
       
    87 
       
    88 	// Set to ETrue for media extension drivers
       
    89 	TBool iMediaExtension;
       
    90 	
       
    91 	// Media change DFCs to allow media change events from attached media
       
    92 	// to be handled in the context of an extension media's thread
       
    93 	TDfc iMediaChangeDfc;
       
    94 	TDfc iMediaPresentDfc;
    81 	};
    95 	};
    82 
    96 
    83 #ifdef __DEMAND_PAGING__
    97 #ifdef __DEMAND_PAGING__
    84 DMediaPagingDevice* ThePagingDevices[KMaxLocalDrives];
    98 DMediaPagingDevice* ThePagingDevices[KMaxLocalDrives];
    85 DPrimaryMediaBase* TheRomPagingMedia = NULL;
    99 DPrimaryMediaBase* TheRomPagingMedia = NULL;
    86 DPrimaryMediaBase* TheDataPagingMedia = NULL;
   100 DPrimaryMediaBase* TheDataPagingMedia = NULL;
       
   101 TLocDrv* TheDataPagingDrive = NULL;
    87 TBool DataPagingDeviceRegistered = EFalse;
   102 TBool DataPagingDeviceRegistered = EFalse;
    88 class DPinObjectAllocator;
   103 class DPinObjectAllocator;
    89 DPinObjectAllocator* ThePinObjectAllocator = NULL;
   104 DPinObjectAllocator* ThePinObjectAllocator = NULL;
    90 
   105 
    91 // The paging media might share a DfcQ with other non-paging media (e.g. 2 MMC/SD cards sharing the same stack)
   106 // The paging media might share a DfcQ with other non-paging media (e.g. 2 MMC/SD cards sharing the same stack)
    92 // In this case, we need to avoid taking page faults on the non-paging media too, hence the need for these checks:
   107 // In this case, we need to avoid taking page faults on the non-paging media too, hence the need for these checks:
    93 inline TBool DataPagingDfcQ(DPrimaryMediaBase* aPrimaryMedia)
   108 inline TBool DataPagingDfcQ(DPrimaryMediaBase* aPrimaryMedia)
    94 	{return TheDataPagingMedia && TheDataPagingMedia->iDfcQ == aPrimaryMedia->iDfcQ;}
   109 	{return TheDataPagingMedia && TheDataPagingMedia->iDfcQ == aPrimaryMedia->iDfcQ;}
       
   110 
       
   111 
       
   112 TBool DataPagingMedia(DPrimaryMediaBase* aPrimaryMedia)
       
   113 	{
       
   114 	for (TLocDrv* drv = TheDataPagingDrive; drv; drv = drv->iNextDrive)
       
   115 		if (drv->iPrimaryMedia == aPrimaryMedia)
       
   116 			return ETrue;
       
   117 	return EFalse;
       
   118 	}
       
   119 
    95 inline TBool RomPagingDfcQ(DPrimaryMediaBase* aPrimaryMedia)
   120 inline TBool RomPagingDfcQ(DPrimaryMediaBase* aPrimaryMedia)
    96 	{return TheRomPagingMedia && TheRomPagingMedia->iDfcQ == aPrimaryMedia->iDfcQ;}
   121 	{return TheRomPagingMedia && TheRomPagingMedia->iDfcQ == aPrimaryMedia->iDfcQ;}
       
   122 
       
   123 
       
   124 #if defined(_DEBUG)
       
   125 	#define SETDEBUGFLAG(aBitNum) {Kern::SuperPage().iDebugMask[aBitNum >> 5] |= (1 << (aBitNum & 31));}
       
   126 	#define CLRDEBUGFLAG(aBitNum) {Kern::SuperPage().iDebugMask[aBitNum >> 5] &= ~(1 << (aBitNum & 31));}
       
   127 #else
       
   128 	#define SETDEBUGFLAG(aBitNum)
       
   129 	#define CLRDEBUGFLAG(aBitNum)
       
   130 #endif
    97 
   131 
    98 
   132 
    99 
   133 
   100 /* 
   134 /* 
   101 DPinObjectAllocator
   135 DPinObjectAllocator
   102 
   136 
   103 Internal class which contains :
   137 Internal class which contains :
   104 	(1) a queue of pre-allocated TVirtualPinObject's; 
   138 	(1) a queue of pre-allocated TVirtualPinObject's; 
   105 	(2) a single pre-allocated DFragmentationPagingLock object: 
   139 	(2) a single pre-allocated DFragmentationPagingLock object: 
   106 		this may be used if there are no TVirtualPinObject's available or if Kern::PinVirtualMemory() fails
   140 		this may be used if there are no TVirtualPinObject's available or if Kern::PinVirtualMemory() fails
       
   141 @internalTechnology
   107 */
   142 */
   108 NONSHARABLE_CLASS(DPinObjectAllocator) : public DBase
   143 NONSHARABLE_CLASS(DPinObjectAllocator) : public DBase
   109 	{
   144 	{
   110 public:
   145 public:
   111 	/*
   146 	/*
   155 		{
   190 		{
   156 		iPreAllocatedDataLock->Cleanup();
   191 		iPreAllocatedDataLock->Cleanup();
   157 		delete iPreAllocatedDataLock;
   192 		delete iPreAllocatedDataLock;
   158 		}
   193 		}
   159 
   194 
   160 	for (TInt n=0; n<iObjectCount; n++)
   195 	for (TInt n=0; iVirtualPinContainers!= NULL && n<iObjectCount; n++)
   161 		{
   196 		{
   162 		SVirtualPinContainer& virtualPinContainer = iVirtualPinContainers[n];
   197 		SVirtualPinContainer& virtualPinContainer = iVirtualPinContainers[n];
   163 		if (virtualPinContainer.iObject)
   198 		if (virtualPinContainer.iObject)
   164 			Kern::DestroyVirtualPinObject(virtualPinContainer.iObject);
   199 			Kern::DestroyVirtualPinObject(virtualPinContainer.iObject);
   165 		}
   200 		}
   190 		OstTraceFunctionExitExt( DPINOBJECTALLOCATOR_CONSTRUCT_EXIT2, this, r );
   225 		OstTraceFunctionExitExt( DPINOBJECTALLOCATOR_CONSTRUCT_EXIT2, this, r );
   191 		return r;
   226 		return r;
   192 	    }
   227 	    }
   193 
   228 
   194 
   229 
   195 	SVirtualPinContainer* iVirtualPinContainers = new SVirtualPinContainer[aObjectCount];
   230 	iVirtualPinContainers = new SVirtualPinContainer[aObjectCount];
   196 	if (iVirtualPinContainers == NULL)
   231 	if (iVirtualPinContainers == NULL)
   197 	    {
   232 	    {
   198 		OstTraceFunctionExitExt( DPINOBJECTALLOCATOR_CONSTRUCT_EXIT3, this, KErrNoMemory );
   233 		OstTraceFunctionExitExt( DPINOBJECTALLOCATOR_CONSTRUCT_EXIT3, this, KErrNoMemory );
   199 		return KErrNoMemory;
   234 		return KErrNoMemory;
   200 	    }
   235 	    }
   258 	}
   293 	}
   259 
   294 
   260 #endif	// __DEMAND_PAGING__
   295 #endif	// __DEMAND_PAGING__
   261 
   296 
   262 
   297 
       
   298 /* 
       
   299 TDriveIterator
       
   300 
       
   301 Internal class which supports iterating through all local drives (TLocDrv's)
       
   302 If there are media extensions present, then this will iterate through all attached drives.
       
   303 @internalTechnology
       
   304 */
       
   305 class TDriveIterator
       
   306 	{
       
   307 public:
       
   308 	TDriveIterator();
       
   309 	TLocDrv* NextDrive();
       
   310 	inline TInt Index()
       
   311 		{return iIndex;}
       
   312 	static TLocDrv* GetDrive(TInt aDriveNum, DPrimaryMediaBase* aPrimaryMedia);
       
   313 	static TLocDrv* GetPhysicalDrive(TLocDrv* aDrv);
       
   314 
       
   315 #if defined(__DEMAND_PAGING__) && defined(__DEMAND_PAGING_BENCHMARKS__)
       
   316 	static DMediaPagingDevice* PagingDevice(TInt aDriveNum, DPagingDevice::TType aType);
       
   317 #endif
       
   318 
       
   319 private:
       
   320 	TInt iIndex;
       
   321 	TLocDrv* iDrive;
       
   322 	};
       
   323 
       
   324 TDriveIterator::TDriveIterator() :
       
   325 	iIndex(0), iDrive(NULL)
       
   326 	{
       
   327 	}
       
   328 
       
   329 TLocDrv* TDriveIterator::NextDrive()
       
   330 	{
       
   331 	if (iDrive)	// i.e. if not first time
       
   332 		{
       
   333 		if (iDrive->iNextDrive)
       
   334 			{
       
   335 			iDrive = iDrive->iNextDrive;
       
   336 			return iDrive;
       
   337 			}
       
   338 		iIndex++;
       
   339 		}
       
   340 
       
   341 	for (iDrive = NULL; iIndex < KMaxLocalDrives; iIndex++)
       
   342 		{
       
   343 		iDrive = TheDrives[iIndex];
       
   344 		if (iDrive)
       
   345 			break;
       
   346 		}
       
   347 
       
   348 	return iDrive;
       
   349 	}
       
   350 
       
   351 /*
       
   352 Returns the first TLocDrv in the chain of attached drives which matches DPrimaryMediaBase
       
   353 */
       
   354 TLocDrv* TDriveIterator::GetDrive(TInt aDriveNum, DPrimaryMediaBase* aPrimaryMedia)
       
   355 	{
       
   356 	TLocDrv* drive = TheDrives[aDriveNum];
       
   357 	while (drive && drive->iPrimaryMedia != aPrimaryMedia)
       
   358 		{
       
   359 		drive = drive->iNextDrive ? drive->iNextDrive : NULL;
       
   360 		}
       
   361 	return drive;
       
   362 	}
       
   363 
       
   364 /*
       
   365 Returns the last TLocDrv in the chain of attached drives - 
       
   366 i.e. the TLocDrv attached to physical media rather than a TLocDrv corresponding to a media extension 
       
   367 */
       
   368 TLocDrv* TDriveIterator::GetPhysicalDrive(TLocDrv* aDrv)
       
   369 	{
       
   370 	__ASSERT_DEBUG(aDrv, LOCM_FAULT());
       
   371 	while (aDrv->iNextDrive)
       
   372 		aDrv = aDrv->iNextDrive;
       
   373 	return aDrv;
       
   374 	}
       
   375 
       
   376 #if defined(__DEMAND_PAGING__) && defined(__DEMAND_PAGING_BENCHMARKS__)
       
   377 DMediaPagingDevice* TDriveIterator::PagingDevice(TInt aDriveNum, DPagingDevice::TType aType)
       
   378 	{
       
   379 	TLocDrv* drive = TheDrives[aDriveNum];
       
   380 	DMediaPagingDevice* pagingDevice = drive ? drive->iPrimaryMedia->iBody->iPagingDevice : NULL;
       
   381 	while (drive && (pagingDevice == NULL || (pagingDevice->iType & aType) == 0))
       
   382 		{
       
   383 		drive = drive->iNextDrive ? drive->iNextDrive : NULL;
       
   384 		pagingDevice = drive ? drive->iPrimaryMedia->iBody->iPagingDevice : NULL;
       
   385 		}
       
   386 	return pagingDevice;
       
   387 	}
       
   388 #endif
       
   389 
   263 /********************************************
   390 /********************************************
   264  * Local drive device base class
   391  * Local drive device base class
   265  ********************************************/
   392  ********************************************/
   266 DECLARE_EXTENSION_LDD()
   393 DECLARE_EXTENSION_LDD()
   267 	{
   394 	{
   310 	}
   437 	}
   311 
   438 
   312 /********************************************
   439 /********************************************
   313  * Local drive interface class
   440  * Local drive interface class
   314  ********************************************/
   441  ********************************************/
   315 DLocalDrive::DLocalDrive()
   442 DLocalDrive::DLocalDrive() :
       
   443 	iMediaChangeObserver(MediaChangeCallback, this, TCallBackLink::EDLocalDriveObject)
   316 	{
   444 	{
   317 //	iLink.iNext=NULL;
   445 //	iLink.iNext=NULL;
   318 	}
   446 	}
   319 
   447 
   320 DLocalDrive::~DLocalDrive()
   448 DLocalDrive::~DLocalDrive()
   487 			m.Id()=ECaps;
   615 			m.Id()=ECaps;
   488 			m.RemoteDes()=(TAny*)capsBuf.Ptr();	// overload this
   616 			m.RemoteDes()=(TAny*)capsBuf.Ptr();	// overload this
   489 			m.Length()=KMaxLocalDriveCapsLength;	// for pinning
   617 			m.Length()=KMaxLocalDriveCapsLength;	// for pinning
   490 			r=iDrive->Request(m);
   618 			r=iDrive->Request(m);
   491 
   619 
   492 			if(r == KErrNone && iDrive->iMedia != NULL && iDrive->iMedia->iDriver != NULL)
       
   493 				{
       
   494 				// Fill in default media size if not specified by the driver
       
   495 				//
       
   496 				// - This uses the members of TLocalDriveCapsV4 which was primarily used
       
   497 				//   to report NAND flash characteristics, but are general enough to be
       
   498 				//	 used to report the size of any type of media without adding yet
       
   499 				//	 another extension to TLocalDriveCapsVx.
       
   500 				//
       
   501 				
       
   502 				TLocalDriveCapsV4& caps = *(TLocalDriveCapsV4*)capsBuf.Ptr();
       
   503 				
       
   504 				if(caps.iSectorSizeInBytes == 0)
       
   505 					{
       
   506 					// Fill in a default value for the disk sector size
       
   507 					caps.iSectorSizeInBytes = 512;
       
   508 
       
   509 					// Zero the number of sectors, as a sector count makes no sense without a sector size
       
   510 					//  - Fault in debug mode if a sector count is provided to ensure that media driver creators
       
   511 					//	  set this value,but in release mode continue gracefully be recalculating the sector count.
       
   512 					__ASSERT_DEBUG(caps.iNumberOfSectors == 0, LOCM_FAULT());
       
   513 					caps.iNumberOfSectors  = 0;
       
   514 					caps.iNumPagesPerBlock = 1;	// ...to ensure compatiility with NAND semantics
       
   515 					}
       
   516 
       
   517 				if(caps.iNumberOfSectors == 0)
       
   518 					{
       
   519 					const Int64 totalSizeInSectors = iDrive->iMedia->iDriver->TotalSizeInBytes() / caps.iSectorSizeInBytes;
       
   520 					__ASSERT_DEBUG(I64HIGH(totalSizeInSectors) == 0, LOCM_FAULT());
       
   521 
       
   522 					if(I64HIGH(totalSizeInSectors) == 0)
       
   523 						{
       
   524 						caps.iNumberOfSectors = I64LOW(totalSizeInSectors);
       
   525 						}
       
   526 					}
       
   527 				}
       
   528 
   620 
   529 #if defined(OST_TRACE_COMPILER_IN_USE) && defined(_DEBUG)
   621 #if defined(OST_TRACE_COMPILER_IN_USE) && defined(_DEBUG)
   530 			const TLocalDriveCapsV5& caps=*(const TLocalDriveCapsV5*)capsBuf.Ptr();
   622 			const TLocalDriveCapsV5& caps=*(const TLocalDriveCapsV5*)capsBuf.Ptr();
   531 #endif
   623 #endif
   532 			
   624 			
   591 			break;
   683 			break;
   592 		case RLocalDrive::EControlIsRemovable:
   684 		case RLocalDrive::EControlIsRemovable:
   593 			{
   685 			{
   594 	        OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_CONTROLISREMOVABLE, "EControlIsRemovable; TLocDrvRequest Object=0x%x", (TUint) &m);
   686 	        OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_CONTROLISREMOVABLE, "EControlIsRemovable; TLocDrvRequest Object=0x%x", (TUint) &m);
   595 			TInt sockNum;
   687 			TInt sockNum;
   596 			r=iDrive->iPrimaryMedia->IsRemovableDevice(sockNum);
   688 
       
   689 			// Pass request on to last chained drive
       
   690 			TLocDrv* drv = TDriveIterator::GetPhysicalDrive(iDrive);
       
   691 			r = drv->iPrimaryMedia->IsRemovableDevice(sockNum);
       
   692 
   597 			if (r)
   693 			if (r)
   598 				kumemput32(a1,&sockNum,sizeof(TInt));
   694 				kumemput32(a1,&sockNum,sizeof(TInt));
   599 			break;	
   695 			break;	
   600 			}
   696 			}
   601 		case RLocalDrive::EControlControlIO:
   697 		case RLocalDrive::EControlControlIO:
   634 		case RLocalDrive::EControlSetMountInfo:
   730 		case RLocalDrive::EControlSetMountInfo:
   635 			{
   731 			{
   636 			OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_CONTROLSETMOUNTINFO, "EControlSetMountInfo; TLocDrvRequest Object=0x%x", (TUint) &m);
   732 			OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_CONTROLSETMOUNTINFO, "EControlSetMountInfo; TLocDrvRequest Object=0x%x", (TUint) &m);
   637 			m.Id()=ERead;
   733 			m.Id()=ERead;
   638 			r=m.ProcessMessageData(a1);
   734 			r=m.ProcessMessageData(a1);
   639 			DPrimaryMediaBase* pM=iDrive->iPrimaryMedia;
   735 
       
   736 			// Pass request on to last chained drive
       
   737 			TLocDrv* drv = TDriveIterator::GetPhysicalDrive(iDrive);
       
   738 			DPrimaryMediaBase* pM = drv->iPrimaryMedia;
       
   739 
   640 			if(!pM || r!=KErrNone)
   740 			if(!pM || r!=KErrNone)
   641 				break;
   741 				break;
   642 
   742 
   643 			if (pM->iMountInfo.iThread)
   743 			if (pM->iMountInfo.iThread)
   644 				{
   744 				{
   872 		case RLocalDrive::EControlQueryDevice:
   972 		case RLocalDrive::EControlQueryDevice:
   873 			{
   973 			{
   874 			TBuf8<KMaxQueryDeviceLength> queryBuf;
   974 			TBuf8<KMaxQueryDeviceLength> queryBuf;
   875 			queryBuf.SetMax();
   975 			queryBuf.SetMax();
   876 			queryBuf.FillZ();
   976 			queryBuf.FillZ();
   877 			
   977 
       
   978 			DThread* pT = m.Client();
       
   979 			r = Kern::ThreadDesRead(pT, (TDes8*)a2, queryBuf, 0 ,KChunkShiftBy0);
       
   980 
       
   981 			queryBuf.SetMax();
   878 			m.Id() = EQueryDevice;
   982 			m.Id() = EQueryDevice;
   879 			m.iArg[0] = a1;		// RLocalDrive::TQueryDevice
   983 			m.iArg[0] = a1;							// RLocalDrive::TQueryDevice
   880 			m.RemoteDes() = (TAny*)queryBuf.Ptr();	// overload this
   984 			m.RemoteDes() = (TAny*)queryBuf.Ptr();	// overload this
   881 			m.Length() = KMaxLocalDriveCapsLength;	// for pinning
   985 			m.Length() = KMaxQueryDeviceLength;
   882 			OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_QUERYDEVICE, "EQueryDevice; TLocDrvRequest Object=0x%x", (TUint) &m);
   986 			OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_QUERYDEVICE, "EQueryDevice; TLocDrvRequest Object=0x%x", (TUint) &m);
   883 			r=iDrive->Request(m);
   987 			r=iDrive->Request(m);
   884 			OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_QUERYDEVICE_RETURN, "EQueryDevice Return; TLocDrvRequest Object=0x%x", (TUint) &m);
   988 			OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_QUERYDEVICE_RETURN, "EQueryDevice Return; TLocDrvRequest Object=0x%x", (TUint) &m);
   885 			Kern::InfoCopy(*(TDes8*)a2, queryBuf);
   989 			Kern::InfoCopy(*(TDes8*)a2, queryBuf);
   886 			break;
   990 			break;
  1031 void DLocalDrive::UnlockMountInfo(DPrimaryMediaBase& aPrimaryMedia)
  1135 void DLocalDrive::UnlockMountInfo(DPrimaryMediaBase& aPrimaryMedia)
  1032 	{
  1136 	{
  1033 	OstTrace1(TRACE_FLOW, DLOCALDRIVE_UNLOCKMOUNTINFO_ENTRY, "> DLocalDrive::UnlockMountInfo;aPrimaryMedia=%x", (TUint) &aPrimaryMedia);
  1137 	OstTrace1(TRACE_FLOW, DLOCALDRIVE_UNLOCKMOUNTINFO_ENTRY, "> DLocalDrive::UnlockMountInfo;aPrimaryMedia=%x", (TUint) &aPrimaryMedia);
  1034 	
  1138 	
  1035 	DMediaPagingDevice* pagingDevice = aPrimaryMedia.iBody->iPagingDevice; 
  1139 	DMediaPagingDevice* pagingDevice = aPrimaryMedia.iBody->iPagingDevice; 
  1036 	if (pagingDevice == NULL || pagingDevice->iMountInfoDataLock == NULL)
  1140 	if (pagingDevice == NULL)
  1037 	    {
  1141 	    {
  1038 		OstTraceFunctionExit1( DLOCALDRIVE_UNLOCKMOUNTINFO_EXIT1, this );
  1142 		OstTraceFunctionExit1( DLOCALDRIVE_UNLOCKMOUNTINFO_EXIT1, this );
  1039 		return;
  1143 		return;
  1040 	    }
  1144 	    }
  1041 
  1145 
  1063 	
  1167 	
  1064 	OstTraceFunctionExit1( DLOCALDRIVE_UNLOCKMOUNTINFO_EXIT2, this );
  1168 	OstTraceFunctionExit1( DLOCALDRIVE_UNLOCKMOUNTINFO_EXIT2, this );
  1065 	}
  1169 	}
  1066 #endif	// __DEMAND_PAGING__
  1170 #endif	// __DEMAND_PAGING__
  1067 
  1171 
  1068 void DLocalDrive::NotifyChange(DPrimaryMediaBase& aPrimaryMedia, TBool aMediaChange)
  1172 void DLocalDrive::NotifyChange()
  1069 	{
  1173 	{
  1070     OstTraceExt2( TRACE_FLOW, DLOCALDRIVE_NOTIFYCHANGE_ENTRY, "> DLocalDrive::NotifyChange;aPrimaryMedia=%x;aMediaChange=%d", (TUint) &aPrimaryMedia, aMediaChange );
  1174     OstTrace0( TRACE_FLOW, DLOCALDRIVE_NOTIFYCHANGE_ENTRY, "> DLocalDrive::NotifyChange");
  1071 #ifndef __DEMAND_PAGING__
  1175 
  1072 	aPrimaryMedia;
  1176 
  1073 #endif
  1177 	// Complete any notification request on media change
  1074 
  1178 	DThread* pC=NULL;
  1075 	// Complete any notification request on media change or power down
  1179 	NKern::LockSystem();
  1076 	if (aMediaChange)
  1180 	if (iCleanup.iThread)
  1077 		{
  1181 		{
  1078 		DThread* pC=NULL;
  1182 		pC=iCleanup.iThread;
  1079 		NKern::LockSystem();
  1183 		pC->Open();
  1080 		if (iCleanup.iThread)
  1184 		}
  1081 			{
  1185 	NKern::UnlockSystem();
  1082 			pC=iCleanup.iThread;
  1186 	if (pC)
  1083 			pC->Open();
  1187 		{
  1084 			}
  1188 		TBool b = ETrue;
  1085 		NKern::UnlockSystem();
  1189 		// if change not yet queued, queue it now
  1086 		if (pC)
  1190 		if (iNotifyChangeRequest->IsReady())
  1087 			{
  1191 			{
  1088 			TBool b = ETrue;
  1192 			*((TBool*) iNotifyChangeRequest->Buffer()) = b;
  1089 			// if change not yet queued, queue it now
  1193 			Kern::QueueRequestComplete(pC,iNotifyChangeRequest,KErrNone);
  1090 			if (iNotifyChangeRequest->IsReady())
  1194 			}
  1091 				{
  1195 		// If change has not even been requested by the client, maintain the pre-wdp behaviour 
  1092 				*((TBool*) iNotifyChangeRequest->Buffer()) = b;
  1196 		// and write data immediately back to client (possibly taking a page fault)
  1093 				Kern::QueueRequestComplete(pC,iNotifyChangeRequest,KErrNone);
  1197 		// N.B. Must NOT do this on data paging media
  1094 				}
       
  1095 			// If change has not even been requested by the client, maintain the pre-wdp behaviour 
       
  1096 			// and write data immediately back to client (possibly taking a page fault)
       
  1097 			// N.B. Must NOT do this on data paging media
       
  1098 #ifdef __DEMAND_PAGING__
  1198 #ifdef __DEMAND_PAGING__
  1099 			else if (!DataPagingDfcQ(&aPrimaryMedia))
  1199 		else if (!DataPagingDfcQ(iDrive->iPrimaryMedia))
  1100 #else
  1200 #else
  1101 			else
  1201 		else
  1102 #endif
  1202 #endif
  1103 				{
  1203 			{
  1104 				Kern::ThreadRawWrite(pC, iNotifyChangeRequest->DestPtr(), &b, sizeof(b), NULL);
  1204 			Kern::ThreadRawWrite(pC, iNotifyChangeRequest->DestPtr(), &b, sizeof(b), NULL);
  1105 				}
  1205 			}
  1106 			pC->AsyncClose();
  1206 		pC->AsyncClose();
  1107 			}
       
  1108 		}
  1207 		}
  1109 	OstTraceFunctionExit1( DLOCALDRIVE_NOTIFYCHANGE_EXIT, this );
  1208 	OstTraceFunctionExit1( DLOCALDRIVE_NOTIFYCHANGE_EXIT, this );
       
  1209 	}
       
  1210 
       
  1211 // This function is called by the primary media when a media change occurs
       
  1212 TInt DLocalDrive::MediaChangeCallback(TAny* aLocalDrive, TInt /* aNotifyType*/)
       
  1213 	{
       
  1214 	((DLocalDrive*) aLocalDrive)->NotifyChange();
       
  1215 	return KErrNone;
  1110 	}
  1216 	}
  1111 
  1217 
  1112 TLocalDriveCleanup::TLocalDriveCleanup()
  1218 TLocalDriveCleanup::TLocalDriveCleanup()
  1113 	{
  1219 	{
  1114 	}
  1220 	}
  1125 	NKern::UnlockSystem();
  1231 	NKern::UnlockSystem();
  1126 	pC->Close(NULL);	// balances Open() in DoCreate
  1232 	pC->Close(NULL);	// balances Open() in DoCreate
  1127 	NKern::LockSystem();
  1233 	NKern::LockSystem();
  1128 	}
  1234 	}
  1129 
  1235 
       
  1236 
       
  1237 EXPORT_C TInt DLocalDrive::Caps(TInt aDriveNumber, TDes8& aCaps)
       
  1238 	{
       
  1239 	if(!Kern::CurrentThreadHasCapability(ECapabilityTCB,__PLATSEC_DIAGNOSTIC_STRING("Checked by ELOCD.LDD (Local Media Driver)")))
       
  1240 	    {
       
  1241 		return KErrPermissionDenied;
       
  1242 	    }
       
  1243 	
       
  1244 
       
  1245 	if (aDriveNumber >= KMaxLocalDrives)
       
  1246 		return KErrArgument;
       
  1247 
       
  1248 	TLocDrv* drive = TheDrives[aDriveNumber];
       
  1249 	if (!drive)
       
  1250 		return KErrNotSupported;
       
  1251 
       
  1252 	TLocDrvRequest request;
       
  1253 	memclr(&request, sizeof(request));
       
  1254 
       
  1255 	request.Drive() = drive;
       
  1256 	request.Id() = DLocalDrive::ECaps;
       
  1257 	request.Length() = aCaps.Length();
       
  1258 	request.RemoteDes() = (TAny*) aCaps.Ptr();
       
  1259 
       
  1260 	return request.SendReceive(&drive->iPrimaryMedia->iMsgQ);
       
  1261 	}
       
  1262 
  1130 /********************************************
  1263 /********************************************
  1131  * Local drive request class
  1264  * Local drive request class
  1132  ********************************************/
  1265  ********************************************/
  1133  
  1266  
  1134 /**
  1267 /**
  1153 */
  1286 */
  1154 EXPORT_C TInt TLocDrvRequest::ReadRemote(TDes8* aDes, TInt anOffset)
  1287 EXPORT_C TInt TLocDrvRequest::ReadRemote(TDes8* aDes, TInt anOffset)
  1155 	{
  1288 	{
  1156 	OstTraceFunctionEntry1( TLOCDRVREQUEST_READREMOTE_ENTRY, this );
  1289 	OstTraceFunctionEntry1( TLOCDRVREQUEST_READREMOTE_ENTRY, this );
  1157 	TInt r;
  1290 	TInt r;
       
  1291 
       
  1292 	if (Flags() & TLocDrvRequest::EKernelBuffer)
       
  1293 		{
       
  1294 		(void)memcpy((TAny*) aDes->Ptr(), (TAny*)((TUint32)RemoteDes()+anOffset), aDes->MaxLength());
       
  1295 		aDes->SetLength(aDes->MaxLength());
       
  1296 		return KErrNone;
       
  1297 		}
       
  1298 
  1158 	DThread* pT=RemoteThread();
  1299 	DThread* pT=RemoteThread();
  1159 	if (!pT)
  1300 	if (!pT)
  1160 		pT=Client();
  1301 		pT=Client();
  1161 
  1302 
  1162 #ifdef __DEMAND_PAGING__	// only if driver has its own thread, we don't support paging in MD which run in the context of their clients
  1303 #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
  1292 */
  1433 */
  1293 EXPORT_C TInt TLocDrvRequest::WriteRemote(const TDesC8* aDes, TInt anOffset)
  1434 EXPORT_C TInt TLocDrvRequest::WriteRemote(const TDesC8* aDes, TInt anOffset)
  1294 	{
  1435 	{
  1295     OstTraceFunctionEntry1( TLOCDRVREQUEST_WRITEREMOTE_ENTRY, this );
  1436     OstTraceFunctionEntry1( TLOCDRVREQUEST_WRITEREMOTE_ENTRY, this );
  1296     TInt r;
  1437     TInt r;
       
  1438 
       
  1439 	if (Flags() & TLocDrvRequest::EKernelBuffer)
       
  1440 		{
       
  1441 		(void)memcpy((TAny*)((TUint32)RemoteDes()+anOffset), (TAny*) aDes->Ptr(), aDes->Length());
       
  1442 		OstTraceFunctionExitExt( TLOCDRVREQUEST_WRITEREMOTE_EXIT1, this, KErrNone );
       
  1443 		return KErrNone;
       
  1444 		}
       
  1445 
  1297 	DThread* pC=Client();
  1446 	DThread* pC=Client();
  1298 	DThread* pT=RemoteThread();
  1447 	DThread* pT=RemoteThread();
  1299 	if (!pT)
  1448 	if (!pT)
  1300 		pT=pC;
  1449 		pT=pC;
  1301 
  1450 
  1302 #ifdef __DEMAND_PAGING__
  1451 #ifdef __DEMAND_PAGING__
  1303 	if (Flags() & ETClientBuffer)
  1452 	if (Flags() & ETClientBuffer)
  1304 	    {
  1453 	    {
  1305         r = Kern::ThreadBufWrite(pT, (TClientBuffer*) RemoteDes(),*aDes,anOffset+RemoteDesOffset(),KChunkShiftBy0,pC);
  1454         r = Kern::ThreadBufWrite(pT, (TClientBuffer*) RemoteDes(),*aDes,anOffset+RemoteDesOffset(),KChunkShiftBy0,pC);
  1306 		OstTraceFunctionExitExt( TLOCDRVREQUEST_WRITEREMOTE_EXIT1, this, r );
  1455 		OstTraceFunctionExitExt( TLOCDRVREQUEST_WRITEREMOTE_EXIT2, this, r );
  1307 		return r;
  1456 		return r;
  1308 	    }
  1457 	    }
  1309 #endif
  1458 #endif
  1310 	r = Kern::ThreadDesWrite(pT,RemoteDes(),*aDes,anOffset+RemoteDesOffset(),KChunkShiftBy0,pC);
  1459 	r = Kern::ThreadDesWrite(pT,RemoteDes(),*aDes,anOffset+RemoteDesOffset(),KChunkShiftBy0,pC);
  1311 	OstTraceFunctionExitExt( TLOCDRVREQUEST_WRITEREMOTE_EXIT2, this, r );
  1460 	OstTraceFunctionExitExt( TLOCDRVREQUEST_WRITEREMOTE_EXIT3, this, r );
  1312 	return r;
  1461 	return r;
  1313 	}
  1462 	}
  1314 
  1463 
  1315 
  1464 
  1316 /**
  1465 /**
  1487 		default:	// read or write or fragment
  1636 		default:	// read or write or fragment
  1488 			__KTRACE_OPT(KLOCDRV,Kern::Printf("R/W request %lx@%lx",Length(),Pos()));
  1637 			__KTRACE_OPT(KLOCDRV,Kern::Printf("R/W request %lx@%lx",Length(),Pos()));
  1489 			OstTraceExt2( TRACE_INTERNALS, TLOCDRVREQUEST_CHECKANDADJUSTFORPARTITION6, "Read/Write request length=0x%x; position=0x%x", (TUint) Length(), (TUint) Pos() );
  1638 			OstTraceExt2( TRACE_INTERNALS, TLOCDRVREQUEST_CHECKANDADJUSTFORPARTITION6, "Read/Write request length=0x%x; position=0x%x", (TUint) Length(), (TUint) Pos() );
  1490 			if (DriverFlags() & RLocalDrive::ELocDrvWholeMedia)
  1639 			if (DriverFlags() & RLocalDrive::ELocDrvWholeMedia)
  1491 				{
  1640 				{
  1492 				if (d.iMedia && d.iMedia->iDriver && Pos()+Length() > d.iMedia->iDriver->iTotalSizeInBytes)
  1641 				if (d.iMedia && d.iMedia->iDriver && Pos()+Length() > d.iMedia->iPartitionInfo.iMediaSizeInBytes)
  1493 				    {
  1642 				    {
  1494 					r = KErrArgument;
  1643 					r = KErrArgument;
  1495 					break;
  1644 					break;
  1496 				    }
  1645 				    }
  1497 				}
  1646 				}
  1517 	{
  1666 	{
  1518 	OstTraceFunctionEntryExt( TLOCDRV_TLOCDRV_ENTRY, this );
  1667 	OstTraceFunctionEntryExt( TLOCDRV_TLOCDRV_ENTRY, this );
  1519 	memclr(this, sizeof(TLocDrv));
  1668 	memclr(this, sizeof(TLocDrv));
  1520 	iDriveNumber=aDriveNumber;
  1669 	iDriveNumber=aDriveNumber;
  1521 	iPartitionNumber=-1;
  1670 	iPartitionNumber=-1;
       
  1671 	iMediaChangeObserver.iFunction = MediaChangeCallback;
       
  1672 	iMediaChangeObserver.iPtr= this;
       
  1673 	iMediaChangeObserver.iObjectType = TCallBackLink::ETLocDrvObject;
  1522 	OstTraceFunctionExit1( TLOCDRV_TLOCDRV_EXIT, this );
  1674 	OstTraceFunctionExit1( TLOCDRV_TLOCDRV_EXIT, this );
  1523 	}
  1675 	}
       
  1676 
       
  1677 TInt TLocDrv::MediaChangeCallback(TAny* aLocDrv, TInt aNotifyType)
       
  1678 	{
       
  1679 	__ASSERT_DEBUG(aNotifyType == DPrimaryMediaBase::EMediaChange || aNotifyType == DPrimaryMediaBase::EMediaPresent, LOCM_FAULT());
       
  1680 	if (aNotifyType == DPrimaryMediaBase::EMediaPresent)
       
  1681 		return ((TLocDrv*) aLocDrv)->iPrimaryMedia->iBody->iMediaPresentDfc.Enque();
       
  1682 	else
       
  1683 		return ((TLocDrv*) aLocDrv)->iPrimaryMedia->iBody->iMediaChangeDfc.Enque();
       
  1684 	}
       
  1685 
  1524 
  1686 
  1525 /**
  1687 /**
  1526 Initialises the DMedia entity with the media device number and ID.
  1688 Initialises the DMedia entity with the media device number and ID.
  1527  
  1689  
  1528 @param	aDevice		The unique ID for this device. This can take one of the
  1690 @param	aDevice		The unique ID for this device. This can take one of the
  1584 		}
  1746 		}
  1585 
  1747 
  1586 
  1748 
  1587 	primaryMedia->iMsgQ.Receive();	// allow reception of more messages
  1749 	primaryMedia->iMsgQ.Receive();	// allow reception of more messages
  1588 	OstTraceFunctionExit0( _HANDLEMSG_EXIT );
  1750 	OstTraceFunctionExit0( _HANDLEMSG_EXIT );
       
  1751 	}
       
  1752 
       
  1753 
       
  1754 void mediaChangeDfc(TAny* aPtr)
       
  1755 	{
       
  1756 	DPrimaryMediaBase* pM = (DPrimaryMediaBase*)aPtr;
       
  1757 	pM->NotifyMediaChange();
       
  1758 	}
       
  1759 
       
  1760 void mediaPresentDfc(TAny* aPtr)
       
  1761 	{
       
  1762 	DPrimaryMediaBase* pM = (DPrimaryMediaBase*)aPtr;
       
  1763 	pM->NotifyMediaPresent();
       
  1764 	}
       
  1765 
       
  1766 DPrimaryMediaBase::DBody::DBody(DPrimaryMediaBase& aPrimaryMediaBase) :
       
  1767 	iPrimaryMediaBase(aPrimaryMediaBase),
       
  1768 	iMediaChangeDfc(mediaChangeDfc, &aPrimaryMediaBase, KMaxDfcPriority),
       
  1769 	iMediaPresentDfc(mediaPresentDfc, &aPrimaryMediaBase, KMaxDfcPriority)
       
  1770 	{
  1589 	}
  1771 	}
  1590 
  1772 
  1591 EXPORT_C DPrimaryMediaBase::DPrimaryMediaBase()
  1773 EXPORT_C DPrimaryMediaBase::DPrimaryMediaBase()
  1592 	:	iMsgQ(handleMsg, this, NULL, 1),
  1774 	:	iMsgQ(handleMsg, this, NULL, 1),
  1593 		iDeferred(NULL, NULL, NULL, 0),			// callback never used
  1775 		iDeferred(NULL, NULL, NULL, 0),			// callback never used
  1625 	
  1807 	
  1626 	if (r != KErrNone)
  1808 	if (r != KErrNone)
  1627 	    {
  1809 	    {
  1628 		OstTraceFunctionExitExt( DPRIMARYMEDIABASE_CREATE_EXIT1, this, r );
  1810 		OstTraceFunctionExitExt( DPRIMARYMEDIABASE_CREATE_EXIT1, this, r );
  1629 		return r;
  1811 		return r;
  1630 	    }
  1812 		}
  1631 	iBody = new DBody;
  1813 	iBody = new DBody(*this);
  1632 	if (iBody == NULL)
  1814 	if (iBody == NULL)
  1633 	    {
  1815 	    {
  1634 		OstTraceFunctionExitExt( DPRIMARYMEDIABASE_CREATE_EXIT2, this, KErrNoMemory );
  1816 		OstTraceFunctionExitExt( DPRIMARYMEDIABASE_CREATE_EXIT2, this, KErrNoMemory );
  1635 		return KErrNoMemory;
  1817 		return KErrNoMemory;
  1636 	    }
  1818 		}
  1637 	
  1819 	if (iDfcQ)
  1638 	
  1820 		{
       
  1821 		iBody->iMediaChangeDfc.SetDfcQ(iDfcQ);
       
  1822 		iBody->iMediaPresentDfc.SetDfcQ(iDfcQ);
       
  1823 		}
  1639 
  1824 
  1640 #ifdef __DEMAND_PAGING__
  1825 #ifdef __DEMAND_PAGING__
  1641 	TInt pageSize = Kern::RoundToPageSize(1);
  1826 	TInt pageSize = Kern::RoundToPageSize(1);
  1642 	iBody->iPageSizeMsk = pageSize-1;
  1827 	iBody->iPageSizeMsk = pageSize-1;
  1643 #endif
  1828 #endif
  1695 	// If this is the first connection, open media driver now
  1880 	// If this is the first connection, open media driver now
  1696 	// Assume no non-primary media exist on this device
  1881 	// Assume no non-primary media exist on this device
  1697 	
  1882 	
  1698 	NKern::LockSystem();
  1883 	NKern::LockSystem();
  1699 	TBool first=iConnectionQ.IsEmpty();
  1884 	TBool first=iConnectionQ.IsEmpty();
  1700 	iConnectionQ.Add(&aLocalDrive->iLink);
  1885 	iConnectionQ.Add(&aLocalDrive->iMediaChangeObserver.iLink);
  1701 	NKern::UnlockSystem();
  1886 	NKern::UnlockSystem();
  1702 	if (first)
  1887 	if (first)
  1703 		{
  1888 		{
  1704 		r=OpenMediaDriver();
  1889 		r=OpenMediaDriver();
  1705 		if (r!=KErrNone)
  1890 		if (r!=KErrNone)
  1763 	if (pD)
  1948 	if (pD)
  1764 		pD->Close();
  1949 		pD->Close();
  1765 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_DISCONNECT_EXIT2, this );
  1950 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_DISCONNECT_EXIT2, this );
  1766 	}
  1951 	}
  1767 
  1952 
       
  1953 
       
  1954 /**
       
  1955 Connects a TLocDrv containing a media extension to the next primary media in the chain
       
  1956 */
       
  1957 TInt DPrimaryMediaBase::Connect(TLocDrv* aLocDrv)
       
  1958 	{
       
  1959 	TInt r = KErrNone;
       
  1960 
       
  1961 	NKern::LockSystem();
       
  1962 	TBool first = iConnectionQ.IsEmpty();
       
  1963 	iConnectionQ.Add(&aLocDrv->iMediaChangeObserver.iLink);
       
  1964 	NKern::UnlockSystem();
       
  1965 
       
  1966 	if (first && !iDfcQ)
       
  1967 		{
       
  1968 		r = OpenMediaDriver();
       
  1969 		if (r!=KErrNone)
       
  1970 			{
       
  1971 			NKern::LockSystem();
       
  1972 			aLocDrv->iMediaChangeObserver.iLink.Deque();
       
  1973 			NKern::UnlockSystem();
       
  1974 			}
       
  1975 		}
       
  1976 	return r;
       
  1977 	}
       
  1978 
       
  1979 TInt DPrimaryMediaBase::HandleMediaNotPresent(TLocDrvRequest& aReq)
       
  1980 	{
       
  1981 	TInt reqId = aReq.Id();
       
  1982 
       
  1983 	if (reqId == DLocalDrive::ECaps)
       
  1984 		DefaultDriveCaps(*(TLocalDriveCapsV2*)aReq.RemoteDes());	// fill in stuff we know even if no media present
       
  1985 
       
  1986 	TInt r = QuickCheckStatus();
       
  1987 	if (r != KErrNone && 
       
  1988 		reqId != DLocalDrive::EForceMediaChange &&			// EForceMediaChange, and 
       
  1989 		reqId != DLocalDrive::EReadPasswordStore &&			// Password store operations 
       
  1990 		reqId != DLocalDrive::EWritePasswordStore &&			// do not require the media 
       
  1991 		reqId != DLocalDrive::EPasswordStoreLengthInBytes)	// to be ready.)
       
  1992  	 	{
       
  1993 		return r;
       
  1994  	  	}
       
  1995 
       
  1996 	return KErrNone;
       
  1997 	}
       
  1998 
  1768 EXPORT_C TInt DPrimaryMediaBase::Request(TLocDrvRequest& aReq)
  1999 EXPORT_C TInt DPrimaryMediaBase::Request(TLocDrvRequest& aReq)
  1769 /**
  2000 /**
  1770 Issues a local drive request. It is called from TLocDrv::Request() function .
  2001 Issues a local drive request. It is called from TLocDrv::Request() function .
  1771 Each local drive request is encapsulated as a TLocDrvRequest- a class derived from TThreadMessage, the kernel message class. 
  2002 Each local drive request is encapsulated as a TLocDrvRequest- a class derived from TThreadMessage, the kernel message class. 
  1772 TLocDrvRequest contains information pertaining to the request, including the ID and any associated parameters such as drive position, length and source/destination location.
  2003 TLocDrvRequest contains information pertaining to the request, including the ID and any associated parameters such as drive position, length and source/destination location.
  1783 	Otherwise, one of the other system wide error codes.
  2014 	Otherwise, one of the other system wide error codes.
  1784 
  2015 
  1785 @see TLocDrvRequest
  2016 @see TLocDrvRequest
  1786 */
  2017 */
  1787 	{
  2018 	{
  1788 OstTraceFunctionEntry1( DPRIMARYMEDIABASE_REQUEST_ENTRY, this );
  2019 	OstTraceFunctionEntry1( DPRIMARYMEDIABASE_REQUEST_ENTRY, this );
  1789 
  2020 
  1790 	__KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::Request(%08x)",iMediaId,&aReq));
  2021 	__KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::Request(%08x)",iMediaId,&aReq));
  1791 	__KTRACE_OPT(KLOCDRV,Kern::Printf("this=%x, ReqId=%d, Pos=%lx, Len=%lx, remote thread %O",this,aReq.Id(),aReq.Pos(),aReq.Length(),aReq.RemoteThread()));
  2022 	__KTRACE_OPT(KLOCDRV,Kern::Printf("this=%x, ReqId=%d, Pos=%lx, Len=%lx, remote thread %O",this,aReq.Id(),aReq.Pos(),aReq.Length(),aReq.RemoteThread()));
  1792 
  2023 
  1793 	OstTraceDefExt4(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DPRIMARYMEDIABASE_REQUEST, "reqId=%d; length=0x%lx; position=0x%lx; remote thread=0x%x", (TInt) aReq.Id(), (TUint) aReq.Length(),  (TUint) aReq.Pos(), (TUint) aReq.RemoteThread());
  2024 	OstTraceDefExt4(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DPRIMARYMEDIABASE_REQUEST, "reqId=%d; length=0x%lx; position=0x%lx; remote thread=0x%x", (TInt) aReq.Id(), (TUint) aReq.Length(),  (TUint) aReq.Pos(), (TUint) aReq.RemoteThread());
  1794 	
  2025 	
  1795 	TInt reqId = aReq.Id();
  2026 	TInt reqId = aReq.Id();
  1796 
  2027 
  1797 	if (reqId == DLocalDrive::ECaps)
  2028 	TInt r = HandleMediaNotPresent(aReq);
  1798 		DefaultDriveCaps(*(TLocalDriveCapsV2*)aReq.RemoteDes());	// fill in stuff we know even if no media present
  2029 	if (r != KErrNone)
  1799 
  2030 		{
  1800 	TInt r = QuickCheckStatus();
       
  1801 	if (r != KErrNone && aReq.Id()!=DLocalDrive::EForceMediaChange &&			// EForceMediaChange, and 
       
  1802  			 			 aReq.Id()!=DLocalDrive::EReadPasswordStore &&			// Password store operations 
       
  1803  						 aReq.Id()!=DLocalDrive::EWritePasswordStore &&			// do not require the media 
       
  1804  						 aReq.Id()!=DLocalDrive::EPasswordStoreLengthInBytes)	// to be ready.)
       
  1805  	 	{
       
  1806 		OstTraceFunctionExitExt( DPRIMARYMEDIABASE_REQUEST_EXIT, this, r );
  2031 		OstTraceFunctionExitExt( DPRIMARYMEDIABASE_REQUEST_EXIT, this, r );
  1807 		return r;
  2032 		return r;
  1808  	  	}
  2033 		}
       
  2034 
  1809  	  	
  2035  	  	
  1810 
  2036 
  1811 	// for ERead & EWrite requests, get the linear address for pinning & DMA
  2037 	// for ERead & EWrite requests, get the linear address for pinning & DMA
  1812 	TUint8* linAddress = NULL;
  2038 	TUint8* linAddress = NULL;
  1813 	TClientBuffer clientBuffer;
  2039 	TClientBuffer clientBuffer;
  2248 	switch (m.iValue)
  2474 	switch (m.iValue)
  2249 		{
  2475 		{
  2250 		case EConnect:
  2476 		case EConnect:
  2251 			{
  2477 			{
  2252 			DLocalDrive* pD=(DLocalDrive*)m.Ptr0();
  2478 			DLocalDrive* pD=(DLocalDrive*)m.Ptr0();
  2253 			iConnectionQ.Add(&pD->iLink);
  2479 			iConnectionQ.Add(&pD->iMediaChangeObserver.iLink);
  2254 			m.Complete(KErrNone, EFalse);
  2480 			m.Complete(KErrNone, EFalse);
  2255 			OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT1, this );
  2481 			OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT1, this );
  2256 			return;
  2482 			return;
  2257 			}
  2483 			}
  2258 		case EDisconnect:
  2484 		case EDisconnect:
  2271 			return;
  2497 			return;
  2272 			}
  2498 			}
  2273 		case DLocalDrive::EForceMediaChange:
  2499 		case DLocalDrive::EForceMediaChange:
  2274 			{
  2500 			{
  2275 			TUint flags = (TUint) m.Pos();
  2501 			TUint flags = (TUint) m.Pos();
       
  2502 
       
  2503 #ifdef __DEMAND_PAGING__
       
  2504 			// if this is a paging media (ROM,code or data), turn off the KMediaRemountForceMediaChange flag 
       
  2505 			// as this normally results in a call to DPBusSocket::ForceMediaChange() which effectively disables 
       
  2506 			// the media for a small time period - which would be disasterous if a paging request arrived
       
  2507 			if (iBody->iPagingDevice)
       
  2508 				flags&= ~KMediaRemountForceMediaChange;
       
  2509 #endif
       
  2510 
       
  2511 			// For media extension drivers, send a copy of the request to the next drive in the chain and wait for it. 
       
  2512 			TLocDrv* drv = m.Drive();
       
  2513 			if (drv->iNextDrive)
       
  2514 				{
       
  2515 				TLocDrvRequest request;
       
  2516 				request.Drive() = drv->iNextDrive;
       
  2517 				request.Id() = DLocalDrive::EForceMediaChange;
       
  2518 				request.Pos() = m.Pos();	// flags
       
  2519 
       
  2520 				request.SendReceive(&drv->iNextDrive->iPrimaryMedia->iMsgQ);
       
  2521 
       
  2522 				CompleteRequest(m, request.iValue);
       
  2523 				return;
       
  2524 				}
       
  2525 
  2276 
  2526 
  2277 			// if KForceMediaChangeReOpenDriver specified wait for power up, 
  2527 			// if KForceMediaChangeReOpenDriver specified wait for power up, 
  2278 			// and then re-open this drive's media driver
  2528 			// and then re-open this drive's media driver
  2279 			__KTRACE_OPT(KLOCDRV, Kern::Printf("EForceMediaChange, flags %08X\n", flags));
  2529 			__KTRACE_OPT(KLOCDRV, Kern::Printf("EForceMediaChange, flags %08X\n", flags));
  2280 			if (flags == (TUint) KForceMediaChangeReOpenMediaDriver)
  2530 			if (flags == (TUint) KForceMediaChangeReOpenMediaDriver)
  2502 	
  2752 	
  2503 	// re-open this drive's media driver ?
  2753 	// re-open this drive's media driver ?
  2504 	if (m.iValue == DLocalDrive::EForceMediaChange)
  2754 	if (m.iValue == DLocalDrive::EForceMediaChange)
  2505 		{
  2755 		{
  2506 		__ASSERT_DEBUG(((TUint) m.Pos()) == (TUint) KForceMediaChangeReOpenMediaDriver, LOCM_FAULT());
  2756 		__ASSERT_DEBUG(((TUint) m.Pos()) == (TUint) KForceMediaChangeReOpenMediaDriver, LOCM_FAULT());
  2507 
       
  2508 		iCurrentReq=NULL;
  2757 		iCurrentReq=NULL;
  2509 
  2758 
  2510 		TLocDrv* pL = m.Drive();
  2759 		TLocDrv* pL = m.Drive();
  2511 		DMedia* media = pL->iMedia;
  2760 		DMedia* media = pL->iMedia;
       
  2761 
  2512 		if (media && media->iDriver)
  2762 		if (media && media->iDriver)
  2513 			CloseMediaDrivers(media);
  2763 			CloseMediaDrivers(media);
  2514 
  2764 
  2515 		iState=EOpening;
  2765 		iState=EOpening;
  2516 		StartOpenMediaDrivers();
  2766 		StartOpenMediaDrivers();
  2517 
  2767 
  2518 		NotifyClients(ETrue,pL);
  2768 		NotifyClients(EMediaChange, pL);
  2519 		CompleteRequest(m, r);
  2769 		CompleteRequest(m, r);
  2520 		OstTraceFunctionExitExt( DPRIMARYMEDIABASE_DOREQUEST_EXIT, this, r );
  2770 		OstTraceFunctionExitExt( DPRIMARYMEDIABASE_DOREQUEST_EXIT, this, r );
  2521 		return r;
  2771 		return r;
  2522 		}
  2772 		}
  2523 
  2773 
  2540 			return KErrNone;
  2790 			return KErrNone;
  2541 			}
  2791 			}
  2542 		if (!(m.Flags() & TLocDrvRequest::EAdjusted))
  2792 		if (!(m.Flags() & TLocDrvRequest::EAdjusted))
  2543 			{
  2793 			{
  2544 			// If this isn't the only partition, don't allow access to the whole media 
  2794 			// If this isn't the only partition, don't allow access to the whole media 
  2545 			if (iTotalPartitionsOpened > 1)
  2795 			if (TDriveIterator::GetPhysicalDrive(m.Drive())->iPrimaryMedia->iTotalPartitionsOpened > 1)
  2546 				m.DriverFlags() &= ~RLocalDrive::ELocDrvWholeMedia;
  2796 				m.DriverFlags() &= ~RLocalDrive::ELocDrvWholeMedia;
  2547 			r=m.CheckAndAdjustForPartition();
  2797 			r=m.CheckAndAdjustForPartition();
  2548 			}
  2798 			}
  2549 		if (r==KErrNone)
  2799 		if (r==KErrNone)
  2550 			{
  2800 			{
  2684 	OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS1, "DPrimaryMediaBase iMediaId=%d", iMediaId );
  2934 	OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS1, "DPrimaryMediaBase iMediaId=%d", iMediaId );
  2685 	
  2935 	
  2686 	// we mustn't ever close the media driver if it's responsible for data paging as re-opening the drive
  2936 	// we mustn't ever close the media driver if it's responsible for data paging as re-opening the drive
  2687 	// would involve memory allocation which might cause deadlock if the kernel heap were to grow
  2937 	// would involve memory allocation which might cause deadlock if the kernel heap were to grow
  2688 #ifdef __DEMAND_PAGING__
  2938 #ifdef __DEMAND_PAGING__
  2689 	if (DataPagingDfcQ(this))
  2939 	if (DataPagingMedia(this))
  2690 		{
  2940 		{
  2691 		__KTRACE_OPT(KLOCDRV,Kern::Printf("CloseMediaDrivers aborting for data paging media %08X", this));
  2941 		__KTRACE_OPT(KLOCDRV,Kern::Printf("CloseMediaDrivers aborting for data paging media %08X", this));
  2692 		OstTrace1(TRACE_FLOW, DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS_EXIT1, "CloseMediaDrivers aborting for data paging media 0x%08x", this);
  2942 		OstTrace1(TRACE_FLOW, DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS_EXIT1, "CloseMediaDrivers aborting for data paging media 0x%08x", this);
  2693 		return;
  2943 		return;
  2694 		}
  2944 		}
  2695 #endif
  2945 #endif
  2696 
  2946 
  2697 	TInt i;
  2947 
  2698 	for (i=0; i<KMaxLocalDrives; i++)
  2948 	// Don't close any media extension drivers either, since it won't serve any purpose
  2699 		{
  2949 	// and keeping the driver open allows it to maintain internal state
  2700 		TLocDrv* pL=TheDrives[i];
  2950 	if (iBody->iMediaExtension)
       
  2951 		{
       
  2952 		__KTRACE_OPT(KLOCDRV,Kern::Printf("CloseMediaDrivers aborting for extension media %08X", this));
       
  2953 		return;
       
  2954 		}
       
  2955 
       
  2956 
       
  2957 	TDriveIterator driveIter;
       
  2958 	for (TLocDrv* pL = driveIter.NextDrive(); pL != NULL; pL = driveIter.NextDrive())
       
  2959 		{
  2701 		if (pL && pL->iPrimaryMedia==this)
  2960 		if (pL && pL->iPrimaryMedia==this)
  2702 			{
  2961 			{
  2703 			__KTRACE_OPT(KLOCDRV,Kern::Printf("Drive %d",i));
  2962 			__KTRACE_OPT(KLOCDRV,Kern::Printf("Drive %d",driveIter.Index()));
  2704 			OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS2, "Drive=%d", i );
  2963 			OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS2, "Drive=%d", driveIter.Index());
  2705 			if (aMedia == NULL || pL->iMedia == aMedia)
  2964 			if (aMedia == NULL || pL->iMedia == aMedia)
  2706 				{
  2965 				{
  2707 				pL->iMedia=NULL;
  2966 				pL->iMedia=NULL;
  2708 				}
  2967 				}
  2709 			}
  2968 			}
  2710 		}
  2969 		}
  2711 	for (i=iLastMediaId; i>=iMediaId; i--)
  2970 	for (TInt i=iLastMediaId; i>=iMediaId; i--)
  2712 		{
  2971 		{
  2713 		DMedia* pM=TheMedia[i];
  2972 		DMedia* pM=TheMedia[i];
  2714 		if (aMedia == NULL || pM == aMedia)
  2973 		if (aMedia == NULL || pM == aMedia)
  2715 			{
  2974 			{
  2716 			DMediaDriver* pD=pM->iDriver;
  2975 			DMediaDriver* pD=pM->iDriver;
  2863 		{
  3122 		{
  2864 		// couldn't read partition info or driver failed to open
  3123 		// couldn't read partition info or driver failed to open
  2865 		if (pM->iDriver)
  3124 		if (pM->iDriver)
  2866 			{
  3125 			{
  2867 #ifdef __DEMAND_PAGING__
  3126 #ifdef __DEMAND_PAGING__
  2868 			if (DataPagingDfcQ(this))
  3127 			if (DataPagingMedia(this))
  2869 				{
  3128 				{
  2870 				__KTRACE_OPT(KLOCDRV,Kern::Printf("DoPartitionInfoComplete(%d) Close Media Driver aborted for data paging media %08X", this));
  3129 				__KTRACE_OPT(KLOCDRV,Kern::Printf("DoPartitionInfoComplete(%d) Close Media Driver aborted for data paging media %08X", this));
  2871 				OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE2, "Close Media Driver for data paging media 0x%08x", this);
  3130 				OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE2, "Close Media Driver for data paging media 0x%08x", this);
  2872 				}
  3131 				}
  2873 			else
  3132 			else
  2929 	// work out mapping of drives to partitions/media
  3188 	// work out mapping of drives to partitions/media
  2930 	TInt totalPartitions=iTotalPartitionsOpened;
  3189 	TInt totalPartitions=iTotalPartitionsOpened;
  2931 	TInt id=iMediaId;	// start with primary media
  3190 	TInt id=iMediaId;	// start with primary media
  2932 	TInt partitionsOnThisMedia=PartitionCount();
  3191 	TInt partitionsOnThisMedia=PartitionCount();
  2933 	TInt partition=0;
  3192 	TInt partition=0;
  2934 	TInt j;
  3193 
  2935 	for (j=0; j<KMaxLocalDrives; j++)
  3194 	TDriveIterator driveIter;
  2936 		{
  3195 	for (TLocDrv* pD = driveIter.NextDrive(); pD != NULL; pD = driveIter.NextDrive())
  2937 		TLocDrv* pD=TheDrives[j];
  3196 		{
  2938 		if (pD && pD->iPrimaryMedia==this)
  3197 		if (pD && pD->iPrimaryMedia==this)
  2939 			{
  3198 			{
  2940 			if (totalPartitions==0)
  3199 			if (totalPartitions==0)
  2941 				{
  3200 				{
  2942 				pD->iMedia=NULL;
  3201 				pD->iMedia=NULL;
  2946 				{
  3205 				{
  2947 				id++;
  3206 				id++;
  2948 				partition=0;
  3207 				partition=0;
  2949 				partitionsOnThisMedia=TheMedia[id]->PartitionCount();
  3208 				partitionsOnThisMedia=TheMedia[id]->PartitionCount();
  2950 				}
  3209 				}
  2951 			__KTRACE_OPT(KLOCDRV,Kern::Printf("Drive %d = Media %d Partition %d",j,id,partition));
  3210 			__KTRACE_OPT(KLOCDRV,Kern::Printf("Drive %d = Media %d Partition %d",driveIter.Index(),id,partition));
  2952 			OstTraceExt3( TRACE_INTERNALS, DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE5, "Local Drive=%d; iMediaId=%d; partition=%d", j, id, partition );
  3211 			OstTraceExt3( TRACE_INTERNALS, DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE5, "Local Drive=%d; iMediaId=%d; partition=%d", driveIter.Index(), id, partition );
  2953 			
       
  2954 			pD->iMedia=TheMedia[id];
  3212 			pD->iMedia=TheMedia[id];
  2955 			pD->iPartitionNumber=partition;
  3213 			pD->iPartitionNumber=partition;
  2956 			memcpy(pD, pD->iMedia->iPartitionInfo.iEntry+partition, sizeof(TPartitionEntry));
  3214 			memcpy(pD, pD->iMedia->iPartitionInfo.iEntry+partition, sizeof(TPartitionEntry));
  2957 			partition++;
  3215 			partition++;
  2958 			totalPartitions--;
  3216 			totalPartitions--;
  3214 
  3472 
  3215 	iWaitMedChg.CompleteAll(KErrNone);
  3473 	iWaitMedChg.CompleteAll(KErrNone);
  3216 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_SETCLOSED_EXIT, this );
  3474 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_SETCLOSED_EXIT, this );
  3217 	}
  3475 	}
  3218 
  3476 
  3219 void DPrimaryMediaBase::NotifyClients(TBool aMediaChange,TLocDrv* aLocDrv)
  3477 void DPrimaryMediaBase::NotifyClients(TNotifyType aNotifyType, TLocDrv* aLocDrv)
  3220 
  3478 
  3221 //
  3479 //
  3222 // Notify all clients of a media change or power-down event
  3480 // Notify all clients of a media change or media present event
  3223 //
  3481 //
  3224 	{
  3482 	{
  3225 	OstTraceFunctionEntryExt( DPRIMARYMEDIABASE_NOTIFYCLIENTS_ENTRY, this );
  3483 	OstTraceFunctionEntryExt( DPRIMARYMEDIABASE_NOTIFYCLIENTS_ENTRY, this );
  3226 	
  3484 	
  3227 	SDblQueLink* pL=iConnectionQ.iA.iNext;
  3485 	SDblQueLink* pL=iConnectionQ.iA.iNext;
  3228 	while (pL!=&iConnectionQ.iA)
  3486 	while (pL!=&iConnectionQ.iA)
  3229 		{
  3487 		{
  3230 		DLocalDrive* pD=_LOFF(pL,DLocalDrive,iLink);
  3488 		// Get pointer to TCallBackLink
       
  3489 		TCallBackLink* pCallBackLink = _LOFF(pL,TCallBackLink,iLink);
       
  3490 
       
  3491 		// The link is embedded in either a TLocDrv or a  DLocalDrive object;
       
  3492 		// find out which one it is and then get TLocDrv pointer from that
       
  3493 		__ASSERT_DEBUG(pCallBackLink->iObjectType == TCallBackLink::EDLocalDriveObject || pCallBackLink->iObjectType == TCallBackLink::ETLocDrvObject, LOCM_FAULT());
       
  3494 		TLocDrv* locDrv;
       
  3495 		if (pCallBackLink->iObjectType == TCallBackLink::EDLocalDriveObject)
       
  3496 			locDrv = ((DLocalDrive*) _LOFF(pCallBackLink,DLocalDrive, iMediaChangeObserver))->iDrive;
       
  3497 		else
       
  3498 			locDrv = ((TLocDrv*) _LOFF(pCallBackLink,TLocDrv, iMediaChangeObserver))->iNextDrive;
       
  3499 
  3231 		// Issue the notification if the caller wants to notify all drives (aLocDrv == NULL) or 
  3500 		// Issue the notification if the caller wants to notify all drives (aLocDrv == NULL) or 
  3232 		// the specified drive matches this one
  3501 		// the specified drive matches this one
  3233 		if (aLocDrv == NULL || aLocDrv == pD->iDrive)
  3502 		if (aLocDrv == NULL || aLocDrv == locDrv)
  3234 			pD->NotifyChange(*this, aMediaChange);
  3503 			pCallBackLink->CallBack(aNotifyType);
       
  3504 
  3235 		pL=pL->iNext;
  3505 		pL=pL->iNext;
  3236 		}
  3506 		}
  3237 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYCLIENTS_EXIT, this );
  3507 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYCLIENTS_EXIT, this );
  3238 	}
  3508 	}
  3239 
  3509 
  3247 	OstTraceFunctionEntry1( DPRIMARYMEDIABASE_NOTIFYMEDIACHANGE_ENTRY, this );
  3517 	OstTraceFunctionEntry1( DPRIMARYMEDIABASE_NOTIFYMEDIACHANGE_ENTRY, this );
  3248 	__KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::NotifyMediaChange state %d",iMediaId,iState));
  3518 	__KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::NotifyMediaChange state %d",iMediaId,iState));
  3249 
  3519 
  3250 	OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_NOTIFYMEDIACHANGE, "iMediaId=%d; iState=%d", iMediaId, iState );
  3520 	OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_NOTIFYMEDIACHANGE, "iMediaId=%d; iState=%d", iMediaId, iState );
  3251 	
  3521 	
  3252 	TInt state=iState;
  3522 	// This should only be called in the context of the media thread
  3253 
  3523 	__ASSERT_ALWAYS(NKern::CurrentThread() == iDfcQ->iThread, LOCM_FAULT());
  3254 	__ASSERT_DEBUG(iBody, LOCM_FAULT());
  3524 
  3255 
  3525 	MediaChange();
  3256 #ifdef __DEMAND_PAGING__
       
  3257 	iBody->iMediaChanges++;
       
  3258 
       
  3259 	// As data paging media never close, need to ensure the media driver cancels
       
  3260 	// any requests it owns as the stack may be powered down by DPBusPrimaryMedia::ForceMediaChange().
       
  3261 	// DMediaDriver::NotifyPowerDown() should do this
       
  3262 	if(DataPagingDfcQ(this))
       
  3263 		NotifyPowerDown();
       
  3264 #endif
       
  3265 
       
  3266 	// complete any outstanding requests with KErrNotReady
       
  3267 	// and any force media change requests with KErrNone
       
  3268 	SetClosed(KErrNotReady);
       
  3269 
       
  3270 	// close all media drivers on this device
       
  3271 	if (state>=EOpening)
       
  3272 		{
       
  3273 		CloseMediaDrivers();
       
  3274 		}
       
  3275 
  3526 
  3276 	// notify all connections that media change has occurred
  3527 	// notify all connections that media change has occurred
  3277 	NotifyClients(ETrue);
  3528 	NotifyClients(EMediaChange);
  3278 
  3529 
  3279 	// complete any force media change requests
  3530 	// complete any force media change requests
  3280 	iWaitMedChg.CompleteAll(KErrNone);
  3531 	iWaitMedChg.CompleteAll(KErrNone);
  3281 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYMEDIACHANGE_EXIT, this );
  3532 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYMEDIACHANGE_EXIT, this );
  3282 	}
  3533 	}
  3341 	else
  3592 	else
  3342 		{
  3593 		{
  3343 		CloseMediaDrivers();
  3594 		CloseMediaDrivers();
  3344 		SetClosed(KErrNotReady);
  3595 		SetClosed(KErrNotReady);
  3345 		}
  3596 		}
  3346 
       
  3347 	NotifyClients(EFalse);
       
  3348 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYPOWERDOWN_EXIT, this );
  3597 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYPOWERDOWN_EXIT, this );
  3349 	}
  3598 	}
  3350 
  3599 
  3351 
  3600 
  3352 EXPORT_C void DPrimaryMediaBase::NotifyPsuFault(TInt anError)
  3601 EXPORT_C void DPrimaryMediaBase::NotifyPsuFault(TInt anError)
  3412 		// if ready, media driver should complete current request
  3661 		// if ready, media driver should complete current request
  3413 		CompleteCurrent(KErrNotReady);
  3662 		CompleteCurrent(KErrNotReady);
  3414 		}
  3663 		}
  3415 	CloseMediaDrivers();
  3664 	CloseMediaDrivers();
  3416 	SetClosed(KErrNotReady);
  3665 	SetClosed(KErrNotReady);
  3417 	NotifyClients(EFalse);
       
  3418 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYEMERGENCYPOWERDOWN_EXIT, this );
  3666 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYEMERGENCYPOWERDOWN_EXIT, this );
       
  3667 	}
       
  3668 
       
  3669 
       
  3670 /**
       
  3671 Called by NotifyMediaPresent() and NotifyMediaChange() to ensure the media is in the correct state
       
  3672 */
       
  3673 void DPrimaryMediaBase::MediaChange()
       
  3674 	{
       
  3675 	// Media has been inserted, so we need to cancel any outstanding requests and 
       
  3676 	// ensure that the partition info is read again
       
  3677 	TInt state = iState;
       
  3678 
       
  3679 	__ASSERT_DEBUG(iBody, LOCM_FAULT());
       
  3680 
       
  3681 #ifdef __DEMAND_PAGING__
       
  3682 	iBody->iMediaChanges++;
       
  3683 
       
  3684 	// As data paging media never close, need to ensure the media driver cancels
       
  3685 	// any requests it owns as the stack may be powered down by DPBusPrimaryMedia::ForceMediaChange().
       
  3686 	// DMediaDriver::NotifyPowerDown() should do this
       
  3687 	if (DataPagingMedia(this))
       
  3688 		NotifyPowerDown();
       
  3689 #endif
       
  3690 
       
  3691 	// complete any outstanding requests with KErrNotReady
       
  3692 	// and any force media change requests with KErrNone
       
  3693 	SetClosed(KErrNotReady);
       
  3694 
       
  3695 	// close all media drivers on this device
       
  3696 	if (state>=EOpening)
       
  3697 		{
       
  3698 		CloseMediaDrivers();
       
  3699 		}
  3419 	}
  3700 	}
  3420 
  3701 
  3421 EXPORT_C void DPrimaryMediaBase::NotifyMediaPresent()
  3702 EXPORT_C void DPrimaryMediaBase::NotifyMediaPresent()
  3422 /**
  3703 /**
  3423 Notifies clients of a media change by calling NotifyClients ( ) function to indicate that media is present.
  3704 Notifies clients of a media change by calling NotifyClients ( ) function to indicate that media is present.
  3424 */
  3705 */
  3425 	{
  3706 	{
  3426 	OstTraceFunctionEntry1( DPRIMARYMEDIABASE_NOTIFYMEDIAPRESENT_ENTRY, this );
  3707 	OstTraceFunctionEntry1( DPRIMARYMEDIABASE_NOTIFYMEDIAPRESENT_ENTRY, this );
  3427 	NotifyClients(ETrue);
  3708 	__KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::NotifyMediaPresent state %d",iMediaId,iState));
       
  3709 
       
  3710 	// This should only be called in the context of the media thread
       
  3711 	__ASSERT_ALWAYS(NKern::CurrentThread() == iDfcQ->iThread, LOCM_FAULT());
       
  3712 
       
  3713 	MediaChange();
       
  3714 
       
  3715 	NotifyClients(EMediaPresent);
  3428 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYMEDIAPRESENT_EXIT, this );
  3716 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYMEDIAPRESENT_EXIT, this );
  3429 	}
  3717 	}
  3430 
  3718 
  3431 EXPORT_C TInt DPrimaryMediaBase::DoInCritical()
  3719 EXPORT_C TInt DPrimaryMediaBase::DoInCritical()
  3432 /**
  3720 /**
  3573 	if (r==KErrNone)
  3861 	if (r==KErrNone)
  3574 		{
  3862 		{
  3575 		TInt id=iMediaId;	// start with primary media
  3863 		TInt id=iMediaId;	// start with primary media
  3576 		TInt partitionsOnThisMedia=PartitionCount();
  3864 		TInt partitionsOnThisMedia=PartitionCount();
  3577 		TInt partition=0;
  3865 		TInt partition=0;
  3578 		TInt j;
  3866 		
  3579 		for (j=0; j<KMaxLocalDrives; j++)
  3867 		TDriveIterator driveIter;
  3580 			{
  3868 		for (TLocDrv* pD = driveIter.NextDrive(); pD != NULL; pD = driveIter.NextDrive())
  3581 			TLocDrv* pD=TheDrives[j];
  3869 			{
  3582 			if (pD && pD->iPrimaryMedia==this)
  3870 			if (pD && pD->iPrimaryMedia==this)
  3583 				{
  3871 				{
  3584 				if (totalPartitions==0)
  3872 				if (totalPartitions==0)
  3585 					{
  3873 					{
  3586 					pD->iMedia=NULL;
  3874 					pD->iMedia=NULL;
  3937 	// Read from the media and allow for retries in the unlikely event of an error.
  4225 	// Read from the media and allow for retries in the unlikely event of an error.
  3938 	const TInt KPageInRetries = 5;
  4226 	const TInt KPageInRetries = 5;
  3939 	TInt retVal = KErrGeneral;
  4227 	TInt retVal = KErrGeneral;
  3940 	for (TInt i=0; retVal != KErrNone && i < KPageInRetries; i++)
  4228 	for (TInt i=0; retVal != KErrNone && i < KPageInRetries; i++)
  3941 		{
  4229 		{
  3942 		m.Flags() = TLocDrvRequest::EPaging;
  4230 		m.Flags() = TLocDrvRequest::EKernelBuffer | TLocDrvRequest::EPaging;
  3943 		TLocDrv* pL=NULL;
  4231 		TLocDrv* pL=NULL;
  3944 		if(aDrvNumber == EDriveRomPaging)					// ROM paging
  4232 		if(aDrvNumber == EDriveRomPaging)					// ROM paging
  3945 			{
  4233 			{
  3946 			m.Id() = DMediaPagingDevice::ERomPageInRequest;
  4234 			m.Id() = DMediaPagingDevice::ERomPageInRequest;
  3947 			if (iRomPagingDriveNumber == KErrNotFound)
  4235 			if (iRomPagingDriveNumber == KErrNotFound)
  3976 		else if ((aDrvNumber >=0) && (aDrvNumber<KMaxLocalDrives))	// Code paging
  4264 		else if ((aDrvNumber >=0) && (aDrvNumber<KMaxLocalDrives))	// Code paging
  3977 			{
  4265 			{
  3978 			m.Id() = DMediaPagingDevice::ECodePageInRequest;
  4266 			m.Id() = DMediaPagingDevice::ECodePageInRequest;
  3979 			m.Flags() |= TLocDrvRequest::ECodePaging;
  4267 			m.Flags() |= TLocDrvRequest::ECodePaging;
  3980 			pL=TheDrives[aDrvNumber];
  4268 			pL=TheDrives[aDrvNumber];
  3981 			__ASSERT_DEBUG(pL&&(pL->iPrimaryMedia==iPrimaryMedia),LOCM_FAULT());	// valid drive number?
  4269 			__ASSERT_DEBUG(pL && TDriveIterator::GetDrive(aDrvNumber, iPrimaryMedia) ,LOCM_FAULT());	// valid drive number?
  3982 			m.Drive()=pL;
  4270 			m.Drive()=pL;
  3983 #ifdef __DEMAND_PAGING_BENCHMARKS__
  4271 #ifdef __DEMAND_PAGING_BENCHMARKS__
  3984 			__e32_atomic_add_ord32(&iMediaPagingInfo.iCodePageInCount, (TUint) 1);
  4272 			__e32_atomic_add_ord32(&iMediaPagingInfo.iCodePageInCount, (TUint) 1);
  3985 			info = &iCodeBenchmarkData;
  4273 			info = &iCodeBenchmarkData;
  3986 #endif
  4274 #endif
  4099 	// Write to the media and allow for retries in the unlikely event of an error.
  4387 	// Write to the media and allow for retries in the unlikely event of an error.
  4100 	const TInt KPageOutRetries = 5;
  4388 	const TInt KPageOutRetries = 5;
  4101 	TInt retVal = KErrGeneral;
  4389 	TInt retVal = KErrGeneral;
  4102 	for (TInt i=0; retVal != KErrNone && i < KPageOutRetries; i++)
  4390 	for (TInt i=0; retVal != KErrNone && i < KPageOutRetries; i++)
  4103 		{
  4391 		{
  4104 		m.Flags() = TLocDrvRequest::EPaging | TLocDrvRequest::EDataPaging | (aBackground ? TLocDrvRequest::EBackgroundPaging : 0);
  4392 		m.Flags() = TLocDrvRequest::EKernelBuffer | TLocDrvRequest::EPaging | TLocDrvRequest::EDataPaging | (aBackground ? TLocDrvRequest::EBackgroundPaging : 0);
  4105 
  4393 
  4106 		m.Id() = DLocalDrive::EWrite;
  4394 		m.Id() = DLocalDrive::EWrite;
  4107 		m.Drive() = TheDrives[iDataPagingDriveNumber];
  4395 		m.Drive() = TheDrives[iDataPagingDriveNumber];
  4108 
  4396 
  4109 		m.RemoteThread()=NULL;
  4397 		m.RemoteThread()=NULL;
  4195 		}
  4483 		}
  4196 
  4484 
  4197 	TLocDrvRequest& m=*(TLocDrvRequest*)(aReq);
  4485 	TLocDrvRequest& m=*(TLocDrvRequest*)(aReq);
  4198 
  4486 
  4199 
  4487 
  4200 	m.Flags() = TLocDrvRequest::EPaging | TLocDrvRequest::EDataPaging;
  4488 	m.Flags() = TLocDrvRequest::EKernelBuffer | TLocDrvRequest::EPaging  | TLocDrvRequest::EDataPaging;
  4201 	m.Id() = DLocalDrive::EDeleteNotify;
  4489 	m.Id() = DLocalDrive::EDeleteNotify;
  4202 	m.Drive() = TheDrives[iDataPagingDriveNumber];
  4490 	m.Drive() = TheDrives[iDataPagingDriveNumber];
  4203 
  4491 
  4204 	m.RemoteThread() = NULL;
  4492 	m.RemoteThread() = NULL;
  4205 	m.Pos() = offset;
  4493 	m.Pos() = offset;
  4226 		iDeleteNotifyNotSupported = ETrue;
  4514 		iDeleteNotifyNotSupported = ETrue;
  4227 
  4515 
  4228 	OstTraceFunctionExitExt( DMEDIAPAGINGDEVICE_DELETENOTIFY_EXIT3, this, retVal );
  4516 	OstTraceFunctionExitExt( DMEDIAPAGINGDEVICE_DELETENOTIFY_EXIT3, this, retVal );
  4229 	return retVal;
  4517 	return retVal;
  4230 	}
  4518 	}
  4231 
       
  4232 
  4519 
  4233 
  4520 
  4234 EXPORT_C TInt TLocDrvRequest::WriteToPageHandler(const TAny* aSrc, TInt aSize, TInt anOffset)
  4521 EXPORT_C TInt TLocDrvRequest::WriteToPageHandler(const TAny* aSrc, TInt aSize, TInt anOffset)
  4235 	{
  4522 	{
  4236 	OstTraceFunctionEntry1( TLOCDRVREQUEST_WRITETOPAGEHANDLER_ENTRY, this );
  4523 	OstTraceFunctionEntry1( TLOCDRVREQUEST_WRITETOPAGEHANDLER_ENTRY, this );
  4416 	if (aLocDrv)
  4703 	if (aLocDrv)
  4417 		aLocDrv->iPartitionLen=aTotalSizeInBytes;
  4704 		aLocDrv->iPartitionLen=aTotalSizeInBytes;
  4418 	OstTraceFunctionExit1( DMEDIADRIVER_SETTOTALSIZEINBYTES_EXIT, this );
  4705 	OstTraceFunctionExit1( DMEDIADRIVER_SETTOTALSIZEINBYTES_EXIT, this );
  4419 	}
  4706 	}
  4420 
  4707 
       
  4708 /**
       
  4709 For non NAND devices, i.e. devices which don't set TLocalDriveCapsV4::iNumOfBlocks,
       
  4710 set iSectorSizeInBytes, iNumberOfSectors & iNumPagesPerBlock appropriately to allow 
       
  4711 TLocalDriveCapsV4::MediaSizeInBytes() to correctly return the media size
       
  4712 
       
  4713 Media drivers should call this when they receive a DLocalDrive::ECaps request
       
  4714 */
       
  4715 EXPORT_C void DMediaDriver::SetTotalSizeInBytes(TLocalDriveCapsV4& aCaps)
       
  4716 	{
       
  4717 	if (aCaps.iNumOfBlocks == 0)
       
  4718 		{
       
  4719 		aCaps.iSectorSizeInBytes = 512;
       
  4720 		aCaps.iNumPagesPerBlock = 1;	// ...to ensure compatibility with NAND semantics
       
  4721 		Int64 numberOfSectors = iTotalSizeInBytes >> 9;
       
  4722 		while (I64HIGH(numberOfSectors) > 0)
       
  4723 			{
       
  4724 			aCaps.iNumPagesPerBlock<<= 1;
       
  4725 			numberOfSectors>>= 1;
       
  4726 			}
       
  4727 		aCaps.iNumberOfSectors = I64LOW(numberOfSectors);
       
  4728 		}
       
  4729 	}
  4421 
  4730 
  4422 
  4731 
  4423 
  4732 
  4424 /**
  4733 /**
  4425 Gets the total size of the media.
  4734 Gets the total size of the media.
  4647 	{
  4956 	{
  4648 	OstTraceFunctionEntry0( LOCDRV_REGISTERMEDIADEVICE_ENTRY );
  4957 	OstTraceFunctionEntry0( LOCDRV_REGISTERMEDIADEVICE_ENTRY );
  4649 	// Create TLocDrv / DMedia objects to handle a media device
  4958 	// Create TLocDrv / DMedia objects to handle a media device
  4650 	__KTRACE_OPT(KBOOT,Kern::Printf("RegisterMediaDevice %lS dev=%1d #drives=%d 1st=%d PM=%08x #media=%d",&aName,aDevice,aDriveCount,*aDriveList,aPrimaryMedia,aNumMedia));
  4959 	__KTRACE_OPT(KBOOT,Kern::Printf("RegisterMediaDevice %lS dev=%1d #drives=%d 1st=%d PM=%08x #media=%d",&aName,aDevice,aDriveCount,*aDriveList,aPrimaryMedia,aNumMedia));
  4651 	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 );
  4960 	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 );
  4652 	
  4961 
  4653 	const TInt* p=aDriveList;
       
  4654 	TInt i;
       
  4655 	TInt r=0;
       
  4656 	if (UsedMedia+aNumMedia>KMaxLocalDrives)
  4962 	if (UsedMedia+aNumMedia>KMaxLocalDrives)
  4657 	    {
  4963 	    {
  4658 		OstTrace0(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT1, "< KErrInUse");
  4964 		OstTrace0(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT1, "< KErrInUse");
  4659 		return KErrInUse;
  4965 		return KErrInUse;
  4660 	    }
  4966 		}
  4661 	for (i=0; i<aDriveCount; ++i)
  4967 
  4662 		{
  4968 	// make a local copy of the name
  4663 		TInt drv = *p++;
       
  4664 		// -1 means not used; this is to enable Dual-slot MMC support 
       
  4665 		if (drv == -1)
       
  4666 			continue;
       
  4667 		__KTRACE_OPT(KBOOT,Kern::Printf("Registering drive %d", drv));
       
  4668 		OstTrace1( TRACE_INTERNALS, LOCDRV_REGISTERMEDIADEVICE2, "Registering drive=%d", drv );
       
  4669 		if (TheDrives[drv])
       
  4670 			{
       
  4671 			__KTRACE_OPT(KBOOT,Kern::Printf("Drive %d already in use", drv));
       
  4672 			OstTrace1( TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT2, "< Drive %d already in use; KErrInUse", drv);
       
  4673 			return KErrInUse;
       
  4674 			}
       
  4675 		}
       
  4676 	HBuf* pN=HBuf::New(aName);
  4969 	HBuf* pN=HBuf::New(aName);
  4677 	if (!pN)
  4970 	if (!pN)
  4678 	    {
  4971 	    {
  4679         OstTrace0(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT3, "< KErrNoMemory");
  4972         OstTrace0(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT3, "< KErrNoMemory");
  4680 		return KErrNoMemory;
  4973 		return KErrNoMemory;
  4681 	    }
  4974 		}
  4682 	TInt lastMedia=UsedMedia+aNumMedia-1;
  4975 
       
  4976 	// Register the primary media and any secondary media
       
  4977 	TInt lastMedia = UsedMedia+aNumMedia-1;
       
  4978 	TInt i;
       
  4979 	TInt r=0;
  4683 	for (i=UsedMedia; i<=lastMedia; ++i)
  4980 	for (i=UsedMedia; i<=lastMedia; ++i)
  4684 		{
  4981 		{
  4685 		if (i==UsedMedia)
  4982 		if (i==UsedMedia)
  4686 			TheMedia[i]=aPrimaryMedia;
  4983 			TheMedia[i]=aPrimaryMedia;
  4687 		else
  4984 		else
  4698 		    {
  4995 		    {
  4699             OstTrace1(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT5, "< retval=%d", r);
  4996             OstTrace1(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT5, "< retval=%d", r);
  4700 			return r;
  4997 			return r;
  4701 		    }
  4998 		    }
  4702 		}
  4999 		}
  4703 
       
  4704 	__KTRACE_OPT(KBOOT,Kern::Printf("FirstMedia %d LastMedia %d",UsedMedia,lastMedia));
  5000 	__KTRACE_OPT(KBOOT,Kern::Printf("FirstMedia %d LastMedia %d",UsedMedia,lastMedia));
  4705 	OstTraceExt2( TRACE_INTERNALS, LOCDRV_REGISTERMEDIADEVICE4, "FirstMedia=%d; LastMedia=%d", UsedMedia, lastMedia );
  5001 	OstTraceExt2( TRACE_INTERNALS, LOCDRV_REGISTERMEDIADEVICE4, "FirstMedia=%d; LastMedia=%d", UsedMedia, lastMedia );
  4706 	UsedMedia+=aNumMedia;
  5002 	UsedMedia+=aNumMedia;
  4707 	p=aDriveList;
  5003 
       
  5004 	if (__IS_EXTENSION(aDevice))
       
  5005 		aPrimaryMedia->iBody->iMediaExtension = ETrue;
       
  5006 
       
  5007 	// Register the drives
       
  5008 	const TInt* p=aDriveList;
  4708 	for (i=0; i<aDriveCount; ++i)
  5009 	for (i=0; i<aDriveCount; ++i)
  4709 		{
  5010 		{
  4710 		TInt drv=*p++;
  5011 		TInt drv = *p++;
       
  5012 		// -1 means not used; this is to enable Dual-slot MMC support 
  4711 		if (drv == -1)
  5013 		if (drv == -1)
  4712 			continue;
  5014 			continue;
  4713 		TLocDrv* pL=new TLocDrv(drv);
  5015 
  4714 		if (!pL)
  5016 		__KTRACE_OPT(KBOOT,Kern::Printf("Registering drive %d", drv));
  4715 		    {
  5017 		if (!__IS_EXTENSION(aDevice) && TheDrives[drv])
       
  5018 			{
       
  5019 			__KTRACE_OPT(KBOOT,Kern::Printf("Drive %d already in use", drv));
       
  5020 			return KErrInUse;
       
  5021 			}
       
  5022 		else if (__IS_EXTENSION(aDevice) && !TheDrives[drv])
       
  5023 			{
       
  5024 			__KTRACE_OPT(KBOOT,Kern::Printf("Drive %d not initialized", drv));
       
  5025 			return KErrNotReady;
       
  5026 			}
       
  5027 
       
  5028 		TLocDrv* pNewDrive = new TLocDrv(drv);
       
  5029 		if (!pNewDrive)
       
  5030 			{
  4716             OstTrace0(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT6, "< KErrNoMemory");
  5031             OstTrace0(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT6, "< KErrNoMemory");
  4717 			return KErrNoMemory;
  5032 			return KErrNoMemory;
  4718 		    }
  5033 			}
  4719 		TheDrives[drv]=pL;
  5034 
  4720 		DriveNames[drv]=pN;
  5035 
  4721 		pL->iPrimaryMedia=aPrimaryMedia;
  5036 		TLocDrv* pOldDrive = TheDrives[drv];
  4722 		__KTRACE_OPT(KBOOT,Kern::Printf("Drive %d: TLocDrv @ %08x",drv,pL));
  5037 		aPrimaryMedia->iBody->iRegisteredDriveMask|= (0x1 << drv);
  4723 		OstTraceExt2( TRACE_INTERNALS, LOCDRV_REGISTERMEDIADEVICE5, "Drive=%d; TLocDrv 0x%08x;", (TInt) drv, (TUint) pL );
  5038 		pNewDrive->iNextDrive = pOldDrive;
  4724 		}
  5039 
       
  5040 		TheDrives[drv] = pNewDrive;
       
  5041 		DriveNames[drv] = pN;
       
  5042 		pNewDrive->iPrimaryMedia = aPrimaryMedia;
       
  5043 
       
  5044 
       
  5045 		if (pOldDrive)
       
  5046 			{
       
  5047 			TInt r = pOldDrive->iPrimaryMedia->Connect(pNewDrive);
       
  5048 			if (r != KErrNone)
       
  5049 				return r;
       
  5050 
       
  5051 #ifdef __DEMAND_PAGING__
       
  5052 			// If we've hooked a drive letter which is being used for ROM paging by a media driver
       
  5053 			// which does not report the ROM partition, then we need to change iFirstLocalDriveNumber
       
  5054 			// so that ROM page-in requests go directly to that driver
       
  5055 			DMediaPagingDevice* oldPagingDevice = pOldDrive->iPrimaryMedia->iBody->iPagingDevice;
       
  5056 			if (oldPagingDevice && 
       
  5057 				(oldPagingDevice->iType & DPagingDevice::ERom) &&
       
  5058 				oldPagingDevice->iRomPagingDriveNumber == KErrNotFound && 
       
  5059 				oldPagingDevice->iFirstLocalDriveNumber == drv)
       
  5060 				{
       
  5061 				__KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("TRACE: hooking ROM paging device with no defined ROM partition"));
       
  5062 				TInt n;
       
  5063 				for (n=0; n<KMaxLocalDrives; ++n)
       
  5064 					{
       
  5065 					if(TheDrives[n] && TheDrives[n]->iPrimaryMedia == pOldDrive->iPrimaryMedia)
       
  5066 						{
       
  5067 						__KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("TRACE: Changing iFirstLocalDriveNumber from %d to %d", oldPagingDevice->iFirstLocalDriveNumber, n));
       
  5068 						oldPagingDevice->iFirstLocalDriveNumber = n;
       
  5069 						break;
       
  5070 						}
       
  5071 					}
       
  5072 				__ASSERT_ALWAYS(n < KMaxLocalDrives, LOCM_FAULT());
       
  5073 				}
       
  5074 #endif
       
  5075 
       
  5076 			}
       
  5077 
       
  5078 		__KTRACE_OPT(KBOOT,Kern::Printf("Drive %d: TLocDrv @ %08x",drv,pNewDrive));
       
  5079 		}
       
  5080 
  4725 
  5081 
  4726 	OstTraceFunctionExit0( LOCDRV_REGISTERMEDIADEVICE_EXIT7 );
  5082 	OstTraceFunctionExit0( LOCDRV_REGISTERMEDIADEVICE_EXIT7 );
  4727 	return KErrNone;
  5083 	return KErrNone;
  4728 	}
  5084 	}
  4729 
  5085 
  4805                      or one of the other system-wide error codes.  
  5161                      or one of the other system-wide error codes.  
  4806 */
  5162 */
  4807 EXPORT_C TInt LocDrv::RegisterPagingDevice(DPrimaryMediaBase* aPrimaryMedia, const TInt* aPagingDriveList, TInt aDriveCount, TUint aPagingType, TInt aReadShift, TUint aNumPages)
  5163 EXPORT_C TInt LocDrv::RegisterPagingDevice(DPrimaryMediaBase* aPrimaryMedia, const TInt* aPagingDriveList, TInt aDriveCount, TUint aPagingType, TInt aReadShift, TUint aNumPages)
  4808 	{
  5164 	{
  4809 	OstTraceFunctionEntry0( LOCDRV_REGISTERPAGINGDEVICE_ENTRY );
  5165 	OstTraceFunctionEntry0( LOCDRV_REGISTERPAGINGDEVICE_ENTRY );
       
  5166 //	SETDEBUGFLAG(KLOCDPAGING);
  4810 	
  5167 	
  4811 	__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf(">RegisterPagingDevice: paging type=%d PM=0x%x read shift=%d",aPagingType,aPrimaryMedia,aReadShift));
  5168 	__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf(">RegisterPagingDevice: paging type=%d PM=0x%x read shift=%d",aPagingType,aPrimaryMedia,aReadShift));
  4812 	OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE1, "aPagingType=%d; aPrimaryMedia=0x%x; aReadShift=%d", (TInt) aPagingType, (TUint) aPrimaryMedia, (TInt) aReadShift);
  5169 	OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE1, "aPagingType=%d; aPrimaryMedia=0x%x; aReadShift=%d", (TInt) aPagingType, (TUint) aPrimaryMedia, (TInt) aReadShift);
  4813 	
  5170 	
  4814 	TInt i;
  5171 	TInt i = 0;
  4815 
  5172 
  4816 	if(!aPagingType || (aPagingType&~(DPagingDevice::ERom | DPagingDevice::ECode | DPagingDevice::EData)))
  5173 	if(!aPagingType || (aPagingType&~(DPagingDevice::ERom | DPagingDevice::ECode | DPagingDevice::EData)))
  4817 		{
  5174 		{
  4818 		__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Unsupported paging type, exiting"));
  5175 		__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Unsupported paging type, exiting"));
  4819 		OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT1, "< Unsupported paging type; KErrArgument");
  5176 		OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT1, "< Unsupported paging type; KErrArgument");
  4820 		return KErrArgument;
  5177 		return KErrArgument;
  4821 		}
  5178 		}
  4822 
  5179 
  4823 
  5180 
  4824 
  5181 	// Check for duplicate drives
  4825 	for(i=0; i<KMaxLocalDrives; i++)
  5182 	if (!aPrimaryMedia->iBody->iMediaExtension)
  4826 		{
  5183 		{
  4827 		if (ThePagingDevices[i] == NULL)
  5184 		for(i=0; i<KMaxLocalDrives; i++)
  4828 			continue;
  5185 			{
  4829 		if ((ThePagingDevices[i]->iType&DPagingDevice::ERom) &&	(aPagingType & DPagingDevice::ERom))
  5186 			if (ThePagingDevices[i] == NULL)
  4830 			{
  5187 				continue;
  4831 			aPagingType&=~DPagingDevice::ERom;		// already have a ROM paging device
  5188 			if ((ThePagingDevices[i]->iType&DPagingDevice::ERom) &&	(aPagingType & DPagingDevice::ERom))
  4832 			__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Already has ROM pager on locdrv no %d",i));
  5189 				{
  4833 			}
  5190 				aPagingType&=~DPagingDevice::ERom;		// already have a ROM paging device
  4834 		if ((ThePagingDevices[i]->iType&DPagingDevice::EData) && (aPagingType & DPagingDevice::EData))
  5191 				__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Already has ROM pager on locdrv no %d",i));
  4835 			{
  5192 				}
  4836 			aPagingType&=~DPagingDevice::EData;		// already have a Data paging device
  5193 			if ((ThePagingDevices[i]->iType&DPagingDevice::EData) && (aPagingType & DPagingDevice::EData))
  4837 			__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Already has Data pager on locdrv no %d",i));
  5194 				{
       
  5195 				aPagingType&=~DPagingDevice::EData;		// already have a Data paging device
       
  5196 				__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Already has Data pager on locdrv no %d",i));
       
  5197 				}
  4838 			}
  5198 			}
  4839 		}
  5199 		}
  4840 
  5200 
  4841 
  5201 
  4842 	if (aPagingType == 0)
  5202 	if (aPagingType == 0)
  4913 	__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("DMediaPagingDevice(), firstLocalDriveNumber %d", firstLocalDriveNumber));
  5273 	__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("DMediaPagingDevice(), firstLocalDriveNumber %d", firstLocalDriveNumber));
  4914 	OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE3, "firstLocalDriveNumber=%d", firstLocalDriveNumber );
  5274 	OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE3, "firstLocalDriveNumber=%d", firstLocalDriveNumber );
  4915 	
  5275 	
  4916 	// Send an ECaps message to wake up the media driver & ensure all partitions are 
  5276 	// Send an ECaps message to wake up the media driver & ensure all partitions are 
  4917 	// reported, then search for paged-data or paged-ROM partitions
  5277 	// reported, then search for paged-data or paged-ROM partitions
       
  5278 	// NB: older media drivers supporting ROM and/or code paging only may not have started their DFC queues, 
       
  5279 	// so for these media drivers, use the first local drive supported for ROM-pagin-in  requests and
       
  5280 	// assume the media driver itself will adjust the request position internally to match the ROM partition
       
  5281 	// @see DMediaPagingDevice::Read()
  4918 	if ((aPagingType & DPagingDevice::EData) ||
  5282 	if ((aPagingType & DPagingDevice::EData) ||
  4919 		(aPagingType & DPagingDevice::ERom && aPrimaryMedia->iDfcQ && aPrimaryMedia->iMsgQ.iReady))
  5283 		(aPagingType & DPagingDevice::ERom && aPrimaryMedia->iDfcQ && aPrimaryMedia->iMsgQ.iReady))
  4920 		{
  5284 		{
  4921 		// the message queue must have been started already (by the media driver calling iMsgQ.Receive())
  5285 		// the message queue must have been started already (by the media driver calling iMsgQ.Receive())
  4922 		// otherwise we can't send the DLocalDrive::EQueryDevice request
  5286 		// otherwise we can't send the DLocalDrive::ECaps request
  4923 		if (aPrimaryMedia->iDfcQ && !aPrimaryMedia->iMsgQ.iReady)
  5287 		if (!aPrimaryMedia->iDfcQ || !aPrimaryMedia->iMsgQ.iReady)
  4924 			{
  5288 			{
  4925 			__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: Message queue not started"));
  5289 			__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: Message queue not started"));
  4926 			OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT8, "< RegisterPagingDevice: Message queue not started; KErrNotReady");
  5290 			OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT8, "< RegisterPagingDevice: Message queue not started; KErrNotReady");
  4927 			return KErrNotReady;
  5291 			return KErrNotReady;
  4928 			}
  5292 			}
  4953 			OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE4, "Paging device ECaps: i %d retval=%d", i, r);
  5317 			OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE4, "Paging device ECaps: i %d retval=%d", i, r);
  4954 			}
  5318 			}
  4955 
  5319 
  4956 		if (r != KErrNone)
  5320 		if (r != KErrNone)
  4957 		    {
  5321 		    {
  4958             OstTrace1(TRACE_FLOW, LOCRV_REGISTERPAGINGDEVICE_EXIT9, "< Caps::retval=%d - return KErrNotSupported",r);
  5322             OstTrace1(TRACE_FLOW, LOCRV_REGISTERPAGINGDEVICE_EXIT9, "< retval=%d",r);
  4959             // Media driver failure; media maybe recoverable after boot.
  5323             // Media driver failure; media maybe recoverable after boot.
  4960             // Can't register any page drives so return not supported.
  5324             // Can't register any page drives so return not supported.
  4961 			return KErrNotSupported;
  5325 			return KErrNotSupported;
  4962 		    }
  5326 		    }
  4963 
  5327 
  4965 		for (i=0; i<KMaxLocalDrives; ++i)
  5329 		for (i=0; i<KMaxLocalDrives; ++i)
  4966 			{
  5330 			{
  4967 			drive = TheDrives[i];
  5331 			drive = TheDrives[i];
  4968 			if(drive && drive->iPrimaryMedia == aPrimaryMedia)
  5332 			if(drive && drive->iPrimaryMedia == aPrimaryMedia)
  4969 				{
  5333 				{
  4970 				__KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("RegisterPagingDevice: local drive %d, partition type %x size %x", i, drive->iPartitionType, I64LOW(drive->iPartitionLen)));
  5334 				__KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("RegisterPagingDevice: local drive %d, partition type %x base %lx size %lx name %lS", i, drive->iPartitionType, drive->iPartitionBaseAddr, drive->iPartitionLen, DriveNames[i] ? DriveNames[i] : &KNullDesC8));
  4971 				// ROM partition ?
  5335 				// ROM partition ?
  4972 				if ((romPagingDriveNumber == KErrNotFound) && (drive->iPartitionType == KPartitionTypeROM))
  5336 				if ((romPagingDriveNumber == KErrNotFound) && 
       
  5337 					(drive->iPartitionType == KPartitionTypeROM) &&
       
  5338 					(aPagingType & DPagingDevice::ERom))
  4973 					{
  5339 					{
  4974 					__KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("Found ROM partition on local drive %d, size %x", i, I64LOW(drive->iPartitionLen)));
  5340 					__KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("Found ROM partition on local drive %d, size %x", i, I64LOW(drive->iPartitionLen)));
  4975 					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));
  5341 					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));
  4976 					romPagingDriveNumber = i;
  5342 					romPagingDriveNumber = i;
  4977 					}
  5343 					}
  4978 			    // swap partition ?
  5344 			    // swap partition ?
  4979 				else if ((dataPagingDriveNumber == KErrNotFound) && (drive->iPartitionType == KPartitionTypePagedData))
  5345 				else if ((dataPagingDriveNumber == KErrNotFound) && 
       
  5346 					(drive->iPartitionType == KPartitionTypePagedData) &&
       
  5347 					(aPagingType & DPagingDevice::EData))
  4980 					{
  5348 					{
  4981 					__KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("Found swap partition on local drive %d, size %x", i, I64LOW(drive->iPartitionLen)));
  5349 					__KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("Found swap partition on local drive %d, size %x", i, I64LOW(drive->iPartitionLen)));
  4982 					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) );			
  5350 					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) );			
  4983 					dataPagingDriveNumber = i;
  5351 					dataPagingDriveNumber = i;
       
  5352 					TheDataPagingDrive = drive;
  4984 					swapSize = drive->iPartitionLen >> aReadShift;
  5353 					swapSize = drive->iPartitionLen >> aReadShift;
  4985 					}
  5354 					}
  4986 				}
  5355 				}
  4987 			}
  5356 			}
  4988 
  5357 
  5004 		OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT_EXIT10, "< RegisterPagingDevice: could not create paging device; KErrNoMemory");
  5373 		OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT_EXIT10, "< RegisterPagingDevice: could not create paging device; KErrNoMemory");
  5005 		return KErrNoMemory;
  5374 		return KErrNoMemory;
  5006 		}
  5375 		}
  5007 
  5376 
  5008 	pagingDevice->iType = aPagingType;
  5377 	pagingDevice->iType = aPagingType;
       
  5378 	if (aPrimaryMedia->iBody->iMediaExtension)
       
  5379 		pagingDevice->iType|= DPagingDevice::EMediaExtension;
       
  5380 
  5009 	pagingDevice->iReadUnitShift = aReadShift;
  5381 	pagingDevice->iReadUnitShift = aReadShift;
  5010 
  5382 
  5011 	pagingDevice->iFirstLocalDriveNumber = firstLocalDriveNumber;
  5383 	pagingDevice->iFirstLocalDriveNumber = firstLocalDriveNumber;
  5012 	pagingDevice->iRomPagingDriveNumber = romPagingDriveNumber;
  5384 	pagingDevice->iRomPagingDriveNumber = romPagingDriveNumber;
  5013 
  5385 
  5014 	pagingDevice->iDataPagingDriveNumber = dataPagingDriveNumber;
  5386 	pagingDevice->iDataPagingDriveNumber = dataPagingDriveNumber;
  5015 	pagingDevice->iSwapSize = swapSize;
  5387 	pagingDevice->iSwapSize = swapSize;
  5016 
  5388 
  5017 #ifdef __DEBUG_DEMAND_PAGING__
  5389 #ifdef __DEBUG_DEMAND_PAGING__
  5018 	Kern::Printf("PagingDevice :");
  5390 	Kern::Printf("PagingDevice :");
  5019 	Kern::Printf("iType 0x%x\n", pagingDevice->iType);
  5391 	Kern::Printf("Name %lS", firstLocalDriveNumber >= 0 && DriveNames[firstLocalDriveNumber] ? DriveNames[firstLocalDriveNumber] : &KNullDesC8);
  5020 	Kern::Printf("iReadUnitShift 0x%x\n", pagingDevice->iReadUnitShift);
  5392 	Kern::Printf("iType 0x%x", pagingDevice->iType);
  5021 	Kern::Printf("iFirstLocalDriveNumber 0x%x\n", pagingDevice->iFirstLocalDriveNumber);
  5393 	Kern::Printf("iReadUnitShift 0x%x", pagingDevice->iReadUnitShift);
  5022 	Kern::Printf("iRomPagingDriveNumber 0x%x\n", pagingDevice->iRomPagingDriveNumber);
  5394 	Kern::Printf("iFirstLocalDriveNumber 0x%x", pagingDevice->iFirstLocalDriveNumber);
  5023 	Kern::Printf("iDataPagingDriveNumber 0x%x\n", pagingDevice->iDataPagingDriveNumber);
  5395 	Kern::Printf("iRomPagingDriveNumber 0x%x", pagingDevice->iRomPagingDriveNumber);
  5024 	Kern::Printf("iSwapSize 0x%x\n", pagingDevice->iSwapSize);
  5396 	Kern::Printf("iDataPagingDriveNumber 0x%x", pagingDevice->iDataPagingDriveNumber);
       
  5397 	Kern::Printf("iSwapSize 0x%x", pagingDevice->iSwapSize);
  5025 #endif
  5398 #endif
  5026 
  5399 
  5027 
  5400 
  5028 	// This table is indexed by DPagingDevice::TType
  5401 	// This table is indexed by DPagingDevice::TType
  5029 	const char* DeviceName[] = 
  5402 	const char* DeviceName[] = 
  5040 
  5413 
  5041 
  5414 
  5042 	if(aPagingType & DPagingDevice::ECode)
  5415 	if(aPagingType & DPagingDevice::ECode)
  5043 		{
  5416 		{
  5044 		for (i=0; i<aDriveCount; ++i)
  5417 		for (i=0; i<aDriveCount; ++i)
  5045 			pagingDevice->iDrivesSupported|=(0x1<<aPagingDriveList[i]);
  5418 			pagingDevice->iDrivesSupported |= (0x1<<aPagingDriveList[i]);
  5046 		}
  5419 		}
  5047 	pagingDevice->iName = DeviceName[aPagingType];
  5420 	pagingDevice->iName = DeviceName[aPagingType];
  5048 
  5421 
       
  5422 	// If ThePinObjectAllocator has already been created with a smaller number of pages,
       
  5423 	// delete it & then re-create it
       
  5424 	__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: ThePinObjectAllocator %x", ThePinObjectAllocator));
       
  5425 	if (ThePinObjectAllocator && ThePinObjectAllocator->iFragmentGranularity < Kern::RoundToPageSize(1) * aNumPages)
       
  5426 		{
       
  5427 		__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: Recreating ThePinObjectAllocator..."));
       
  5428 		delete ThePinObjectAllocator;
       
  5429 		ThePinObjectAllocator = NULL;
       
  5430 		}
       
  5431 
       
  5432 
       
  5433 	TInt r;
  5049 	if (ThePinObjectAllocator == NULL)
  5434 	if (ThePinObjectAllocator == NULL)
       
  5435 		{
  5050 		ThePinObjectAllocator = new DPinObjectAllocator();
  5436 		ThePinObjectAllocator = new DPinObjectAllocator();
  5051 	if(!ThePinObjectAllocator)
  5437 		if(!ThePinObjectAllocator)
  5052 		{
  5438 			{
  5053 		__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: could not create ThePinObjectAllocator"));
  5439 			__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: could not create ThePinObjectAllocator"));
  5054 		OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT11, "RegisterPagingDevice: could not create ThePinObjectAllocator; KErrNoMemory");
  5440 			OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT11, "RegisterPagingDevice: could not create ThePinObjectAllocator; KErrNoMemory");
  5055 		return KErrNoMemory;
  5441 			return KErrNoMemory;
  5056 		}
  5442 			}
  5057 	TInt r = ThePinObjectAllocator->Construct(KDynamicPagingLockCount, aNumPages);
  5443 		r = ThePinObjectAllocator->Construct(KDynamicPagingLockCount, aNumPages);
  5058 	if (r != KErrNone)
  5444 		if (r != KErrNone)
  5059 		{
  5445 			{
  5060 		__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: could not construct ThePinObjectAllocator"));
  5446 			__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: could not construct ThePinObjectAllocator"));
  5061 		OstTrace1(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT12, "< RegisterPagingDevice: could not construct ThePinObjectAllocator; retval=%d",r);
  5447 			OstTrace1(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT12, "< RegisterPagingDevice: could not construct ThePinObjectAllocator; retval=%d",r);
  5062 		return r;
  5448 			return r;
       
  5449 			}
  5063 		}
  5450 		}
  5064 
  5451 
  5065 
  5452 
  5066 	// Register our DPagingDevice with the Kernel
  5453 	// Register our DPagingDevice with the Kernel
  5067 	r=Kern::InstallPagingDevice(pagingDevice);
  5454 	r=Kern::InstallPagingDevice(pagingDevice);
  5087 	if (aPagingType&DPagingDevice::ECode)
  5474 	if (aPagingType&DPagingDevice::ECode)
  5088 		{
  5475 		{
  5089 		for (i=0; i<aDriveCount; ++i)
  5476 		for (i=0; i<aDriveCount; ++i)
  5090 			{
  5477 			{
  5091 			TLocDrv* pD=TheDrives[*p++];
  5478 			TLocDrv* pD=TheDrives[*p++];
  5092 			pD->iPagingDrv=1;
  5479 			pD->iPagingDrv = 1;
       
  5480 			// mark all attached drives as pageable too - this is really 
       
  5481 			// only to avoid hitting an ASSERT in DMediaDriver::Complete()
       
  5482 			while (pD->iNextDrive)
       
  5483 				{
       
  5484 				pD->iNextDrive->iPagingDrv = 1;
       
  5485 				pD = pD->iNextDrive;
       
  5486 				}
  5093 			}
  5487 			}
  5094 		}
  5488 		}
  5095 
  5489 
  5096 	// Flags to indicate that a paging device is registered and pinning of user requests may be required
  5490 	// Flags to indicate that a paging device is registered and pinning of user requests may be required
  5097 	aPrimaryMedia->iPagingMedia = 1;
  5491 	aPrimaryMedia->iPagingMedia = 1;
  5131 		TheDataPagingMedia = aPrimaryMedia;
  5525 		TheDataPagingMedia = aPrimaryMedia;
  5132 		}
  5526 		}
  5133 
  5527 
  5134 	__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("< RegisterPagingDevice"));
  5528 	__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("< RegisterPagingDevice"));
  5135 	OstTraceFunctionExit0( LOCDRV_REGISTERPAGINGDEVICE_EXIT14 );
  5529 	OstTraceFunctionExit0( LOCDRV_REGISTERPAGINGDEVICE_EXIT14 );
       
  5530 //	CLRDEBUGFLAG(KLOCDPAGING);
  5136 	return KErrNone;
  5531 	return KErrNone;
  5137 	}
  5532 	}
  5138 
  5533 
  5139 #else //__DEMAND_PAGING__
  5534 #else //__DEMAND_PAGING__
  5140 
  5535 
  5206 	for (i=0; i<KMaxLocalDrives; ++i)
  5601 	for (i=0; i<KMaxLocalDrives; ++i)
  5207 		{
  5602 		{
  5208 		TLocDrv* pL=TheDrives[i];
  5603 		TLocDrv* pL=TheDrives[i];
  5209 		if (pL)
  5604 		if (pL)
  5210 			{
  5605 			{
       
  5606 			pL = TDriveIterator::GetPhysicalDrive(TheDrives[i]);
  5211 			++drives;
  5607 			++drives;
  5212 			TInt sockNum;
  5608 			TInt sockNum;
  5213 			DPrimaryMediaBase* pM=pL->iPrimaryMedia;
  5609 			DPrimaryMediaBase* pM=pL->iPrimaryMedia;
  5214 			if (pM->IsRemovableDevice(sockNum))
  5610 			if (pM->IsRemovableDevice(sockNum))
  5215 				{
  5611 				{
  5345 			break;
  5741 			break;
  5346 			}
  5742 			}
  5347 #if defined(__DEMAND_PAGING__) && defined(__CONCURRENT_PAGING_INSTRUMENTATION__)
  5743 #if defined(__DEMAND_PAGING__) && defined(__CONCURRENT_PAGING_INSTRUMENTATION__)
  5348 		case EMediaHalGetROMConcurrencyInfo:
  5744 		case EMediaHalGetROMConcurrencyInfo:
  5349 			{
  5745 			{
  5350 			TInt drvNo=(TInt)a1;
  5746 			DMediaPagingDevice* device = TDriveIterator::PagingDevice((TInt)a1, DPagingDevice::ERom);
  5351 			TLocDrv* drv=TheDrives[drvNo];
       
  5352 			if(!drv)
       
  5353 				break;
       
  5354 			DMediaPagingDevice* device = drv->iPrimaryMedia->iBody->iPagingDevice;
       
  5355 			if(!device)
  5747 			if(!device)
  5356 				break;
  5748 				break;
  5357 			NKern::FMWait(&device->iInstrumentationLock);
  5749 			NKern::FMWait(&device->iInstrumentationLock);
  5358 			SMediaROMPagingConcurrencyInfo info=device->iROMStats;
  5750 			SMediaROMPagingConcurrencyInfo info=device->iROMStats;
  5359 			NKern::FMSignal(&device->iInstrumentationLock);
  5751 			NKern::FMSignal(&device->iInstrumentationLock);
  5361 			r=KErrNone;
  5753 			r=KErrNone;
  5362 			break;
  5754 			break;
  5363 			}
  5755 			}
  5364 		case EMediaHalGetCodeConcurrencyInfo:
  5756 		case EMediaHalGetCodeConcurrencyInfo:
  5365 			{
  5757 			{
  5366 			TInt drvNo=(TInt)a1;
  5758 			DMediaPagingDevice* device = TDriveIterator::PagingDevice((TInt)a1, DPagingDevice::ECode);
  5367 			TLocDrv* drv=TheDrives[drvNo];
       
  5368 			if(!drv)
       
  5369 				break;
       
  5370 			DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice;
       
  5371 			if(!device)
  5759 			if(!device)
  5372 				break;
  5760 				break;
  5373 			NKern::FMWait(&device->iInstrumentationLock);
  5761 			NKern::FMWait(&device->iInstrumentationLock);
  5374 			SMediaCodePagingConcurrencyInfo info=device->iCodeStats;
  5762 			SMediaCodePagingConcurrencyInfo info=device->iCodeStats;
  5375 			NKern::FMSignal(&device->iInstrumentationLock);
  5763 			NKern::FMSignal(&device->iInstrumentationLock);
  5377 			r=KErrNone;
  5765 			r=KErrNone;
  5378 			break;
  5766 			break;
  5379 			}
  5767 			}
  5380 		case EMediaHalGetDataConcurrencyInfo:
  5768 		case EMediaHalGetDataConcurrencyInfo:
  5381 			{
  5769 			{
  5382 			TInt drvNo=(TInt)a1;
  5770 			DMediaPagingDevice* device = TDriveIterator::PagingDevice((TInt)a1, DPagingDevice::EData);
  5383 			TLocDrv* drv=TheDrives[drvNo];
       
  5384 			if(!drv)
       
  5385 				break;
       
  5386 			DMediaPagingDevice* device = drv->iPrimaryMedia->iBody->iPagingDevice;
       
  5387 			if(!device)
  5771 			if(!device)
  5388 				break;
  5772 				break;
  5389 			NKern::FMWait(&device->iInstrumentationLock);
  5773 			NKern::FMWait(&device->iInstrumentationLock);
  5390 			SMediaDataPagingConcurrencyInfo info=device->iDataStats;
  5774 			SMediaDataPagingConcurrencyInfo info=device->iDataStats;
  5391 			NKern::FMSignal(&device->iInstrumentationLock);
  5775 			NKern::FMSignal(&device->iInstrumentationLock);
  5393 			r=KErrNone;
  5777 			r=KErrNone;
  5394 			break;
  5778 			break;
  5395 			}
  5779 			}
  5396 		case EMediaHalResetConcurrencyInfo:
  5780 		case EMediaHalResetConcurrencyInfo:
  5397 			{
  5781 			{
  5398 			TInt drvNo=(TInt)a1;
       
  5399 			TLocDrv* drv=TheDrives[drvNo];
       
  5400 			if(!drv)
       
  5401 				break;
       
  5402 			DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice;
       
  5403 			if(!device)
       
  5404 				break;
       
  5405 			TUint index=(TInt)a2;
  5782 			TUint index=(TInt)a2;
  5406 			if(index>EMediaPagingStatsCode)
  5783 			if(index>EMediaPagingStatsCode)
  5407 				break;
  5784 				break;
  5408 			ResetConcurrencyStats(device, (TMediaPagingStats)index);
  5785 
       
  5786 			DMediaPagingDevice* device = TDriveIterator::PagingDevice((TInt)a1, DPagingDevice::ERom);
       
  5787 			if (device)
       
  5788 				ResetConcurrencyStats(device, (TMediaPagingStats)index);
       
  5789 			device = TDriveIterator::PagingDevice((TInt)a1, DPagingDevice::ECode);
       
  5790 			if (device)
       
  5791 				ResetConcurrencyStats(device, (TMediaPagingStats)index);
       
  5792 			device = TDriveIterator::PagingDevice((TInt)a1, DPagingDevice::EData);
       
  5793 			if (device)
       
  5794 				ResetConcurrencyStats(device, (TMediaPagingStats)index);
       
  5795 
  5409 			r=KErrNone;
  5796 			r=KErrNone;
  5410 			break;
  5797 			break;
  5411 			}
  5798 			}
  5412 #endif
  5799 #endif
  5413 #if defined(__DEMAND_PAGING__) && defined(__DEMAND_PAGING_BENCHMARKS__)
  5800 #if defined(__DEMAND_PAGING__) && defined(__DEMAND_PAGING_BENCHMARKS__)
  5414 		case EMediaHalGetROMPagingBenchmark:
  5801 		case EMediaHalGetROMPagingBenchmark:
  5415 			{
  5802 			{
  5416 			TInt drvNo=(TInt)a1;
  5803 			DMediaPagingDevice* device = TDriveIterator::PagingDevice((TInt)a1, DPagingDevice::ERom);
  5417 			TLocDrv* drv=TheDrives[drvNo];
       
  5418 			if(!drv)
       
  5419 				break;
       
  5420 			DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice;
       
  5421 			if(!device)
  5804 			if(!device)
  5422 				break;
  5805 				break;
  5423 			NKern::FMWait(&device->iInstrumentationLock);
  5806 			NKern::FMWait(&device->iInstrumentationLock);
  5424 			SPagingBenchmarkInfo info = device->iROMBenchmarkData;
  5807 			SPagingBenchmarkInfo info = device->iROMBenchmarkData;
  5425 			NKern::FMSignal(&device->iInstrumentationLock);
  5808 			NKern::FMSignal(&device->iInstrumentationLock);
  5427 			r=KErrNone;
  5810 			r=KErrNone;
  5428 			break;
  5811 			break;
  5429 			}		
  5812 			}		
  5430 		case EMediaHalGetCodePagingBenchmark:
  5813 		case EMediaHalGetCodePagingBenchmark:
  5431 			{
  5814 			{
  5432 			TInt drvNo=(TInt)a1;
  5815 			DMediaPagingDevice* device = TDriveIterator::PagingDevice((TInt)a1, DPagingDevice::ECode);
  5433 			TLocDrv* drv=TheDrives[drvNo];
       
  5434 			if(!drv)
       
  5435 				break;
       
  5436 			DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice;
       
  5437 			if(!device)
  5816 			if(!device)
  5438 				break;
  5817 				break;
  5439 			NKern::FMWait(&device->iInstrumentationLock);
  5818 			NKern::FMWait(&device->iInstrumentationLock);
  5440 			SPagingBenchmarkInfo info = device->iCodeBenchmarkData;
  5819 			SPagingBenchmarkInfo info = device->iCodeBenchmarkData;
  5441 			NKern::FMSignal(&device->iInstrumentationLock);
  5820 			NKern::FMSignal(&device->iInstrumentationLock);
  5443 			r=KErrNone;
  5822 			r=KErrNone;
  5444 			break;
  5823 			break;
  5445 			}	
  5824 			}	
  5446 		case EMediaHalGetDataInPagingBenchmark:
  5825 		case EMediaHalGetDataInPagingBenchmark:
  5447 			{
  5826 			{
  5448 			TInt drvNo=(TInt)a1;
  5827 			DMediaPagingDevice* device = TDriveIterator::PagingDevice((TInt)a1, DPagingDevice::EData);
  5449 			TLocDrv* drv=TheDrives[drvNo];
       
  5450 			if(!drv)
       
  5451 				break;
       
  5452 			DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice;
       
  5453 			if(!device)
  5828 			if(!device)
  5454 				break;
  5829 				break;
  5455 			NKern::FMWait(&device->iInstrumentationLock);
  5830 			NKern::FMWait(&device->iInstrumentationLock);
  5456 			SPagingBenchmarkInfo info = device->iDataInBenchmarkData;
  5831 			SPagingBenchmarkInfo info = device->iDataInBenchmarkData;
  5457 			NKern::FMSignal(&device->iInstrumentationLock);
  5832 			NKern::FMSignal(&device->iInstrumentationLock);
  5459 			r=KErrNone;
  5834 			r=KErrNone;
  5460 			break;
  5835 			break;
  5461 			}		
  5836 			}		
  5462 		case EMediaHalGetDataOutPagingBenchmark:
  5837 		case EMediaHalGetDataOutPagingBenchmark:
  5463 			{
  5838 			{
  5464 			TInt drvNo=(TInt)a1;
  5839 			DMediaPagingDevice* device = TDriveIterator::PagingDevice((TInt)a1, DPagingDevice::EData);
  5465 			TLocDrv* drv=TheDrives[drvNo];
       
  5466 			if(!drv)
       
  5467 				break;
       
  5468 			DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice;
       
  5469 			if(!device)
  5840 			if(!device)
  5470 				break;
  5841 				break;
  5471 			NKern::FMWait(&device->iInstrumentationLock);
  5842 			NKern::FMWait(&device->iInstrumentationLock);
  5472 			SPagingBenchmarkInfo info = device->iDataOutBenchmarkData;
  5843 			SPagingBenchmarkInfo info = device->iDataOutBenchmarkData;
  5473 			NKern::FMSignal(&device->iInstrumentationLock);
  5844 			NKern::FMSignal(&device->iInstrumentationLock);
  5475 			r=KErrNone;
  5846 			r=KErrNone;
  5476 			break;
  5847 			break;
  5477 			}		
  5848 			}		
  5478 		case EMediaHalResetPagingBenchmark:
  5849 		case EMediaHalResetPagingBenchmark:
  5479 			{
  5850 			{
  5480 			TInt drvNo=(TInt)a1;
       
  5481 			TLocDrv* drv=TheDrives[drvNo];
       
  5482 			if(!drv)
       
  5483 				break;
       
  5484 			DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice;
       
  5485 			if(!device)
       
  5486 				break;
       
  5487 			TUint index=(TInt)a2;
  5851 			TUint index=(TInt)a2;
  5488 			if(index>EMediaPagingStatsCode)
  5852 			if(index>EMediaPagingStatsCode)
  5489 				break;
  5853 				break;
  5490 			ResetBenchmarkStats(device, (TMediaPagingStats)index);
  5854 
       
  5855 			DMediaPagingDevice* device = TDriveIterator::PagingDevice((TInt)a1, DPagingDevice::ERom);
       
  5856 			if (device)
       
  5857 				ResetBenchmarkStats(device, (TMediaPagingStats)index);
       
  5858 			device = TDriveIterator::PagingDevice((TInt)a1, DPagingDevice::ECode);
       
  5859 			if (device)
       
  5860 				ResetBenchmarkStats(device, (TMediaPagingStats)index);
       
  5861 			device = TDriveIterator::PagingDevice((TInt)a1, DPagingDevice::EData);
       
  5862 			if (device)
       
  5863 				ResetBenchmarkStats(device, (TMediaPagingStats)index);
       
  5864 
  5491 			r=KErrNone;
  5865 			r=KErrNone;
  5492 			break;
  5866 			break;
  5493 			}
  5867 			}
  5494 		case EMediaHalGetPagingInfo:
  5868 		case EMediaHalGetPagingInfo:
  5495 			{
  5869 			{
  5496 			TInt drvNo=(TInt)a1;
  5870 			DMediaPagingDevice* device = TDriveIterator::PagingDevice((TInt)a1, (DPagingDevice::TType) 0xFF);
  5497 			TLocDrv* drv=TheDrives[drvNo];
       
  5498 			if(!drv)
       
  5499 				break;
       
  5500 			DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice;
       
  5501 			if(!device)
  5871 			if(!device)
  5502 				break;
  5872 				break;
  5503 			NKern::FMWait(&device->iInstrumentationLock);
  5873 			NKern::FMWait(&device->iInstrumentationLock);
  5504 			SMediaPagingInfo info = device->iMediaPagingInfo;
  5874 			SMediaPagingInfo info = device->iMediaPagingInfo;
  5505 			NKern::FMSignal(&device->iInstrumentationLock);
  5875 			NKern::FMSignal(&device->iInstrumentationLock);
  5735 		}
  6105 		}
  5736 	}
  6106 	}
  5737 
  6107 
  5738 
  6108 
  5739 /******************************************************************************
  6109 /******************************************************************************
       
  6110  DMediaDriverExtension base class
       
  6111  ******************************************************************************/
       
  6112 
       
  6113 EXPORT_C DMediaDriverExtension::DMediaDriverExtension(TInt aMediaId) :
       
  6114 	DMediaDriver(aMediaId)
       
  6115 	{
       
  6116 	}
       
  6117 
       
  6118 /**
       
  6119 */
       
  6120 EXPORT_C DMediaDriverExtension::~DMediaDriverExtension()
       
  6121 	{
       
  6122 	}
       
  6123 
       
  6124 /**
       
  6125 Closes the media driver.
       
  6126 
       
  6127 This default implementation simply deletes this DMediaDriverExtension object.
       
  6128 
       
  6129 Media drivers can provide their own implementation, which gives them
       
  6130 the opportunity to clean up resources before closure; for example,
       
  6131 cancelling a DFC.
       
  6132 Any replacement function must call this base class function as
       
  6133 the last instruction. 
       
  6134 */
       
  6135 EXPORT_C void DMediaDriverExtension::Close()
       
  6136 	{
       
  6137 	DMediaDriver::Close();
       
  6138 	}
       
  6139 
       
  6140 /**
       
  6141 DoDrivePartitionInfo()
       
  6142 
       
  6143 Fills out the passed TPartitionInfo object with information from the attached drives
       
  6144 */
       
  6145 EXPORT_C TInt DMediaDriverExtension::DoDrivePartitionInfo(TPartitionInfo& aInfo)
       
  6146 	{
       
  6147 	memclr(&aInfo, sizeof(aInfo));
       
  6148 	aInfo.iPartitionCount = 0;
       
  6149 	aInfo.iMediaSizeInBytes = 0;
       
  6150 
       
  6151 	TDriveIterator driveIter;
       
  6152 	for (TLocDrv* drv = driveIter.NextDrive(); drv != NULL; drv = driveIter.NextDrive())
       
  6153 		{
       
  6154 		if (drv && drv->iPrimaryMedia == iPrimaryMedia)
       
  6155 			{
       
  6156 			TLocDrv* attachedDrive = drv->iNextDrive;
       
  6157 			__ASSERT_DEBUG(attachedDrive, LOCM_FAULT());
       
  6158 			TLocDrvRequest m;
       
  6159 			memclr(&m, sizeof(m));
       
  6160 
       
  6161 			// Get the Caps from the device. NB for MMC/SD we may need to retry as there may have been an earlier 
       
  6162 			// EForceMediaChange request which can result in the cancellation of requests already in the queue
       
  6163 			TBuf8<KMaxLocalDriveCapsLength> capsBuf;
       
  6164 			TInt i;
       
  6165 			const TInt KRetries = 5;
       
  6166 			TInt r = KErrNotReady;
       
  6167 			for (i=0; r == KErrNotReady && i < KRetries; i++)
       
  6168 				{
       
  6169 				capsBuf.SetMax();
       
  6170 				capsBuf.FillZ();
       
  6171 				m.Drive() = attachedDrive;
       
  6172 				m.Id() = DLocalDrive::ECaps;
       
  6173 				m.RemoteDes() = (TAny*)capsBuf.Ptr();
       
  6174 				m.Length() = KMaxLocalDriveCapsLength;
       
  6175 				r = attachedDrive->iPrimaryMedia->Request(m);
       
  6176 				}
       
  6177 
       
  6178 			__KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("DMediaDriverExtension::PartitionInfo(ECaps: i %d: r %d ", driveIter.Index(), r));
       
  6179 			
       
  6180 			// NB The ECaps call might legitimately fail if one of the attached drives is removable
       
  6181 			// If this happens, just ignore & proceed to the next attached drive
       
  6182 			if (r == KErrNone)
       
  6183 				{
       
  6184 				aInfo.iEntry[aInfo.iPartitionCount] = *attachedDrive;
       
  6185 				// Set the media size to be that of the largest attached media
       
  6186 				// This is only needed to ensure that the test in TLocDrvRequest::CheckAndAdjustForPartition()
       
  6187 				// with the ELocDrvWholeMedia flag set succeeds: A further check on whether a request's
       
  6188 				// position & length are outside the media will be made when its is delievered  to the attached media....
       
  6189 				aInfo.iMediaSizeInBytes = Max(
       
  6190 					aInfo.iMediaSizeInBytes, 
       
  6191 					((TLocalDriveCapsV4*) capsBuf.Ptr())->MediaSizeInBytes());
       
  6192 				}
       
  6193 
       
  6194 
       
  6195 			aInfo.iPartitionCount++;
       
  6196 			}
       
  6197 		}
       
  6198 
       
  6199 	return KErrNone;
       
  6200 	}
       
  6201 
       
  6202 /**
       
  6203 ForwardRequest() - 
       
  6204 
       
  6205 forwards the request onto the next attached drive in the chain
       
  6206 */
       
  6207 EXPORT_C TInt DMediaDriverExtension::ForwardRequest(TLocDrvRequest& aRequest)
       
  6208 	{
       
  6209 	TLocDrv* drive = aRequest.Drive();
       
  6210 	TLocDrv* attachedDrive = drive->iNextDrive;
       
  6211 	__ASSERT_DEBUG(attachedDrive, LOCM_FAULT());
       
  6212 	aRequest.Drive() = attachedDrive;
       
  6213 
       
  6214 
       
  6215 	TInt r = attachedDrive->iPrimaryMedia->HandleMediaNotPresent(aRequest);
       
  6216 	if (r != KErrNone)
       
  6217 		{
       
  6218 		return r;
       
  6219 		}
       
  6220 	
       
  6221 	aRequest.Forward(&attachedDrive->iPrimaryMedia->iMsgQ, EFalse);
       
  6222 	return KErrNone;
       
  6223 	}
       
  6224 
       
  6225 
       
  6226 TInt DMediaDriverExtension::SendRequest(TInt aReqId, TBool aPagingRequest, TInt aDriveNumber, TInt64 aPos, TLinAddr aData, TUint aLen)
       
  6227 	{
       
  6228 	__ASSERT_DEBUG(aLen > 0, LOCM_FAULT());
       
  6229 
       
  6230 	// Ensure this is a legitimate attached drive registered using LocDrv::RegisterMediaDevice()
       
  6231 	if (!(iPrimaryMedia->iBody->iRegisteredDriveMask & (0x1 << aDriveNumber)))
       
  6232 		return KErrArgument;
       
  6233 
       
  6234 	TLocDrv* drive = TDriveIterator::GetDrive(aDriveNumber, iPrimaryMedia);
       
  6235 	__ASSERT_DEBUG(drive, LOCM_FAULT());
       
  6236 	TLocDrv* attachedDrive = drive->iNextDrive;
       
  6237 	__ASSERT_DEBUG(attachedDrive, LOCM_FAULT());
       
  6238 
       
  6239 	TLocDrvRequest request;
       
  6240 	memclr(&request, sizeof(request));
       
  6241 
       
  6242 	request.Drive() = attachedDrive;
       
  6243 	request.Id() = aReqId;
       
  6244 	request.Length() = aLen;
       
  6245 	request.RemoteDes() = (TAny*) aData;
       
  6246 	request.Pos() = aPos;
       
  6247 	request.Flags() = TLocDrvRequest::EKernelBuffer | TLocDrvRequest::EAdjusted;
       
  6248 
       
  6249 #ifdef __DEMAND_PAGING__
       
  6250 	if (aPagingRequest)
       
  6251 		{
       
  6252 		request.Flags()|= TLocDrvRequest::EPaging;
       
  6253 		// If the buffer is page aligned, use SendToMainQueueDfcAndBlock() as this 
       
  6254 		// is more efficient if the attached drive use DMA.
       
  6255 		const TInt KPageSizeMask = 4096-1;
       
  6256 		if (aData & KPageSizeMask)
       
  6257 			{
       
  6258 			return attachedDrive->iPrimaryMedia->SendReceive(request, aData);
       
  6259 			}
       
  6260 		else
       
  6261 			{
       
  6262 			attachedDrive->iPrimaryMedia->iBody->iPagingDevice->SendToMainQueueDfcAndBlock(&request);
       
  6263 			return 0;
       
  6264 			}
       
  6265 		}
       
  6266 #else
       
  6267 	aPagingRequest;
       
  6268 #endif
       
  6269 
       
  6270 	return attachedDrive->iPrimaryMedia->SendReceive(request, aData);
       
  6271 	}
       
  6272 
       
  6273 
       
  6274 /**
       
  6275 Read() - 
       
  6276 
       
  6277 reads data from the next attached drive in the chain
       
  6278 
       
  6279 N.B. The position is assumed to be already adjusted i.e. relative to the start of the
       
  6280 media, not the partition
       
  6281 */
       
  6282 EXPORT_C TInt DMediaDriverExtension::Read(TInt aDriveNumber, TInt64 aPos, TLinAddr aData, TUint aLen)
       
  6283 	{
       
  6284 	return SendRequest(DLocalDrive::ERead, EFalse, aDriveNumber, aPos, aData, aLen);
       
  6285 	}
       
  6286 
       
  6287 /**
       
  6288 Write() - 
       
  6289 
       
  6290 writes data to the next attached drive in the chain
       
  6291 
       
  6292 N.B. The position is assumed to be already adjusted i.e. relative to the start of the
       
  6293 media, not the partition
       
  6294 */
       
  6295 EXPORT_C TInt DMediaDriverExtension::Write(TInt aDriveNumber, TInt64 aPos, TLinAddr aData, TUint aLen)
       
  6296 	{
       
  6297 	return SendRequest(DLocalDrive::EWrite, EFalse, aDriveNumber, aPos, aData, aLen);
       
  6298 	}
       
  6299 
       
  6300 
       
  6301 #ifdef __DEMAND_PAGING__
       
  6302 /**
       
  6303 ReadPaged() - 
       
  6304 
       
  6305 Sends a paging read request to the specified attached drive
       
  6306 
       
  6307 N.B. The position is assumed to be already adjusted i.e. relative to the start of the
       
  6308 media, not the partition
       
  6309 */
       
  6310 EXPORT_C TInt DMediaDriverExtension::ReadPaged(TInt aDriveNumber, TInt64 aPos, TLinAddr aData, TUint aLen)
       
  6311 	{
       
  6312 	return SendRequest(DLocalDrive::ERead, ETrue, aDriveNumber, aPos, aData, aLen);
       
  6313 	}
       
  6314 
       
  6315 /**
       
  6316 WritePaged() - 
       
  6317 
       
  6318 Send a paging write request to the specified attached drive
       
  6319 
       
  6320 N.B. The position is assumed to be already adjusted i.e. relative to the start of the
       
  6321 media, not the partition
       
  6322 */
       
  6323 EXPORT_C TInt DMediaDriverExtension::WritePaged(TInt aDriveNumber, TInt64 aPos, TLinAddr aData, TUint aLen)
       
  6324 	{
       
  6325 	return SendRequest(DLocalDrive::EWrite, ETrue, aDriveNumber, aPos, aData, aLen);
       
  6326 	}
       
  6327 #endif	// __DEMAND_PAGING__
       
  6328 
       
  6329 
       
  6330 
       
  6331 /**
       
  6332 Caps() - 
       
  6333 
       
  6334 gets the caps from the next attached drive in the chain
       
  6335 
       
  6336 N.B. The position is assumed to be already adjusted i.e. relative to the start of the
       
  6337 media, not the partition
       
  6338 */
       
  6339 EXPORT_C TInt DMediaDriverExtension::Caps(TInt aDriveNumber, TDes8& aCaps)
       
  6340 	{
       
  6341 	// Ensure this is a legitimate attached drive registered using LocDrv::RegisterMediaDevice()
       
  6342 	if (!(iPrimaryMedia->iBody->iRegisteredDriveMask & (0x1 << aDriveNumber)))
       
  6343 		return KErrArgument;
       
  6344 
       
  6345 	TLocDrv* drive = TDriveIterator::GetDrive(aDriveNumber, iPrimaryMedia);
       
  6346 	__ASSERT_DEBUG(drive, LOCM_FAULT());
       
  6347 	TLocDrv* attachedDrive = drive->iNextDrive;
       
  6348 	__ASSERT_DEBUG(attachedDrive, LOCM_FAULT());
       
  6349 
       
  6350 	TLocDrvRequest request;
       
  6351 	memclr(&request, sizeof(request));
       
  6352 
       
  6353 	request.Drive() = attachedDrive;
       
  6354 	request.Id() = DLocalDrive::ECaps;
       
  6355 	request.Length() = aCaps.Length();
       
  6356 	request.RemoteDes() = (TAny*) aCaps.Ptr();
       
  6357 
       
  6358 	return request.SendReceive(&attachedDrive->iPrimaryMedia->iMsgQ);
       
  6359 	}
       
  6360 
       
  6361 
       
  6362 
       
  6363 EXPORT_C void DMediaDriverExtension::NotifyPowerDown()
       
  6364 	{
       
  6365 	}
       
  6366 
       
  6367 EXPORT_C void DMediaDriverExtension::NotifyEmergencyPowerDown()
       
  6368 	{
       
  6369 	}
       
  6370 
       
  6371 
       
  6372 /**
       
  6373 Returns ETrue if this media - or any media which this TLocDrv is attached to - is busy
       
  6374 */
       
  6375 EXPORT_C TBool DMediaDriverExtension::MediaBusy(TInt aDriveNumber)
       
  6376 	{
       
  6377 	for (TLocDrv* drive = TDriveIterator::GetDrive(aDriveNumber, iPrimaryMedia); 
       
  6378 		drive; 
       
  6379 		drive = drive->iNextDrive)
       
  6380 		{
       
  6381 		DPrimaryMediaBase* primaryMedia = drive->iPrimaryMedia;
       
  6382 		__ASSERT_DEBUG(primaryMedia, LOCM_FAULT());
       
  6383 
       
  6384 		if ((primaryMedia->iMsgQ.iMessage && primaryMedia->iMsgQ.iMessage->iState != TMessageBase::EFree) || 
       
  6385 			!primaryMedia->iMsgQ.iQ.IsEmpty() ||
       
  6386 			primaryMedia->iBody->iMediaChangeDfc.Queued() ||
       
  6387 			primaryMedia->iBody->iMediaPresentDfc.Queued())
       
  6388 			return ETrue;
       
  6389 
       
  6390 #ifdef __DEMAND_PAGING__
       
  6391 		DMediaPagingDevice* pagingDevice = iPrimaryMedia->iBody->iPagingDevice;
       
  6392 		if (pagingDevice)
       
  6393 			{
       
  6394 			if ((pagingDevice->iMainQ.iMessage && pagingDevice->iMainQ.iMessage->iState != TMessageBase::EFree) || 
       
  6395 				!pagingDevice->iMainQ.iQ.IsEmpty())
       
  6396 			return ETrue;
       
  6397 			}
       
  6398 #endif
       
  6399 		}
       
  6400 
       
  6401 	return EFalse;
       
  6402 	}
       
  6403 
       
  6404 
       
  6405 TCallBackLink::TCallBackLink()
       
  6406 	{
       
  6407 	memclr(this, sizeof(this));
       
  6408 	}
       
  6409 
       
  6410 TCallBackLink::TCallBackLink(TInt (*aFunction)(TAny* aPtr, TInt aParam),TAny* aPtr, TObjectType aObjectType) : 
       
  6411 	iFunction(aFunction), iPtr(aPtr), iObjectType(aObjectType)
       
  6412 	{
       
  6413 	}
       
  6414 
       
  6415 TInt TCallBackLink::CallBack(TInt aParam) const
       
  6416 	{
       
  6417 	return (*iFunction)(iPtr, aParam);
       
  6418 	}
       
  6419 
       
  6420 /******************************************************************************
  5740  Entry point
  6421  Entry point
  5741  ******************************************************************************/
  6422  ******************************************************************************/
  5742 DECLARE_STANDARD_EXTENSION()
  6423 DECLARE_STANDARD_EXTENSION()
  5743 	{
  6424 	{
  5744 	__KTRACE_OPT(KBOOT,Kern::Printf("Starting LOCMEDIA extension"));
  6425 	__KTRACE_OPT(KBOOT,Kern::Printf("Starting LOCMEDIA extension"));
  5745 
  6426 
  5746 	// install the HAL function
  6427 	// install the HAL function
  5747 	TInt r=Kern::AddHalEntry(EHalGroupMedia,MediaHalFunction,NULL);
  6428 	TInt r=Kern::AddHalEntry(EHalGroupMedia,MediaHalFunction,NULL);
       
  6429 
  5748 #ifdef __DEMAND_PAGING__
  6430 #ifdef __DEMAND_PAGING__
  5749 	if (r==KErrNone)
  6431 	if (r==KErrNone)
  5750 		{
  6432 		{
  5751 		__KTRACE_OPT(KBOOT,Kern::Printf("Creating LocDrv device"));
  6433 		__KTRACE_OPT(KBOOT,Kern::Printf("Creating LocDrv device"));
  5752 		DLocalDriveFactory* device = new DLocalDriveFactory;
  6434 		DLocalDriveFactory* device = new DLocalDriveFactory;
  5755 		else
  6437 		else
  5756 			r=Kern::InstallLogicalDevice(device);
  6438 			r=Kern::InstallLogicalDevice(device);
  5757 		__KTRACE_OPT(KBOOT,Kern::Printf("Installing LocDrv device in kernel returned %d",r));
  6439 		__KTRACE_OPT(KBOOT,Kern::Printf("Installing LocDrv device in kernel returned %d",r));
  5758 		}
  6440 		}
  5759 #endif // __DEMAND_PAGING__
  6441 #endif // __DEMAND_PAGING__
       
  6442 
  5760 	return r;
  6443 	return r;
  5761 	}
  6444 	}
  5762 
  6445 
  5763 
  6446