diff -r 000000000000 -r a41df078684a kerneltest/e32test/mmu/d_sharedio.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/mmu/d_sharedio.cpp Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,573 @@ +// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// e32test\mmu\d_sharedio.cpp +// LDD for testing SharedIoBuffers +// +// + +#include +#include "d_sharedio.h" + +// +// LDD factory +// + +class DSharedIoTestFactory : public DLogicalDevice + { +public: + DSharedIoTestFactory(); + ~DSharedIoTestFactory(); + virtual TInt Install(); + virtual void GetCaps(TDes8& aDes) const; + virtual TInt Create(DLogicalChannelBase*& aChannel); +public: + DSharedIoBuffer* iGlobalBuffer; + }; + +// +// Logical Channel +// + +class DSharedIoTest : public DLogicalChannelBase + { +public: + virtual ~DSharedIoTest(); +protected: + virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer); + virtual TInt Request(TInt aFunction, TAny* a1, TAny* a2); +public: + DSharedIoBuffer* iIoBuffer; + DSharedIoBuffer* iGlobalBuffer; + DSharedIoTestFactory* iFactory; +#ifndef __WINS__ + TPhysAddr iPhysAddress; +#endif + }; + +// +// LDD factory +// + +DSharedIoTestFactory::DSharedIoTestFactory() + { + iGlobalBuffer=NULL; + } + +DSharedIoTestFactory::~DSharedIoTestFactory() + { + delete iGlobalBuffer; + } +TInt DSharedIoTestFactory::Create(DLogicalChannelBase*& aChannel) + { + __KTRACE_OPT(KMMU,Kern::Printf(">DSharedIoTestFactory::Create iGlobalBuffer=%x",iGlobalBuffer)); + if(!iGlobalBuffer) + { +#ifdef __WINS__ + TUint aAttribs=0; +#else + TUint aAttribs=EMapAttrSupRw | EMapAttrFullyBlocking; +#endif + TInt r=DSharedIoBuffer::New(iGlobalBuffer,KSizeGlobalBuffer,aAttribs); + if(r!=KErrNone) + return r; + } + aChannel=new DSharedIoTest; + if(!aChannel) + return KErrNoMemory; + ((DSharedIoTest*)aChannel)->iGlobalBuffer=iGlobalBuffer; + ((DSharedIoTest*)aChannel)->iFactory=this; + __KTRACE_OPT(KMMU,Kern::Printf(" line; + TBuf8<24> val; + TChar space(' '); + + TInt i = (TInt)aStart & 0xF; // first byte in this line to dump + TInt n = 16; // end byte in this line + + while (aSize > 0) + { + if (i + aSize < 16) + n = i + aSize; + + val.Num((TUint32)aStart & ~0xF, EHex); + AppendNumToBuf(line, val, 8, '0'); + line.Append(space); + line.Append(space); + + TInt j; + + for (j = 0; j < i; ++j) + { + line.Append(space); + line.Append(space); + line.Append(space); + + if (j == 7) line.Append(space); + } + + for (; j < n; ++j) + { + val.Num(aStart[j-i], EHex); + line.Append(space); + AppendNumToBuf(line, val, 2, '0'); + + if (j == 7) line.Append(space); + } + + for (; j < 16; ++j) + { + line.Append(space); + line.Append(space); + line.Append(space); + + if (j == 7) line.Append(space); + } + + line.Append(space); + line.Append(space); + + for (j = 0; j < i; ++j) + line.Append(space); + + for (; j < n; ++j) + { + char c = aStart[j-i]; + if (c < ' ' || c > 126) c = '.'; + line.Append(TChar(c)); + } + + Kern::Printf("%S", &line); + + line.SetLength(0); + + aStart += (n - i); + aSize -= (n - i); + + i = 0; + } +} + +TBool CheckMemCleared(TLinAddr aAddress, TInt aSize) +{ + TUint8* aPtr = (TUint8*)aAddress; + for(TInt i = 0; i aSize - n) // if (p + n > aPtr + aSize) rearranged (to avoid overflow) + n = aPtr + aSize - p; + + DumpMemory(p, n); + return EFalse; + } + } + return ETrue; +} + +TInt DSharedIoTest::Request(TInt aFunction, TAny* a1, TAny* a2) + { + TInt r=KErrNone; + switch (aFunction) + { + case RTestLdd::ECreateBuffer: + { + TUint32 size = (TUint32)a1; + r = KErrNoMemory; +#ifdef __WINS__ + TUint aAttribs1=0; + TUint aAttribs2=0; + TUint aAttribs3=0; +#else + TUint aAttribs1=EMapAttrSupRw | EMapAttrBufferedNC; + TUint aAttribs2=EMapAttrSupRw | EMapAttrFullyBlocking; + TUint aAttribs3=EMapAttrSupRw | EMapAttrCachedMax; +#endif + NKern::ThreadEnterCS(); + r=DSharedIoBuffer::New(iIoBuffer,size,aAttribs1); + if(r!=KErrNone) + { + Kern::Printf("Error creating buffer r=%d\n",r); + NKern::ThreadLeaveCS(); + return r; + } + + //Check the buffer is properly initialized (the previous content + //deleted by inserting all 0x03s) + if (!CheckMemCleared(iIoBuffer->iAddress, iIoBuffer->iSize)) + { + Kern::Printf("Error memory zeroing test for shared io buffers"); + NKern::ThreadLeaveCS(); + return KErrCorrupt; + } + + //just test that we can construct a second shared buffer + DSharedIoBuffer* ptr; + r=DSharedIoBuffer::New(ptr,size,aAttribs2); + if(r!=KErrNone) + { + Kern::Printf("Error creating the 2nd buffer r=%d\n",r); + delete iIoBuffer; + iIoBuffer=NULL; + NKern::ThreadLeaveCS(); + return r; + } + delete ptr; //creation successfull, simply delete the object + + // and the third one, this time fully cached. + r=DSharedIoBuffer::New(ptr,size,aAttribs3); + if(r!=KErrNone) + { + Kern::Printf("Error creating the 3rd buffer r=%d\n",r); + delete iIoBuffer; + iIoBuffer=NULL; + NKern::ThreadLeaveCS(); + return r; + } + delete ptr; //creation successfull, simply delete the object + + NKern::ThreadLeaveCS(); + if(iIoBuffer->iSize!=size) // test + { + Kern::Printf("Error checking size iIoBuffer->iSize=%d size=%d\n",iIoBuffer->iSize,size); + return KErrGeneral; + } + memset((void*)iIoBuffer->iAddress,0,size); + } + return r; + + case RTestLdd::EMapInGlobalBuffer: + { + if(!iGlobalBuffer) + return KErrGeneral; + + TUint id; + kumemget32(&id,a1,sizeof(TUint)); + + NKern::ThreadEnterCS(); + Kern::Containers()[EProcess]->Wait(); + DProcess* process=Kern::ProcessFromId(id); + if(process) + process->Open(); + Kern::Containers()[EProcess]->Signal(); + if(process) + { + r=iGlobalBuffer->UserMap(process); + process->Close(0); + } + else + r = KErrGeneral; + NKern::ThreadLeaveCS(); + + if(r!=KErrNone) + return r; + + if(iGlobalBuffer->UserToKernel(iGlobalBuffer->iUserAddress,iGlobalBuffer->iSize)!=iGlobalBuffer->iAddress) + return KErrGeneral; + + if(iGlobalBuffer->UserToKernel(iGlobalBuffer->iUserAddress,iGlobalBuffer->iSize+1)!=NULL) + return KErrGeneral; + + if(iGlobalBuffer->KernelToUser(iGlobalBuffer->iAddress)!=iGlobalBuffer->iUserAddress) + return KErrGeneral; + + kumemput32(a1,&iGlobalBuffer->iUserAddress,sizeof(TAny*)); + kumemput32(a2,&iGlobalBuffer->iSize,sizeof(TInt)); + + return KErrNone; + } + + case RTestLdd::EMapOutGlobalBuffer: + { + if(!iGlobalBuffer) + return KErrGeneral; + r=iGlobalBuffer->UserUnmap(); + if(r==KErrNone) + if(iGlobalBuffer->iUserProcess) + r = KErrGeneral; + return r; + } + + case RTestLdd::EDestroyGlobalBuffer: + { + NKern::ThreadEnterCS(); + delete iGlobalBuffer; + iGlobalBuffer = NULL; + iFactory->iGlobalBuffer=NULL; + NKern::ThreadLeaveCS(); + return KErrNone; + } + + case RTestLdd::ECreateBufferPhysAddr: + { +#ifdef __WINS__ + return KErrNotSupported; +#else + TUint32 size=Kern::RoundToPageSize(1); + NKern::ThreadEnterCS(); + r=Epoc::AllocPhysicalRam(size,iPhysAddress); + Kern::Printf("phys addr = %X!\n",iPhysAddress); + if(r!=KErrNone) + { + NKern::ThreadLeaveCS(); + return r; + } + r = KErrNoMemory; + + //test that we can construct a fully cached sharedio + DSharedIoBuffer* ptr; + r=DSharedIoBuffer::New(ptr,iPhysAddress,size,EMapAttrSupRw|EMapAttrCachedMax); + if(r!=KErrNone) + { + Kern::Printf("Error creating the physical cached buffer r=%d\n",r); + Epoc::FreePhysicalRam(iPhysAddress,size); + iPhysAddress=0; + NKern::ThreadLeaveCS(); + return r; + } + delete ptr; //creation successfull, simply delete the object + + + r=DSharedIoBuffer::New(iIoBuffer,iPhysAddress,size,EMapAttrSupRw|EMapAttrFullyBlocking); + if(r!=KErrNone) + { + Epoc::FreePhysicalRam(iPhysAddress,size); + iPhysAddress=0; + NKern::ThreadLeaveCS(); + return r; + } + + if(iIoBuffer->iSize!=size) // test + { + delete iIoBuffer; + iIoBuffer=NULL; + Epoc::FreePhysicalRam(iPhysAddress,size); + iPhysAddress=0; + NKern::ThreadLeaveCS(); + return KErrGeneral; + } + + fillBuffer((TAny*)iIoBuffer->iAddress,size,180); + + DPlatChunkHw* hwChunk; + r=DPlatChunkHw::New(hwChunk, iPhysAddress, size, EMapAttrSupRw|EMapAttrFullyBlocking); + if(r!=KErrNone) + { + delete iIoBuffer; + iIoBuffer=NULL; + Epoc::FreePhysicalRam(iPhysAddress,size); + iPhysAddress=0; + NKern::ThreadLeaveCS(); + return r; + } + + r=checkBuffer((TAny*)hwChunk->LinearAddress(),size,180); + if(r!=KErrNone) + { + delete iIoBuffer; + iIoBuffer=NULL; + hwChunk->Close(NULL); + Epoc::FreePhysicalRam(iPhysAddress,size); + iPhysAddress=0; + NKern::ThreadLeaveCS(); + return r; + } + + hwChunk->Close(NULL); + NKern::ThreadLeaveCS(); + return r; +#endif + } + + case RTestLdd::EDestroyBufferPhysAddr: + { +#ifdef __WINS__ + return KErrNotSupported; +#else + TUint32 size=Kern::RoundToPageSize(1); + NKern::ThreadEnterCS(); + delete iIoBuffer; + iIoBuffer = NULL; + r=Epoc::FreePhysicalRam(iPhysAddress,size); + iPhysAddress=0; + NKern::ThreadLeaveCS(); + return r; +#endif + } + + + case RTestLdd::EMapInBuffer: + { + r=iIoBuffer->UserMap(&Kern::CurrentProcess()); + if(r!=KErrNone) + return r; + + TAny** p = (TAny**)iIoBuffer->iAddress; + TAny* ua = (TAny*)iIoBuffer->iUserAddress; + TAny** end = (TAny**)((TInt)p+iIoBuffer->iSize); + while(pUserToKernel(iIoBuffer->iUserAddress,iIoBuffer->iSize)!=iIoBuffer->iAddress) + return KErrGeneral; + + if(iIoBuffer->UserToKernel(iIoBuffer->iUserAddress,iIoBuffer->iSize+1)!=NULL) + return KErrGeneral; + + if(iIoBuffer->KernelToUser(iIoBuffer->iAddress)!=iIoBuffer->iUserAddress) + return KErrGeneral; + kumemput32(a1,&iIoBuffer->iUserAddress,sizeof(TAny*)); + kumemput32(a2,&iIoBuffer->iSize,sizeof(TInt)); + return r; + } + + case RTestLdd::EMapOutBuffer: + { + r=iIoBuffer->UserUnmap(); + if(r==KErrNone) + if(iIoBuffer->iUserProcess) + r = KErrGeneral; + return r; + } + + case RTestLdd::EDestroyBuffer: + NKern::ThreadEnterCS(); + delete iIoBuffer; + iIoBuffer = NULL; + NKern::ThreadLeaveCS(); + return KErrNone; + + case RTestLdd::ECheckBuffer: + if(!iIoBuffer->iAddress || !iIoBuffer->iUserAddress || !iIoBuffer->iUserProcess) + return KErrGeneral; + return checkBuffer((TAny*)iIoBuffer->iAddress,iIoBuffer->iSize,(TUint32)a1); + + case RTestLdd::EFillBuffer: + if(!iIoBuffer->iAddress || !iIoBuffer->iUserAddress || !iIoBuffer->iUserProcess) + return KErrGeneral; + return fillBuffer((TAny*)iIoBuffer->iAddress,iIoBuffer->iSize,(TUint32)a1); + + case RTestLdd::EThreadRW: + { + TInt dummy; + TPckg a(dummy); + DThread* pT; + if((TInt)a2==-1) + { + pT=&Kern::CurrentThread(); + } + else + { + NKern::ThreadEnterCS(); + DObjectCon* pC=Kern::Containers()[EThread]; + pC->Wait(); + pT=Kern::ThreadFromId((TInt)a2); + pC->Signal(); + if(!pT) + return KErrNotFound; + NKern::ThreadLeaveCS(); + } + r=Kern::ThreadDesRead(pT,a1,a,0,KChunkShiftBy0); + if(r!=KErrNone) + return r; + if(dummy!=KMagic1) + return KErrCorrupt; + dummy=KMagic2; + r=Kern::ThreadDesWrite(pT,a1,a,0,KChunkShiftBy0,&Kern::CurrentThread()); + if(r!=KErrNone) + return r; + return KErrNone; + } + + default: + r=KErrNotSupported; + break; + } + return r; + } +