--- /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 <kernel/kern_priv.h>
+#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("<DSharedIoTestFactory::Create iGlobalBuffer=%x",iGlobalBuffer));
+ return KErrNone;
+ }
+
+TInt DSharedIoTestFactory::Install()
+ {
+ return SetName(&KSharedIoTestLddName);
+ }
+
+void DSharedIoTestFactory::GetCaps(TDes8& /* aDes */) const
+ {
+ //aDes.FillZ(aDes.MaxLength());
+ }
+
+DECLARE_STANDARD_LDD()
+ {
+ return new DSharedIoTestFactory;
+ }
+
+//
+// Logical Channel
+//
+
+TInt DSharedIoTest::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& /*aVer*/)
+ {
+ return KErrNone;
+ }
+
+DSharedIoTest::~DSharedIoTest()
+ {
+ delete iIoBuffer;
+ }
+
+TInt checkBuffer(TAny* buffer, TUint32 aSize, TUint32 key)
+ {
+ TInt r=KErrNone;
+ TUint8* m=(TUint8*)buffer;
+ for(TUint32 size=0;size<aSize;size++,key+=5,m++)
+ {
+ if(*m!=(TUint8)(key%256))
+ {
+ r=KErrCorrupt;
+ break;
+ }
+ }
+ return r;
+ }
+
+TInt fillBuffer(TAny* buffer, TUint32 aSize, TUint32 key)
+ {
+ TUint8* m=(TUint8*)buffer;
+ for(TUint32 size=0;size<aSize;size++,key+=5,m++)
+ {
+ *m=(TUint8)(key%256);
+ }
+ return KErrNone;
+ }
+
+static void AppendNumToBuf(TDes8& aDes, const TDesC& aNum, TInt width, char fill)
+{
+ TInt l = aNum.Length();
+ for (; l < width; ++l)
+ aDes.Append(TChar(fill));
+ aDes.Append(aNum);
+}
+
+static void DumpMemory(TUint8* aStart, TInt aSize)
+{
+ TBuf8<80> 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; i++)
+ {
+ if(aPtr[i] != 0x03)
+ {
+ Kern::Printf("CheckMemCleared(0x%x, %d) failed at i = 0x%x", aAddress, aSize, i);
+ // Start on current line & ~0xF, run for 16 lines x 16 bytes
+ TUint8 *p = (TUint8*)((aAddress + i) & ~0x0F);
+ TInt n = 256;
+
+ if (p < aPtr) p = aPtr;
+ if (p - aPtr > 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(p<end)
+ {
+ *p++ = ua;
+ ua = (TAny*)((TInt)ua+sizeof(TAny*));
+ }
+ if(iIoBuffer->UserToKernel(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<TInt> 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;
+ }
+