0
|
1 |
// Copyright (c) 2002-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\dma\d_dma.cpp
|
|
15 |
//
|
|
16 |
//
|
|
17 |
|
|
18 |
#include "platform.h"
|
|
19 |
#include <kernel/kern_priv.h>
|
|
20 |
#include <drivers/dma.h>
|
|
21 |
#include "d_dma.h"
|
|
22 |
|
|
23 |
_LIT(KClientPanicCat, "D_DMA");
|
|
24 |
_LIT(KDFCThreadName,"D_DMA_DFC_THREAD");
|
|
25 |
const TInt KDFCThreadPriority=26;
|
|
26 |
|
|
27 |
//////////////////////////////////////////////////////////////////////////////
|
|
28 |
|
|
29 |
//
|
|
30 |
// Class abstracting the way DMA buffers are created and destroyed to
|
|
31 |
// allow tests to run both on WINS and hardware.
|
|
32 |
//
|
|
33 |
|
|
34 |
class TBufferMgr
|
|
35 |
{
|
|
36 |
public:
|
|
37 |
TInt Alloc(TInt aIdx, TInt aSize);
|
|
38 |
void FreeAll();
|
|
39 |
TUint8* Addr(TInt aIdx) const;
|
|
40 |
TPhysAddr PhysAddr(TInt aIdx) const;
|
|
41 |
TInt Size(TInt aIdx) const;
|
|
42 |
enum { KMaxBuf = 8 };
|
|
43 |
private:
|
|
44 |
#ifdef __WINS__
|
|
45 |
struct {TUint8* iPtr; TInt iSize;} iBufs[KMaxBuf];
|
|
46 |
#else
|
|
47 |
struct {DPlatChunkHw* iChunk; TInt iSize;} iBufs[KMaxBuf];
|
|
48 |
#endif
|
|
49 |
};
|
|
50 |
|
|
51 |
#ifdef __WINS__
|
|
52 |
|
|
53 |
TUint8* TBufferMgr::Addr(TInt aIdx) const
|
|
54 |
{
|
|
55 |
__ASSERT_DEBUG(0 <= aIdx && aIdx < KMaxBuf, Kern::PanicCurrentThread(KClientPanicCat, __LINE__));
|
|
56 |
__ASSERT_DEBUG(iBufs[aIdx].iPtr != NULL, Kern::PanicCurrentThread(KClientPanicCat, __LINE__));
|
|
57 |
return iBufs[aIdx].iPtr;
|
|
58 |
}
|
|
59 |
|
|
60 |
|
|
61 |
TInt TBufferMgr::Size(TInt aIdx) const
|
|
62 |
{
|
|
63 |
__ASSERT_DEBUG(0 <= aIdx && aIdx < KMaxBuf, Kern::PanicCurrentThread(KClientPanicCat, __LINE__));
|
|
64 |
__ASSERT_DEBUG(iBufs[aIdx].iPtr != NULL, Kern::PanicCurrentThread(KClientPanicCat, __LINE__));
|
|
65 |
return iBufs[aIdx].iSize;
|
|
66 |
}
|
|
67 |
|
|
68 |
|
|
69 |
TInt TBufferMgr::Alloc(TInt aIdx, TInt aSize)
|
|
70 |
{
|
|
71 |
__ASSERT_DEBUG(0 <= aIdx && aIdx < KMaxBuf, Kern::PanicCurrentThread(KClientPanicCat, __LINE__));
|
|
72 |
__ASSERT_DEBUG(iBufs[aIdx].iPtr == NULL, Kern::PanicCurrentThread(KClientPanicCat, __LINE__));
|
|
73 |
NKern::ThreadEnterCS();
|
|
74 |
iBufs[aIdx].iPtr = new TUint8[aSize];
|
|
75 |
NKern::ThreadLeaveCS();
|
|
76 |
iBufs[aIdx].iSize = aSize;
|
|
77 |
return iBufs[aIdx].iPtr ? KErrNone : KErrNoMemory;
|
|
78 |
}
|
|
79 |
|
|
80 |
|
|
81 |
void TBufferMgr::FreeAll()
|
|
82 |
{
|
|
83 |
NKern::ThreadEnterCS();
|
|
84 |
for (TInt i=0; i<KMaxBuf; ++i)
|
|
85 |
{
|
|
86 |
delete iBufs[i].iPtr;
|
|
87 |
iBufs[i].iPtr = NULL;
|
|
88 |
}
|
|
89 |
NKern::ThreadLeaveCS();
|
|
90 |
}
|
|
91 |
|
|
92 |
#else
|
|
93 |
|
|
94 |
TUint8* TBufferMgr::Addr(TInt aIdx) const
|
|
95 |
{
|
|
96 |
__ASSERT_DEBUG(0 <= aIdx && aIdx < KMaxBuf, Kern::PanicCurrentThread(KClientPanicCat, __LINE__));
|
|
97 |
__ASSERT_DEBUG(iBufs[aIdx].iChunk != NULL, Kern::PanicCurrentThread(KClientPanicCat, __LINE__));
|
|
98 |
return (TUint8*)iBufs[aIdx].iChunk->LinearAddress();
|
|
99 |
}
|
|
100 |
|
|
101 |
|
|
102 |
TPhysAddr TBufferMgr::PhysAddr(TInt aIdx) const
|
|
103 |
{
|
|
104 |
__ASSERT_DEBUG(0 <= aIdx && aIdx < KMaxBuf, Kern::PanicCurrentThread(KClientPanicCat, __LINE__));
|
|
105 |
__ASSERT_DEBUG(iBufs[aIdx].iChunk != NULL, Kern::PanicCurrentThread(KClientPanicCat, __LINE__));
|
|
106 |
return iBufs[aIdx].iChunk->PhysicalAddress();
|
|
107 |
}
|
|
108 |
|
|
109 |
|
|
110 |
TInt TBufferMgr::Size(TInt aIdx) const
|
|
111 |
{
|
|
112 |
__ASSERT_DEBUG(0 <= aIdx && aIdx < KMaxBuf, Kern::PanicCurrentThread(KClientPanicCat, __LINE__));
|
|
113 |
__ASSERT_DEBUG(iBufs[aIdx].iChunk != NULL, Kern::PanicCurrentThread(KClientPanicCat, __LINE__));
|
|
114 |
return iBufs[aIdx].iSize;
|
|
115 |
}
|
|
116 |
|
|
117 |
|
|
118 |
TInt TBufferMgr::Alloc(TInt aIdx, TInt aSize)
|
|
119 |
{
|
|
120 |
__ASSERT_DEBUG(0 <= aIdx && aIdx < KMaxBuf, Kern::PanicCurrentThread(KClientPanicCat, __LINE__));
|
|
121 |
__ASSERT_DEBUG(iBufs[aIdx].iChunk == NULL, Kern::PanicCurrentThread(KClientPanicCat, __LINE__));
|
|
122 |
NKern::ThreadEnterCS();
|
|
123 |
TPhysAddr phys;
|
|
124 |
TInt r = Epoc::AllocPhysicalRam(aSize, phys);
|
|
125 |
if (r == KErrNone)
|
|
126 |
{
|
|
127 |
r = DPlatChunkHw::New(iBufs[aIdx].iChunk, phys, aSize, EMapAttrSupRw | EMapAttrFullyBlocking);
|
|
128 |
if (r != KErrNone)
|
|
129 |
Epoc::FreePhysicalRam(phys, aSize);
|
|
130 |
iBufs[aIdx].iSize = aSize;
|
|
131 |
}
|
|
132 |
NKern::ThreadLeaveCS();
|
|
133 |
return r;
|
|
134 |
}
|
|
135 |
|
|
136 |
|
|
137 |
void TBufferMgr::FreeAll()
|
|
138 |
{
|
|
139 |
for (TInt i=0; i<KMaxBuf; ++i)
|
|
140 |
{
|
|
141 |
if (iBufs[i].iChunk)
|
|
142 |
{
|
|
143 |
TPhysAddr base = iBufs[i].iChunk->PhysicalAddress();
|
|
144 |
TInt size = iBufs[i].iSize;
|
|
145 |
__ASSERT_DEBUG(iBufs[i].iChunk->AccessCount() == 1,
|
|
146 |
Kern::PanicCurrentThread(KClientPanicCat, __LINE__));
|
|
147 |
NKern::ThreadEnterCS();
|
|
148 |
iBufs[i].iChunk->Close(NULL);
|
|
149 |
iBufs[i].iChunk = NULL;
|
|
150 |
Epoc::FreePhysicalRam(base, size);
|
|
151 |
NKern::ThreadLeaveCS();
|
|
152 |
}
|
|
153 |
}
|
|
154 |
}
|
|
155 |
|
|
156 |
#endif
|
|
157 |
|
|
158 |
static TInt FragmentCount(DDmaRequest* aRequest)
|
|
159 |
{
|
|
160 |
TInt count = 0;
|
|
161 |
for (SDmaDesHdr* pH = aRequest->iFirstHdr; pH != NULL; pH = pH->iNext)
|
|
162 |
count++;
|
|
163 |
return count;
|
|
164 |
}
|
|
165 |
|
|
166 |
//////////////////////////////////////////////////////////////////////////////
|
|
167 |
|
|
168 |
class DDmaTestChannel : public DLogicalChannelBase
|
|
169 |
{
|
|
170 |
public:
|
|
171 |
virtual ~DDmaTestChannel();
|
|
172 |
protected:
|
|
173 |
// from DLogicalChannelBase
|
|
174 |
virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer);
|
|
175 |
virtual TInt Request(TInt aFunction, TAny* a1, TAny* a2);
|
|
176 |
virtual TInt RequestUserHandle(DThread* aThread, TOwnerType aType);
|
|
177 |
private:
|
|
178 |
TInt Execute(const TDesC8& aDes);
|
|
179 |
static void Dfc(DDmaRequest::TResult aResult, TAny* aArg);
|
|
180 |
TInt DoGetInfo(TAny* aInfo);
|
|
181 |
private:
|
|
182 |
TUint32 iCookie;
|
|
183 |
TBufferMgr iBufMgr;
|
|
184 |
TDmaChannel* iChannel;
|
|
185 |
enum { KMaxRequests = 8 };
|
|
186 |
DDmaRequest* iRequests[KMaxRequests];
|
|
187 |
TClientRequest* iClientRequests[KMaxRequests];
|
|
188 |
DDmaTestChannel* iMap[KMaxRequests];
|
|
189 |
TUint32 iMemMemPslInfo;
|
|
190 |
DThread* iClient;
|
|
191 |
TDynamicDfcQue* iDfcQ;
|
|
192 |
};
|
|
193 |
|
|
194 |
|
|
195 |
TInt DDmaTestChannel::RequestUserHandle(DThread* aThread, TOwnerType aType)
|
|
196 |
{
|
|
197 |
if (aType!=EOwnerThread || aThread!=iClient)
|
|
198 |
return KErrAccessDenied;
|
|
199 |
return KErrNone;
|
|
200 |
}
|
|
201 |
|
|
202 |
TInt DDmaTestChannel::DoGetInfo(TAny* aInfo)
|
|
203 |
{
|
|
204 |
RTestDma::TInfo uinfo;
|
|
205 |
const TDmaTestInfo& kinfo = DmaTestInfo();
|
|
206 |
uinfo.iMaxTransferSize = kinfo.iMaxTransferSize;
|
|
207 |
uinfo.iMemAlignMask = kinfo.iMemAlignMask;
|
|
208 |
uinfo.iMaxSbChannels = kinfo.iMaxSbChannels;
|
|
209 |
memcpy(&(uinfo.iSbChannels), kinfo.iSbChannels, 4 * kinfo.iMaxSbChannels);
|
|
210 |
uinfo.iMaxDbChannels = kinfo.iMaxDbChannels;
|
|
211 |
memcpy(&(uinfo.iDbChannels), kinfo.iDbChannels, 4 * kinfo.iMaxDbChannels);
|
|
212 |
uinfo.iMaxSgChannels = kinfo.iMaxSgChannels;
|
|
213 |
memcpy(&(uinfo.iSgChannels), kinfo.iSgChannels, 4 * kinfo.iMaxSgChannels);
|
|
214 |
|
|
215 |
XTRAPD(r, XT_DEFAULT, kumemput(aInfo, &uinfo, sizeof(RTestDma::TInfo)));
|
|
216 |
return r == KErrNone ? KErrDied : KErrGeneral;
|
|
217 |
}
|
|
218 |
|
|
219 |
|
|
220 |
// called in thread critical section
|
|
221 |
TInt DDmaTestChannel::DoCreate(TInt /*aUnit*/, const TDesC8* aInfo, const TVersion& /*aVer*/)
|
|
222 |
{
|
|
223 |
TPckgBuf<RTestDma::TOpenInfo> infoBuf;
|
|
224 |
|
|
225 |
TInt r=Kern::ThreadDesRead(&Kern::CurrentThread(), aInfo, infoBuf, 0, KChunkShiftBy0);
|
|
226 |
if (r != KErrNone)
|
|
227 |
return r;
|
|
228 |
|
|
229 |
if (infoBuf().iWhat == RTestDma::TOpenInfo::EGetInfo)
|
|
230 |
return DoGetInfo(infoBuf().U.iInfo);
|
|
231 |
else
|
|
232 |
{
|
|
233 |
if (!iDfcQ)
|
|
234 |
{
|
|
235 |
r = Kern::DynamicDfcQCreate(iDfcQ, KDFCThreadPriority, KDFCThreadName);
|
|
236 |
if (r != KErrNone)
|
|
237 |
return r;
|
|
238 |
#ifdef CPU_AFFINITY_ANY
|
|
239 |
NKern::ThreadSetCpuAffinity((NThread*)(iDfcQ->iThread), KCpuAffinityAny);
|
|
240 |
#endif
|
|
241 |
}
|
|
242 |
|
|
243 |
iMemMemPslInfo = DmaTestInfo().iMemMemPslInfo;
|
|
244 |
iCookie = infoBuf().U.iOpen.iId;
|
|
245 |
TDmaChannel::SCreateInfo info;
|
|
246 |
info.iCookie = iCookie;
|
|
247 |
info.iDfcQ = iDfcQ;
|
|
248 |
info.iDfcPriority = 3;
|
|
249 |
info.iDesCount = infoBuf().U.iOpen.iDesCount;
|
|
250 |
r = TDmaChannel::Open(info, iChannel);
|
|
251 |
if (r!= KErrNone)
|
|
252 |
return r;
|
|
253 |
iClient = &Kern::CurrentThread();
|
|
254 |
for (TInt i=0; i<KMaxRequests; ++i)
|
|
255 |
{
|
|
256 |
r = Kern::CreateClientRequest(iClientRequests[i]);
|
|
257 |
if (r!=KErrNone)
|
|
258 |
return r;
|
|
259 |
iMap[i] = this;
|
|
260 |
TInt max = infoBuf().U.iOpen.iMaxTransferSize;
|
|
261 |
if (max)
|
|
262 |
{
|
|
263 |
// Exercise request with custom limit
|
|
264 |
iRequests[i] = new DDmaRequest(*iChannel, Dfc, iMap+i, max);
|
|
265 |
}
|
|
266 |
else
|
|
267 |
{
|
|
268 |
// Exercise request with default limit
|
|
269 |
iRequests[i] = new DDmaRequest(*iChannel, Dfc, iMap+i);
|
|
270 |
}
|
|
271 |
if (! iRequests[i])
|
|
272 |
return KErrNoMemory;
|
|
273 |
}
|
|
274 |
return KErrNone;
|
|
275 |
}
|
|
276 |
}
|
|
277 |
|
|
278 |
|
|
279 |
DDmaTestChannel::~DDmaTestChannel()
|
|
280 |
{
|
|
281 |
if (iChannel)
|
|
282 |
{
|
|
283 |
iChannel->CancelAll();
|
|
284 |
TInt i;
|
|
285 |
for (i=0; i<KMaxRequests; ++i)
|
|
286 |
delete iRequests[i];
|
|
287 |
iChannel->Close();
|
|
288 |
for (i=0; i<KMaxRequests; ++i)
|
|
289 |
Kern::DestroyClientRequest(iClientRequests[i]);
|
|
290 |
}
|
|
291 |
if (iDfcQ)
|
|
292 |
{
|
|
293 |
iDfcQ->Destroy();
|
|
294 |
}
|
|
295 |
iBufMgr.FreeAll();
|
|
296 |
}
|
|
297 |
|
|
298 |
|
|
299 |
TInt DDmaTestChannel::Request(TInt aFunction, TAny* a1, TAny* a2)
|
|
300 |
{
|
|
301 |
switch (aFunction)
|
|
302 |
{
|
|
303 |
case RTestDma::EAllocBuffer:
|
|
304 |
return iBufMgr.Alloc((TInt)a1, (TInt)a2);
|
|
305 |
case RTestDma::EFreeAllBuffers:
|
|
306 |
iBufMgr.FreeAll();
|
|
307 |
return KErrNone;
|
|
308 |
case RTestDma::EFillBuffer:
|
|
309 |
{
|
|
310 |
TInt i = (TInt)a1;
|
|
311 |
TUint8 val = (TUint8)(TUint)a2;
|
|
312 |
memset(iBufMgr.Addr(i), val, iBufMgr.Size(i));
|
|
313 |
return KErrNone;
|
|
314 |
}
|
|
315 |
case RTestDma::ECheckBuffer:
|
|
316 |
{
|
|
317 |
TInt i = (TInt)a1;
|
|
318 |
TUint8 val = (TUint8)(TUint)a2;
|
|
319 |
TUint8* p = iBufMgr.Addr(i);
|
|
320 |
TUint8* end = p + iBufMgr.Size(i);
|
|
321 |
while (p < end)
|
|
322 |
if (*p++ != val)
|
|
323 |
{
|
|
324 |
__KTRACE_OPT(KDMA, Kern::Printf("Check DMA buffer failed offset: %d value: %d",
|
|
325 |
p-iBufMgr.Addr(i)-1, *(p-1)));
|
|
326 |
return EFalse;
|
|
327 |
}
|
|
328 |
return ETrue;
|
|
329 |
}
|
|
330 |
case RTestDma::EFragment:
|
|
331 |
{
|
|
332 |
RTestDma::TFragmentInfo info;
|
|
333 |
kumemget(&info, a1, sizeof info);
|
|
334 |
__ASSERT_DEBUG(iBufMgr.Size(info.iSrcBufIdx) == iBufMgr.Size(info.iDestBufIdx),
|
|
335 |
Kern::PanicCurrentThread(KClientPanicCat, __LINE__));
|
|
336 |
__ASSERT_DEBUG(info.iSize <= iBufMgr.Size(info.iSrcBufIdx),
|
|
337 |
Kern::PanicCurrentThread(KClientPanicCat, __LINE__));
|
|
338 |
__ASSERT_DEBUG(0 <= info.iRequestIdx && info.iRequestIdx < KMaxRequests,
|
|
339 |
Kern::PanicCurrentThread(KClientPanicCat, __LINE__));
|
|
340 |
#ifdef __DMASIM__
|
|
341 |
// DMASIM doesn't use physical addresses
|
|
342 |
TUint32 src = (TUint32)iBufMgr.Addr(info.iSrcBufIdx);
|
|
343 |
TUint32 dest = (TUint32)iBufMgr.Addr(info.iDestBufIdx);
|
|
344 |
TUint KFlags = KDmaMemSrc | KDmaIncSrc | KDmaMemDest | KDmaIncDest;
|
|
345 |
#else
|
|
346 |
TUint32 src = iBufMgr.PhysAddr(info.iSrcBufIdx);
|
|
347 |
TUint32 dest = iBufMgr.PhysAddr(info.iDestBufIdx);
|
|
348 |
TUint KFlags = KDmaMemSrc | KDmaIncSrc | KDmaPhysAddrSrc |
|
|
349 |
KDmaMemDest | KDmaIncDest | KDmaPhysAddrDest | KDmaAltTransferLen;
|
|
350 |
#endif
|
|
351 |
TInt r = iRequests[info.iRequestIdx]->Fragment(src, dest, info.iSize, KFlags, iMemMemPslInfo);
|
|
352 |
if (r == KErrNone && info.iRs)
|
|
353 |
r = iClientRequests[info.iRequestIdx]->SetStatus(info.iRs);
|
|
354 |
return r;
|
|
355 |
}
|
|
356 |
case RTestDma::EExecute:
|
|
357 |
return Execute(*(TDesC8*)a1);
|
|
358 |
case RTestDma::EFailNext:
|
|
359 |
return iChannel->FailNext((TInt)a1);
|
|
360 |
case RTestDma::EFragmentCount:
|
|
361 |
{
|
|
362 |
TInt reqIdx = (TInt)a1;
|
|
363 |
__ASSERT_DEBUG(0 <= reqIdx && reqIdx < KMaxRequests, Kern::PanicCurrentThread(KClientPanicCat, __LINE__));
|
|
364 |
return FragmentCount(iRequests[reqIdx]);
|
|
365 |
}
|
|
366 |
case RTestDma::EMissInterrupts:
|
|
367 |
return iChannel->MissNextInterrupts((TInt)a1);
|
|
368 |
default:
|
|
369 |
Kern::PanicCurrentThread(KClientPanicCat, __LINE__);
|
|
370 |
return KErrNone; // work-around spurious warning
|
|
371 |
}
|
|
372 |
}
|
|
373 |
|
|
374 |
|
|
375 |
TInt DDmaTestChannel::Execute(const TDesC8& aDes)
|
|
376 |
{
|
|
377 |
TBuf8<64> cmd;
|
|
378 |
Kern::KUDesGet(cmd, aDes);
|
|
379 |
const TText8* p = cmd.Ptr();
|
|
380 |
const TText8* pEnd = p + cmd.Length();
|
|
381 |
while (p<pEnd)
|
|
382 |
{
|
|
383 |
TText8 opcode = *p++;
|
|
384 |
switch (opcode)
|
|
385 |
{
|
|
386 |
case 'Q':
|
|
387 |
{
|
|
388 |
TInt arg = *p++ - '0';
|
|
389 |
__ASSERT_DEBUG(0 <= arg && arg < KMaxRequests, Kern::PanicCurrentThread(KClientPanicCat, __LINE__));
|
|
390 |
iRequests[arg]->Queue();
|
|
391 |
break;
|
|
392 |
}
|
|
393 |
case 'C':
|
|
394 |
iChannel->CancelAll();
|
|
395 |
break;
|
|
396 |
default:
|
|
397 |
Kern::PanicCurrentThread(KClientPanicCat, __LINE__);
|
|
398 |
}
|
|
399 |
}
|
|
400 |
return KErrNone;
|
|
401 |
}
|
|
402 |
|
|
403 |
|
|
404 |
void DDmaTestChannel::Dfc(DDmaRequest::TResult aResult, TAny* aArg)
|
|
405 |
{
|
|
406 |
DDmaTestChannel** ppC = (DDmaTestChannel**)aArg;
|
|
407 |
DDmaTestChannel* pC = *ppC;
|
|
408 |
TInt i = ppC - pC->iMap;
|
|
409 |
TClientRequest* req = pC->iClientRequests[i];
|
|
410 |
TInt r = (aResult==DDmaRequest::EOk) ? KErrNone : KErrGeneral;
|
|
411 |
if (req->IsReady())
|
|
412 |
Kern::QueueRequestComplete(pC->iClient, req, r);
|
|
413 |
}
|
|
414 |
|
|
415 |
//////////////////////////////////////////////////////////////////////////////
|
|
416 |
|
|
417 |
class DDmaTestFactory : public DLogicalDevice
|
|
418 |
{
|
|
419 |
public:
|
|
420 |
DDmaTestFactory();
|
|
421 |
// from DLogicalDevice
|
|
422 |
virtual TInt Install();
|
|
423 |
virtual void GetCaps(TDes8& aDes) const;
|
|
424 |
virtual TInt Create(DLogicalChannelBase*& aChannel);
|
|
425 |
};
|
|
426 |
|
|
427 |
|
|
428 |
DDmaTestFactory::DDmaTestFactory()
|
|
429 |
{
|
|
430 |
iVersion = TestDmaLddVersion();
|
|
431 |
iParseMask = KDeviceAllowUnit; // no info, no PDD
|
|
432 |
// iUnitsMask = 0; // Only one thing
|
|
433 |
}
|
|
434 |
|
|
435 |
|
|
436 |
TInt DDmaTestFactory::Create(DLogicalChannelBase*& aChannel)
|
|
437 |
{
|
|
438 |
aChannel=new DDmaTestChannel;
|
|
439 |
return aChannel ? KErrNone : KErrNoMemory;
|
|
440 |
}
|
|
441 |
|
|
442 |
|
|
443 |
TInt DDmaTestFactory::Install()
|
|
444 |
{
|
|
445 |
return SetName(&KTestDmaLddName);
|
|
446 |
}
|
|
447 |
|
|
448 |
|
|
449 |
void DDmaTestFactory::GetCaps(TDes8& /*aDes*/) const
|
|
450 |
{
|
|
451 |
}
|
|
452 |
|
|
453 |
//////////////////////////////////////////////////////////////////////////////
|
|
454 |
|
|
455 |
DECLARE_STANDARD_LDD()
|
|
456 |
{
|
|
457 |
return new DDmaTestFactory;
|
|
458 |
}
|