Update contrib.
1 // Copyright (c) 1997-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\misc\d_ipccpy.cpp
15 // LDD for testing IPC copy functions
20 #include <kernel/kern_priv.h>
23 const TInt KMajorVersionNumber=0;
24 const TInt KMinorVersionNumber=1;
25 const TInt KBuildVersionNumber=1;
27 const TInt KBigBufferSize = 65536;
29 _LIT(KDIpcCpyPanicCategory,"DIpcCpy");
31 class DIpcCpyFactory : public DLogicalDevice
33 // IPC copy LDD factory
39 virtual TInt Install(); //overriding pure virtual
40 virtual void GetCaps(TDes8& aDes) const; //overriding pure virtual
41 virtual TInt Create(DLogicalChannelBase*& aChannel); //overriding pure virtual
44 TDynamicDfcQue* iDfcQ;
47 class DIpcCpy : public DLogicalChannel
49 // Millisecond timer LDD channel
53 DIpcCpy(TDfcQue* aDfcQ);
56 virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer);
57 virtual TInt Request(TInt aFunc, TAny* a1, TAny* a2);
58 virtual void HandleMsg(TMessageBase* aMsg);
61 TInt CreateHardwareChunks(TPtr8& aUserDes);
66 ERequestAlreadyPending = 1
70 TClientRequest* iAsyncRequest;
78 DPlatChunkHw* iHwChunks[RIpcCpy::ENumHwChunkTypes];
80 TLinAddr iHwChunkLinAddrs[RIpcCpy::ENumHwChunkTypes];
83 DECLARE_STANDARD_LDD()
85 return new DIpcCpyFactory;
88 DIpcCpyFactory::DIpcCpyFactory()
93 iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
94 //iParseMask=0;//No units, no info, no PDD
95 //iUnitsMask=0;//Only one thing
98 DIpcCpyFactory::~DIpcCpyFactory()
107 TInt DIpcCpyFactory::Create(DLogicalChannelBase*& aChannel)
109 // Create a new DIpcCpy on this logical device
112 aChannel=new DIpcCpy(iDfcQ);
113 return aChannel?KErrNone:KErrNoMemory;
116 const TInt KIpcCpyThreadPriority = 27;
117 _LIT(KIpcCpyThread,"IpcCpyThread");
119 TInt DIpcCpyFactory::Install()
121 // Install the LDD - overriding pure virtual
124 // Allocate a kernel thread to run the DFC
125 TInt r = Kern::DynamicDfcQCreate(iDfcQ, KIpcCpyThreadPriority, KIpcCpyThread);
127 #ifdef CPU_AFFINITY_ANY
128 NKern::ThreadSetCpuAffinity((NThread*)(iDfcQ->iThread), KCpuAffinityAny);
134 return SetName(&KIpcCpyLddName);
137 void DIpcCpyFactory::GetCaps(TDes8& aDes) const
139 // Get capabilities - overriding pure virtual
143 b.iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
144 Kern::InfoCopy(aDes,(TUint8*)&b,sizeof(b));
147 void timerExpired(TAny* aPtr)
149 DIpcCpy* p=(DIpcCpy*)aPtr;
153 void dfcFn(TAny* aPtr)
155 DIpcCpy* p=(DIpcCpy*)aPtr;
159 DIpcCpy::DIpcCpy(TDfcQue* aDfcQ)
163 : iTimer(timerExpired,this),
164 iDfc(dfcFn,this,aDfcQ,1)
166 iThread=&Kern::CurrentThread();
177 Kern::QueueRequestComplete(iThread, iAsyncRequest, KErrCancel); // does nothing if request not pending
178 Kern::DestroyClientRequest(iAsyncRequest);
180 Kern::Free(iBigBuffer);
181 Kern::SafeClose((DObject*&)iThread, NULL);
184 for(TInt i=0; i<RIpcCpy::ENumHwChunkTypes; i++)
185 Kern::SafeClose((DObject*&)iHwChunks[i], NULL);
189 TInt DIpcCpy::DoCreate(TInt /*aUnit*/, const TDesC8* /*anInfo*/, const TVersion& aVer)
195 if (!Kern::QueryVersionSupported(TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber),aVer))
196 return KErrNotSupported;
197 TInt r = Kern::CreateClientRequest(iAsyncRequest);
200 iBigBuffer = (TUint8*)Kern::Alloc(KBigBufferSize);
208 TInt DIpcCpy::CreateHardwareChunks(TPtr8& aUserDes)
214 NKern::ThreadEnterCS();
216 TUint32 size=Kern::RoundToPageSize(1);
218 const TUint attrs[] = { EMapAttrSupRw, EMapAttrUserRw, EMapAttrReadUser }; // X86 does support EMapAttrUserRo, so use EMapAttrReadUser
220 const TUint attrs[] = { EMapAttrSupRw, EMapAttrUserRw, EMapAttrUserRo };
222 for(TInt i=0; i<RIpcCpy::ENumHwChunkTypes; i++)
225 r = Epoc::AllocPhysicalRam(size,phys);
228 NKern::ThreadLeaveCS();
232 TChunkCreateInfo info;
233 info.iType = TChunkCreateInfo::ESharedKernelMultiple;
234 info.iMaxSize = size;
236 info.iOwnsMemory = EFalse;
240 r = Kern::ChunkCreate(info,chunk,base,attr);
243 r=Kern::ChunkCommitPhysical(chunk, 0, size, phys);
246 memcpy((TAny*)base,&aUserDes,sizeof(TPtr8));
248 Kern::ChunkClose(chunk);
250 r = DPlatChunkHw::New(iHwChunks[i], phys, size, attrs[i]);
255 iHwChunkLinAddrs[i] = iHwChunks[i]->LinearAddress();
257 else if (r==KErrNotSupported) //ARMv6K && ARMv7 do not support EMapAttrUserRo
259 iHwChunkLinAddrs[i] = 0;
264 Epoc::FreePhysicalRam(phys,size);
265 NKern::ThreadLeaveCS();
270 NKern::ThreadLeaveCS();
276 TInt DIpcCpy::Request(TInt aFunc, TAny* a1, TAny* a2)
278 if (aFunc == RIpcCpy::EControlBigRead)
280 TUint size = (TUint)a2;
281 if (size > (TUint)KBigBufferSize)
283 kumemput(a1, iBigBuffer, size);
286 else if (aFunc == RIpcCpy::EControlBigWrite)
288 TUint size = (TUint)a2;
289 if (size > (TUint)KBigBufferSize)
291 kumemget(iBigBuffer, a1, size);
294 else if (aFunc == RIpcCpy::EControlHardwareChunks)
297 kumemget(&des,a2,sizeof(TPtr8));
298 TInt r=CreateHardwareChunks(des);
300 kumemput(a1, iHwChunkLinAddrs, sizeof(iHwChunkLinAddrs));
303 return DLogicalChannel::Request(aFunc, a1, a2);
306 void DIpcCpy::HandleMsg(TMessageBase* aMsg)
309 TThreadMessage& m=*(TThreadMessage*)aMsg;
311 if (id==(TInt)ECloseMsg)
315 m.Complete(KErrNone,EFalse);
316 iMsgQ.CompleteAll(KErrServerTerminated);
321 TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
322 if (iAsyncRequest->SetStatus(pS) != KErrNone)
323 Kern::ThreadKill(iThread,EExitPanic,ERequestAlreadyPending,KDIpcCpyPanicCategory);
325 if (id==~RIpcCpy::ERequestIpcCpy)
337 Kern::QueueRequestComplete(iThread, iAsyncRequest, r);
349 void DIpcCpy::TimerExpired()
351 TInt src_offset=iSeqNum&3;
352 TInt dest_offset=(iSeqNum>>2)&3;
353 TInt length=(iSeqNum>>4)+1;
355 for (i=src_offset; i<length+src_offset; ++i)
356 iBuffer[i]=(TUint8)(i+1);
357 TPtrC8 ptr(iBuffer+src_offset, length);
358 TInt r=Kern::ThreadDesWrite(iThread, iDest, ptr, dest_offset, KChunkShiftBy0, NULL);
365 Kern::QueueRequestComplete(iThread, iAsyncRequest, r);