os/kernelhwsrv/kerneltest/e32test/misc/d_ipccpy.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
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".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // e32test\misc\d_ipccpy.cpp
    15 // LDD for testing IPC copy functions
    16 // 
    17 //
    18 
    19 #include "platform.h"
    20 #include <kernel/kern_priv.h>
    21 #include "d_ipccpy.h"
    22 
    23 const TInt KMajorVersionNumber=0;
    24 const TInt KMinorVersionNumber=1;
    25 const TInt KBuildVersionNumber=1;
    26 
    27 const TInt KBigBufferSize = 65536;
    28 
    29 _LIT(KDIpcCpyPanicCategory,"DIpcCpy");
    30 
    31 class DIpcCpyFactory : public DLogicalDevice
    32 //
    33 // IPC copy LDD factory
    34 //
    35 	{
    36 public:
    37 	DIpcCpyFactory();
    38 	~DIpcCpyFactory();
    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
    42 
    43 private:
    44 	TDynamicDfcQue* iDfcQ;
    45 	};
    46 
    47 class DIpcCpy : public DLogicalChannel
    48 //
    49 // Millisecond timer LDD channel
    50 //
    51 	{
    52 public:
    53 	DIpcCpy(TDfcQue* aDfcQ);
    54 	virtual ~DIpcCpy();
    55 protected:
    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);
    59 public:
    60 	void TimerExpired();
    61 	TInt CreateHardwareChunks(TPtr8& aUserDes);
    62 
    63 	// Panic reasons
    64 	enum TPanic
    65 		{
    66 		ERequestAlreadyPending = 1
    67 		};
    68 public:
    69 	DThread* iThread;
    70 	TClientRequest* iAsyncRequest;
    71 	TAny* iDest;
    72 	TInt iSeqNum;
    73 	NTimer iTimer;
    74 	TDfc iDfc;
    75 	TUint8 iBuffer[260];
    76 	TUint8* iBigBuffer;
    77 #ifdef __EPOC32__
    78 	DPlatChunkHw* iHwChunks[RIpcCpy::ENumHwChunkTypes];
    79 #endif
    80 	TLinAddr iHwChunkLinAddrs[RIpcCpy::ENumHwChunkTypes];
    81 	};
    82 
    83 DECLARE_STANDARD_LDD()
    84 	{
    85     return new DIpcCpyFactory;
    86     }
    87 
    88 DIpcCpyFactory::DIpcCpyFactory()
    89 //
    90 // Constructor
    91 //
    92     {
    93     iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
    94     //iParseMask=0;//No units, no info, no PDD
    95     //iUnitsMask=0;//Only one thing
    96     }
    97 
    98 DIpcCpyFactory::~DIpcCpyFactory()
    99 //
   100 // Destructor
   101 //
   102 	{
   103 	if (iDfcQ)
   104 		iDfcQ->Destroy();
   105 	}
   106 
   107 TInt DIpcCpyFactory::Create(DLogicalChannelBase*& aChannel)
   108 //
   109 // Create a new DIpcCpy on this logical device
   110 //
   111     {
   112 	aChannel=new DIpcCpy(iDfcQ);
   113     return aChannel?KErrNone:KErrNoMemory;
   114     }
   115 
   116 const TInt KIpcCpyThreadPriority = 27;
   117 _LIT(KIpcCpyThread,"IpcCpyThread");
   118 
   119 TInt DIpcCpyFactory::Install()
   120 //
   121 // Install the LDD - overriding pure virtual
   122 //
   123     {
   124 	// Allocate a kernel thread to run the DFC 
   125 	TInt r = Kern::DynamicDfcQCreate(iDfcQ, KIpcCpyThreadPriority, KIpcCpyThread);
   126 
   127 #ifdef CPU_AFFINITY_ANY
   128 	NKern::ThreadSetCpuAffinity((NThread*)(iDfcQ->iThread), KCpuAffinityAny);			
   129 #endif
   130 
   131 	if (r != KErrNone)
   132 		return r; 	
   133 
   134     return SetName(&KIpcCpyLddName);
   135     }
   136 
   137 void DIpcCpyFactory::GetCaps(TDes8& aDes) const
   138 //
   139 // Get capabilities - overriding pure virtual
   140 //
   141     {
   142     TCapsIpcCpyV01 b;
   143     b.iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
   144     Kern::InfoCopy(aDes,(TUint8*)&b,sizeof(b));
   145     }
   146 
   147 void timerExpired(TAny* aPtr)
   148 	{
   149 	DIpcCpy* p=(DIpcCpy*)aPtr;
   150 	p->iDfc.Add();
   151 	}
   152 
   153 void dfcFn(TAny* aPtr)
   154 	{
   155 	DIpcCpy* p=(DIpcCpy*)aPtr;
   156 	p->TimerExpired();
   157 	}
   158 
   159 DIpcCpy::DIpcCpy(TDfcQue* aDfcQ)
   160 //
   161 // Constructor
   162 //
   163 	:	iTimer(timerExpired,this),
   164 		iDfc(dfcFn,this,aDfcQ,1)
   165     {
   166 	iThread=&Kern::CurrentThread();
   167 	iThread->Open();
   168 //	iSeqNum=0;
   169 //	iDest=NULL;
   170 	SetDfcQ(aDfcQ);
   171     }
   172 
   173 DIpcCpy::~DIpcCpy()
   174 	{
   175 	if (iAsyncRequest)
   176 		{
   177 		Kern::QueueRequestComplete(iThread, iAsyncRequest, KErrCancel);	// does nothing if request not pending
   178 		Kern::DestroyClientRequest(iAsyncRequest);
   179 		}
   180 	Kern::Free(iBigBuffer);
   181 	Kern::SafeClose((DObject*&)iThread, NULL);
   182 
   183 #ifdef __EPOC32__
   184 	for(TInt i=0; i<RIpcCpy::ENumHwChunkTypes; i++)
   185 		Kern::SafeClose((DObject*&)iHwChunks[i], NULL);
   186 #endif
   187 	}
   188 
   189 TInt DIpcCpy::DoCreate(TInt /*aUnit*/, const TDesC8* /*anInfo*/, const TVersion& aVer)
   190 //
   191 // Create channel
   192 //
   193     {
   194 
   195     if (!Kern::QueryVersionSupported(TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber),aVer))
   196     	return KErrNotSupported;
   197 	TInt r = Kern::CreateClientRequest(iAsyncRequest);
   198 	if (r!=KErrNone)
   199 		return r;
   200 	iBigBuffer = (TUint8*)Kern::Alloc(KBigBufferSize);
   201 	if (!iBigBuffer)
   202 		return KErrNoMemory;
   203 	iMsgQ.Receive();
   204 	return KErrNone;
   205 	}
   206 
   207 
   208 TInt DIpcCpy::CreateHardwareChunks(TPtr8& aUserDes)
   209 	{
   210 #ifndef __EPOC32__
   211 	(void)aUserDes;
   212 	return KErrNone;
   213 #else
   214 	NKern::ThreadEnterCS();
   215 	TInt r;
   216 	TUint32 size=Kern::RoundToPageSize(1);
   217 #ifdef __X86__
   218 	const TUint attrs[] = { EMapAttrSupRw, EMapAttrUserRw, EMapAttrReadUser }; // X86 does support EMapAttrUserRo, so use EMapAttrReadUser
   219 #else
   220 	const TUint attrs[] = { EMapAttrSupRw, EMapAttrUserRw, EMapAttrUserRo };
   221 #endif
   222 	for(TInt i=0; i<RIpcCpy::ENumHwChunkTypes; i++)
   223 		{
   224 		TPhysAddr phys;
   225 		r = Epoc::AllocPhysicalRam(size,phys);
   226 		if(r!=KErrNone)
   227 			{
   228 			NKern::ThreadLeaveCS();
   229 			return r;
   230 			}
   231 
   232 		TChunkCreateInfo info;
   233 		info.iType = TChunkCreateInfo::ESharedKernelMultiple;
   234 		info.iMaxSize = size;
   235 		info.iMapAttr = 0;
   236 		info.iOwnsMemory = EFalse;
   237 		DChunk* chunk;
   238 		TLinAddr base;
   239 		TUint32 attr;
   240 		r = Kern::ChunkCreate(info,chunk,base,attr);
   241 		if(r==KErrNone)
   242 			{
   243 			r=Kern::ChunkCommitPhysical(chunk, 0, size, phys);
   244 			if(r==KErrNone)
   245 				{
   246 				memcpy((TAny*)base,&aUserDes,sizeof(TPtr8));
   247 				}
   248 			Kern::ChunkClose(chunk);
   249 			if(r==KErrNone)
   250 				r = DPlatChunkHw::New(iHwChunks[i], phys, size, attrs[i]);
   251 			}
   252 
   253 		if(r==KErrNone)
   254 			{
   255 			iHwChunkLinAddrs[i] = iHwChunks[i]->LinearAddress();
   256 			}
   257 		else if (r==KErrNotSupported) //ARMv6K && ARMv7 do not support EMapAttrUserRo
   258 			{
   259 			iHwChunkLinAddrs[i] = 0;
   260 			r = KErrNone;			
   261 			}
   262 		else
   263 			{
   264 			Epoc::FreePhysicalRam(phys,size);
   265 			NKern::ThreadLeaveCS();
   266 			return r;
   267 			}
   268 
   269 		}
   270 	NKern::ThreadLeaveCS();
   271 	return r;
   272 #endif
   273 	}
   274 
   275 
   276 TInt DIpcCpy::Request(TInt aFunc, TAny* a1, TAny* a2)
   277 	{
   278 	if (aFunc == RIpcCpy::EControlBigRead)
   279 		{
   280 		TUint size = (TUint)a2;
   281 		if (size > (TUint)KBigBufferSize)
   282 			return KErrOverflow;
   283 		kumemput(a1, iBigBuffer, size);
   284 		return KErrNone;
   285 		}
   286 	else if (aFunc == RIpcCpy::EControlBigWrite)
   287 		{
   288 		TUint size = (TUint)a2;
   289 		if (size > (TUint)KBigBufferSize)
   290 			return KErrOverflow;
   291 		kumemget(iBigBuffer, a1, size);
   292 		return KErrNone;
   293 		}
   294 	else if (aFunc == RIpcCpy::EControlHardwareChunks)
   295 		{
   296 		TPtr8 des(0,0,0);
   297 		kumemget(&des,a2,sizeof(TPtr8));
   298 		TInt r=CreateHardwareChunks(des);
   299 		if(r==KErrNone)
   300 			kumemput(a1, iHwChunkLinAddrs, sizeof(iHwChunkLinAddrs));
   301 		return r;
   302 		}
   303 	return DLogicalChannel::Request(aFunc, a1, a2);
   304 	}
   305 
   306 void DIpcCpy::HandleMsg(TMessageBase* aMsg)
   307 	{
   308 	TInt r=KErrNone;
   309 	TThreadMessage& m=*(TThreadMessage*)aMsg;
   310 	TInt id=m.iValue;
   311 	if (id==(TInt)ECloseMsg)
   312 		{
   313 		iTimer.Cancel();
   314 		iDfc.Cancel();
   315 		m.Complete(KErrNone,EFalse);
   316 		iMsgQ.CompleteAll(KErrServerTerminated);
   317 		return;
   318 		}
   319 	else if (id<0)
   320 		{
   321 		TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
   322 		if (iAsyncRequest->SetStatus(pS) != KErrNone)
   323 			Kern::ThreadKill(iThread,EExitPanic,ERequestAlreadyPending,KDIpcCpyPanicCategory);
   324 
   325 		if (id==~RIpcCpy::ERequestIpcCpy)
   326 			{
   327 			iDest=m.Ptr1();
   328 			iTimer.OneShot(1);
   329 			}
   330 		else
   331 			{
   332 			r=KErrNotSupported;
   333 			}
   334 
   335 		if(r!=KErrNone)
   336 			{
   337 			Kern::QueueRequestComplete(iThread, iAsyncRequest, r);
   338 			r = KErrNone;
   339 			}
   340 		}
   341 	else
   342 		{
   343 		r=KErrNotSupported;
   344 		}
   345 
   346 	m.Complete(r,ETrue);
   347 	}
   348 
   349 void DIpcCpy::TimerExpired()
   350 	{
   351 	TInt src_offset=iSeqNum&3;
   352 	TInt dest_offset=(iSeqNum>>2)&3;
   353 	TInt length=(iSeqNum>>4)+1;
   354 	TInt i;
   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);
   359 	if (r==KErrNone)
   360 		{
   361 		r=iSeqNum;
   362 		if (++iSeqNum==4096)
   363 			iSeqNum=0;
   364 		}
   365 	Kern::QueueRequestComplete(iThread, iAsyncRequest, r);
   366 	}
   367