Update contrib.
1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32test\demandpaging\t_pagingexample.cpp
15 // Test device driver migration examples
19 #define __E32TEST_EXTENSION__
28 #include "../mmu/t_codepaging_dll.h"
29 #include "d_pagingexample.h"
31 const TInt KBufferSize = KMaxTransferSize;
32 _LIT(KTCodePagingDll4, "t_codepaging_dll4.dll");
36 TRequestStatus iStatus;
37 RPagingExample::TConfigData iConfig;
38 RPagingExample::TValueStruct iValue;
42 TUint8 iBuffer[KBufferSize];
44 TTestData() : iPtr(NULL, 0) { }
47 RTest test(_L("T_PAGINGEXAMPLE"));
49 RLibrary PagedLibrary;
50 TTestData* UnpagedInputData = NULL;
51 TTestData* UnpagedOutputData = NULL;
52 TTestData* PagedInputData = NULL;
53 TTestData* PagedOutputData = NULL;
55 void InitInputData(TTestData* aData)
57 aData->iConfig.iParam1 = 2;
58 aData->iConfig.iParam2 = 3;
59 aData->iConfig.iParam3 = 5;
60 aData->iConfig.iParam4 = 7;
61 for (TInt i = 0 ; i < KBufferSize ; ++i)
62 aData->iBuffer[i] = (TUint8)(i + 123);
65 void DoTestDriver(const TDesC& aDriverName, const TTestData* aInputData, TTestData* aOutputData)
67 test.Start(_L("Load logical device"));
68 TInt r = User::LoadLogicalDevice(aDriverName);
69 test(r==KErrNone || r==KErrAlreadyExists);
71 test.Next(_L("Open logical device"));
73 test_KErrNone(ldd.Open(aDriverName));
75 test.Next(_L("Set config"));
77 test_KErrNone(ldd.SetConfig(aInputData->iConfig));
79 test.Next(_L("Get config"));
80 Mem::FillZ(&aOutputData->iConfig, sizeof(RPagingExample::TConfigData));
82 test_KErrNone(ldd.GetConfig(aOutputData->iConfig));
83 test_Equal(0, Mem::Compare((TUint8*)&aInputData->iConfig, sizeof(RPagingExample::TConfigData),
84 (TUint8*)&aOutputData->iConfig, sizeof(RPagingExample::TConfigData)));
86 TRequestStatus& status = aOutputData->iStatus;
88 test.Next(_L("Notify"));
92 User::WaitForRequest(status);
93 test_Equal(KErrNone, status.Int());
95 test.Next(_L("Async get value"));
96 memclr(&aOutputData->iValue, sizeof(RPagingExample::TValueStruct));
98 ldd.AsyncGetValue(status, aOutputData->iValue);
100 User::WaitForRequest(status);
101 test_Equal(KErrNone, status.Int());
102 test_Equal(1, aOutputData->iValue.iValue1);
103 test(aOutputData->iValue.iValue2 == _L8("shrt"));
105 test.Next(_L("Cancel async get value"));
106 ldd.AsyncGetValue(status, aOutputData->iValue);
108 User::WaitForRequest(status);
109 test_Equal(KErrCancel, status.Int());
111 test.Next(_L("Async get value 2"));
112 aOutputData->iIntValue1 = 0;
113 aOutputData->iIntValue2 = 0;
114 DPTest::FlushCache();
115 ldd.AsyncGetValue2(status, aOutputData->iIntValue1, aOutputData->iIntValue2);
116 DPTest::FlushCache();
117 User::WaitForRequest(status);
118 test_Equal(KErrNone, status.Int());
119 test_Equal(1, aOutputData->iIntValue1);
120 test_Equal(2, aOutputData->iIntValue2);
122 test.Next(_L("Cancel async get value 2"));
123 ldd.AsyncGetValue2(status, aOutputData->iIntValue1, aOutputData->iIntValue2);
125 User::WaitForRequest(status);
126 test_Equal(KErrCancel, status.Int());
128 test.Next(_L("Write buffer too short"));
129 ldd.Write(status, NULL, 0);
130 User::WaitForRequest(status);
131 test_Equal(KErrArgument, status.Int());
133 test.Next(_L("Write buffer too long"));
134 ldd.Write(status, NULL, KMaxTransferSize + 1);
135 User::WaitForRequest(status);
136 test_Equal(KErrArgument, status.Int());
138 test.Next(_L("Write"));
139 DPTest::FlushCache();
140 ldd.Write(status, aInputData->iBuffer, KBufferSize);
141 DPTest::FlushCache();
142 User::WaitForRequest(status);
143 test_KErrNone(status.Int());
145 test.Next(_L("Cancel write"));
146 ldd.Write(status, aInputData->iBuffer, KBufferSize);
148 User::WaitForRequest(status);
149 test_Equal(KErrCancel, status.Int());
151 test.Next(_L("Read buffer too short"));
152 ldd.Read(status, NULL, 0);
153 User::WaitForRequest(status);
154 test_Equal(KErrArgument, status.Int());
156 test.Next(_L("Read buffer too long"));
157 ldd.Read(status, NULL, KMaxTransferSize + 1);
158 User::WaitForRequest(status);
159 test_Equal(KErrArgument, status.Int());
161 test.Next(_L("Read"));
162 Mem::FillZ(aOutputData->iBuffer, KBufferSize);
163 DPTest::FlushCache();
164 ldd.Read(status, aOutputData->iBuffer, KBufferSize);
165 DPTest::FlushCache();
166 User::WaitForRequest(status);
167 test_KErrNone(status.Int());
168 test_Equal(0, Mem::Compare(aInputData->iBuffer, KBufferSize,
169 aOutputData->iBuffer, KBufferSize));
171 test.Next(_L("Cancel read"));
172 ldd.Read(status, aOutputData->iBuffer, KBufferSize);
174 User::WaitForRequest(status);
175 test_Equal(KErrCancel, status.Int());
177 test.Next(_L("Cancel nothing"));
180 test.Next(_L("Write while write pending"));
181 TRequestStatus status2;
182 ldd.Write(status, aInputData->iBuffer, KBufferSize);
183 ldd.Write(status2, aInputData->iBuffer, KBufferSize);
184 User::WaitForRequest(status);
185 test_KErrNone(status.Int());
186 User::WaitForRequest(status2);
187 test_Equal(KErrInUse, status2.Int());
189 test.Next(_L("Read while read pending"));
190 ldd.Read(status, aOutputData->iBuffer, KBufferSize);
191 ldd.Read(status2, aOutputData->iBuffer, KBufferSize);
192 User::WaitForRequest(status);
193 test_KErrNone(status.Int());
194 User::WaitForRequest(status2);
195 test_Equal(KErrInUse, status2.Int());
197 test.Next(_L("Write des"));
198 TPtrC8 writeDes(aInputData->iBuffer + 1, KBufferSize - 1);
199 DPTest::FlushCache();
200 ldd.WriteDes(status, writeDes);
201 DPTest::FlushCache();
202 User::WaitForRequest(status);
203 test_KErrNone(status.Int());
205 test.Next(_L("Cancel write des"));
206 ldd.WriteDes(status, writeDes);
208 User::WaitForRequest(status);
209 test_Equal(KErrCancel, status.Int());
211 test.Next(_L("Read des"));
212 TPtr8 readDes(aOutputData->iBuffer, KBufferSize - 1);
213 Mem::FillZ(aOutputData->iBuffer, KBufferSize);
214 DPTest::FlushCache();
215 ldd.ReadDes(status, readDes);
216 DPTest::FlushCache();
217 User::WaitForRequest(status);
218 test_KErrNone(status.Int());
219 test(readDes == writeDes);
221 test.Next(_L("Read des 2")); // has paged header but unpaged contnet, if output data is paged
222 aOutputData->iPtr.Set(UnpagedOutputData->iBuffer, 0, KBufferSize - 1);
223 Mem::FillZ(UnpagedOutputData->iBuffer, KBufferSize);
224 DPTest::FlushCache();
225 ldd.ReadDes(status, aOutputData->iPtr);
226 DPTest::FlushCache();
227 User::WaitForRequest(status);
228 test_KErrNone(status.Int());
229 test(aOutputData->iPtr == writeDes);
231 test.Next(_L("Cancel read des"));
232 ldd.ReadDes(status, readDes);
234 User::WaitForRequest(status);
235 test_Equal(KErrCancel, status.Int());
237 test.Next(_L("Read and write at the same time"));
238 ldd.Write(status, aInputData->iBuffer, KBufferSize);
239 ldd.Read(status2, aOutputData->iBuffer, KBufferSize);
240 DPTest::FlushCache();
241 User::WaitForRequest(status);
242 test_KErrNone(status.Int());
243 User::WaitForRequest(status2);
244 test_KErrNone(status2.Int());
246 test.Next(_L("Cancel read and write"));
247 ldd.Write(status, aInputData->iBuffer, KBufferSize);
248 ldd.Read(status2, aOutputData->iBuffer, KBufferSize);
250 User::WaitForRequest(status);
251 test_Equal(KErrCancel, status.Int());
252 User::WaitForRequest(status2);
253 test_Equal(KErrCancel, status2.Int());
255 test.Next(_L("Close and free logical device"));
257 test_KErrNone(User::FreeLogicalDevice(aDriverName));
262 void TestDriver(const TDesC& aDriverName, TBool aMigrated)
265 string.Format(_L("Testing driver %S"), &aDriverName);
268 test.Start(_L("Test reading from unpaged memory and writing to unpaged memory"));
269 DoTestDriver(aDriverName, UnpagedInputData, UnpagedOutputData);
271 if (aMigrated && PagedInputData)
275 test.Next(_L("Test reading from paged memory and writing to paged memory"));
276 DoTestDriver(aDriverName, PagedInputData, PagedOutputData);
280 test.Next(_L("Test reading from paged memory and writing to unpaged memory"));
281 DoTestDriver(aDriverName, PagedInputData, UnpagedOutputData);
285 // todo: test pinning failures
292 ETestRequestComplete,
308 EOutcomeRealtimePanic
311 TInt RealtimeTestFunc(TAny* aArg)
313 TTestAction action = (TTestAction)((TUint)aArg & 255);
314 TTestAccess access = (TTestAccess)((TUint)aArg >> 8);
316 TTestData* inputData = access == EAccessPaged ? PagedInputData : UnpagedInputData;
317 TTestData* outputData = access == EAccessPaged ? PagedOutputData : UnpagedOutputData;
320 TInt r = ldd.Open(KPagingExample1PreLdd);
323 ldd.SetDfcThreadRealtimeState(ETrue);
325 TRequestStatus unpagedStatus;
326 TRequestStatus* status = &unpagedStatus;
330 case ETestRequestComplete:
332 RDebug::Printf("Test RequestComplete");
333 status = &outputData->iStatus;
334 RPagingExample::TValueStruct value;
335 DPTest::FlushCache();
336 ldd.AsyncGetValue(*status, value);
337 DPTest::FlushCache();
342 RDebug::Printf("Test ThreadRawRead");
343 ldd.Write(*status, inputData->iBuffer, KBufferSize);
344 DPTest::FlushCache();
348 RDebug::Printf("Test ThreadRawWrite");
349 ldd.Read(*status, outputData->iBuffer, KBufferSize);
350 DPTest::FlushCache();
355 RDebug::Printf("Test ThreadDesRead");
356 TPtrC8 writeDes(inputData->iBuffer, KBufferSize);
357 ldd.WriteDes(*status, writeDes);
358 DPTest::FlushCache();
364 RDebug::Printf("Test ThreadDesWrite");
365 TPtr8 readDes(outputData->iBuffer, KBufferSize);
366 ldd.ReadDes(*status, readDes);
367 DPTest::FlushCache();
373 User::WaitForAnyRequest();
379 void RunRealtimeTestThread(TTestAction aTestAction, TTestAccess aAccess, TTestOutcome aExpectedOutcome)
382 TUint arg = aTestAction | (aAccess << 8);
383 test_KErrNone(thread.Create(KNullDesC, RealtimeTestFunc, 4096, NULL, (TAny*)arg));
384 TRequestStatus status;
385 thread.Logon(status);
387 User::WaitForRequest(status);
388 switch (aExpectedOutcome)
390 case EOutcomeSuccess:
391 test_Equal(EExitKill, thread.ExitType());
392 test_Equal(KErrNone, thread.ExitReason());
395 case EOutcomeRealtimePanic:
396 test_Equal(EExitPanic, thread.ExitType());
397 test_Equal(EIllegalFunctionForRealtimeThread, thread.ExitReason());
403 CLOSE_AND_WAIT(thread);
406 void TestPagedAccessInRealtimeThread()
408 // Test driver access to paged memory from realtime DFC thread. This can happen if a client
409 // passes paged memory to a driver that doesn't expect it, and has set its realtime state to
410 // enfore this. The client should be panicked in this case.
412 test.Start(_L("Test memory access from realtime threads"));
413 test.Next(_L("Load logical device"));
414 TInt r = User::LoadLogicalDevice(KPagingExample1PreLdd);
415 test(r==KErrNone || r==KErrAlreadyExists);
417 test.Next(_L("Test access to unpaged memory from realtime thread"));
418 RunRealtimeTestThread(ETestRequestComplete, EAccessUnpaged, EOutcomeSuccess);
419 RunRealtimeTestThread(ETestRawRead, EAccessUnpaged, EOutcomeSuccess);
420 RunRealtimeTestThread(ETestRawWrite, EAccessUnpaged, EOutcomeSuccess);
421 RunRealtimeTestThread(ETestDesRead, EAccessUnpaged, EOutcomeSuccess);
422 RunRealtimeTestThread(ETestDesWrite, EAccessUnpaged, EOutcomeSuccess);
424 test.Next(_L("Test access to paged memory from realtime thread"));
427 RunRealtimeTestThread(ETestRawRead, EAccessPaged, EOutcomeRealtimePanic);
428 RunRealtimeTestThread(ETestDesRead, EAccessPaged, EOutcomeRealtimePanic);
432 RunRealtimeTestThread(ETestRequestComplete, EAccessPaged, EOutcomeRealtimePanic);
433 RunRealtimeTestThread(ETestRawWrite, EAccessPaged, EOutcomeRealtimePanic);
434 RunRealtimeTestThread(ETestDesWrite, EAccessPaged, EOutcomeRealtimePanic);
437 test.Next(_L("Close and free logical device"));
438 test_KErrNone(User::FreeLogicalDevice(KPagingExample1PreLdd));
447 test.Start(_L("Test device driver migration examples"));
449 UnpagedInputData = (TTestData*)User::Alloc(sizeof(TTestData));
450 test_NotNull(UnpagedInputData);
451 UnpagedOutputData = (TTestData*)User::Alloc(sizeof(TTestData));
452 test_NotNull(UnpagedOutputData);
454 test_KErrNone(UserSvr::HalFunction(EHalGroupKernel,EKernelHalPageSizeInBytes,&PageSize,0));
457 if (DPTest::Attributes() & DPTest::EDataPaging)
459 TChunkCreateInfo info;
460 TInt size = (sizeof(TTestData) + PageSize - 1) & ~(PageSize - 1);
461 info.SetNormal(size, size);
462 info.SetPaging(TChunkCreateInfo::EPaged);
463 test_KErrNone(chunk.Create(info));
464 test(chunk.IsPaged());
465 PagedOutputData = (TTestData*)chunk.Base();
466 test.Printf(_L("Using data pagd output buffer at %08x\n"), PagedOutputData);
469 if (DPTest::Attributes() & DPTest::ERomPaging)
471 // use paged part of rom for read-only data
472 TRomHeader* romHeader = (TRomHeader*)UserSvr::RomHeaderAddress();
473 test(romHeader->iPageableRomStart);
474 // todo: for some reason the first part of page of paged rom doesn't seem to get paged out
475 // when we flush the paging cache, hence PagedInputData starts some way into this
476 PagedInputData = (TTestData*)((TUint8*)romHeader + romHeader->iPageableRomStart + 64 * PageSize);
477 TInt romDataSize = romHeader->iPageableRomSize - 64 * PageSize;
478 test(romDataSize >= (TInt)sizeof(TTestData));
479 test.Printf(_L("Using rom paged input data at %08x\n"), PagedInputData);
481 else if (DPTest::Attributes() & DPTest::ECodePaging)
483 // use code paged DLL for read-only buffer
484 test_KErrNone(PagedLibrary.Load(KTCodePagingDll4));
485 TGetAddressOfDataFunction func = (TGetAddressOfDataFunction)PagedLibrary.Lookup(KGetAddressOfDataFunctionOrdinal);
487 PagedInputData = (TTestData*)func(codeDataSize);
488 test_NotNull(PagedInputData);
489 test(codeDataSize >= (TInt)sizeof(TTestData));
490 test.Printf(_L("Using code paged input data at %08x\n"), PagedInputData);
493 InitInputData(UnpagedInputData);
495 TestDriver(KPagingExample1PreLdd, EFalse);
496 TestDriver(KPagingExample1PostLdd, ETrue);
497 TestDriver(KPagingExample2PreLdd, EFalse);
498 TestDriver(KPagingExample2PostLdd, ETrue);
499 TestPagedAccessInRealtimeThread();
501 PagedLibrary.Close();
502 User::Free(UnpagedInputData);
503 User::Free(UnpagedOutputData);