kernel/eka/drivers/locmedia/locmedia.cpp
changeset 123 fc55edbf3919
parent 90 947f0dc9f7a8
child 126 2b2a51c87b12
equal deleted inserted replaced
122:70ba09fd07a5 123:fc55edbf3919
    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 			// For media extension drivers, send a copy of the request to the next drive in the chain and wait for it. 
       
  2504 			TLocDrv* drv = m.Drive();
       
  2505 			if (drv->iNextDrive)
       
  2506 				{
       
  2507 				TLocDrvRequest request;
       
  2508 				request.Drive() = drv->iNextDrive;
       
  2509 				request.Id() = DLocalDrive::EForceMediaChange;
       
  2510 				request.Pos() = m.Pos();	// flags
       
  2511 
       
  2512 				request.SendReceive(&drv->iNextDrive->iPrimaryMedia->iMsgQ);
       
  2513 
       
  2514 				CompleteRequest(m, request.iValue);
       
  2515 				return;
       
  2516 				}
       
  2517 
  2276 
  2518 
  2277 			// if KForceMediaChangeReOpenDriver specified wait for power up, 
  2519 			// if KForceMediaChangeReOpenDriver specified wait for power up, 
  2278 			// and then re-open this drive's media driver
  2520 			// and then re-open this drive's media driver
  2279 			__KTRACE_OPT(KLOCDRV, Kern::Printf("EForceMediaChange, flags %08X\n", flags));
  2521 			__KTRACE_OPT(KLOCDRV, Kern::Printf("EForceMediaChange, flags %08X\n", flags));
  2280 			if (flags == (TUint) KForceMediaChangeReOpenMediaDriver)
  2522 			if (flags == (TUint) KForceMediaChangeReOpenMediaDriver)
  2502 	
  2744 	
  2503 	// re-open this drive's media driver ?
  2745 	// re-open this drive's media driver ?
  2504 	if (m.iValue == DLocalDrive::EForceMediaChange)
  2746 	if (m.iValue == DLocalDrive::EForceMediaChange)
  2505 		{
  2747 		{
  2506 		__ASSERT_DEBUG(((TUint) m.Pos()) == (TUint) KForceMediaChangeReOpenMediaDriver, LOCM_FAULT());
  2748 		__ASSERT_DEBUG(((TUint) m.Pos()) == (TUint) KForceMediaChangeReOpenMediaDriver, LOCM_FAULT());
  2507 
       
  2508 		iCurrentReq=NULL;
  2749 		iCurrentReq=NULL;
  2509 
  2750 
  2510 		TLocDrv* pL = m.Drive();
  2751 		TLocDrv* pL = m.Drive();
  2511 		DMedia* media = pL->iMedia;
  2752 		DMedia* media = pL->iMedia;
       
  2753 
  2512 		if (media && media->iDriver)
  2754 		if (media && media->iDriver)
  2513 			CloseMediaDrivers(media);
  2755 			CloseMediaDrivers(media);
  2514 
  2756 
  2515 		iState=EOpening;
  2757 		iState=EOpening;
  2516 		StartOpenMediaDrivers();
  2758 		StartOpenMediaDrivers();
  2517 
  2759 
  2518 		NotifyClients(ETrue,pL);
  2760 		NotifyClients(EMediaChange, pL);
  2519 		CompleteRequest(m, r);
  2761 		CompleteRequest(m, r);
  2520 		OstTraceFunctionExitExt( DPRIMARYMEDIABASE_DOREQUEST_EXIT, this, r );
  2762 		OstTraceFunctionExitExt( DPRIMARYMEDIABASE_DOREQUEST_EXIT, this, r );
  2521 		return r;
  2763 		return r;
  2522 		}
  2764 		}
  2523 
  2765 
  2540 			return KErrNone;
  2782 			return KErrNone;
  2541 			}
  2783 			}
  2542 		if (!(m.Flags() & TLocDrvRequest::EAdjusted))
  2784 		if (!(m.Flags() & TLocDrvRequest::EAdjusted))
  2543 			{
  2785 			{
  2544 			// If this isn't the only partition, don't allow access to the whole media 
  2786 			// If this isn't the only partition, don't allow access to the whole media 
  2545 			if (iTotalPartitionsOpened > 1)
  2787 			if (TDriveIterator::GetPhysicalDrive(m.Drive())->iPrimaryMedia->iTotalPartitionsOpened > 1)
  2546 				m.DriverFlags() &= ~RLocalDrive::ELocDrvWholeMedia;
  2788 				m.DriverFlags() &= ~RLocalDrive::ELocDrvWholeMedia;
  2547 			r=m.CheckAndAdjustForPartition();
  2789 			r=m.CheckAndAdjustForPartition();
  2548 			}
  2790 			}
  2549 		if (r==KErrNone)
  2791 		if (r==KErrNone)
  2550 			{
  2792 			{
  2684 	OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS1, "DPrimaryMediaBase iMediaId=%d", iMediaId );
  2926 	OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS1, "DPrimaryMediaBase iMediaId=%d", iMediaId );
  2685 	
  2927 	
  2686 	// we mustn't ever close the media driver if it's responsible for data paging as re-opening the drive
  2928 	// 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
  2929 	// would involve memory allocation which might cause deadlock if the kernel heap were to grow
  2688 #ifdef __DEMAND_PAGING__
  2930 #ifdef __DEMAND_PAGING__
  2689 	if (DataPagingDfcQ(this))
  2931 	if (DataPagingMedia(this))
  2690 		{
  2932 		{
  2691 		__KTRACE_OPT(KLOCDRV,Kern::Printf("CloseMediaDrivers aborting for data paging media %08X", this));
  2933 		__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);
  2934 		OstTrace1(TRACE_FLOW, DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS_EXIT1, "CloseMediaDrivers aborting for data paging media 0x%08x", this);
  2693 		return;
  2935 		return;
  2694 		}
  2936 		}
  2695 #endif
  2937 #endif
  2696 
  2938 
  2697 	TInt i;
  2939 
  2698 	for (i=0; i<KMaxLocalDrives; i++)
  2940 	// Don't close any media extension drivers either, since it won't serve any purpose
  2699 		{
  2941 	// and keeping the driver open allows it to maintain internal state
  2700 		TLocDrv* pL=TheDrives[i];
  2942 	if (iBody->iMediaExtension)
       
  2943 		{
       
  2944 		__KTRACE_OPT(KLOCDRV,Kern::Printf("CloseMediaDrivers aborting for extension media %08X", this));
       
  2945 		return;
       
  2946 		}
       
  2947 
       
  2948 
       
  2949 	TDriveIterator driveIter;
       
  2950 	for (TLocDrv* pL = driveIter.NextDrive(); pL != NULL; pL = driveIter.NextDrive())
       
  2951 		{
  2701 		if (pL && pL->iPrimaryMedia==this)
  2952 		if (pL && pL->iPrimaryMedia==this)
  2702 			{
  2953 			{
  2703 			__KTRACE_OPT(KLOCDRV,Kern::Printf("Drive %d",i));
  2954 			__KTRACE_OPT(KLOCDRV,Kern::Printf("Drive %d",driveIter.Index()));
  2704 			OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS2, "Drive=%d", i );
  2955 			OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS2, "Drive=%d", driveIter.Index());
  2705 			if (aMedia == NULL || pL->iMedia == aMedia)
  2956 			if (aMedia == NULL || pL->iMedia == aMedia)
  2706 				{
  2957 				{
  2707 				pL->iMedia=NULL;
  2958 				pL->iMedia=NULL;
  2708 				}
  2959 				}
  2709 			}
  2960 			}
  2710 		}
  2961 		}
  2711 	for (i=iLastMediaId; i>=iMediaId; i--)
  2962 	for (TInt i=iLastMediaId; i>=iMediaId; i--)
  2712 		{
  2963 		{
  2713 		DMedia* pM=TheMedia[i];
  2964 		DMedia* pM=TheMedia[i];
  2714 		if (aMedia == NULL || pM == aMedia)
  2965 		if (aMedia == NULL || pM == aMedia)
  2715 			{
  2966 			{
  2716 			DMediaDriver* pD=pM->iDriver;
  2967 			DMediaDriver* pD=pM->iDriver;
  2863 		{
  3114 		{
  2864 		// couldn't read partition info or driver failed to open
  3115 		// couldn't read partition info or driver failed to open
  2865 		if (pM->iDriver)
  3116 		if (pM->iDriver)
  2866 			{
  3117 			{
  2867 #ifdef __DEMAND_PAGING__
  3118 #ifdef __DEMAND_PAGING__
  2868 			if (DataPagingDfcQ(this))
  3119 			if (DataPagingMedia(this))
  2869 				{
  3120 				{
  2870 				__KTRACE_OPT(KLOCDRV,Kern::Printf("DoPartitionInfoComplete(%d) Close Media Driver aborted for data paging media %08X", this));
  3121 				__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);
  3122 				OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE2, "Close Media Driver for data paging media 0x%08x", this);
  2872 				}
  3123 				}
  2873 			else
  3124 			else
  2929 	// work out mapping of drives to partitions/media
  3180 	// work out mapping of drives to partitions/media
  2930 	TInt totalPartitions=iTotalPartitionsOpened;
  3181 	TInt totalPartitions=iTotalPartitionsOpened;
  2931 	TInt id=iMediaId;	// start with primary media
  3182 	TInt id=iMediaId;	// start with primary media
  2932 	TInt partitionsOnThisMedia=PartitionCount();
  3183 	TInt partitionsOnThisMedia=PartitionCount();
  2933 	TInt partition=0;
  3184 	TInt partition=0;
  2934 	TInt j;
  3185 
  2935 	for (j=0; j<KMaxLocalDrives; j++)
  3186 	TDriveIterator driveIter;
  2936 		{
  3187 	for (TLocDrv* pD = driveIter.NextDrive(); pD != NULL; pD = driveIter.NextDrive())
  2937 		TLocDrv* pD=TheDrives[j];
  3188 		{
  2938 		if (pD && pD->iPrimaryMedia==this)
  3189 		if (pD && pD->iPrimaryMedia==this)
  2939 			{
  3190 			{
  2940 			if (totalPartitions==0)
  3191 			if (totalPartitions==0)
  2941 				{
  3192 				{
  2942 				pD->iMedia=NULL;
  3193 				pD->iMedia=NULL;
  2946 				{
  3197 				{
  2947 				id++;
  3198 				id++;
  2948 				partition=0;
  3199 				partition=0;
  2949 				partitionsOnThisMedia=TheMedia[id]->PartitionCount();
  3200 				partitionsOnThisMedia=TheMedia[id]->PartitionCount();
  2950 				}
  3201 				}
  2951 			__KTRACE_OPT(KLOCDRV,Kern::Printf("Drive %d = Media %d Partition %d",j,id,partition));
  3202 			__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 );
  3203 			OstTraceExt3( TRACE_INTERNALS, DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE5, "Local Drive=%d; iMediaId=%d; partition=%d", driveIter.Index(), id, partition );
  2953 			
       
  2954 			pD->iMedia=TheMedia[id];
  3204 			pD->iMedia=TheMedia[id];
  2955 			pD->iPartitionNumber=partition;
  3205 			pD->iPartitionNumber=partition;
  2956 			memcpy(pD, pD->iMedia->iPartitionInfo.iEntry+partition, sizeof(TPartitionEntry));
  3206 			memcpy(pD, pD->iMedia->iPartitionInfo.iEntry+partition, sizeof(TPartitionEntry));
  2957 			partition++;
  3207 			partition++;
  2958 			totalPartitions--;
  3208 			totalPartitions--;
  3214 
  3464 
  3215 	iWaitMedChg.CompleteAll(KErrNone);
  3465 	iWaitMedChg.CompleteAll(KErrNone);
  3216 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_SETCLOSED_EXIT, this );
  3466 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_SETCLOSED_EXIT, this );
  3217 	}
  3467 	}
  3218 
  3468 
  3219 void DPrimaryMediaBase::NotifyClients(TBool aMediaChange,TLocDrv* aLocDrv)
  3469 void DPrimaryMediaBase::NotifyClients(TNotifyType aNotifyType, TLocDrv* aLocDrv)
  3220 
  3470 
  3221 //
  3471 //
  3222 // Notify all clients of a media change or power-down event
  3472 // Notify all clients of a media change or media present event
  3223 //
  3473 //
  3224 	{
  3474 	{
  3225 	OstTraceFunctionEntryExt( DPRIMARYMEDIABASE_NOTIFYCLIENTS_ENTRY, this );
  3475 	OstTraceFunctionEntryExt( DPRIMARYMEDIABASE_NOTIFYCLIENTS_ENTRY, this );
  3226 	
  3476 	
  3227 	SDblQueLink* pL=iConnectionQ.iA.iNext;
  3477 	SDblQueLink* pL=iConnectionQ.iA.iNext;
  3228 	while (pL!=&iConnectionQ.iA)
  3478 	while (pL!=&iConnectionQ.iA)
  3229 		{
  3479 		{
  3230 		DLocalDrive* pD=_LOFF(pL,DLocalDrive,iLink);
  3480 		// Get pointer to TCallBackLink
       
  3481 		TCallBackLink* pCallBackLink = _LOFF(pL,TCallBackLink,iLink);
       
  3482 
       
  3483 		// The link is embedded in either a TLocDrv or a  DLocalDrive object;
       
  3484 		// find out which one it is and then get TLocDrv pointer from that
       
  3485 		__ASSERT_DEBUG(pCallBackLink->iObjectType == TCallBackLink::EDLocalDriveObject || pCallBackLink->iObjectType == TCallBackLink::ETLocDrvObject, LOCM_FAULT());
       
  3486 		TLocDrv* locDrv;
       
  3487 		if (pCallBackLink->iObjectType == TCallBackLink::EDLocalDriveObject)
       
  3488 			locDrv = ((DLocalDrive*) _LOFF(pCallBackLink,DLocalDrive, iMediaChangeObserver))->iDrive;
       
  3489 		else
       
  3490 			locDrv = ((TLocDrv*) _LOFF(pCallBackLink,TLocDrv, iMediaChangeObserver))->iNextDrive;
       
  3491 
  3231 		// Issue the notification if the caller wants to notify all drives (aLocDrv == NULL) or 
  3492 		// Issue the notification if the caller wants to notify all drives (aLocDrv == NULL) or 
  3232 		// the specified drive matches this one
  3493 		// the specified drive matches this one
  3233 		if (aLocDrv == NULL || aLocDrv == pD->iDrive)
  3494 		if (aLocDrv == NULL || aLocDrv == locDrv)
  3234 			pD->NotifyChange(*this, aMediaChange);
  3495 			pCallBackLink->CallBack(aNotifyType);
       
  3496 
  3235 		pL=pL->iNext;
  3497 		pL=pL->iNext;
  3236 		}
  3498 		}
  3237 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYCLIENTS_EXIT, this );
  3499 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYCLIENTS_EXIT, this );
  3238 	}
  3500 	}
  3239 
  3501 
  3247 	OstTraceFunctionEntry1( DPRIMARYMEDIABASE_NOTIFYMEDIACHANGE_ENTRY, this );
  3509 	OstTraceFunctionEntry1( DPRIMARYMEDIABASE_NOTIFYMEDIACHANGE_ENTRY, this );
  3248 	__KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::NotifyMediaChange state %d",iMediaId,iState));
  3510 	__KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::NotifyMediaChange state %d",iMediaId,iState));
  3249 
  3511 
  3250 	OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_NOTIFYMEDIACHANGE, "iMediaId=%d; iState=%d", iMediaId, iState );
  3512 	OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_NOTIFYMEDIACHANGE, "iMediaId=%d; iState=%d", iMediaId, iState );
  3251 	
  3513 	
  3252 	TInt state=iState;
  3514 	// This should only be called in the context of the media thread
  3253 
  3515 	__ASSERT_ALWAYS(NKern::CurrentThread() == iDfcQ->iThread, LOCM_FAULT());
  3254 	__ASSERT_DEBUG(iBody, LOCM_FAULT());
  3516 
  3255 
  3517 	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 
  3518 
  3276 	// notify all connections that media change has occurred
  3519 	// notify all connections that media change has occurred
  3277 	NotifyClients(ETrue);
  3520 	NotifyClients(EMediaChange);
  3278 
  3521 
  3279 	// complete any force media change requests
  3522 	// complete any force media change requests
  3280 	iWaitMedChg.CompleteAll(KErrNone);
  3523 	iWaitMedChg.CompleteAll(KErrNone);
  3281 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYMEDIACHANGE_EXIT, this );
  3524 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYMEDIACHANGE_EXIT, this );
  3282 	}
  3525 	}
  3341 	else
  3584 	else
  3342 		{
  3585 		{
  3343 		CloseMediaDrivers();
  3586 		CloseMediaDrivers();
  3344 		SetClosed(KErrNotReady);
  3587 		SetClosed(KErrNotReady);
  3345 		}
  3588 		}
  3346 
       
  3347 	NotifyClients(EFalse);
       
  3348 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYPOWERDOWN_EXIT, this );
  3589 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYPOWERDOWN_EXIT, this );
  3349 	}
  3590 	}
  3350 
  3591 
  3351 
  3592 
  3352 EXPORT_C void DPrimaryMediaBase::NotifyPsuFault(TInt anError)
  3593 EXPORT_C void DPrimaryMediaBase::NotifyPsuFault(TInt anError)
  3412 		// if ready, media driver should complete current request
  3653 		// if ready, media driver should complete current request
  3413 		CompleteCurrent(KErrNotReady);
  3654 		CompleteCurrent(KErrNotReady);
  3414 		}
  3655 		}
  3415 	CloseMediaDrivers();
  3656 	CloseMediaDrivers();
  3416 	SetClosed(KErrNotReady);
  3657 	SetClosed(KErrNotReady);
  3417 	NotifyClients(EFalse);
       
  3418 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYEMERGENCYPOWERDOWN_EXIT, this );
  3658 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYEMERGENCYPOWERDOWN_EXIT, this );
       
  3659 	}
       
  3660 
       
  3661 
       
  3662 /**
       
  3663 Called by NotifyMediaPresent() and NotifyMediaChange() to ensure the media is in the correct state
       
  3664 */
       
  3665 void DPrimaryMediaBase::MediaChange()
       
  3666 	{
       
  3667 	// Media has been inserted, so we need to cancel any outstanding requests and 
       
  3668 	// ensure that the partition info is read again
       
  3669 	TInt state = iState;
       
  3670 
       
  3671 	__ASSERT_DEBUG(iBody, LOCM_FAULT());
       
  3672 
       
  3673 #ifdef __DEMAND_PAGING__
       
  3674 	iBody->iMediaChanges++;
       
  3675 
       
  3676 	// As data paging media never close, need to ensure the media driver cancels
       
  3677 	// any requests it owns as the stack may be powered down by DPBusPrimaryMedia::ForceMediaChange().
       
  3678 	// DMediaDriver::NotifyPowerDown() should do this
       
  3679 	if (DataPagingMedia(this))
       
  3680 		NotifyPowerDown();
       
  3681 #endif
       
  3682 
       
  3683 	// complete any outstanding requests with KErrNotReady
       
  3684 	// and any force media change requests with KErrNone
       
  3685 	SetClosed(KErrNotReady);
       
  3686 
       
  3687 	// close all media drivers on this device
       
  3688 	if (state>=EOpening)
       
  3689 		{
       
  3690 		CloseMediaDrivers();
       
  3691 		}
  3419 	}
  3692 	}
  3420 
  3693 
  3421 EXPORT_C void DPrimaryMediaBase::NotifyMediaPresent()
  3694 EXPORT_C void DPrimaryMediaBase::NotifyMediaPresent()
  3422 /**
  3695 /**
  3423 Notifies clients of a media change by calling NotifyClients ( ) function to indicate that media is present.
  3696 Notifies clients of a media change by calling NotifyClients ( ) function to indicate that media is present.
  3424 */
  3697 */
  3425 	{
  3698 	{
  3426 	OstTraceFunctionEntry1( DPRIMARYMEDIABASE_NOTIFYMEDIAPRESENT_ENTRY, this );
  3699 	OstTraceFunctionEntry1( DPRIMARYMEDIABASE_NOTIFYMEDIAPRESENT_ENTRY, this );
  3427 	NotifyClients(ETrue);
  3700 	__KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::NotifyMediaPresent state %d",iMediaId,iState));
       
  3701 
       
  3702 	// This should only be called in the context of the media thread
       
  3703 	__ASSERT_ALWAYS(NKern::CurrentThread() == iDfcQ->iThread, LOCM_FAULT());
       
  3704 
       
  3705 	MediaChange();
       
  3706 
       
  3707 	NotifyClients(EMediaPresent);
  3428 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYMEDIAPRESENT_EXIT, this );
  3708 	OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYMEDIAPRESENT_EXIT, this );
  3429 	}
  3709 	}
  3430 
  3710 
  3431 EXPORT_C TInt DPrimaryMediaBase::DoInCritical()
  3711 EXPORT_C TInt DPrimaryMediaBase::DoInCritical()
  3432 /**
  3712 /**
  3573 	if (r==KErrNone)
  3853 	if (r==KErrNone)
  3574 		{
  3854 		{
  3575 		TInt id=iMediaId;	// start with primary media
  3855 		TInt id=iMediaId;	// start with primary media
  3576 		TInt partitionsOnThisMedia=PartitionCount();
  3856 		TInt partitionsOnThisMedia=PartitionCount();
  3577 		TInt partition=0;
  3857 		TInt partition=0;
  3578 		TInt j;
  3858 		
  3579 		for (j=0; j<KMaxLocalDrives; j++)
  3859 		TDriveIterator driveIter;
  3580 			{
  3860 		for (TLocDrv* pD = driveIter.NextDrive(); pD != NULL; pD = driveIter.NextDrive())
  3581 			TLocDrv* pD=TheDrives[j];
  3861 			{
  3582 			if (pD && pD->iPrimaryMedia==this)
  3862 			if (pD && pD->iPrimaryMedia==this)
  3583 				{
  3863 				{
  3584 				if (totalPartitions==0)
  3864 				if (totalPartitions==0)
  3585 					{
  3865 					{
  3586 					pD->iMedia=NULL;
  3866 					pD->iMedia=NULL;
  3937 	// Read from the media and allow for retries in the unlikely event of an error.
  4217 	// Read from the media and allow for retries in the unlikely event of an error.
  3938 	const TInt KPageInRetries = 5;
  4218 	const TInt KPageInRetries = 5;
  3939 	TInt retVal = KErrGeneral;
  4219 	TInt retVal = KErrGeneral;
  3940 	for (TInt i=0; retVal != KErrNone && i < KPageInRetries; i++)
  4220 	for (TInt i=0; retVal != KErrNone && i < KPageInRetries; i++)
  3941 		{
  4221 		{
  3942 		m.Flags() = TLocDrvRequest::EPaging;
  4222 		m.Flags() = TLocDrvRequest::EKernelBuffer | TLocDrvRequest::EPaging;
  3943 		TLocDrv* pL=NULL;
  4223 		TLocDrv* pL=NULL;
  3944 		if(aDrvNumber == EDriveRomPaging)					// ROM paging
  4224 		if(aDrvNumber == EDriveRomPaging)					// ROM paging
  3945 			{
  4225 			{
  3946 			m.Id() = DMediaPagingDevice::ERomPageInRequest;
  4226 			m.Id() = DMediaPagingDevice::ERomPageInRequest;
  3947 			if (iRomPagingDriveNumber == KErrNotFound)
  4227 			if (iRomPagingDriveNumber == KErrNotFound)
  3976 		else if ((aDrvNumber >=0) && (aDrvNumber<KMaxLocalDrives))	// Code paging
  4256 		else if ((aDrvNumber >=0) && (aDrvNumber<KMaxLocalDrives))	// Code paging
  3977 			{
  4257 			{
  3978 			m.Id() = DMediaPagingDevice::ECodePageInRequest;
  4258 			m.Id() = DMediaPagingDevice::ECodePageInRequest;
  3979 			m.Flags() |= TLocDrvRequest::ECodePaging;
  4259 			m.Flags() |= TLocDrvRequest::ECodePaging;
  3980 			pL=TheDrives[aDrvNumber];
  4260 			pL=TheDrives[aDrvNumber];
  3981 			__ASSERT_DEBUG(pL&&(pL->iPrimaryMedia==iPrimaryMedia),LOCM_FAULT());	// valid drive number?
  4261 			__ASSERT_DEBUG(pL && TDriveIterator::GetDrive(aDrvNumber, iPrimaryMedia) ,LOCM_FAULT());	// valid drive number?
  3982 			m.Drive()=pL;
  4262 			m.Drive()=pL;
  3983 #ifdef __DEMAND_PAGING_BENCHMARKS__
  4263 #ifdef __DEMAND_PAGING_BENCHMARKS__
  3984 			__e32_atomic_add_ord32(&iMediaPagingInfo.iCodePageInCount, (TUint) 1);
  4264 			__e32_atomic_add_ord32(&iMediaPagingInfo.iCodePageInCount, (TUint) 1);
  3985 			info = &iCodeBenchmarkData;
  4265 			info = &iCodeBenchmarkData;
  3986 #endif
  4266 #endif
  4099 	// Write to the media and allow for retries in the unlikely event of an error.
  4379 	// Write to the media and allow for retries in the unlikely event of an error.
  4100 	const TInt KPageOutRetries = 5;
  4380 	const TInt KPageOutRetries = 5;
  4101 	TInt retVal = KErrGeneral;
  4381 	TInt retVal = KErrGeneral;
  4102 	for (TInt i=0; retVal != KErrNone && i < KPageOutRetries; i++)
  4382 	for (TInt i=0; retVal != KErrNone && i < KPageOutRetries; i++)
  4103 		{
  4383 		{
  4104 		m.Flags() = TLocDrvRequest::EPaging | TLocDrvRequest::EDataPaging | (aBackground ? TLocDrvRequest::EBackgroundPaging : 0);
  4384 		m.Flags() = TLocDrvRequest::EKernelBuffer | TLocDrvRequest::EPaging | TLocDrvRequest::EDataPaging | (aBackground ? TLocDrvRequest::EBackgroundPaging : 0);
  4105 
  4385 
  4106 		m.Id() = DLocalDrive::EWrite;
  4386 		m.Id() = DLocalDrive::EWrite;
  4107 		m.Drive() = TheDrives[iDataPagingDriveNumber];
  4387 		m.Drive() = TheDrives[iDataPagingDriveNumber];
  4108 
  4388 
  4109 		m.RemoteThread()=NULL;
  4389 		m.RemoteThread()=NULL;
  4195 		}
  4475 		}
  4196 
  4476 
  4197 	TLocDrvRequest& m=*(TLocDrvRequest*)(aReq);
  4477 	TLocDrvRequest& m=*(TLocDrvRequest*)(aReq);
  4198 
  4478 
  4199 
  4479 
  4200 	m.Flags() = TLocDrvRequest::EPaging | TLocDrvRequest::EDataPaging;
  4480 	m.Flags() = TLocDrvRequest::EKernelBuffer | TLocDrvRequest::EPaging  | TLocDrvRequest::EDataPaging;
  4201 	m.Id() = DLocalDrive::EDeleteNotify;
  4481 	m.Id() = DLocalDrive::EDeleteNotify;
  4202 	m.Drive() = TheDrives[iDataPagingDriveNumber];
  4482 	m.Drive() = TheDrives[iDataPagingDriveNumber];
  4203 
  4483 
  4204 	m.RemoteThread() = NULL;
  4484 	m.RemoteThread() = NULL;
  4205 	m.Pos() = offset;
  4485 	m.Pos() = offset;
  4226 		iDeleteNotifyNotSupported = ETrue;
  4506 		iDeleteNotifyNotSupported = ETrue;
  4227 
  4507 
  4228 	OstTraceFunctionExitExt( DMEDIAPAGINGDEVICE_DELETENOTIFY_EXIT3, this, retVal );
  4508 	OstTraceFunctionExitExt( DMEDIAPAGINGDEVICE_DELETENOTIFY_EXIT3, this, retVal );
  4229 	return retVal;
  4509 	return retVal;
  4230 	}
  4510 	}
  4231 
       
  4232 
  4511 
  4233 
  4512 
  4234 EXPORT_C TInt TLocDrvRequest::WriteToPageHandler(const TAny* aSrc, TInt aSize, TInt anOffset)
  4513 EXPORT_C TInt TLocDrvRequest::WriteToPageHandler(const TAny* aSrc, TInt aSize, TInt anOffset)
  4235 	{
  4514 	{
  4236 	OstTraceFunctionEntry1( TLOCDRVREQUEST_WRITETOPAGEHANDLER_ENTRY, this );
  4515 	OstTraceFunctionEntry1( TLOCDRVREQUEST_WRITETOPAGEHANDLER_ENTRY, this );
  4416 	if (aLocDrv)
  4695 	if (aLocDrv)
  4417 		aLocDrv->iPartitionLen=aTotalSizeInBytes;
  4696 		aLocDrv->iPartitionLen=aTotalSizeInBytes;
  4418 	OstTraceFunctionExit1( DMEDIADRIVER_SETTOTALSIZEINBYTES_EXIT, this );
  4697 	OstTraceFunctionExit1( DMEDIADRIVER_SETTOTALSIZEINBYTES_EXIT, this );
  4419 	}
  4698 	}
  4420 
  4699 
       
  4700 /**
       
  4701 For non NAND devices, i.e. devices which don't set TLocalDriveCapsV4::iNumOfBlocks,
       
  4702 set iSectorSizeInBytes, iNumberOfSectors & iNumPagesPerBlock appropriately to allow 
       
  4703 TLocalDriveCapsV4::MediaSizeInBytes() to correctly return the media size
       
  4704 
       
  4705 Media drivers should call this when they receive a DLocalDrive::ECaps request
       
  4706 */
       
  4707 EXPORT_C void DMediaDriver::SetTotalSizeInBytes(TLocalDriveCapsV4& aCaps)
       
  4708 	{
       
  4709 	if (aCaps.iNumOfBlocks == 0)
       
  4710 		{
       
  4711 		aCaps.iSectorSizeInBytes = 512;
       
  4712 		aCaps.iNumPagesPerBlock = 1;	// ...to ensure compatibility with NAND semantics
       
  4713 		Int64 numberOfSectors = iTotalSizeInBytes >> 9;
       
  4714 		while (I64HIGH(numberOfSectors) > 0)
       
  4715 			{
       
  4716 			aCaps.iNumPagesPerBlock<<= 1;
       
  4717 			numberOfSectors>>= 1;
       
  4718 			}
       
  4719 		aCaps.iNumberOfSectors = I64LOW(numberOfSectors);
       
  4720 		}
       
  4721 	}
  4421 
  4722 
  4422 
  4723 
  4423 
  4724 
  4424 /**
  4725 /**
  4425 Gets the total size of the media.
  4726 Gets the total size of the media.
  4647 	{
  4948 	{
  4648 	OstTraceFunctionEntry0( LOCDRV_REGISTERMEDIADEVICE_ENTRY );
  4949 	OstTraceFunctionEntry0( LOCDRV_REGISTERMEDIADEVICE_ENTRY );
  4649 	// Create TLocDrv / DMedia objects to handle a media device
  4950 	// 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));
  4951 	__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 );
  4952 	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 	
  4953 
  4653 	const TInt* p=aDriveList;
       
  4654 	TInt i;
       
  4655 	TInt r=0;
       
  4656 	if (UsedMedia+aNumMedia>KMaxLocalDrives)
  4954 	if (UsedMedia+aNumMedia>KMaxLocalDrives)
  4657 	    {
  4955 	    {
  4658 		OstTrace0(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT1, "< KErrInUse");
  4956 		OstTrace0(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT1, "< KErrInUse");
  4659 		return KErrInUse;
  4957 		return KErrInUse;
  4660 	    }
  4958 		}
  4661 	for (i=0; i<aDriveCount; ++i)
  4959 
  4662 		{
  4960 	// 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);
  4961 	HBuf* pN=HBuf::New(aName);
  4677 	if (!pN)
  4962 	if (!pN)
  4678 	    {
  4963 	    {
  4679         OstTrace0(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT3, "< KErrNoMemory");
  4964         OstTrace0(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT3, "< KErrNoMemory");
  4680 		return KErrNoMemory;
  4965 		return KErrNoMemory;
  4681 	    }
  4966 		}
  4682 	TInt lastMedia=UsedMedia+aNumMedia-1;
  4967 
       
  4968 	// Register the primary media and any secondary media
       
  4969 	TInt lastMedia = UsedMedia+aNumMedia-1;
       
  4970 	TInt i;
       
  4971 	TInt r=0;
  4683 	for (i=UsedMedia; i<=lastMedia; ++i)
  4972 	for (i=UsedMedia; i<=lastMedia; ++i)
  4684 		{
  4973 		{
  4685 		if (i==UsedMedia)
  4974 		if (i==UsedMedia)
  4686 			TheMedia[i]=aPrimaryMedia;
  4975 			TheMedia[i]=aPrimaryMedia;
  4687 		else
  4976 		else
  4698 		    {
  4987 		    {
  4699             OstTrace1(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT5, "< retval=%d", r);
  4988             OstTrace1(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT5, "< retval=%d", r);
  4700 			return r;
  4989 			return r;
  4701 		    }
  4990 		    }
  4702 		}
  4991 		}
  4703 
       
  4704 	__KTRACE_OPT(KBOOT,Kern::Printf("FirstMedia %d LastMedia %d",UsedMedia,lastMedia));
  4992 	__KTRACE_OPT(KBOOT,Kern::Printf("FirstMedia %d LastMedia %d",UsedMedia,lastMedia));
  4705 	OstTraceExt2( TRACE_INTERNALS, LOCDRV_REGISTERMEDIADEVICE4, "FirstMedia=%d; LastMedia=%d", UsedMedia, lastMedia );
  4993 	OstTraceExt2( TRACE_INTERNALS, LOCDRV_REGISTERMEDIADEVICE4, "FirstMedia=%d; LastMedia=%d", UsedMedia, lastMedia );
  4706 	UsedMedia+=aNumMedia;
  4994 	UsedMedia+=aNumMedia;
  4707 	p=aDriveList;
  4995 
       
  4996 	if (__IS_EXTENSION(aDevice))
       
  4997 		aPrimaryMedia->iBody->iMediaExtension = ETrue;
       
  4998 
       
  4999 	// Register the drives
       
  5000 	const TInt* p=aDriveList;
  4708 	for (i=0; i<aDriveCount; ++i)
  5001 	for (i=0; i<aDriveCount; ++i)
  4709 		{
  5002 		{
  4710 		TInt drv=*p++;
  5003 		TInt drv = *p++;
       
  5004 		// -1 means not used; this is to enable Dual-slot MMC support 
  4711 		if (drv == -1)
  5005 		if (drv == -1)
  4712 			continue;
  5006 			continue;
  4713 		TLocDrv* pL=new TLocDrv(drv);
  5007 
  4714 		if (!pL)
  5008 		__KTRACE_OPT(KBOOT,Kern::Printf("Registering drive %d", drv));
  4715 		    {
  5009 		if (!__IS_EXTENSION(aDevice) && TheDrives[drv])
       
  5010 			{
       
  5011 			__KTRACE_OPT(KBOOT,Kern::Printf("Drive %d already in use", drv));
       
  5012 			return KErrInUse;
       
  5013 			}
       
  5014 		else if (__IS_EXTENSION(aDevice) && !TheDrives[drv])
       
  5015 			{
       
  5016 			__KTRACE_OPT(KBOOT,Kern::Printf("Drive %d not initialized", drv));
       
  5017 			return KErrNotReady;
       
  5018 			}
       
  5019 
       
  5020 		TLocDrv* pNewDrive = new TLocDrv(drv);
       
  5021 		if (!pNewDrive)
       
  5022 			{
  4716             OstTrace0(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT6, "< KErrNoMemory");
  5023             OstTrace0(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT6, "< KErrNoMemory");
  4717 			return KErrNoMemory;
  5024 			return KErrNoMemory;
  4718 		    }
  5025 			}
  4719 		TheDrives[drv]=pL;
  5026 
  4720 		DriveNames[drv]=pN;
  5027 
  4721 		pL->iPrimaryMedia=aPrimaryMedia;
  5028 		TLocDrv* pOldDrive = TheDrives[drv];
  4722 		__KTRACE_OPT(KBOOT,Kern::Printf("Drive %d: TLocDrv @ %08x",drv,pL));
  5029 		aPrimaryMedia->iBody->iRegisteredDriveMask|= (0x1 << drv);
  4723 		OstTraceExt2( TRACE_INTERNALS, LOCDRV_REGISTERMEDIADEVICE5, "Drive=%d; TLocDrv 0x%08x;", (TInt) drv, (TUint) pL );
  5030 		pNewDrive->iNextDrive = pOldDrive;
  4724 		}
  5031 
       
  5032 		TheDrives[drv] = pNewDrive;
       
  5033 		DriveNames[drv] = pN;
       
  5034 		pNewDrive->iPrimaryMedia = aPrimaryMedia;
       
  5035 
       
  5036 
       
  5037 		if (pOldDrive)
       
  5038 			{
       
  5039 			TInt r = pOldDrive->iPrimaryMedia->Connect(pNewDrive);
       
  5040 			if (r != KErrNone)
       
  5041 				return r;
       
  5042 
       
  5043 #ifdef __DEMAND_PAGING__
       
  5044 			// If we've hooked a drive letter which is being used for ROM paging by a media driver
       
  5045 			// which does not report the ROM partition, then we need to change iFirstLocalDriveNumber
       
  5046 			// so that ROM page-in requests go directly to that driver
       
  5047 			DMediaPagingDevice* oldPagingDevice = pOldDrive->iPrimaryMedia->iBody->iPagingDevice;
       
  5048 			if (oldPagingDevice && 
       
  5049 				(oldPagingDevice->iType & DPagingDevice::ERom) &&
       
  5050 				oldPagingDevice->iRomPagingDriveNumber == KErrNotFound && 
       
  5051 				oldPagingDevice->iFirstLocalDriveNumber == drv)
       
  5052 				{
       
  5053 				__KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("TRACE: hooking ROM paging device with no defined ROM partition"));
       
  5054 				TInt n;
       
  5055 				for (n=0; n<KMaxLocalDrives; ++n)
       
  5056 					{
       
  5057 					if(TheDrives[n] && TheDrives[n]->iPrimaryMedia == pOldDrive->iPrimaryMedia)
       
  5058 						{
       
  5059 						__KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("TRACE: Changing iFirstLocalDriveNumber from %d to %d", oldPagingDevice->iFirstLocalDriveNumber, n));
       
  5060 						oldPagingDevice->iFirstLocalDriveNumber = n;
       
  5061 						break;
       
  5062 						}
       
  5063 					}
       
  5064 				__ASSERT_ALWAYS(n < KMaxLocalDrives, LOCM_FAULT());
       
  5065 				}
       
  5066 #endif
       
  5067 
       
  5068 			}
       
  5069 
       
  5070 		__KTRACE_OPT(KBOOT,Kern::Printf("Drive %d: TLocDrv @ %08x",drv,pNewDrive));
       
  5071 		}
       
  5072 
  4725 
  5073 
  4726 	OstTraceFunctionExit0( LOCDRV_REGISTERMEDIADEVICE_EXIT7 );
  5074 	OstTraceFunctionExit0( LOCDRV_REGISTERMEDIADEVICE_EXIT7 );
  4727 	return KErrNone;
  5075 	return KErrNone;
  4728 	}
  5076 	}
  4729 
  5077 
  4805                      or one of the other system-wide error codes.  
  5153                      or one of the other system-wide error codes.  
  4806 */
  5154 */
  4807 EXPORT_C TInt LocDrv::RegisterPagingDevice(DPrimaryMediaBase* aPrimaryMedia, const TInt* aPagingDriveList, TInt aDriveCount, TUint aPagingType, TInt aReadShift, TUint aNumPages)
  5155 EXPORT_C TInt LocDrv::RegisterPagingDevice(DPrimaryMediaBase* aPrimaryMedia, const TInt* aPagingDriveList, TInt aDriveCount, TUint aPagingType, TInt aReadShift, TUint aNumPages)
  4808 	{
  5156 	{
  4809 	OstTraceFunctionEntry0( LOCDRV_REGISTERPAGINGDEVICE_ENTRY );
  5157 	OstTraceFunctionEntry0( LOCDRV_REGISTERPAGINGDEVICE_ENTRY );
       
  5158 //	SETDEBUGFLAG(KLOCDPAGING);
  4810 	
  5159 	
  4811 	__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf(">RegisterPagingDevice: paging type=%d PM=0x%x read shift=%d",aPagingType,aPrimaryMedia,aReadShift));
  5160 	__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);
  5161 	OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE1, "aPagingType=%d; aPrimaryMedia=0x%x; aReadShift=%d", (TInt) aPagingType, (TUint) aPrimaryMedia, (TInt) aReadShift);
  4813 	
  5162 	
  4814 	TInt i;
  5163 	TInt i = 0;
  4815 
  5164 
  4816 	if(!aPagingType || (aPagingType&~(DPagingDevice::ERom | DPagingDevice::ECode | DPagingDevice::EData)))
  5165 	if(!aPagingType || (aPagingType&~(DPagingDevice::ERom | DPagingDevice::ECode | DPagingDevice::EData)))
  4817 		{
  5166 		{
  4818 		__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Unsupported paging type, exiting"));
  5167 		__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Unsupported paging type, exiting"));
  4819 		OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT1, "< Unsupported paging type; KErrArgument");
  5168 		OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT1, "< Unsupported paging type; KErrArgument");
  4820 		return KErrArgument;
  5169 		return KErrArgument;
  4821 		}
  5170 		}
  4822 
  5171 
  4823 
  5172 
  4824 
  5173 	// Check for duplicate drives
  4825 	for(i=0; i<KMaxLocalDrives; i++)
  5174 	if (!aPrimaryMedia->iBody->iMediaExtension)
  4826 		{
  5175 		{
  4827 		if (ThePagingDevices[i] == NULL)
  5176 		for(i=0; i<KMaxLocalDrives; i++)
  4828 			continue;
  5177 			{
  4829 		if ((ThePagingDevices[i]->iType&DPagingDevice::ERom) &&	(aPagingType & DPagingDevice::ERom))
  5178 			if (ThePagingDevices[i] == NULL)
  4830 			{
  5179 				continue;
  4831 			aPagingType&=~DPagingDevice::ERom;		// already have a ROM paging device
  5180 			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));
  5181 				{
  4833 			}
  5182 				aPagingType&=~DPagingDevice::ERom;		// already have a ROM paging device
  4834 		if ((ThePagingDevices[i]->iType&DPagingDevice::EData) && (aPagingType & DPagingDevice::EData))
  5183 				__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Already has ROM pager on locdrv no %d",i));
  4835 			{
  5184 				}
  4836 			aPagingType&=~DPagingDevice::EData;		// already have a Data paging device
  5185 			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));
  5186 				{
       
  5187 				aPagingType&=~DPagingDevice::EData;		// already have a Data paging device
       
  5188 				__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Already has Data pager on locdrv no %d",i));
       
  5189 				}
  4838 			}
  5190 			}
  4839 		}
  5191 		}
  4840 
  5192 
  4841 
  5193 
  4842 	if (aPagingType == 0)
  5194 	if (aPagingType == 0)
  4913 	__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("DMediaPagingDevice(), firstLocalDriveNumber %d", firstLocalDriveNumber));
  5265 	__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("DMediaPagingDevice(), firstLocalDriveNumber %d", firstLocalDriveNumber));
  4914 	OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE3, "firstLocalDriveNumber=%d", firstLocalDriveNumber );
  5266 	OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE3, "firstLocalDriveNumber=%d", firstLocalDriveNumber );
  4915 	
  5267 	
  4916 	// Send an ECaps message to wake up the media driver & ensure all partitions are 
  5268 	// 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
  5269 	// reported, then search for paged-data or paged-ROM partitions
       
  5270 	// NB: older media drivers supporting ROM and/or code paging only may not have started their DFC queues, 
       
  5271 	// so for these media drivers, use the first local drive supported for ROM-pagin-in  requests and
       
  5272 	// assume the media driver itself will adjust the request position internally to match the ROM partition
       
  5273 	// @see DMediaPagingDevice::Read()
  4918 	if ((aPagingType & DPagingDevice::EData) ||
  5274 	if ((aPagingType & DPagingDevice::EData) ||
  4919 		(aPagingType & DPagingDevice::ERom && aPrimaryMedia->iDfcQ && aPrimaryMedia->iMsgQ.iReady))
  5275 		(aPagingType & DPagingDevice::ERom && aPrimaryMedia->iDfcQ && aPrimaryMedia->iMsgQ.iReady))
  4920 		{
  5276 		{
  4921 		// the message queue must have been started already (by the media driver calling iMsgQ.Receive())
  5277 		// 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
  5278 		// otherwise we can't send the DLocalDrive::ECaps request
  4923 		if (aPrimaryMedia->iDfcQ && !aPrimaryMedia->iMsgQ.iReady)
  5279 		if (!aPrimaryMedia->iDfcQ || !aPrimaryMedia->iMsgQ.iReady)
  4924 			{
  5280 			{
  4925 			__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: Message queue not started"));
  5281 			__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: Message queue not started"));
  4926 			OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT8, "< RegisterPagingDevice: Message queue not started; KErrNotReady");
  5282 			OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT8, "< RegisterPagingDevice: Message queue not started; KErrNotReady");
  4927 			return KErrNotReady;
  5283 			return KErrNotReady;
  4928 			}
  5284 			}
  4953 			OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE4, "Paging device ECaps: i %d retval=%d", i, r);
  5309 			OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE4, "Paging device ECaps: i %d retval=%d", i, r);
  4954 			}
  5310 			}
  4955 
  5311 
  4956 		if (r != KErrNone)
  5312 		if (r != KErrNone)
  4957 		    {
  5313 		    {
  4958             OstTrace1(TRACE_FLOW, LOCRV_REGISTERPAGINGDEVICE_EXIT9, "< Caps::retval=%d - return KErrNotSupported",r);
  5314             OstTrace1(TRACE_FLOW, LOCRV_REGISTERPAGINGDEVICE_EXIT9, "< retval=%d",r);
  4959             // Media driver failure; media maybe recoverable after boot.
  5315             // Media driver failure; media maybe recoverable after boot.
  4960             // Can't register any page drives so return not supported.
  5316             // Can't register any page drives so return not supported.
  4961 			return KErrNotSupported;
  5317 			return KErrNotSupported;
  4962 		    }
  5318 		    }
  4963 
  5319 
  4965 		for (i=0; i<KMaxLocalDrives; ++i)
  5321 		for (i=0; i<KMaxLocalDrives; ++i)
  4966 			{
  5322 			{
  4967 			drive = TheDrives[i];
  5323 			drive = TheDrives[i];
  4968 			if(drive && drive->iPrimaryMedia == aPrimaryMedia)
  5324 			if(drive && drive->iPrimaryMedia == aPrimaryMedia)
  4969 				{
  5325 				{
  4970 				__KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("RegisterPagingDevice: local drive %d, partition type %x size %x", i, drive->iPartitionType, I64LOW(drive->iPartitionLen)));
  5326 				__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 ?
  5327 				// ROM partition ?
  4972 				if ((romPagingDriveNumber == KErrNotFound) && (drive->iPartitionType == KPartitionTypeROM))
  5328 				if ((romPagingDriveNumber == KErrNotFound) && 
       
  5329 					(drive->iPartitionType == KPartitionTypeROM) &&
       
  5330 					(aPagingType & DPagingDevice::ERom))
  4973 					{
  5331 					{
  4974 					__KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("Found ROM partition on local drive %d, size %x", i, I64LOW(drive->iPartitionLen)));
  5332 					__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));
  5333 					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;
  5334 					romPagingDriveNumber = i;
  4977 					}
  5335 					}
  4978 			    // swap partition ?
  5336 			    // swap partition ?
  4979 				else if ((dataPagingDriveNumber == KErrNotFound) && (drive->iPartitionType == KPartitionTypePagedData))
  5337 				else if ((dataPagingDriveNumber == KErrNotFound) && 
       
  5338 					(drive->iPartitionType == KPartitionTypePagedData) &&
       
  5339 					(aPagingType & DPagingDevice::EData))
  4980 					{
  5340 					{
  4981 					__KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("Found swap partition on local drive %d, size %x", i, I64LOW(drive->iPartitionLen)));
  5341 					__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) );			
  5342 					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;
  5343 					dataPagingDriveNumber = i;
       
  5344 					TheDataPagingDrive = drive;
  4984 					swapSize = drive->iPartitionLen >> aReadShift;
  5345 					swapSize = drive->iPartitionLen >> aReadShift;
  4985 					}
  5346 					}
  4986 				}
  5347 				}
  4987 			}
  5348 			}
  4988 
  5349 
  5004 		OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT_EXIT10, "< RegisterPagingDevice: could not create paging device; KErrNoMemory");
  5365 		OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT_EXIT10, "< RegisterPagingDevice: could not create paging device; KErrNoMemory");
  5005 		return KErrNoMemory;
  5366 		return KErrNoMemory;
  5006 		}
  5367 		}
  5007 
  5368 
  5008 	pagingDevice->iType = aPagingType;
  5369 	pagingDevice->iType = aPagingType;
       
  5370 	if (aPrimaryMedia->iBody->iMediaExtension)
       
  5371 		pagingDevice->iType|= DPagingDevice::EMediaExtension;
       
  5372 
  5009 	pagingDevice->iReadUnitShift = aReadShift;
  5373 	pagingDevice->iReadUnitShift = aReadShift;
  5010 
  5374 
  5011 	pagingDevice->iFirstLocalDriveNumber = firstLocalDriveNumber;
  5375 	pagingDevice->iFirstLocalDriveNumber = firstLocalDriveNumber;
  5012 	pagingDevice->iRomPagingDriveNumber = romPagingDriveNumber;
  5376 	pagingDevice->iRomPagingDriveNumber = romPagingDriveNumber;
  5013 
  5377 
  5014 	pagingDevice->iDataPagingDriveNumber = dataPagingDriveNumber;
  5378 	pagingDevice->iDataPagingDriveNumber = dataPagingDriveNumber;
  5015 	pagingDevice->iSwapSize = swapSize;
  5379 	pagingDevice->iSwapSize = swapSize;
  5016 
  5380 
  5017 #ifdef __DEBUG_DEMAND_PAGING__
  5381 #ifdef __DEBUG_DEMAND_PAGING__
  5018 	Kern::Printf("PagingDevice :");
  5382 	Kern::Printf("PagingDevice :");
  5019 	Kern::Printf("iType 0x%x\n", pagingDevice->iType);
  5383 	Kern::Printf("Name %lS", firstLocalDriveNumber >= 0 && DriveNames[firstLocalDriveNumber] ? DriveNames[firstLocalDriveNumber] : &KNullDesC8);
  5020 	Kern::Printf("iReadUnitShift 0x%x\n", pagingDevice->iReadUnitShift);
  5384 	Kern::Printf("iType 0x%x", pagingDevice->iType);
  5021 	Kern::Printf("iFirstLocalDriveNumber 0x%x\n", pagingDevice->iFirstLocalDriveNumber);
  5385 	Kern::Printf("iReadUnitShift 0x%x", pagingDevice->iReadUnitShift);
  5022 	Kern::Printf("iRomPagingDriveNumber 0x%x\n", pagingDevice->iRomPagingDriveNumber);
  5386 	Kern::Printf("iFirstLocalDriveNumber 0x%x", pagingDevice->iFirstLocalDriveNumber);
  5023 	Kern::Printf("iDataPagingDriveNumber 0x%x\n", pagingDevice->iDataPagingDriveNumber);
  5387 	Kern::Printf("iRomPagingDriveNumber 0x%x", pagingDevice->iRomPagingDriveNumber);
  5024 	Kern::Printf("iSwapSize 0x%x\n", pagingDevice->iSwapSize);
  5388 	Kern::Printf("iDataPagingDriveNumber 0x%x", pagingDevice->iDataPagingDriveNumber);
       
  5389 	Kern::Printf("iSwapSize 0x%x", pagingDevice->iSwapSize);
  5025 #endif
  5390 #endif
  5026 
  5391 
  5027 
  5392 
  5028 	// This table is indexed by DPagingDevice::TType
  5393 	// This table is indexed by DPagingDevice::TType
  5029 	const char* DeviceName[] = 
  5394 	const char* DeviceName[] = 
  5040 
  5405 
  5041 
  5406 
  5042 	if(aPagingType & DPagingDevice::ECode)
  5407 	if(aPagingType & DPagingDevice::ECode)
  5043 		{
  5408 		{
  5044 		for (i=0; i<aDriveCount; ++i)
  5409 		for (i=0; i<aDriveCount; ++i)
  5045 			pagingDevice->iDrivesSupported|=(0x1<<aPagingDriveList[i]);
  5410 			pagingDevice->iDrivesSupported |= (0x1<<aPagingDriveList[i]);
  5046 		}
  5411 		}
  5047 	pagingDevice->iName = DeviceName[aPagingType];
  5412 	pagingDevice->iName = DeviceName[aPagingType];
  5048 
  5413 
       
  5414 	// If ThePinObjectAllocator has already been created with a smaller number of pages,
       
  5415 	// delete it & then re-create it
       
  5416 	__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: ThePinObjectAllocator %x", ThePinObjectAllocator));
       
  5417 	if (ThePinObjectAllocator && ThePinObjectAllocator->iFragmentGranularity < Kern::RoundToPageSize(1) * aNumPages)
       
  5418 		{
       
  5419 		__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: Recreating ThePinObjectAllocator..."));
       
  5420 		delete ThePinObjectAllocator;
       
  5421 		ThePinObjectAllocator = NULL;
       
  5422 		}
       
  5423 
       
  5424 
       
  5425 	TInt r;
  5049 	if (ThePinObjectAllocator == NULL)
  5426 	if (ThePinObjectAllocator == NULL)
       
  5427 		{
  5050 		ThePinObjectAllocator = new DPinObjectAllocator();
  5428 		ThePinObjectAllocator = new DPinObjectAllocator();
  5051 	if(!ThePinObjectAllocator)
  5429 		if(!ThePinObjectAllocator)
  5052 		{
  5430 			{
  5053 		__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: could not create ThePinObjectAllocator"));
  5431 			__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: could not create ThePinObjectAllocator"));
  5054 		OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT11, "RegisterPagingDevice: could not create ThePinObjectAllocator; KErrNoMemory");
  5432 			OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT11, "RegisterPagingDevice: could not create ThePinObjectAllocator; KErrNoMemory");
  5055 		return KErrNoMemory;
  5433 			return KErrNoMemory;
  5056 		}
  5434 			}
  5057 	TInt r = ThePinObjectAllocator->Construct(KDynamicPagingLockCount, aNumPages);
  5435 		r = ThePinObjectAllocator->Construct(KDynamicPagingLockCount, aNumPages);
  5058 	if (r != KErrNone)
  5436 		if (r != KErrNone)
  5059 		{
  5437 			{
  5060 		__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: could not construct ThePinObjectAllocator"));
  5438 			__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);
  5439 			OstTrace1(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT12, "< RegisterPagingDevice: could not construct ThePinObjectAllocator; retval=%d",r);
  5062 		return r;
  5440 			return r;
       
  5441 			}
  5063 		}
  5442 		}
  5064 
  5443 
  5065 
  5444 
  5066 	// Register our DPagingDevice with the Kernel
  5445 	// Register our DPagingDevice with the Kernel
  5067 	r=Kern::InstallPagingDevice(pagingDevice);
  5446 	r=Kern::InstallPagingDevice(pagingDevice);
  5087 	if (aPagingType&DPagingDevice::ECode)
  5466 	if (aPagingType&DPagingDevice::ECode)
  5088 		{
  5467 		{
  5089 		for (i=0; i<aDriveCount; ++i)
  5468 		for (i=0; i<aDriveCount; ++i)
  5090 			{
  5469 			{
  5091 			TLocDrv* pD=TheDrives[*p++];
  5470 			TLocDrv* pD=TheDrives[*p++];
  5092 			pD->iPagingDrv=1;
  5471 			pD->iPagingDrv = 1;
       
  5472 			// mark all attached drives as pageable too - this is really 
       
  5473 			// only to avoid hitting an ASSERT in DMediaDriver::Complete()
       
  5474 			while (pD->iNextDrive)
       
  5475 				{
       
  5476 				pD->iNextDrive->iPagingDrv = 1;
       
  5477 				pD = pD->iNextDrive;
       
  5478 				}
  5093 			}
  5479 			}
  5094 		}
  5480 		}
  5095 
  5481 
  5096 	// Flags to indicate that a paging device is registered and pinning of user requests may be required
  5482 	// Flags to indicate that a paging device is registered and pinning of user requests may be required
  5097 	aPrimaryMedia->iPagingMedia = 1;
  5483 	aPrimaryMedia->iPagingMedia = 1;
  5131 		TheDataPagingMedia = aPrimaryMedia;
  5517 		TheDataPagingMedia = aPrimaryMedia;
  5132 		}
  5518 		}
  5133 
  5519 
  5134 	__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("< RegisterPagingDevice"));
  5520 	__KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("< RegisterPagingDevice"));
  5135 	OstTraceFunctionExit0( LOCDRV_REGISTERPAGINGDEVICE_EXIT14 );
  5521 	OstTraceFunctionExit0( LOCDRV_REGISTERPAGINGDEVICE_EXIT14 );
       
  5522 //	CLRDEBUGFLAG(KLOCDPAGING);
  5136 	return KErrNone;
  5523 	return KErrNone;
  5137 	}
  5524 	}
  5138 
  5525 
  5139 #else //__DEMAND_PAGING__
  5526 #else //__DEMAND_PAGING__
  5140 
  5527 
  5206 	for (i=0; i<KMaxLocalDrives; ++i)
  5593 	for (i=0; i<KMaxLocalDrives; ++i)
  5207 		{
  5594 		{
  5208 		TLocDrv* pL=TheDrives[i];
  5595 		TLocDrv* pL=TheDrives[i];
  5209 		if (pL)
  5596 		if (pL)
  5210 			{
  5597 			{
       
  5598 			pL = TDriveIterator::GetPhysicalDrive(TheDrives[i]);
  5211 			++drives;
  5599 			++drives;
  5212 			TInt sockNum;
  5600 			TInt sockNum;
  5213 			DPrimaryMediaBase* pM=pL->iPrimaryMedia;
  5601 			DPrimaryMediaBase* pM=pL->iPrimaryMedia;
  5214 			if (pM->IsRemovableDevice(sockNum))
  5602 			if (pM->IsRemovableDevice(sockNum))
  5215 				{
  5603 				{
  5345 			break;
  5733 			break;
  5346 			}
  5734 			}
  5347 #if defined(__DEMAND_PAGING__) && defined(__CONCURRENT_PAGING_INSTRUMENTATION__)
  5735 #if defined(__DEMAND_PAGING__) && defined(__CONCURRENT_PAGING_INSTRUMENTATION__)
  5348 		case EMediaHalGetROMConcurrencyInfo:
  5736 		case EMediaHalGetROMConcurrencyInfo:
  5349 			{
  5737 			{
  5350 			TInt drvNo=(TInt)a1;
  5738 			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)
  5739 			if(!device)
  5356 				break;
  5740 				break;
  5357 			NKern::FMWait(&device->iInstrumentationLock);
  5741 			NKern::FMWait(&device->iInstrumentationLock);
  5358 			SMediaROMPagingConcurrencyInfo info=device->iROMStats;
  5742 			SMediaROMPagingConcurrencyInfo info=device->iROMStats;
  5359 			NKern::FMSignal(&device->iInstrumentationLock);
  5743 			NKern::FMSignal(&device->iInstrumentationLock);
  5361 			r=KErrNone;
  5745 			r=KErrNone;
  5362 			break;
  5746 			break;
  5363 			}
  5747 			}
  5364 		case EMediaHalGetCodeConcurrencyInfo:
  5748 		case EMediaHalGetCodeConcurrencyInfo:
  5365 			{
  5749 			{
  5366 			TInt drvNo=(TInt)a1;
  5750 			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)
  5751 			if(!device)
  5372 				break;
  5752 				break;
  5373 			NKern::FMWait(&device->iInstrumentationLock);
  5753 			NKern::FMWait(&device->iInstrumentationLock);
  5374 			SMediaCodePagingConcurrencyInfo info=device->iCodeStats;
  5754 			SMediaCodePagingConcurrencyInfo info=device->iCodeStats;
  5375 			NKern::FMSignal(&device->iInstrumentationLock);
  5755 			NKern::FMSignal(&device->iInstrumentationLock);
  5377 			r=KErrNone;
  5757 			r=KErrNone;
  5378 			break;
  5758 			break;
  5379 			}
  5759 			}
  5380 		case EMediaHalGetDataConcurrencyInfo:
  5760 		case EMediaHalGetDataConcurrencyInfo:
  5381 			{
  5761 			{
  5382 			TInt drvNo=(TInt)a1;
  5762 			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)
  5763 			if(!device)
  5388 				break;
  5764 				break;
  5389 			NKern::FMWait(&device->iInstrumentationLock);
  5765 			NKern::FMWait(&device->iInstrumentationLock);
  5390 			SMediaDataPagingConcurrencyInfo info=device->iDataStats;
  5766 			SMediaDataPagingConcurrencyInfo info=device->iDataStats;
  5391 			NKern::FMSignal(&device->iInstrumentationLock);
  5767 			NKern::FMSignal(&device->iInstrumentationLock);
  5393 			r=KErrNone;
  5769 			r=KErrNone;
  5394 			break;
  5770 			break;
  5395 			}
  5771 			}
  5396 		case EMediaHalResetConcurrencyInfo:
  5772 		case EMediaHalResetConcurrencyInfo:
  5397 			{
  5773 			{
  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;
  5774 			TUint index=(TInt)a2;
  5406 			if(index>EMediaPagingStatsCode)
  5775 			if(index>EMediaPagingStatsCode)
  5407 				break;
  5776 				break;
  5408 			ResetConcurrencyStats(device, (TMediaPagingStats)index);
  5777 
       
  5778 			DMediaPagingDevice* device = TDriveIterator::PagingDevice((TInt)a1, DPagingDevice::ERom);
       
  5779 			if (device)
       
  5780 				ResetConcurrencyStats(device, (TMediaPagingStats)index);
       
  5781 			device = TDriveIterator::PagingDevice((TInt)a1, DPagingDevice::ECode);
       
  5782 			if (device)
       
  5783 				ResetConcurrencyStats(device, (TMediaPagingStats)index);
       
  5784 			device = TDriveIterator::PagingDevice((TInt)a1, DPagingDevice::EData);
       
  5785 			if (device)
       
  5786 				ResetConcurrencyStats(device, (TMediaPagingStats)index);
       
  5787 
  5409 			r=KErrNone;
  5788 			r=KErrNone;
  5410 			break;
  5789 			break;
  5411 			}
  5790 			}
  5412 #endif
  5791 #endif
  5413 #if defined(__DEMAND_PAGING__) && defined(__DEMAND_PAGING_BENCHMARKS__)
  5792 #if defined(__DEMAND_PAGING__) && defined(__DEMAND_PAGING_BENCHMARKS__)
  5414 		case EMediaHalGetROMPagingBenchmark:
  5793 		case EMediaHalGetROMPagingBenchmark:
  5415 			{
  5794 			{
  5416 			TInt drvNo=(TInt)a1;
  5795 			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)
  5796 			if(!device)
  5422 				break;
  5797 				break;
  5423 			NKern::FMWait(&device->iInstrumentationLock);
  5798 			NKern::FMWait(&device->iInstrumentationLock);
  5424 			SPagingBenchmarkInfo info = device->iROMBenchmarkData;
  5799 			SPagingBenchmarkInfo info = device->iROMBenchmarkData;
  5425 			NKern::FMSignal(&device->iInstrumentationLock);
  5800 			NKern::FMSignal(&device->iInstrumentationLock);
  5427 			r=KErrNone;
  5802 			r=KErrNone;
  5428 			break;
  5803 			break;
  5429 			}		
  5804 			}		
  5430 		case EMediaHalGetCodePagingBenchmark:
  5805 		case EMediaHalGetCodePagingBenchmark:
  5431 			{
  5806 			{
  5432 			TInt drvNo=(TInt)a1;
  5807 			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)
  5808 			if(!device)
  5438 				break;
  5809 				break;
  5439 			NKern::FMWait(&device->iInstrumentationLock);
  5810 			NKern::FMWait(&device->iInstrumentationLock);
  5440 			SPagingBenchmarkInfo info = device->iCodeBenchmarkData;
  5811 			SPagingBenchmarkInfo info = device->iCodeBenchmarkData;
  5441 			NKern::FMSignal(&device->iInstrumentationLock);
  5812 			NKern::FMSignal(&device->iInstrumentationLock);
  5443 			r=KErrNone;
  5814 			r=KErrNone;
  5444 			break;
  5815 			break;
  5445 			}	
  5816 			}	
  5446 		case EMediaHalGetDataInPagingBenchmark:
  5817 		case EMediaHalGetDataInPagingBenchmark:
  5447 			{
  5818 			{
  5448 			TInt drvNo=(TInt)a1;
  5819 			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)
  5820 			if(!device)
  5454 				break;
  5821 				break;
  5455 			NKern::FMWait(&device->iInstrumentationLock);
  5822 			NKern::FMWait(&device->iInstrumentationLock);
  5456 			SPagingBenchmarkInfo info = device->iDataInBenchmarkData;
  5823 			SPagingBenchmarkInfo info = device->iDataInBenchmarkData;
  5457 			NKern::FMSignal(&device->iInstrumentationLock);
  5824 			NKern::FMSignal(&device->iInstrumentationLock);
  5459 			r=KErrNone;
  5826 			r=KErrNone;
  5460 			break;
  5827 			break;
  5461 			}		
  5828 			}		
  5462 		case EMediaHalGetDataOutPagingBenchmark:
  5829 		case EMediaHalGetDataOutPagingBenchmark:
  5463 			{
  5830 			{
  5464 			TInt drvNo=(TInt)a1;
  5831 			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)
  5832 			if(!device)
  5470 				break;
  5833 				break;
  5471 			NKern::FMWait(&device->iInstrumentationLock);
  5834 			NKern::FMWait(&device->iInstrumentationLock);
  5472 			SPagingBenchmarkInfo info = device->iDataOutBenchmarkData;
  5835 			SPagingBenchmarkInfo info = device->iDataOutBenchmarkData;
  5473 			NKern::FMSignal(&device->iInstrumentationLock);
  5836 			NKern::FMSignal(&device->iInstrumentationLock);
  5475 			r=KErrNone;
  5838 			r=KErrNone;
  5476 			break;
  5839 			break;
  5477 			}		
  5840 			}		
  5478 		case EMediaHalResetPagingBenchmark:
  5841 		case EMediaHalResetPagingBenchmark:
  5479 			{
  5842 			{
  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;
  5843 			TUint index=(TInt)a2;
  5488 			if(index>EMediaPagingStatsCode)
  5844 			if(index>EMediaPagingStatsCode)
  5489 				break;
  5845 				break;
  5490 			ResetBenchmarkStats(device, (TMediaPagingStats)index);
  5846 
       
  5847 			DMediaPagingDevice* device = TDriveIterator::PagingDevice((TInt)a1, DPagingDevice::ERom);
       
  5848 			if (device)
       
  5849 				ResetBenchmarkStats(device, (TMediaPagingStats)index);
       
  5850 			device = TDriveIterator::PagingDevice((TInt)a1, DPagingDevice::ECode);
       
  5851 			if (device)
       
  5852 				ResetBenchmarkStats(device, (TMediaPagingStats)index);
       
  5853 			device = TDriveIterator::PagingDevice((TInt)a1, DPagingDevice::EData);
       
  5854 			if (device)
       
  5855 				ResetBenchmarkStats(device, (TMediaPagingStats)index);
       
  5856 
  5491 			r=KErrNone;
  5857 			r=KErrNone;
  5492 			break;
  5858 			break;
  5493 			}
  5859 			}
  5494 		case EMediaHalGetPagingInfo:
  5860 		case EMediaHalGetPagingInfo:
  5495 			{
  5861 			{
  5496 			TInt drvNo=(TInt)a1;
  5862 			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)
  5863 			if(!device)
  5502 				break;
  5864 				break;
  5503 			NKern::FMWait(&device->iInstrumentationLock);
  5865 			NKern::FMWait(&device->iInstrumentationLock);
  5504 			SMediaPagingInfo info = device->iMediaPagingInfo;
  5866 			SMediaPagingInfo info = device->iMediaPagingInfo;
  5505 			NKern::FMSignal(&device->iInstrumentationLock);
  5867 			NKern::FMSignal(&device->iInstrumentationLock);
  5735 		}
  6097 		}
  5736 	}
  6098 	}
  5737 
  6099 
  5738 
  6100 
  5739 /******************************************************************************
  6101 /******************************************************************************
       
  6102  DMediaDriverExtension base class
       
  6103  ******************************************************************************/
       
  6104 
       
  6105 EXPORT_C DMediaDriverExtension::DMediaDriverExtension(TInt aMediaId) :
       
  6106 	DMediaDriver(aMediaId)
       
  6107 	{
       
  6108 	}
       
  6109 
       
  6110 /**
       
  6111 */
       
  6112 EXPORT_C DMediaDriverExtension::~DMediaDriverExtension()
       
  6113 	{
       
  6114 	}
       
  6115 
       
  6116 /**
       
  6117 Closes the media driver.
       
  6118 
       
  6119 This default implementation simply deletes this DMediaDriverExtension object.
       
  6120 
       
  6121 Media drivers can provide their own implementation, which gives them
       
  6122 the opportunity to clean up resources before closure; for example,
       
  6123 cancelling a DFC.
       
  6124 Any replacement function must call this base class function as
       
  6125 the last instruction. 
       
  6126 */
       
  6127 EXPORT_C void DMediaDriverExtension::Close()
       
  6128 	{
       
  6129 	DMediaDriver::Close();
       
  6130 	}
       
  6131 
       
  6132 /**
       
  6133 DoDrivePartitionInfo()
       
  6134 
       
  6135 Fills out the passed TPartitionInfo object with information from the attached drives
       
  6136 */
       
  6137 EXPORT_C TInt DMediaDriverExtension::DoDrivePartitionInfo(TPartitionInfo& aInfo)
       
  6138 	{
       
  6139 	memclr(&aInfo, sizeof(aInfo));
       
  6140 	aInfo.iPartitionCount = 0;
       
  6141 	aInfo.iMediaSizeInBytes = 0;
       
  6142 
       
  6143 	TDriveIterator driveIter;
       
  6144 	for (TLocDrv* drv = driveIter.NextDrive(); drv != NULL; drv = driveIter.NextDrive())
       
  6145 		{
       
  6146 		if (drv && drv->iPrimaryMedia == iPrimaryMedia)
       
  6147 			{
       
  6148 			TLocDrv* attachedDrive = drv->iNextDrive;
       
  6149 			__ASSERT_DEBUG(attachedDrive, LOCM_FAULT());
       
  6150 			TLocDrvRequest m;
       
  6151 			memclr(&m, sizeof(m));
       
  6152 
       
  6153 			TBuf8<KMaxLocalDriveCapsLength> capsBuf;
       
  6154 			capsBuf.SetMax();
       
  6155 			capsBuf.FillZ();
       
  6156 			m.Drive() = attachedDrive;
       
  6157 			m.Id() = DLocalDrive::ECaps;
       
  6158 			m.RemoteDes() = (TAny*)capsBuf.Ptr();
       
  6159 			m.Length() = KMaxLocalDriveCapsLength;
       
  6160 			TInt r = attachedDrive->iPrimaryMedia->Request(m);
       
  6161 
       
  6162 			__KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("DMediaDriverExtension::PartitionInfo(ECaps: i %d: r %d ", driveIter.Index(), r));
       
  6163 			
       
  6164 			// NB The ECaps call might legitimately fail if one of the attached drives is removable
       
  6165 			// If this happens, just ignore & proceed to the next attached drive
       
  6166 			if (r == KErrNone)
       
  6167 				{
       
  6168 				aInfo.iEntry[aInfo.iPartitionCount] = *attachedDrive;
       
  6169 				// Set the media size to be that of the largest attached media
       
  6170 				// This is only needed to ensure that the test in TLocDrvRequest::CheckAndAdjustForPartition()
       
  6171 				// with the ELocDrvWholeMedia flag set succeeds: A further check on whether a request's
       
  6172 				// position & length are outside the media will be made when its is delievered  to the attached media....
       
  6173 				aInfo.iMediaSizeInBytes = Max(
       
  6174 					aInfo.iMediaSizeInBytes, 
       
  6175 					((TLocalDriveCapsV4*) capsBuf.Ptr())->MediaSizeInBytes());
       
  6176 				}
       
  6177 
       
  6178 
       
  6179 			aInfo.iPartitionCount++;
       
  6180 			}
       
  6181 		}
       
  6182 
       
  6183 	return KErrNone;
       
  6184 	}
       
  6185 
       
  6186 /**
       
  6187 ForwardRequest() - 
       
  6188 
       
  6189 forwards the request onto the next attached drive in the chain
       
  6190 */
       
  6191 EXPORT_C TInt DMediaDriverExtension::ForwardRequest(TLocDrvRequest& aRequest)
       
  6192 	{
       
  6193 	TLocDrv* drive = aRequest.Drive();
       
  6194 	TLocDrv* attachedDrive = drive->iNextDrive;
       
  6195 	__ASSERT_DEBUG(attachedDrive, LOCM_FAULT());
       
  6196 	aRequest.Drive() = attachedDrive;
       
  6197 
       
  6198 
       
  6199 	TInt r = attachedDrive->iPrimaryMedia->HandleMediaNotPresent(aRequest);
       
  6200 	if (r != KErrNone)
       
  6201 		{
       
  6202 		return r;
       
  6203 		}
       
  6204 	
       
  6205 	aRequest.Forward(&attachedDrive->iPrimaryMedia->iMsgQ, EFalse);
       
  6206 	return KErrNone;
       
  6207 	}
       
  6208 
       
  6209 
       
  6210 TInt DMediaDriverExtension::SendRequest(TInt aReqId, TBool aPagingRequest, TInt aDriveNumber, TInt64 aPos, TLinAddr aData, TUint aLen)
       
  6211 	{
       
  6212 	__ASSERT_DEBUG(aLen > 0, LOCM_FAULT());
       
  6213 
       
  6214 	// Ensure this is a legitimate attached drive registered using LocDrv::RegisterMediaDevice()
       
  6215 	if (!(iPrimaryMedia->iBody->iRegisteredDriveMask & (0x1 << aDriveNumber)))
       
  6216 		return KErrArgument;
       
  6217 
       
  6218 	TLocDrv* drive = TDriveIterator::GetDrive(aDriveNumber, iPrimaryMedia);
       
  6219 	__ASSERT_DEBUG(drive, LOCM_FAULT());
       
  6220 	TLocDrv* attachedDrive = drive->iNextDrive;
       
  6221 	__ASSERT_DEBUG(attachedDrive, LOCM_FAULT());
       
  6222 
       
  6223 	TLocDrvRequest request;
       
  6224 	memclr(&request, sizeof(request));
       
  6225 
       
  6226 	request.Drive() = attachedDrive;
       
  6227 	request.Id() = aReqId;
       
  6228 	request.Length() = aLen;
       
  6229 	request.RemoteDes() = (TAny*) aData;
       
  6230 	request.Pos() = aPos;
       
  6231 	request.Flags() = TLocDrvRequest::EKernelBuffer | TLocDrvRequest::EAdjusted;
       
  6232 
       
  6233 #ifdef __DEMAND_PAGING__
       
  6234 	if (aPagingRequest)
       
  6235 		{
       
  6236 		request.Flags()|= TLocDrvRequest::EPaging;
       
  6237 		// If the buffer is page aligned, use SendToMainQueueDfcAndBlock() as this 
       
  6238 		// is more efficient if the attached drive use DMA.
       
  6239 		const TInt KPageSizeMask = 4096-1;
       
  6240 		if (aData & KPageSizeMask)
       
  6241 			{
       
  6242 			return attachedDrive->iPrimaryMedia->SendReceive(request, aData);
       
  6243 			}
       
  6244 		else
       
  6245 			{
       
  6246 			attachedDrive->iPrimaryMedia->iBody->iPagingDevice->SendToMainQueueDfcAndBlock(&request);
       
  6247 			return 0;
       
  6248 			}
       
  6249 		}
       
  6250 #else
       
  6251 	aPagingRequest;
       
  6252 #endif
       
  6253 
       
  6254 	return attachedDrive->iPrimaryMedia->SendReceive(request, aData);
       
  6255 	}
       
  6256 
       
  6257 
       
  6258 /**
       
  6259 Read() - 
       
  6260 
       
  6261 reads data from the next attached drive in the chain
       
  6262 
       
  6263 N.B. The position is assumed to be already adjusted i.e. relative to the start of the
       
  6264 media, not the partition
       
  6265 */
       
  6266 EXPORT_C TInt DMediaDriverExtension::Read(TInt aDriveNumber, TInt64 aPos, TLinAddr aData, TUint aLen)
       
  6267 	{
       
  6268 	return SendRequest(DLocalDrive::ERead, EFalse, aDriveNumber, aPos, aData, aLen);
       
  6269 	}
       
  6270 
       
  6271 /**
       
  6272 Write() - 
       
  6273 
       
  6274 writes data to the next attached drive in the chain
       
  6275 
       
  6276 N.B. The position is assumed to be already adjusted i.e. relative to the start of the
       
  6277 media, not the partition
       
  6278 */
       
  6279 EXPORT_C TInt DMediaDriverExtension::Write(TInt aDriveNumber, TInt64 aPos, TLinAddr aData, TUint aLen)
       
  6280 	{
       
  6281 	return SendRequest(DLocalDrive::EWrite, EFalse, aDriveNumber, aPos, aData, aLen);
       
  6282 	}
       
  6283 
       
  6284 
       
  6285 #ifdef __DEMAND_PAGING__
       
  6286 /**
       
  6287 ReadPaged() - 
       
  6288 
       
  6289 Sends a paging read request to the specified attached drive
       
  6290 
       
  6291 N.B. The position is assumed to be already adjusted i.e. relative to the start of the
       
  6292 media, not the partition
       
  6293 */
       
  6294 EXPORT_C TInt DMediaDriverExtension::ReadPaged(TInt aDriveNumber, TInt64 aPos, TLinAddr aData, TUint aLen)
       
  6295 	{
       
  6296 	return SendRequest(DLocalDrive::ERead, ETrue, aDriveNumber, aPos, aData, aLen);
       
  6297 	}
       
  6298 
       
  6299 /**
       
  6300 WritePaged() - 
       
  6301 
       
  6302 Send a paging write request to the specified attached drive
       
  6303 
       
  6304 N.B. The position is assumed to be already adjusted i.e. relative to the start of the
       
  6305 media, not the partition
       
  6306 */
       
  6307 EXPORT_C TInt DMediaDriverExtension::WritePaged(TInt aDriveNumber, TInt64 aPos, TLinAddr aData, TUint aLen)
       
  6308 	{
       
  6309 	return SendRequest(DLocalDrive::EWrite, ETrue, aDriveNumber, aPos, aData, aLen);
       
  6310 	}
       
  6311 #endif	// __DEMAND_PAGING__
       
  6312 
       
  6313 
       
  6314 
       
  6315 /**
       
  6316 Caps() - 
       
  6317 
       
  6318 gets the caps from the next attached drive in the chain
       
  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::Caps(TInt aDriveNumber, TDes8& aCaps)
       
  6324 	{
       
  6325 	// Ensure this is a legitimate attached drive registered using LocDrv::RegisterMediaDevice()
       
  6326 	if (!(iPrimaryMedia->iBody->iRegisteredDriveMask & (0x1 << aDriveNumber)))
       
  6327 		return KErrArgument;
       
  6328 
       
  6329 	TLocDrv* drive = TDriveIterator::GetDrive(aDriveNumber, iPrimaryMedia);
       
  6330 	__ASSERT_DEBUG(drive, LOCM_FAULT());
       
  6331 	TLocDrv* attachedDrive = drive->iNextDrive;
       
  6332 	__ASSERT_DEBUG(attachedDrive, LOCM_FAULT());
       
  6333 
       
  6334 	TLocDrvRequest request;
       
  6335 	memclr(&request, sizeof(request));
       
  6336 
       
  6337 	request.Drive() = attachedDrive;
       
  6338 	request.Id() = DLocalDrive::ECaps;
       
  6339 	request.Length() = aCaps.Length();
       
  6340 	request.RemoteDes() = (TAny*) aCaps.Ptr();
       
  6341 
       
  6342 	return request.SendReceive(&attachedDrive->iPrimaryMedia->iMsgQ);
       
  6343 	}
       
  6344 
       
  6345 
       
  6346 
       
  6347 EXPORT_C void DMediaDriverExtension::NotifyPowerDown()
       
  6348 	{
       
  6349 	}
       
  6350 
       
  6351 EXPORT_C void DMediaDriverExtension::NotifyEmergencyPowerDown()
       
  6352 	{
       
  6353 	}
       
  6354 
       
  6355 
       
  6356 /**
       
  6357 Returns ETrue if this media - or any media which this TLocDrv is attached to - is busy
       
  6358 */
       
  6359 EXPORT_C TBool DMediaDriverExtension::MediaBusy(TInt aDriveNumber)
       
  6360 	{
       
  6361 	for (TLocDrv* drive = TDriveIterator::GetDrive(aDriveNumber, iPrimaryMedia); 
       
  6362 		drive; 
       
  6363 		drive = drive->iNextDrive)
       
  6364 		{
       
  6365 		DPrimaryMediaBase* primaryMedia = drive->iPrimaryMedia;
       
  6366 		__ASSERT_DEBUG(primaryMedia, LOCM_FAULT());
       
  6367 
       
  6368 		if ((primaryMedia->iMsgQ.iMessage && primaryMedia->iMsgQ.iMessage->iState != TMessageBase::EFree) || 
       
  6369 			!primaryMedia->iMsgQ.iQ.IsEmpty() ||
       
  6370 			primaryMedia->iBody->iMediaChangeDfc.Queued() ||
       
  6371 			primaryMedia->iBody->iMediaPresentDfc.Queued())
       
  6372 			return ETrue;
       
  6373 
       
  6374 #ifdef __DEMAND_PAGING__
       
  6375 		DMediaPagingDevice* pagingDevice = iPrimaryMedia->iBody->iPagingDevice;
       
  6376 		if (pagingDevice)
       
  6377 			{
       
  6378 			if ((pagingDevice->iMainQ.iMessage && pagingDevice->iMainQ.iMessage->iState != TMessageBase::EFree) || 
       
  6379 				!pagingDevice->iMainQ.iQ.IsEmpty())
       
  6380 			return ETrue;
       
  6381 			}
       
  6382 #endif
       
  6383 		}
       
  6384 
       
  6385 	return EFalse;
       
  6386 	}
       
  6387 
       
  6388 
       
  6389 TCallBackLink::TCallBackLink()
       
  6390 	{
       
  6391 	memclr(this, sizeof(this));
       
  6392 	}
       
  6393 
       
  6394 TCallBackLink::TCallBackLink(TInt (*aFunction)(TAny* aPtr, TInt aParam),TAny* aPtr, TObjectType aObjectType) : 
       
  6395 	iFunction(aFunction), iPtr(aPtr), iObjectType(aObjectType)
       
  6396 	{
       
  6397 	}
       
  6398 
       
  6399 TInt TCallBackLink::CallBack(TInt aParam) const
       
  6400 	{
       
  6401 	return (*iFunction)(iPtr, aParam);
       
  6402 	}
       
  6403 
       
  6404 /******************************************************************************
  5740  Entry point
  6405  Entry point
  5741  ******************************************************************************/
  6406  ******************************************************************************/
  5742 DECLARE_STANDARD_EXTENSION()
  6407 DECLARE_STANDARD_EXTENSION()
  5743 	{
  6408 	{
  5744 	__KTRACE_OPT(KBOOT,Kern::Printf("Starting LOCMEDIA extension"));
  6409 	__KTRACE_OPT(KBOOT,Kern::Printf("Starting LOCMEDIA extension"));
  5745 
  6410 
  5746 	// install the HAL function
  6411 	// install the HAL function
  5747 	TInt r=Kern::AddHalEntry(EHalGroupMedia,MediaHalFunction,NULL);
  6412 	TInt r=Kern::AddHalEntry(EHalGroupMedia,MediaHalFunction,NULL);
       
  6413 
  5748 #ifdef __DEMAND_PAGING__
  6414 #ifdef __DEMAND_PAGING__
  5749 	if (r==KErrNone)
  6415 	if (r==KErrNone)
  5750 		{
  6416 		{
  5751 		__KTRACE_OPT(KBOOT,Kern::Printf("Creating LocDrv device"));
  6417 		__KTRACE_OPT(KBOOT,Kern::Printf("Creating LocDrv device"));
  5752 		DLocalDriveFactory* device = new DLocalDriveFactory;
  6418 		DLocalDriveFactory* device = new DLocalDriveFactory;
  5755 		else
  6421 		else
  5756 			r=Kern::InstallLogicalDevice(device);
  6422 			r=Kern::InstallLogicalDevice(device);
  5757 		__KTRACE_OPT(KBOOT,Kern::Printf("Installing LocDrv device in kernel returned %d",r));
  6423 		__KTRACE_OPT(KBOOT,Kern::Printf("Installing LocDrv device in kernel returned %d",r));
  5758 		}
  6424 		}
  5759 #endif // __DEMAND_PAGING__
  6425 #endif // __DEMAND_PAGING__
       
  6426 
  5760 	return r;
  6427 	return r;
  5761 	}
  6428 	}
  5762 
  6429 
  5763 
  6430