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 /* |
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 { |
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 } |
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; |
2684 OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS1, "DPrimaryMediaBase iMediaId=%d", iMediaId ); |
2934 OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS1, "DPrimaryMediaBase iMediaId=%d", iMediaId ); |
2685 |
2935 |
2686 // we mustn't ever close the media driver if it's responsible for data paging as re-opening the drive |
2936 // we mustn't ever close the media driver if it's responsible for data paging as re-opening the drive |
2687 // would involve memory allocation which might cause deadlock if the kernel heap were to grow |
2937 // would involve memory allocation which might cause deadlock if the kernel heap were to grow |
2688 #ifdef __DEMAND_PAGING__ |
2938 #ifdef __DEMAND_PAGING__ |
2689 if (DataPagingDfcQ(this)) |
2939 if (DataPagingMedia(this)) |
2690 { |
2940 { |
2691 __KTRACE_OPT(KLOCDRV,Kern::Printf("CloseMediaDrivers aborting for data paging media %08X", this)); |
2941 __KTRACE_OPT(KLOCDRV,Kern::Printf("CloseMediaDrivers aborting for data paging media %08X", this)); |
2692 OstTrace1(TRACE_FLOW, DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS_EXIT1, "CloseMediaDrivers aborting for data paging media 0x%08x", this); |
2942 OstTrace1(TRACE_FLOW, DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS_EXIT1, "CloseMediaDrivers aborting for data paging media 0x%08x", this); |
2693 return; |
2943 return; |
2694 } |
2944 } |
2695 #endif |
2945 #endif |
2696 |
2946 |
2697 TInt i; |
2947 |
2698 for (i=0; i<KMaxLocalDrives; i++) |
2948 // Don't close any media extension drivers either, since it won't serve any purpose |
2699 { |
2949 // and keeping the driver open allows it to maintain internal state |
2700 TLocDrv* pL=TheDrives[i]; |
2950 if (iBody->iMediaExtension) |
|
2951 { |
|
2952 __KTRACE_OPT(KLOCDRV,Kern::Printf("CloseMediaDrivers aborting for extension media %08X", this)); |
|
2953 return; |
|
2954 } |
|
2955 |
|
2956 |
|
2957 TDriveIterator driveIter; |
|
2958 for (TLocDrv* pL = driveIter.NextDrive(); pL != NULL; pL = driveIter.NextDrive()) |
|
2959 { |
2701 if (pL && pL->iPrimaryMedia==this) |
2960 if (pL && pL->iPrimaryMedia==this) |
2702 { |
2961 { |
2703 __KTRACE_OPT(KLOCDRV,Kern::Printf("Drive %d",i)); |
2962 __KTRACE_OPT(KLOCDRV,Kern::Printf("Drive %d",driveIter.Index())); |
2704 OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS2, "Drive=%d", i ); |
2963 OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS2, "Drive=%d", driveIter.Index()); |
2705 if (aMedia == NULL || pL->iMedia == aMedia) |
2964 if (aMedia == NULL || pL->iMedia == aMedia) |
2706 { |
2965 { |
2707 pL->iMedia=NULL; |
2966 pL->iMedia=NULL; |
2708 } |
2967 } |
2709 } |
2968 } |
2710 } |
2969 } |
2711 for (i=iLastMediaId; i>=iMediaId; i--) |
2970 for (TInt i=iLastMediaId; i>=iMediaId; i--) |
2712 { |
2971 { |
2713 DMedia* pM=TheMedia[i]; |
2972 DMedia* pM=TheMedia[i]; |
2714 if (aMedia == NULL || pM == aMedia) |
2973 if (aMedia == NULL || pM == aMedia) |
2715 { |
2974 { |
2716 DMediaDriver* pD=pM->iDriver; |
2975 DMediaDriver* pD=pM->iDriver; |
3214 |
3472 |
3215 iWaitMedChg.CompleteAll(KErrNone); |
3473 iWaitMedChg.CompleteAll(KErrNone); |
3216 OstTraceFunctionExit1( DPRIMARYMEDIABASE_SETCLOSED_EXIT, this ); |
3474 OstTraceFunctionExit1( DPRIMARYMEDIABASE_SETCLOSED_EXIT, this ); |
3217 } |
3475 } |
3218 |
3476 |
3219 void DPrimaryMediaBase::NotifyClients(TBool aMediaChange,TLocDrv* aLocDrv) |
3477 void DPrimaryMediaBase::NotifyClients(TNotifyType aNotifyType, TLocDrv* aLocDrv) |
3220 |
3478 |
3221 // |
3479 // |
3222 // Notify all clients of a media change or power-down event |
3480 // Notify all clients of a media change or media present event |
3223 // |
3481 // |
3224 { |
3482 { |
3225 OstTraceFunctionEntryExt( DPRIMARYMEDIABASE_NOTIFYCLIENTS_ENTRY, this ); |
3483 OstTraceFunctionEntryExt( DPRIMARYMEDIABASE_NOTIFYCLIENTS_ENTRY, this ); |
3226 |
3484 |
3227 SDblQueLink* pL=iConnectionQ.iA.iNext; |
3485 SDblQueLink* pL=iConnectionQ.iA.iNext; |
3228 while (pL!=&iConnectionQ.iA) |
3486 while (pL!=&iConnectionQ.iA) |
3229 { |
3487 { |
3230 DLocalDrive* pD=_LOFF(pL,DLocalDrive,iLink); |
3488 // Get pointer to TCallBackLink |
|
3489 TCallBackLink* pCallBackLink = _LOFF(pL,TCallBackLink,iLink); |
|
3490 |
|
3491 // The link is embedded in either a TLocDrv or a DLocalDrive object; |
|
3492 // find out which one it is and then get TLocDrv pointer from that |
|
3493 __ASSERT_DEBUG(pCallBackLink->iObjectType == TCallBackLink::EDLocalDriveObject || pCallBackLink->iObjectType == TCallBackLink::ETLocDrvObject, LOCM_FAULT()); |
|
3494 TLocDrv* locDrv; |
|
3495 if (pCallBackLink->iObjectType == TCallBackLink::EDLocalDriveObject) |
|
3496 locDrv = ((DLocalDrive*) _LOFF(pCallBackLink,DLocalDrive, iMediaChangeObserver))->iDrive; |
|
3497 else |
|
3498 locDrv = ((TLocDrv*) _LOFF(pCallBackLink,TLocDrv, iMediaChangeObserver))->iNextDrive; |
|
3499 |
3231 // Issue the notification if the caller wants to notify all drives (aLocDrv == NULL) or |
3500 // Issue the notification if the caller wants to notify all drives (aLocDrv == NULL) or |
3232 // the specified drive matches this one |
3501 // the specified drive matches this one |
3233 if (aLocDrv == NULL || aLocDrv == pD->iDrive) |
3502 if (aLocDrv == NULL || aLocDrv == locDrv) |
3234 pD->NotifyChange(*this, aMediaChange); |
3503 pCallBackLink->CallBack(aNotifyType); |
|
3504 |
3235 pL=pL->iNext; |
3505 pL=pL->iNext; |
3236 } |
3506 } |
3237 OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYCLIENTS_EXIT, this ); |
3507 OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYCLIENTS_EXIT, this ); |
3238 } |
3508 } |
3239 |
3509 |
3247 OstTraceFunctionEntry1( DPRIMARYMEDIABASE_NOTIFYMEDIACHANGE_ENTRY, this ); |
3517 OstTraceFunctionEntry1( DPRIMARYMEDIABASE_NOTIFYMEDIACHANGE_ENTRY, this ); |
3248 __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::NotifyMediaChange state %d",iMediaId,iState)); |
3518 __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::NotifyMediaChange state %d",iMediaId,iState)); |
3249 |
3519 |
3250 OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_NOTIFYMEDIACHANGE, "iMediaId=%d; iState=%d", iMediaId, iState ); |
3520 OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_NOTIFYMEDIACHANGE, "iMediaId=%d; iState=%d", iMediaId, iState ); |
3251 |
3521 |
3252 TInt state=iState; |
3522 // This should only be called in the context of the media thread |
3253 |
3523 __ASSERT_ALWAYS(NKern::CurrentThread() == iDfcQ->iThread, LOCM_FAULT()); |
3254 __ASSERT_DEBUG(iBody, LOCM_FAULT()); |
3524 |
3255 |
3525 MediaChange(); |
3256 #ifdef __DEMAND_PAGING__ |
|
3257 iBody->iMediaChanges++; |
|
3258 |
|
3259 // As data paging media never close, need to ensure the media driver cancels |
|
3260 // any requests it owns as the stack may be powered down by DPBusPrimaryMedia::ForceMediaChange(). |
|
3261 // DMediaDriver::NotifyPowerDown() should do this |
|
3262 if(DataPagingDfcQ(this)) |
|
3263 NotifyPowerDown(); |
|
3264 #endif |
|
3265 |
|
3266 // complete any outstanding requests with KErrNotReady |
|
3267 // and any force media change requests with KErrNone |
|
3268 SetClosed(KErrNotReady); |
|
3269 |
|
3270 // close all media drivers on this device |
|
3271 if (state>=EOpening) |
|
3272 { |
|
3273 CloseMediaDrivers(); |
|
3274 } |
|
3275 |
3526 |
3276 // notify all connections that media change has occurred |
3527 // notify all connections that media change has occurred |
3277 NotifyClients(ETrue); |
3528 NotifyClients(EMediaChange); |
3278 |
3529 |
3279 // complete any force media change requests |
3530 // complete any force media change requests |
3280 iWaitMedChg.CompleteAll(KErrNone); |
3531 iWaitMedChg.CompleteAll(KErrNone); |
3281 OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYMEDIACHANGE_EXIT, this ); |
3532 OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYMEDIACHANGE_EXIT, this ); |
3282 } |
3533 } |
3412 // if ready, media driver should complete current request |
3661 // if ready, media driver should complete current request |
3413 CompleteCurrent(KErrNotReady); |
3662 CompleteCurrent(KErrNotReady); |
3414 } |
3663 } |
3415 CloseMediaDrivers(); |
3664 CloseMediaDrivers(); |
3416 SetClosed(KErrNotReady); |
3665 SetClosed(KErrNotReady); |
3417 NotifyClients(EFalse); |
|
3418 OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYEMERGENCYPOWERDOWN_EXIT, this ); |
3666 OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYEMERGENCYPOWERDOWN_EXIT, this ); |
|
3667 } |
|
3668 |
|
3669 |
|
3670 /** |
|
3671 Called by NotifyMediaPresent() and NotifyMediaChange() to ensure the media is in the correct state |
|
3672 */ |
|
3673 void DPrimaryMediaBase::MediaChange() |
|
3674 { |
|
3675 // Media has been inserted, so we need to cancel any outstanding requests and |
|
3676 // ensure that the partition info is read again |
|
3677 TInt state = iState; |
|
3678 |
|
3679 __ASSERT_DEBUG(iBody, LOCM_FAULT()); |
|
3680 |
|
3681 #ifdef __DEMAND_PAGING__ |
|
3682 iBody->iMediaChanges++; |
|
3683 |
|
3684 // As data paging media never close, need to ensure the media driver cancels |
|
3685 // any requests it owns as the stack may be powered down by DPBusPrimaryMedia::ForceMediaChange(). |
|
3686 // DMediaDriver::NotifyPowerDown() should do this |
|
3687 if (DataPagingMedia(this)) |
|
3688 NotifyPowerDown(); |
|
3689 #endif |
|
3690 |
|
3691 // complete any outstanding requests with KErrNotReady |
|
3692 // and any force media change requests with KErrNone |
|
3693 SetClosed(KErrNotReady); |
|
3694 |
|
3695 // close all media drivers on this device |
|
3696 if (state>=EOpening) |
|
3697 { |
|
3698 CloseMediaDrivers(); |
|
3699 } |
3419 } |
3700 } |
3420 |
3701 |
3421 EXPORT_C void DPrimaryMediaBase::NotifyMediaPresent() |
3702 EXPORT_C void DPrimaryMediaBase::NotifyMediaPresent() |
3422 /** |
3703 /** |
3423 Notifies clients of a media change by calling NotifyClients ( ) function to indicate that media is present. |
3704 Notifies clients of a media change by calling NotifyClients ( ) function to indicate that media is present. |
3424 */ |
3705 */ |
3425 { |
3706 { |
3426 OstTraceFunctionEntry1( DPRIMARYMEDIABASE_NOTIFYMEDIAPRESENT_ENTRY, this ); |
3707 OstTraceFunctionEntry1( DPRIMARYMEDIABASE_NOTIFYMEDIAPRESENT_ENTRY, this ); |
3427 NotifyClients(ETrue); |
3708 __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::NotifyMediaPresent state %d",iMediaId,iState)); |
|
3709 |
|
3710 // This should only be called in the context of the media thread |
|
3711 __ASSERT_ALWAYS(NKern::CurrentThread() == iDfcQ->iThread, LOCM_FAULT()); |
|
3712 |
|
3713 MediaChange(); |
|
3714 |
|
3715 NotifyClients(EMediaPresent); |
3428 OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYMEDIAPRESENT_EXIT, this ); |
3716 OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYMEDIAPRESENT_EXIT, this ); |
3429 } |
3717 } |
3430 |
3718 |
3431 EXPORT_C TInt DPrimaryMediaBase::DoInCritical() |
3719 EXPORT_C TInt DPrimaryMediaBase::DoInCritical() |
3432 /** |
3720 /** |
4647 { |
4956 { |
4648 OstTraceFunctionEntry0( LOCDRV_REGISTERMEDIADEVICE_ENTRY ); |
4957 OstTraceFunctionEntry0( LOCDRV_REGISTERMEDIADEVICE_ENTRY ); |
4649 // Create TLocDrv / DMedia objects to handle a media device |
4958 // Create TLocDrv / DMedia objects to handle a media device |
4650 __KTRACE_OPT(KBOOT,Kern::Printf("RegisterMediaDevice %lS dev=%1d #drives=%d 1st=%d PM=%08x #media=%d",&aName,aDevice,aDriveCount,*aDriveList,aPrimaryMedia,aNumMedia)); |
4959 __KTRACE_OPT(KBOOT,Kern::Printf("RegisterMediaDevice %lS dev=%1d #drives=%d 1st=%d PM=%08x #media=%d",&aName,aDevice,aDriveCount,*aDriveList,aPrimaryMedia,aNumMedia)); |
4651 OstTraceExt5( TRACE_INTERNALS, LOCDRV_REGISTERMEDIADEVICE1, "aDevice=%d; aDriveCount=%d; aDriveList=%d; aPrimaryMedia=0x%08x; aNumMedia=%d", (TInt) aDevice, (TInt) aDriveCount, (TInt) *aDriveList, (TUint) aPrimaryMedia, (TInt) aNumMedia ); |
4960 OstTraceExt5( TRACE_INTERNALS, LOCDRV_REGISTERMEDIADEVICE1, "aDevice=%d; aDriveCount=%d; aDriveList=%d; aPrimaryMedia=0x%08x; aNumMedia=%d", (TInt) aDevice, (TInt) aDriveCount, (TInt) *aDriveList, (TUint) aPrimaryMedia, (TInt) aNumMedia ); |
4652 |
4961 |
4653 const TInt* p=aDriveList; |
|
4654 TInt i; |
|
4655 TInt r=0; |
|
4656 if (UsedMedia+aNumMedia>KMaxLocalDrives) |
4962 if (UsedMedia+aNumMedia>KMaxLocalDrives) |
4657 { |
4963 { |
4658 OstTrace0(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT1, "< KErrInUse"); |
4964 OstTrace0(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT1, "< KErrInUse"); |
4659 return KErrInUse; |
4965 return KErrInUse; |
4660 } |
4966 } |
4661 for (i=0; i<aDriveCount; ++i) |
4967 |
4662 { |
4968 // make a local copy of the name |
4663 TInt drv = *p++; |
|
4664 // -1 means not used; this is to enable Dual-slot MMC support |
|
4665 if (drv == -1) |
|
4666 continue; |
|
4667 __KTRACE_OPT(KBOOT,Kern::Printf("Registering drive %d", drv)); |
|
4668 OstTrace1( TRACE_INTERNALS, LOCDRV_REGISTERMEDIADEVICE2, "Registering drive=%d", drv ); |
|
4669 if (TheDrives[drv]) |
|
4670 { |
|
4671 __KTRACE_OPT(KBOOT,Kern::Printf("Drive %d already in use", drv)); |
|
4672 OstTrace1( TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT2, "< Drive %d already in use; KErrInUse", drv); |
|
4673 return KErrInUse; |
|
4674 } |
|
4675 } |
|
4676 HBuf* pN=HBuf::New(aName); |
4969 HBuf* pN=HBuf::New(aName); |
4677 if (!pN) |
4970 if (!pN) |
4678 { |
4971 { |
4679 OstTrace0(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT3, "< KErrNoMemory"); |
4972 OstTrace0(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT3, "< KErrNoMemory"); |
4680 return KErrNoMemory; |
4973 return KErrNoMemory; |
4681 } |
4974 } |
4682 TInt lastMedia=UsedMedia+aNumMedia-1; |
4975 |
|
4976 // Register the primary media and any secondary media |
|
4977 TInt lastMedia = UsedMedia+aNumMedia-1; |
|
4978 TInt i; |
|
4979 TInt r=0; |
4683 for (i=UsedMedia; i<=lastMedia; ++i) |
4980 for (i=UsedMedia; i<=lastMedia; ++i) |
4684 { |
4981 { |
4685 if (i==UsedMedia) |
4982 if (i==UsedMedia) |
4686 TheMedia[i]=aPrimaryMedia; |
4983 TheMedia[i]=aPrimaryMedia; |
4687 else |
4984 else |
4698 { |
4995 { |
4699 OstTrace1(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT5, "< retval=%d", r); |
4996 OstTrace1(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT5, "< retval=%d", r); |
4700 return r; |
4997 return r; |
4701 } |
4998 } |
4702 } |
4999 } |
4703 |
|
4704 __KTRACE_OPT(KBOOT,Kern::Printf("FirstMedia %d LastMedia %d",UsedMedia,lastMedia)); |
5000 __KTRACE_OPT(KBOOT,Kern::Printf("FirstMedia %d LastMedia %d",UsedMedia,lastMedia)); |
4705 OstTraceExt2( TRACE_INTERNALS, LOCDRV_REGISTERMEDIADEVICE4, "FirstMedia=%d; LastMedia=%d", UsedMedia, lastMedia ); |
5001 OstTraceExt2( TRACE_INTERNALS, LOCDRV_REGISTERMEDIADEVICE4, "FirstMedia=%d; LastMedia=%d", UsedMedia, lastMedia ); |
4706 UsedMedia+=aNumMedia; |
5002 UsedMedia+=aNumMedia; |
4707 p=aDriveList; |
5003 |
|
5004 if (__IS_EXTENSION(aDevice)) |
|
5005 aPrimaryMedia->iBody->iMediaExtension = ETrue; |
|
5006 |
|
5007 // Register the drives |
|
5008 const TInt* p=aDriveList; |
4708 for (i=0; i<aDriveCount; ++i) |
5009 for (i=0; i<aDriveCount; ++i) |
4709 { |
5010 { |
4710 TInt drv=*p++; |
5011 TInt drv = *p++; |
|
5012 // -1 means not used; this is to enable Dual-slot MMC support |
4711 if (drv == -1) |
5013 if (drv == -1) |
4712 continue; |
5014 continue; |
4713 TLocDrv* pL=new TLocDrv(drv); |
5015 |
4714 if (!pL) |
5016 __KTRACE_OPT(KBOOT,Kern::Printf("Registering drive %d", drv)); |
4715 { |
5017 if (!__IS_EXTENSION(aDevice) && TheDrives[drv]) |
|
5018 { |
|
5019 __KTRACE_OPT(KBOOT,Kern::Printf("Drive %d already in use", drv)); |
|
5020 return KErrInUse; |
|
5021 } |
|
5022 else if (__IS_EXTENSION(aDevice) && !TheDrives[drv]) |
|
5023 { |
|
5024 __KTRACE_OPT(KBOOT,Kern::Printf("Drive %d not initialized", drv)); |
|
5025 return KErrNotReady; |
|
5026 } |
|
5027 |
|
5028 TLocDrv* pNewDrive = new TLocDrv(drv); |
|
5029 if (!pNewDrive) |
|
5030 { |
4716 OstTrace0(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT6, "< KErrNoMemory"); |
5031 OstTrace0(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT6, "< KErrNoMemory"); |
4717 return KErrNoMemory; |
5032 return KErrNoMemory; |
4718 } |
5033 } |
4719 TheDrives[drv]=pL; |
5034 |
4720 DriveNames[drv]=pN; |
5035 |
4721 pL->iPrimaryMedia=aPrimaryMedia; |
5036 TLocDrv* pOldDrive = TheDrives[drv]; |
4722 __KTRACE_OPT(KBOOT,Kern::Printf("Drive %d: TLocDrv @ %08x",drv,pL)); |
5037 aPrimaryMedia->iBody->iRegisteredDriveMask|= (0x1 << drv); |
4723 OstTraceExt2( TRACE_INTERNALS, LOCDRV_REGISTERMEDIADEVICE5, "Drive=%d; TLocDrv 0x%08x;", (TInt) drv, (TUint) pL ); |
5038 pNewDrive->iNextDrive = pOldDrive; |
4724 } |
5039 |
|
5040 TheDrives[drv] = pNewDrive; |
|
5041 DriveNames[drv] = pN; |
|
5042 pNewDrive->iPrimaryMedia = aPrimaryMedia; |
|
5043 |
|
5044 |
|
5045 if (pOldDrive) |
|
5046 { |
|
5047 TInt r = pOldDrive->iPrimaryMedia->Connect(pNewDrive); |
|
5048 if (r != KErrNone) |
|
5049 return r; |
|
5050 |
|
5051 #ifdef __DEMAND_PAGING__ |
|
5052 // If we've hooked a drive letter which is being used for ROM paging by a media driver |
|
5053 // which does not report the ROM partition, then we need to change iFirstLocalDriveNumber |
|
5054 // so that ROM page-in requests go directly to that driver |
|
5055 DMediaPagingDevice* oldPagingDevice = pOldDrive->iPrimaryMedia->iBody->iPagingDevice; |
|
5056 if (oldPagingDevice && |
|
5057 (oldPagingDevice->iType & DPagingDevice::ERom) && |
|
5058 oldPagingDevice->iRomPagingDriveNumber == KErrNotFound && |
|
5059 oldPagingDevice->iFirstLocalDriveNumber == drv) |
|
5060 { |
|
5061 __KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("TRACE: hooking ROM paging device with no defined ROM partition")); |
|
5062 TInt n; |
|
5063 for (n=0; n<KMaxLocalDrives; ++n) |
|
5064 { |
|
5065 if(TheDrives[n] && TheDrives[n]->iPrimaryMedia == pOldDrive->iPrimaryMedia) |
|
5066 { |
|
5067 __KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("TRACE: Changing iFirstLocalDriveNumber from %d to %d", oldPagingDevice->iFirstLocalDriveNumber, n)); |
|
5068 oldPagingDevice->iFirstLocalDriveNumber = n; |
|
5069 break; |
|
5070 } |
|
5071 } |
|
5072 __ASSERT_ALWAYS(n < KMaxLocalDrives, LOCM_FAULT()); |
|
5073 } |
|
5074 #endif |
|
5075 |
|
5076 } |
|
5077 |
|
5078 __KTRACE_OPT(KBOOT,Kern::Printf("Drive %d: TLocDrv @ %08x",drv,pNewDrive)); |
|
5079 } |
|
5080 |
4725 |
5081 |
4726 OstTraceFunctionExit0( LOCDRV_REGISTERMEDIADEVICE_EXIT7 ); |
5082 OstTraceFunctionExit0( LOCDRV_REGISTERMEDIADEVICE_EXIT7 ); |
4727 return KErrNone; |
5083 return KErrNone; |
4728 } |
5084 } |
4729 |
5085 |
4805 or one of the other system-wide error codes. |
5161 or one of the other system-wide error codes. |
4806 */ |
5162 */ |
4807 EXPORT_C TInt LocDrv::RegisterPagingDevice(DPrimaryMediaBase* aPrimaryMedia, const TInt* aPagingDriveList, TInt aDriveCount, TUint aPagingType, TInt aReadShift, TUint aNumPages) |
5163 EXPORT_C TInt LocDrv::RegisterPagingDevice(DPrimaryMediaBase* aPrimaryMedia, const TInt* aPagingDriveList, TInt aDriveCount, TUint aPagingType, TInt aReadShift, TUint aNumPages) |
4808 { |
5164 { |
4809 OstTraceFunctionEntry0( LOCDRV_REGISTERPAGINGDEVICE_ENTRY ); |
5165 OstTraceFunctionEntry0( LOCDRV_REGISTERPAGINGDEVICE_ENTRY ); |
|
5166 // SETDEBUGFLAG(KLOCDPAGING); |
4810 |
5167 |
4811 __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf(">RegisterPagingDevice: paging type=%d PM=0x%x read shift=%d",aPagingType,aPrimaryMedia,aReadShift)); |
5168 __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf(">RegisterPagingDevice: paging type=%d PM=0x%x read shift=%d",aPagingType,aPrimaryMedia,aReadShift)); |
4812 OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE1, "aPagingType=%d; aPrimaryMedia=0x%x; aReadShift=%d", (TInt) aPagingType, (TUint) aPrimaryMedia, (TInt) aReadShift); |
5169 OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE1, "aPagingType=%d; aPrimaryMedia=0x%x; aReadShift=%d", (TInt) aPagingType, (TUint) aPrimaryMedia, (TInt) aReadShift); |
4813 |
5170 |
4814 TInt i; |
5171 TInt i = 0; |
4815 |
5172 |
4816 if(!aPagingType || (aPagingType&~(DPagingDevice::ERom | DPagingDevice::ECode | DPagingDevice::EData))) |
5173 if(!aPagingType || (aPagingType&~(DPagingDevice::ERom | DPagingDevice::ECode | DPagingDevice::EData))) |
4817 { |
5174 { |
4818 __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Unsupported paging type, exiting")); |
5175 __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Unsupported paging type, exiting")); |
4819 OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT1, "< Unsupported paging type; KErrArgument"); |
5176 OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT1, "< Unsupported paging type; KErrArgument"); |
4820 return KErrArgument; |
5177 return KErrArgument; |
4821 } |
5178 } |
4822 |
5179 |
4823 |
5180 |
4824 |
5181 // Check for duplicate drives |
4825 for(i=0; i<KMaxLocalDrives; i++) |
5182 if (!aPrimaryMedia->iBody->iMediaExtension) |
4826 { |
5183 { |
4827 if (ThePagingDevices[i] == NULL) |
5184 for(i=0; i<KMaxLocalDrives; i++) |
4828 continue; |
5185 { |
4829 if ((ThePagingDevices[i]->iType&DPagingDevice::ERom) && (aPagingType & DPagingDevice::ERom)) |
5186 if (ThePagingDevices[i] == NULL) |
4830 { |
5187 continue; |
4831 aPagingType&=~DPagingDevice::ERom; // already have a ROM paging device |
5188 if ((ThePagingDevices[i]->iType&DPagingDevice::ERom) && (aPagingType & DPagingDevice::ERom)) |
4832 __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Already has ROM pager on locdrv no %d",i)); |
5189 { |
4833 } |
5190 aPagingType&=~DPagingDevice::ERom; // already have a ROM paging device |
4834 if ((ThePagingDevices[i]->iType&DPagingDevice::EData) && (aPagingType & DPagingDevice::EData)) |
5191 __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Already has ROM pager on locdrv no %d",i)); |
4835 { |
5192 } |
4836 aPagingType&=~DPagingDevice::EData; // already have a Data paging device |
5193 if ((ThePagingDevices[i]->iType&DPagingDevice::EData) && (aPagingType & DPagingDevice::EData)) |
4837 __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Already has Data pager on locdrv no %d",i)); |
5194 { |
|
5195 aPagingType&=~DPagingDevice::EData; // already have a Data paging device |
|
5196 __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Already has Data pager on locdrv no %d",i)); |
|
5197 } |
4838 } |
5198 } |
4839 } |
5199 } |
4840 |
5200 |
4841 |
5201 |
4842 if (aPagingType == 0) |
5202 if (aPagingType == 0) |
4913 __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("DMediaPagingDevice(), firstLocalDriveNumber %d", firstLocalDriveNumber)); |
5273 __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("DMediaPagingDevice(), firstLocalDriveNumber %d", firstLocalDriveNumber)); |
4914 OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE3, "firstLocalDriveNumber=%d", firstLocalDriveNumber ); |
5274 OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE3, "firstLocalDriveNumber=%d", firstLocalDriveNumber ); |
4915 |
5275 |
4916 // Send an ECaps message to wake up the media driver & ensure all partitions are |
5276 // Send an ECaps message to wake up the media driver & ensure all partitions are |
4917 // reported, then search for paged-data or paged-ROM partitions |
5277 // reported, then search for paged-data or paged-ROM partitions |
|
5278 // NB: older media drivers supporting ROM and/or code paging only may not have started their DFC queues, |
|
5279 // so for these media drivers, use the first local drive supported for ROM-pagin-in requests and |
|
5280 // assume the media driver itself will adjust the request position internally to match the ROM partition |
|
5281 // @see DMediaPagingDevice::Read() |
4918 if ((aPagingType & DPagingDevice::EData) || |
5282 if ((aPagingType & DPagingDevice::EData) || |
4919 (aPagingType & DPagingDevice::ERom && aPrimaryMedia->iDfcQ && aPrimaryMedia->iMsgQ.iReady)) |
5283 (aPagingType & DPagingDevice::ERom && aPrimaryMedia->iDfcQ && aPrimaryMedia->iMsgQ.iReady)) |
4920 { |
5284 { |
4921 // the message queue must have been started already (by the media driver calling iMsgQ.Receive()) |
5285 // the message queue must have been started already (by the media driver calling iMsgQ.Receive()) |
4922 // otherwise we can't send the DLocalDrive::EQueryDevice request |
5286 // otherwise we can't send the DLocalDrive::ECaps request |
4923 if (aPrimaryMedia->iDfcQ && !aPrimaryMedia->iMsgQ.iReady) |
5287 if (!aPrimaryMedia->iDfcQ || !aPrimaryMedia->iMsgQ.iReady) |
4924 { |
5288 { |
4925 __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: Message queue not started")); |
5289 __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: Message queue not started")); |
4926 OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT8, "< RegisterPagingDevice: Message queue not started; KErrNotReady"); |
5290 OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT8, "< RegisterPagingDevice: Message queue not started; KErrNotReady"); |
4927 return KErrNotReady; |
5291 return KErrNotReady; |
4928 } |
5292 } |
4965 for (i=0; i<KMaxLocalDrives; ++i) |
5329 for (i=0; i<KMaxLocalDrives; ++i) |
4966 { |
5330 { |
4967 drive = TheDrives[i]; |
5331 drive = TheDrives[i]; |
4968 if(drive && drive->iPrimaryMedia == aPrimaryMedia) |
5332 if(drive && drive->iPrimaryMedia == aPrimaryMedia) |
4969 { |
5333 { |
4970 __KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("RegisterPagingDevice: local drive %d, partition type %x size %x", i, drive->iPartitionType, I64LOW(drive->iPartitionLen))); |
5334 __KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("RegisterPagingDevice: local drive %d, partition type %x base %lx size %lx name %lS", i, drive->iPartitionType, drive->iPartitionBaseAddr, drive->iPartitionLen, DriveNames[i] ? DriveNames[i] : &KNullDesC8)); |
4971 // ROM partition ? |
5335 // ROM partition ? |
4972 if ((romPagingDriveNumber == KErrNotFound) && (drive->iPartitionType == KPartitionTypeROM)) |
5336 if ((romPagingDriveNumber == KErrNotFound) && |
|
5337 (drive->iPartitionType == KPartitionTypeROM) && |
|
5338 (aPagingType & DPagingDevice::ERom)) |
4973 { |
5339 { |
4974 __KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("Found ROM partition on local drive %d, size %x", i, I64LOW(drive->iPartitionLen))); |
5340 __KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("Found ROM partition on local drive %d, size %x", i, I64LOW(drive->iPartitionLen))); |
4975 OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE5, "Found ROM partition on local drive=%d; size=0x%x", (TInt) i, (TUint) I64LOW(drive->iPartitionLen)); |
5341 OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE5, "Found ROM partition on local drive=%d; size=0x%x", (TInt) i, (TUint) I64LOW(drive->iPartitionLen)); |
4976 romPagingDriveNumber = i; |
5342 romPagingDriveNumber = i; |
4977 } |
5343 } |
4978 // swap partition ? |
5344 // swap partition ? |
4979 else if ((dataPagingDriveNumber == KErrNotFound) && (drive->iPartitionType == KPartitionTypePagedData)) |
5345 else if ((dataPagingDriveNumber == KErrNotFound) && |
|
5346 (drive->iPartitionType == KPartitionTypePagedData) && |
|
5347 (aPagingType & DPagingDevice::EData)) |
4980 { |
5348 { |
4981 __KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("Found swap partition on local drive %d, size %x", i, I64LOW(drive->iPartitionLen))); |
5349 __KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("Found swap partition on local drive %d, size %x", i, I64LOW(drive->iPartitionLen))); |
4982 OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE6, "Found SWAP partition on local drive=%d; size=0x%x", (TInt) i, (TUint) I64LOW(drive->iPartitionLen) ); |
5350 OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE6, "Found SWAP partition on local drive=%d; size=0x%x", (TInt) i, (TUint) I64LOW(drive->iPartitionLen) ); |
4983 dataPagingDriveNumber = i; |
5351 dataPagingDriveNumber = i; |
|
5352 TheDataPagingDrive = drive; |
4984 swapSize = drive->iPartitionLen >> aReadShift; |
5353 swapSize = drive->iPartitionLen >> aReadShift; |
4985 } |
5354 } |
4986 } |
5355 } |
4987 } |
5356 } |
4988 |
5357 |
5004 OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT_EXIT10, "< RegisterPagingDevice: could not create paging device; KErrNoMemory"); |
5373 OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT_EXIT10, "< RegisterPagingDevice: could not create paging device; KErrNoMemory"); |
5005 return KErrNoMemory; |
5374 return KErrNoMemory; |
5006 } |
5375 } |
5007 |
5376 |
5008 pagingDevice->iType = aPagingType; |
5377 pagingDevice->iType = aPagingType; |
|
5378 if (aPrimaryMedia->iBody->iMediaExtension) |
|
5379 pagingDevice->iType|= DPagingDevice::EMediaExtension; |
|
5380 |
5009 pagingDevice->iReadUnitShift = aReadShift; |
5381 pagingDevice->iReadUnitShift = aReadShift; |
5010 |
5382 |
5011 pagingDevice->iFirstLocalDriveNumber = firstLocalDriveNumber; |
5383 pagingDevice->iFirstLocalDriveNumber = firstLocalDriveNumber; |
5012 pagingDevice->iRomPagingDriveNumber = romPagingDriveNumber; |
5384 pagingDevice->iRomPagingDriveNumber = romPagingDriveNumber; |
5013 |
5385 |
5014 pagingDevice->iDataPagingDriveNumber = dataPagingDriveNumber; |
5386 pagingDevice->iDataPagingDriveNumber = dataPagingDriveNumber; |
5015 pagingDevice->iSwapSize = swapSize; |
5387 pagingDevice->iSwapSize = swapSize; |
5016 |
5388 |
5017 #ifdef __DEBUG_DEMAND_PAGING__ |
5389 #ifdef __DEBUG_DEMAND_PAGING__ |
5018 Kern::Printf("PagingDevice :"); |
5390 Kern::Printf("PagingDevice :"); |
5019 Kern::Printf("iType 0x%x\n", pagingDevice->iType); |
5391 Kern::Printf("Name %lS", firstLocalDriveNumber >= 0 && DriveNames[firstLocalDriveNumber] ? DriveNames[firstLocalDriveNumber] : &KNullDesC8); |
5020 Kern::Printf("iReadUnitShift 0x%x\n", pagingDevice->iReadUnitShift); |
5392 Kern::Printf("iType 0x%x", pagingDevice->iType); |
5021 Kern::Printf("iFirstLocalDriveNumber 0x%x\n", pagingDevice->iFirstLocalDriveNumber); |
5393 Kern::Printf("iReadUnitShift 0x%x", pagingDevice->iReadUnitShift); |
5022 Kern::Printf("iRomPagingDriveNumber 0x%x\n", pagingDevice->iRomPagingDriveNumber); |
5394 Kern::Printf("iFirstLocalDriveNumber 0x%x", pagingDevice->iFirstLocalDriveNumber); |
5023 Kern::Printf("iDataPagingDriveNumber 0x%x\n", pagingDevice->iDataPagingDriveNumber); |
5395 Kern::Printf("iRomPagingDriveNumber 0x%x", pagingDevice->iRomPagingDriveNumber); |
5024 Kern::Printf("iSwapSize 0x%x\n", pagingDevice->iSwapSize); |
5396 Kern::Printf("iDataPagingDriveNumber 0x%x", pagingDevice->iDataPagingDriveNumber); |
|
5397 Kern::Printf("iSwapSize 0x%x", pagingDevice->iSwapSize); |
5025 #endif |
5398 #endif |
5026 |
5399 |
5027 |
5400 |
5028 // This table is indexed by DPagingDevice::TType |
5401 // This table is indexed by DPagingDevice::TType |
5029 const char* DeviceName[] = |
5402 const char* DeviceName[] = |
5040 |
5413 |
5041 |
5414 |
5042 if(aPagingType & DPagingDevice::ECode) |
5415 if(aPagingType & DPagingDevice::ECode) |
5043 { |
5416 { |
5044 for (i=0; i<aDriveCount; ++i) |
5417 for (i=0; i<aDriveCount; ++i) |
5045 pagingDevice->iDrivesSupported|=(0x1<<aPagingDriveList[i]); |
5418 pagingDevice->iDrivesSupported |= (0x1<<aPagingDriveList[i]); |
5046 } |
5419 } |
5047 pagingDevice->iName = DeviceName[aPagingType]; |
5420 pagingDevice->iName = DeviceName[aPagingType]; |
5048 |
5421 |
|
5422 // If ThePinObjectAllocator has already been created with a smaller number of pages, |
|
5423 // delete it & then re-create it |
|
5424 __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: ThePinObjectAllocator %x", ThePinObjectAllocator)); |
|
5425 if (ThePinObjectAllocator && ThePinObjectAllocator->iFragmentGranularity < Kern::RoundToPageSize(1) * aNumPages) |
|
5426 { |
|
5427 __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: Recreating ThePinObjectAllocator...")); |
|
5428 delete ThePinObjectAllocator; |
|
5429 ThePinObjectAllocator = NULL; |
|
5430 } |
|
5431 |
|
5432 |
|
5433 TInt r; |
5049 if (ThePinObjectAllocator == NULL) |
5434 if (ThePinObjectAllocator == NULL) |
|
5435 { |
5050 ThePinObjectAllocator = new DPinObjectAllocator(); |
5436 ThePinObjectAllocator = new DPinObjectAllocator(); |
5051 if(!ThePinObjectAllocator) |
5437 if(!ThePinObjectAllocator) |
5052 { |
5438 { |
5053 __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: could not create ThePinObjectAllocator")); |
5439 __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: could not create ThePinObjectAllocator")); |
5054 OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT11, "RegisterPagingDevice: could not create ThePinObjectAllocator; KErrNoMemory"); |
5440 OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT11, "RegisterPagingDevice: could not create ThePinObjectAllocator; KErrNoMemory"); |
5055 return KErrNoMemory; |
5441 return KErrNoMemory; |
5056 } |
5442 } |
5057 TInt r = ThePinObjectAllocator->Construct(KDynamicPagingLockCount, aNumPages); |
5443 r = ThePinObjectAllocator->Construct(KDynamicPagingLockCount, aNumPages); |
5058 if (r != KErrNone) |
5444 if (r != KErrNone) |
5059 { |
5445 { |
5060 __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: could not construct ThePinObjectAllocator")); |
5446 __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: could not construct ThePinObjectAllocator")); |
5061 OstTrace1(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT12, "< RegisterPagingDevice: could not construct ThePinObjectAllocator; retval=%d",r); |
5447 OstTrace1(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT12, "< RegisterPagingDevice: could not construct ThePinObjectAllocator; retval=%d",r); |
5062 return r; |
5448 return r; |
|
5449 } |
5063 } |
5450 } |
5064 |
5451 |
5065 |
5452 |
5066 // Register our DPagingDevice with the Kernel |
5453 // Register our DPagingDevice with the Kernel |
5067 r=Kern::InstallPagingDevice(pagingDevice); |
5454 r=Kern::InstallPagingDevice(pagingDevice); |
5735 } |
6105 } |
5736 } |
6106 } |
5737 |
6107 |
5738 |
6108 |
5739 /****************************************************************************** |
6109 /****************************************************************************** |
|
6110 DMediaDriverExtension base class |
|
6111 ******************************************************************************/ |
|
6112 |
|
6113 EXPORT_C DMediaDriverExtension::DMediaDriverExtension(TInt aMediaId) : |
|
6114 DMediaDriver(aMediaId) |
|
6115 { |
|
6116 } |
|
6117 |
|
6118 /** |
|
6119 */ |
|
6120 EXPORT_C DMediaDriverExtension::~DMediaDriverExtension() |
|
6121 { |
|
6122 } |
|
6123 |
|
6124 /** |
|
6125 Closes the media driver. |
|
6126 |
|
6127 This default implementation simply deletes this DMediaDriverExtension object. |
|
6128 |
|
6129 Media drivers can provide their own implementation, which gives them |
|
6130 the opportunity to clean up resources before closure; for example, |
|
6131 cancelling a DFC. |
|
6132 Any replacement function must call this base class function as |
|
6133 the last instruction. |
|
6134 */ |
|
6135 EXPORT_C void DMediaDriverExtension::Close() |
|
6136 { |
|
6137 DMediaDriver::Close(); |
|
6138 } |
|
6139 |
|
6140 /** |
|
6141 DoDrivePartitionInfo() |
|
6142 |
|
6143 Fills out the passed TPartitionInfo object with information from the attached drives |
|
6144 */ |
|
6145 EXPORT_C TInt DMediaDriverExtension::DoDrivePartitionInfo(TPartitionInfo& aInfo) |
|
6146 { |
|
6147 memclr(&aInfo, sizeof(aInfo)); |
|
6148 aInfo.iPartitionCount = 0; |
|
6149 aInfo.iMediaSizeInBytes = 0; |
|
6150 |
|
6151 TDriveIterator driveIter; |
|
6152 for (TLocDrv* drv = driveIter.NextDrive(); drv != NULL; drv = driveIter.NextDrive()) |
|
6153 { |
|
6154 if (drv && drv->iPrimaryMedia == iPrimaryMedia) |
|
6155 { |
|
6156 TLocDrv* attachedDrive = drv->iNextDrive; |
|
6157 __ASSERT_DEBUG(attachedDrive, LOCM_FAULT()); |
|
6158 TLocDrvRequest m; |
|
6159 memclr(&m, sizeof(m)); |
|
6160 |
|
6161 // Get the Caps from the device. NB for MMC/SD we may need to retry as there may have been an earlier |
|
6162 // EForceMediaChange request which can result in the cancellation of requests already in the queue |
|
6163 TBuf8<KMaxLocalDriveCapsLength> capsBuf; |
|
6164 TInt i; |
|
6165 const TInt KRetries = 5; |
|
6166 TInt r = KErrNotReady; |
|
6167 for (i=0; r == KErrNotReady && i < KRetries; i++) |
|
6168 { |
|
6169 capsBuf.SetMax(); |
|
6170 capsBuf.FillZ(); |
|
6171 m.Drive() = attachedDrive; |
|
6172 m.Id() = DLocalDrive::ECaps; |
|
6173 m.RemoteDes() = (TAny*)capsBuf.Ptr(); |
|
6174 m.Length() = KMaxLocalDriveCapsLength; |
|
6175 r = attachedDrive->iPrimaryMedia->Request(m); |
|
6176 } |
|
6177 |
|
6178 __KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("DMediaDriverExtension::PartitionInfo(ECaps: i %d: r %d ", driveIter.Index(), r)); |
|
6179 |
|
6180 // NB The ECaps call might legitimately fail if one of the attached drives is removable |
|
6181 // If this happens, just ignore & proceed to the next attached drive |
|
6182 if (r == KErrNone) |
|
6183 { |
|
6184 aInfo.iEntry[aInfo.iPartitionCount] = *attachedDrive; |
|
6185 // Set the media size to be that of the largest attached media |
|
6186 // This is only needed to ensure that the test in TLocDrvRequest::CheckAndAdjustForPartition() |
|
6187 // with the ELocDrvWholeMedia flag set succeeds: A further check on whether a request's |
|
6188 // position & length are outside the media will be made when its is delievered to the attached media.... |
|
6189 aInfo.iMediaSizeInBytes = Max( |
|
6190 aInfo.iMediaSizeInBytes, |
|
6191 ((TLocalDriveCapsV4*) capsBuf.Ptr())->MediaSizeInBytes()); |
|
6192 } |
|
6193 |
|
6194 |
|
6195 aInfo.iPartitionCount++; |
|
6196 } |
|
6197 } |
|
6198 |
|
6199 return KErrNone; |
|
6200 } |
|
6201 |
|
6202 /** |
|
6203 ForwardRequest() - |
|
6204 |
|
6205 forwards the request onto the next attached drive in the chain |
|
6206 */ |
|
6207 EXPORT_C TInt DMediaDriverExtension::ForwardRequest(TLocDrvRequest& aRequest) |
|
6208 { |
|
6209 TLocDrv* drive = aRequest.Drive(); |
|
6210 TLocDrv* attachedDrive = drive->iNextDrive; |
|
6211 __ASSERT_DEBUG(attachedDrive, LOCM_FAULT()); |
|
6212 aRequest.Drive() = attachedDrive; |
|
6213 |
|
6214 |
|
6215 TInt r = attachedDrive->iPrimaryMedia->HandleMediaNotPresent(aRequest); |
|
6216 if (r != KErrNone) |
|
6217 { |
|
6218 return r; |
|
6219 } |
|
6220 |
|
6221 aRequest.Forward(&attachedDrive->iPrimaryMedia->iMsgQ, EFalse); |
|
6222 return KErrNone; |
|
6223 } |
|
6224 |
|
6225 |
|
6226 TInt DMediaDriverExtension::SendRequest(TInt aReqId, TBool aPagingRequest, TInt aDriveNumber, TInt64 aPos, TLinAddr aData, TUint aLen) |
|
6227 { |
|
6228 __ASSERT_DEBUG(aLen > 0, LOCM_FAULT()); |
|
6229 |
|
6230 // Ensure this is a legitimate attached drive registered using LocDrv::RegisterMediaDevice() |
|
6231 if (!(iPrimaryMedia->iBody->iRegisteredDriveMask & (0x1 << aDriveNumber))) |
|
6232 return KErrArgument; |
|
6233 |
|
6234 TLocDrv* drive = TDriveIterator::GetDrive(aDriveNumber, iPrimaryMedia); |
|
6235 __ASSERT_DEBUG(drive, LOCM_FAULT()); |
|
6236 TLocDrv* attachedDrive = drive->iNextDrive; |
|
6237 __ASSERT_DEBUG(attachedDrive, LOCM_FAULT()); |
|
6238 |
|
6239 TLocDrvRequest request; |
|
6240 memclr(&request, sizeof(request)); |
|
6241 |
|
6242 request.Drive() = attachedDrive; |
|
6243 request.Id() = aReqId; |
|
6244 request.Length() = aLen; |
|
6245 request.RemoteDes() = (TAny*) aData; |
|
6246 request.Pos() = aPos; |
|
6247 request.Flags() = TLocDrvRequest::EKernelBuffer | TLocDrvRequest::EAdjusted; |
|
6248 |
|
6249 #ifdef __DEMAND_PAGING__ |
|
6250 if (aPagingRequest) |
|
6251 { |
|
6252 request.Flags()|= TLocDrvRequest::EPaging; |
|
6253 // If the buffer is page aligned, use SendToMainQueueDfcAndBlock() as this |
|
6254 // is more efficient if the attached drive use DMA. |
|
6255 const TInt KPageSizeMask = 4096-1; |
|
6256 if (aData & KPageSizeMask) |
|
6257 { |
|
6258 return attachedDrive->iPrimaryMedia->SendReceive(request, aData); |
|
6259 } |
|
6260 else |
|
6261 { |
|
6262 attachedDrive->iPrimaryMedia->iBody->iPagingDevice->SendToMainQueueDfcAndBlock(&request); |
|
6263 return 0; |
|
6264 } |
|
6265 } |
|
6266 #else |
|
6267 aPagingRequest; |
|
6268 #endif |
|
6269 |
|
6270 return attachedDrive->iPrimaryMedia->SendReceive(request, aData); |
|
6271 } |
|
6272 |
|
6273 |
|
6274 /** |
|
6275 Read() - |
|
6276 |
|
6277 reads data from the next attached drive in the chain |
|
6278 |
|
6279 N.B. The position is assumed to be already adjusted i.e. relative to the start of the |
|
6280 media, not the partition |
|
6281 */ |
|
6282 EXPORT_C TInt DMediaDriverExtension::Read(TInt aDriveNumber, TInt64 aPos, TLinAddr aData, TUint aLen) |
|
6283 { |
|
6284 return SendRequest(DLocalDrive::ERead, EFalse, aDriveNumber, aPos, aData, aLen); |
|
6285 } |
|
6286 |
|
6287 /** |
|
6288 Write() - |
|
6289 |
|
6290 writes data to the next attached drive in the chain |
|
6291 |
|
6292 N.B. The position is assumed to be already adjusted i.e. relative to the start of the |
|
6293 media, not the partition |
|
6294 */ |
|
6295 EXPORT_C TInt DMediaDriverExtension::Write(TInt aDriveNumber, TInt64 aPos, TLinAddr aData, TUint aLen) |
|
6296 { |
|
6297 return SendRequest(DLocalDrive::EWrite, EFalse, aDriveNumber, aPos, aData, aLen); |
|
6298 } |
|
6299 |
|
6300 |
|
6301 #ifdef __DEMAND_PAGING__ |
|
6302 /** |
|
6303 ReadPaged() - |
|
6304 |
|
6305 Sends a paging read request to the specified attached drive |
|
6306 |
|
6307 N.B. The position is assumed to be already adjusted i.e. relative to the start of the |
|
6308 media, not the partition |
|
6309 */ |
|
6310 EXPORT_C TInt DMediaDriverExtension::ReadPaged(TInt aDriveNumber, TInt64 aPos, TLinAddr aData, TUint aLen) |
|
6311 { |
|
6312 return SendRequest(DLocalDrive::ERead, ETrue, aDriveNumber, aPos, aData, aLen); |
|
6313 } |
|
6314 |
|
6315 /** |
|
6316 WritePaged() - |
|
6317 |
|
6318 Send a paging write request to the specified attached drive |
|
6319 |
|
6320 N.B. The position is assumed to be already adjusted i.e. relative to the start of the |
|
6321 media, not the partition |
|
6322 */ |
|
6323 EXPORT_C TInt DMediaDriverExtension::WritePaged(TInt aDriveNumber, TInt64 aPos, TLinAddr aData, TUint aLen) |
|
6324 { |
|
6325 return SendRequest(DLocalDrive::EWrite, ETrue, aDriveNumber, aPos, aData, aLen); |
|
6326 } |
|
6327 #endif // __DEMAND_PAGING__ |
|
6328 |
|
6329 |
|
6330 |
|
6331 /** |
|
6332 Caps() - |
|
6333 |
|
6334 gets the caps from the next attached drive in the chain |
|
6335 |
|
6336 N.B. The position is assumed to be already adjusted i.e. relative to the start of the |
|
6337 media, not the partition |
|
6338 */ |
|
6339 EXPORT_C TInt DMediaDriverExtension::Caps(TInt aDriveNumber, TDes8& aCaps) |
|
6340 { |
|
6341 // Ensure this is a legitimate attached drive registered using LocDrv::RegisterMediaDevice() |
|
6342 if (!(iPrimaryMedia->iBody->iRegisteredDriveMask & (0x1 << aDriveNumber))) |
|
6343 return KErrArgument; |
|
6344 |
|
6345 TLocDrv* drive = TDriveIterator::GetDrive(aDriveNumber, iPrimaryMedia); |
|
6346 __ASSERT_DEBUG(drive, LOCM_FAULT()); |
|
6347 TLocDrv* attachedDrive = drive->iNextDrive; |
|
6348 __ASSERT_DEBUG(attachedDrive, LOCM_FAULT()); |
|
6349 |
|
6350 TLocDrvRequest request; |
|
6351 memclr(&request, sizeof(request)); |
|
6352 |
|
6353 request.Drive() = attachedDrive; |
|
6354 request.Id() = DLocalDrive::ECaps; |
|
6355 request.Length() = aCaps.Length(); |
|
6356 request.RemoteDes() = (TAny*) aCaps.Ptr(); |
|
6357 |
|
6358 return request.SendReceive(&attachedDrive->iPrimaryMedia->iMsgQ); |
|
6359 } |
|
6360 |
|
6361 |
|
6362 |
|
6363 EXPORT_C void DMediaDriverExtension::NotifyPowerDown() |
|
6364 { |
|
6365 } |
|
6366 |
|
6367 EXPORT_C void DMediaDriverExtension::NotifyEmergencyPowerDown() |
|
6368 { |
|
6369 } |
|
6370 |
|
6371 |
|
6372 /** |
|
6373 Returns ETrue if this media - or any media which this TLocDrv is attached to - is busy |
|
6374 */ |
|
6375 EXPORT_C TBool DMediaDriverExtension::MediaBusy(TInt aDriveNumber) |
|
6376 { |
|
6377 for (TLocDrv* drive = TDriveIterator::GetDrive(aDriveNumber, iPrimaryMedia); |
|
6378 drive; |
|
6379 drive = drive->iNextDrive) |
|
6380 { |
|
6381 DPrimaryMediaBase* primaryMedia = drive->iPrimaryMedia; |
|
6382 __ASSERT_DEBUG(primaryMedia, LOCM_FAULT()); |
|
6383 |
|
6384 if ((primaryMedia->iMsgQ.iMessage && primaryMedia->iMsgQ.iMessage->iState != TMessageBase::EFree) || |
|
6385 !primaryMedia->iMsgQ.iQ.IsEmpty() || |
|
6386 primaryMedia->iBody->iMediaChangeDfc.Queued() || |
|
6387 primaryMedia->iBody->iMediaPresentDfc.Queued()) |
|
6388 return ETrue; |
|
6389 |
|
6390 #ifdef __DEMAND_PAGING__ |
|
6391 DMediaPagingDevice* pagingDevice = iPrimaryMedia->iBody->iPagingDevice; |
|
6392 if (pagingDevice) |
|
6393 { |
|
6394 if ((pagingDevice->iMainQ.iMessage && pagingDevice->iMainQ.iMessage->iState != TMessageBase::EFree) || |
|
6395 !pagingDevice->iMainQ.iQ.IsEmpty()) |
|
6396 return ETrue; |
|
6397 } |
|
6398 #endif |
|
6399 } |
|
6400 |
|
6401 return EFalse; |
|
6402 } |
|
6403 |
|
6404 |
|
6405 TCallBackLink::TCallBackLink() |
|
6406 { |
|
6407 memclr(this, sizeof(this)); |
|
6408 } |
|
6409 |
|
6410 TCallBackLink::TCallBackLink(TInt (*aFunction)(TAny* aPtr, TInt aParam),TAny* aPtr, TObjectType aObjectType) : |
|
6411 iFunction(aFunction), iPtr(aPtr), iObjectType(aObjectType) |
|
6412 { |
|
6413 } |
|
6414 |
|
6415 TInt TCallBackLink::CallBack(TInt aParam) const |
|
6416 { |
|
6417 return (*iFunction)(iPtr, aParam); |
|
6418 } |
|
6419 |
|
6420 /****************************************************************************** |
5740 Entry point |
6421 Entry point |
5741 ******************************************************************************/ |
6422 ******************************************************************************/ |
5742 DECLARE_STANDARD_EXTENSION() |
6423 DECLARE_STANDARD_EXTENSION() |
5743 { |
6424 { |
5744 __KTRACE_OPT(KBOOT,Kern::Printf("Starting LOCMEDIA extension")); |
6425 __KTRACE_OPT(KBOOT,Kern::Printf("Starting LOCMEDIA extension")); |
5745 |
6426 |
5746 // install the HAL function |
6427 // install the HAL function |
5747 TInt r=Kern::AddHalEntry(EHalGroupMedia,MediaHalFunction,NULL); |
6428 TInt r=Kern::AddHalEntry(EHalGroupMedia,MediaHalFunction,NULL); |
|
6429 |
5748 #ifdef __DEMAND_PAGING__ |
6430 #ifdef __DEMAND_PAGING__ |
5749 if (r==KErrNone) |
6431 if (r==KErrNone) |
5750 { |
6432 { |
5751 __KTRACE_OPT(KBOOT,Kern::Printf("Creating LocDrv device")); |
6433 __KTRACE_OPT(KBOOT,Kern::Printf("Creating LocDrv device")); |
5752 DLocalDriveFactory* device = new DLocalDriveFactory; |
6434 DLocalDriveFactory* device = new DLocalDriveFactory; |