diff -r f497542af8e4 -r 538db54a451d kerneltest/e32test/dmav2/d_dma2.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/dmav2/d_dma2.h Mon Jan 18 21:31:10 2010 +0200 @@ -0,0 +1,572 @@ +// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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\dmav2\d_dma2.h +// User-side API for LDD used to test DMAv2 framework. +// +// + +#ifndef __D_DMA2_H__ +#define __D_DMA2_H__ + +#include +#include + + +#define ARRAY_LENGTH(ARRAY) sizeof(ARRAY)/sizeof(ARRAY[0]) + +#ifdef __KERNEL_MODE__ + #include + #include + #define TEST_FAULT FAULT(); + #define PRINT(N) Kern::Printf("%s = 0x%08x (%d)", #N, (N), (N)) +#else + #include + #include + #define TEST_FAULT RDebug::Printf("Assertion failure in %s, %d", __FILE__, __LINE__); User::Invariant() + #define PRINT(N) RDebug::Printf("%s = 0x%08x (%d)", #N, (N), (N)) +#endif + +#define TEST_ASSERT(C) if(!(C)) {TEST_FAULT;} + +const TUint KPhysAddrInvalidUser=0xFFFFFFFFu; // KPhysAddrInvalid is not defined on the user side +#ifdef __KERNEL_MODE__ +//if this fails then KPhysAddrInvalidUser must be updated to match +//KPhysAddrInvalid +__ASSERT_COMPILE(KPhysAddrInvalidUser == KPhysAddrInvalid); +#endif + + +_LIT(KTestDmaLddName, "TestDmaV2"); + +inline TVersion TestDmaLddVersion() { return TVersion(1, 0, 1); } + +TInt Log2(TInt aNum); + +/** +Indicates the number of each type of call back received +and their context + +TODO as yet, it does not indicate the context of each callback, only +the final one +*/ +const TInt KNumberOfCallbacks = 12; + +class TCallbackRecord + { +public: + enum TCbContext + { EInvalid, EThread, EIsr }; + + TCallbackRecord( + TCbContext aContext = EThread, + TInt aReq = 0, + TInt aReqSrc = 0, + TInt aReqDst = 0, + + TInt aDes = 0, + TInt aDesSrc = 0, + TInt aDesDst = 0, + + TInt aFrame = 0, + TInt aFrameSrc = 0, + TInt aFrameDst = 0, + + TInt aPause = 0, + TInt aPauseSrc = 0, + TInt aPauseDst = 0, + TDmaResult aResult = EDmaResultOK + ); + + static TCallbackRecord Empty(); + + void Reset(); + + /** + Allows 2 callback records to be compared + */ + TBool operator == (const TCallbackRecord aOther) const; + void Print() const; + + /** + Get the number of callbacks for callback aCbType + */ + TInt GetCount(TDmaCallbackType aCbType) const; + + void SetCount(TDmaCallbackType aCbType, TInt aCount); + + /** + Set the result (expected or actual) from + TDmaChannel::IsrRedoRequest + */ + inline TCallbackRecord& IsrRedoResult(TInt aResult) {iIsrRedoRequestResult = aResult; return *this;} + + /** + Reports the context in which the callback occurred. + */ + inline TCbContext GetContext() + {return iContext;} + + /** + Updates data based on callback mask aCallbackMask + @param aCallbackMask Bitmask of callback events @see TDmaCallbackType + @oaram aResult The result reported by the current callback + */ + void ProcessCallback(TUint aCallbackMask, TDmaResult aResultaContext); + + static void SelfTest(); + + // The below methods are setters, which may be chained together + // ie. The Named Parameter Idiom + // @see http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.18 + TCallbackRecord& Context(TCbContext aContext) {iContext = aContext; return *this;} + +private: + TInt BitToIndex(TDmaCallbackType aCbType) const; + + TCbContext CurrentContext() const; + + TInt iCallbackLog[KNumberOfCallbacks]; + + TDmaResult iResult; + TCbContext iContext; + /** Result of the most recent redo request call */ + TInt iIsrRedoRequestResult; + }; + +/** +Extends SDmacCaps to contain the DMA PIL +version being used +*/ +struct TDmacTestCaps : public SDmacCaps + { + TDmacTestCaps(); + TDmacTestCaps(const SDmacCaps& aDmacCaps, TInt aVersion = 2); + + TInt iPILVersion; + }; + + +class TDmaChannel; + +struct TAddrRange + { + TAddrRange(TUint aStart, TUint aLength); + inline TUint End() const {return (iStart + iLength -1);} + inline TUint Start() const {return iStart;} + + inline TBool Contains(TUint aValue) const {return Rng(iStart, aValue, End());} + TBool Contains(TAddrRange aRange) const; + + TBool Overlaps(const TAddrRange& aRange) const; + static void SelfTest(); + +private: + TUint iStart; + TUint iLength; + }; + + +struct TAddressParms + { + TAddressParms(TUint32 aSrcAddr=0, TUint32 aDstAddr=0, TUint aTransferCount=0) + :iSrcAddr(aSrcAddr), iDstAddr(aDstAddr), iTransferCount(aTransferCount) + {} + + TAddressParms(const TDmaTransferArgs& aArgs) + :iSrcAddr(aArgs.iSrcConfig.iAddr), + iDstAddr(aArgs.iDstConfig.iAddr), + iTransferCount(aArgs.iTransferCount) + {} + + /** + If any src, dst, or transfer count are zero, substitute the values from + aTransferArgs in their place + */ + void Substitute(const TDmaTransferArgs& aTransferArgs); + + /** + When recieved by the test driver, src and dst + addresses will be offsets from the dma test session's + chunk base. They must be converted to absolute, *physical* addresses + */ + void Fixup(TLinAddr aChunkBase); + + /** + Check that both the src and destination lie within the area + defined by aStart and aSize + */ + TBool CheckRange(TLinAddr aStart, TUint aSize); + + TAddrRange SourceRange() const; + TAddrRange DestRange() const; + + TBool Overlaps(const TAddrRange aRange) const; + TBool Overlaps(const TAddressParms aParm) const; + + TBool operator==(const TAddressParms& aOther) const; + + static void SelfTest(); + + TUint32 iSrcAddr; + TUint32 iDstAddr; + TUint iTransferCount; + }; + +// These functions can be used for accessing TDmaTransferArgs in +// terms of TAddressParms. (TAddressParms would be a natural base +// class for TDmaTransferArgs but changing the production code +// is undesirable) +TAddressParms GetAddrParms(const TDmaTransferArgs&); +void SetAddrParms(TDmaTransferArgs&, const TAddressParms&); + +/** +This struct holds the arguments which can be used with TDmaChannel::IsrRedoRequest +*/ +struct TIsrRequeArgs : public TAddressParms + { + TIsrRequeArgs(TUint32 aSrcAddr=KPhysAddrInvalidUser, TUint32 aDstAddr=KPhysAddrInvalidUser, + TUint aTransferCount=0, TUint32 aPslRequestInfo=0, + TBool aIsrCb=ETrue) + : TAddressParms(aSrcAddr, aDstAddr, aTransferCount), iPslRequestInfo(aPslRequestInfo), iIsrCb(aIsrCb) + {} + + + TInt Call(TDmaChannel& aChannel); + + TBool CheckRange(TLinAddr aStart, TUint aSize) const; + + TUint32 iPslRequestInfo; + TBool iIsrCb; + }; +class CISrRequeTest; +/** +A collection of TIsrRequeArgs +*/ +struct TIsrRequeArgsSet + { + + friend class CIsrRequeTest; //TODO see line 394 t_dma2.cpp + TIsrRequeArgsSet(TIsrRequeArgs* aRequeueArgs=NULL, TInt aCount =0) + :iCount(aCount), iIndex(0) + { + TEST_ASSERT(iCount <= MaxCount); + for(TInt i=0; i(aDriverCookie), &aQueueEmpty); + } + + TInt ChannelIsOpened(TUint aDriverCookie,TBool &aChannelOpen) + { + return DoControl(EIsOpened, reinterpret_cast(aDriverCookie), &aChannelOpen); + } + + TInt ChannelIsrRedoRequest(TUint aDriverCookie,TUint32 aSrcAddr,TUint32 aDstAddr,TInt aTransferCount,TUint32 aPslRequestInfo,TBool aIsrCb) + { + TIsrRedoReqArgs args(aDriverCookie,aSrcAddr,aDstAddr,aTransferCount,aPslRequestInfo,aIsrCb); + TPckgC package(args); + return DoControl(EIsrRedoRequest,&package); + } + + TInt ChannelCancelAll(TUint aDriverCookie) + { + return DoControl(ECancelAllChannel, reinterpret_cast(aDriverCookie)); + } + + TInt ChannelOpen(TUint aPslCookie, TUint& aDriverCookie) + { + return DoControl(EOpenChannel, reinterpret_cast(aPslCookie), &aDriverCookie); + } + + TInt ChannelClose(TUint aDriverCookie) + { + return DoControl(ECloseChannel, reinterpret_cast(aDriverCookie)); + } + + TInt ChannelPause(TUint aDriverCookie) + { + return DoControl(EPauseChannel, reinterpret_cast(aDriverCookie)); + } + + TInt ChannelResume(TUint aDriverCookie) + { + return DoControl(EResumeChannel, reinterpret_cast(aDriverCookie)); + } + + TInt ChannelCaps(TUint aDriverCookie, SDmacCaps& aChannelCaps) + { + TDmacTestCaps caps; + TInt r = ChannelCaps(aDriverCookie, caps); + aChannelCaps = caps; + return r; + } + + TInt ChannelCaps(TUint aDriverCookie, TDmacTestCaps& aChannelCaps) + { + TPckg package(aChannelCaps); + return DoControl(EChannelCaps, reinterpret_cast(aDriverCookie), &package); + } + + TInt Open() + {// TO DO: Add Info , this class is just to test the opening of channels + //TPckgBuf infoBuf; + //infoBuf().iWhat = TOpenInfo::EOpen; + //infoBuf().U.iOpen.iId = aId; + //infoBuf().U.iOpen.iDesCount = aDesCount; + //infoBuf().U.iOpen.iMaxTransferSize = aMaxTransferSize; + return DoCreate(KTestDmaLddName,TestDmaLddVersion(), 0, NULL, NULL, EOwnerThread); + } + + //TODO rename this (append "old") + TInt RequestCreate(TUint aChannelCookie, TUint& aRequestCookie, TUint aMaxTransferSize=0) + { + return DoRequestCreate(aChannelCookie, EFalse, aMaxTransferSize, aRequestCookie); + } + + //TODO rename this (get rid of "new" + TInt RequestCreateNew(TUint aChannelCookie, TUint& aRequestCookie, TUint aMaxTransferSize=0) + { + return DoRequestCreate(aChannelCookie, ETrue, aMaxTransferSize, aRequestCookie); + } + + TInt RequestDestroy(TUint aRequestCookie) + { + return DoControl(ERequestClose, reinterpret_cast(aRequestCookie)); + } + + TInt RequestFragmentCount(TUint aRequestCookie) + { + return DoControl(EFragmentCount, reinterpret_cast(aRequestCookie)); + } + + /** + Will fragment a DMA request using the legacy API + */ + TInt FragmentRequestOld(TUint aRequestCookie, const TDmaTransferArgs& aTransferArgs, TUint64* aDurationMicroSecs=NULL) + { + const TFragmentArgs args(aRequestCookie, aTransferArgs, aDurationMicroSecs); + TPckgC package(args); + return DoControl(EFragmentLegacy, &package); + } + + /** + Will fragment a DMA request using the new API + */ + TInt FragmentRequest(TUint aRequestCookie, const TDmaTransferArgs& aTransferArgs, TUint64* aDurationMicroSecs=NULL) + { + const TFragmentArgs args(aRequestCookie, aTransferArgs, aDurationMicroSecs); + TPckgC package(args); + return DoControl(EFragment, &package); + } + + TInt QueueRequest(TUint aRequestCookie, TRequestStatus& aStatus, TCallbackRecord* aRecord = NULL, TUint64* aDurationMicroSecs=NULL) + { + //These dummy values can accept the writeback from the driver + //if the client does not want them. + //(TClientDataRequest can not be programmed with a NULL to + //indicate that an argument is unwanted) + TCallbackRecord dummyRec; + TUint64 dummyTime=0; + + TQueueArgs args(aRequestCookie, &aStatus, aRecord ? aRecord : &dummyRec, aDurationMicroSecs ? aDurationMicroSecs : &dummyTime); + TPckgC package(args); + return DoControl(EQueueRequest, &package); + } + + /** + Synchronous version of QueueRequest + */ + TInt QueueRequest(TUint aRequestCookie, TCallbackRecord* aRecord = NULL, TUint64* aDurationMicroSecs=NULL) + { + TRequestStatus status; + TInt r = QueueRequest(aRequestCookie, status, aRecord, aDurationMicroSecs); + User::WaitForRequest(status); + return r; + } + + /** + Queue a previously fragmented request. + Additional request parameters are included in iRequeueArgs, these will be + transferred from ISR context callback using the TDmaChannel::IsrRedoRequest function + + @pre Isr callback for completion must have been requested at request fragmentation time + */ + TInt QueueRequestWithRequeue(TUint aRequestCookie, TIsrRequeArgs* aRequeueArgs, TInt aCount, TRequestStatus& aStatus, TCallbackRecord* aRecord = NULL, TUint64* aDurationMicroSecs=NULL) + { + //These dummy values can accept the writeback from the driver + //if the client does not want them. + //(TClientDataRequest can not be programmed with a NULL to + //indicate that an argument is unwanted) + TCallbackRecord dummyRec; + TUint64 dummyTime=0; + + TQueueArgsWithReque args(aRequeueArgs, aCount, aRequestCookie, &aStatus, aRecord ? aRecord : &dummyRec, aDurationMicroSecs ? aDurationMicroSecs : &dummyTime); + TPckgC package(args); + return DoControl(EQueueRequestWithReque, &package); + } + + /** + Synchronous version of QueueRequestWithRequeue + */ + TInt QueueRequestWithRequeue(TUint aRequestCookie, TIsrRequeArgs* aRequeueArgs, TInt aCount, TCallbackRecord* aRecord = NULL, TUint64* aDurationMicroSecs=NULL) + { + TRequestStatus status; + TInt r = QueueRequestWithRequeue(aRequestCookie, aRequeueArgs, aCount, status, aRecord, aDurationMicroSecs); + User::WaitForRequest(status); + return r; + } + + TInt OpenSharedChunk(RChunk& aChunk) + { + TUint chunkHandle = DoControl(EOpenSharedChunk); + return aChunk.SetReturnedHandle(chunkHandle); + } + + TInt GetTestInfo(TDmaV2TestInfo& aInfo) + { + TPckg package(aInfo); + return DoControl(EGetTestInfo, &package); + } + + static void SelfTest(); + + static void ApiTest(); +#endif // __KERNEL_MODE__ + +private: + + TInt DoRequestCreate(TUint aChannelCookie, TBool aNewStyle, TUint aMaxTransferSize, TUint& aRequestCookie) + { + TRequestCreateArgs args(aChannelCookie, aNewStyle, aMaxTransferSize); + TPckgC package(args); + return DoControl(ERequestOpen, &package, &aRequestCookie); + } + + + struct TRequestCreateArgs + { + TRequestCreateArgs(TUint aChannelCookie, TBool aNewStyle, TUint aMaxFragmentSize) + :iChannelCookie(aChannelCookie), iNewStyle(aNewStyle), iMaxFragmentSize(aMaxFragmentSize) + {} + + TUint iChannelCookie; + TBool iNewStyle; + TUint iMaxFragmentSize; + }; + + struct TFragmentArgs + { + TFragmentArgs() + :iRequestCookie(0), iTransferArgs(), iDurationMicroSecs(NULL) + {} + TFragmentArgs(TUint aRequestCookie, const TDmaTransferArgs& aTransferArgs, TUint64* aDurationMicroSecs = NULL) + :iRequestCookie(aRequestCookie), iTransferArgs(aTransferArgs), iDurationMicroSecs(aDurationMicroSecs) + {} + + const TUint iRequestCookie; + const TDmaTransferArgs iTransferArgs; + TUint64* const iDurationMicroSecs; + }; + + struct TQueueArgs + { + TQueueArgs(TUint aRequestCookie=0, TRequestStatus* aStatus=NULL, TCallbackRecord* aCallbackRecord=NULL, TUint64* aDurationMicroSecs=NULL) + :iRequestCookie(aRequestCookie), iStatus(aStatus), iCallbackRecord(aCallbackRecord), iDurationMicroSecs(aDurationMicroSecs) + {} + TUint iRequestCookie; + TRequestStatus* iStatus; + TCallbackRecord* iCallbackRecord; + TUint64* iDurationMicroSecs; + }; + + struct TIsrRedoReqArgs + { + TIsrRedoReqArgs(TUint aDriverCookie=0,TUint32 aSrcAddr=0, TUint32 aDstAddr=0, TInt aTransferCount=0, TUint32 aPslRequestInfo=0,TBool aIsrCb=ETrue) + :iDriverCookie(aDriverCookie),iSrcAddr(aSrcAddr),iDstAddr(aDstAddr),iTransferCount(aTransferCount),iPslRequestInfo(aPslRequestInfo),iIsrCb(aIsrCb) + {} + TUint iDriverCookie; + TUint32 iSrcAddr; + TUint32 iDstAddr; + TInt iTransferCount; + TUint32 iPslRequestInfo; + TBool iIsrCb; + }; + + /** + This struct is used for queing and including a set of transfers + to be setup from ISR context callback + */ + struct TQueueArgsWithReque : public TQueueArgs + { + TQueueArgsWithReque(TIsrRequeArgs* aRequeueArgs=NULL, TInt aCount=0, + TUint aRequestCookie=0, TRequestStatus* aStatus=NULL, TCallbackRecord* aCallbackRecord=NULL, TUint64* aDurationMicroSecs=NULL) + :TQueueArgs(aRequestCookie, aStatus, aCallbackRecord, aDurationMicroSecs), iRequeSet(aRequeueArgs, aCount) + { + } + + TIsrRequeArgsSet iRequeSet; + }; + + + enum TControl + { + EOpenChannel, + ECloseChannel, + EPauseChannel, + EResumeChannel, + EChannelCaps, + ERequestOpen, + ERequestClose, + EOpenSharedChunk, + EFragmentLegacy, + EFragment, + EFragmentCount, + EQueueRequest, + EGetTestInfo, + EIsQueueEmpty, + EIsOpened, + EIsrRedoRequest, + ECancelAllChannel, + EQueueRequestWithReque + }; + }; +#endif // __D_DMA2_H__