9 // Nokia Corporation - initial contribution. |
9 // Nokia Corporation - initial contribution. |
10 // |
10 // |
11 // Contributors: |
11 // Contributors: |
12 // |
12 // |
13 // Description: |
13 // Description: |
14 // template\template_assp\dmapsl.cpp |
14 // bsptemplate/asspvariant/template_assp/dmapsl.cpp |
15 // Template DMA Platform Specific Layer (PSL). |
15 // Template DMA Platform Specific Layer (PSL). |
16 // |
16 // |
17 // |
17 // |
18 |
18 |
19 |
19 |
20 #include <kernel/kern_priv.h> |
20 #include <kernel/kern_priv.h> |
21 #include <template_assp.h> // /assp/template_assp/ |
21 #include <template_assp.h> // /assp/template_assp/ |
|
22 |
22 #include <drivers/dma.h> |
23 #include <drivers/dma.h> |
|
24 #include <drivers/dma_hai.h> |
|
25 |
23 |
26 |
24 // Debug support |
27 // Debug support |
25 static const char KDmaPanicCat[] = "DMA PSL"; |
28 static const char KDmaPanicCat[] = "DMA PSL - " __FILE__; |
26 |
29 |
27 static const TInt KMaxTransferLen = 0x1FE0; // max transfer length for this DMAC |
30 static const TInt KMaxTransferLen = 0x1FE0; // max transfer length for this DMAC |
28 static const TInt KMemAlignMask = 7; // memory addresses passed to DMAC must be multiple of 8 |
31 static const TInt KMemAlignMask = 7; // memory addresses passed to DMAC must be multiple of 8 |
29 static const TInt KChannelCount = 16; // we got 16 channels |
32 static const TInt KChannelCount = 16; // we got 16 channels |
30 static const TInt KDesCount = 1024; // DMA descriptor count |
33 static const TInt KDesCount = 160; // Initial DMA descriptor count |
31 |
34 |
32 |
35 |
33 class TDmaDesc |
36 class TDmaDesc |
34 // |
37 // |
35 // Hardware DMA descriptor |
38 // Hardware DMA descriptor |
83 { |
109 { |
84 return ((TLinAddr)aDes & 0xF) == 0; |
110 return ((TLinAddr)aDes & 0xF) == 0; |
85 } |
111 } |
86 |
112 |
87 |
113 |
88 static TUint32 DcmdReg(TInt aCount, TUint aFlags, TUint32 aPslInfo) |
114 static TUint32 DmaCmdReg(TUint aCount, TUint aFlags, TUint32 aSrcPslInfo, TUint32 aDstPslInfo) |
89 // |
115 // |
90 // Returns value to set in DMA command register or in descriptor command field. |
116 // Returns value to set in DMA command register or in descriptor command field. |
91 // |
117 // |
92 { |
118 { |
93 // TO DO: Construct CMD word from input values. |
119 // TO DO: Construct CMD word from input values. |
94 // The return value should reflect the actual control word. |
120 // The return value should reflect the actual control word. |
95 return (aCount | aFlags | aPslInfo); |
121 return (aCount | aFlags | aSrcPslInfo | aDstPslInfo); |
96 } |
122 } |
97 |
123 |
98 |
124 |
99 ////////////////////////////////////////////////////////////////////////////// |
125 ////////////////////////////////////////////////////////////////////////////// |
100 // Derived Channel (Scatter/Gather) |
126 // Derived Channel (Scatter/Gather) |
117 public: |
143 public: |
118 TTemplateDmac(); |
144 TTemplateDmac(); |
119 TInt Create(); |
145 TInt Create(); |
120 private: |
146 private: |
121 // from TDmac (PIL pure virtual) |
147 // from TDmac (PIL pure virtual) |
122 virtual void Transfer(const TDmaChannel& aChannel, const SDmaDesHdr& aHdr); |
|
123 virtual void StopTransfer(const TDmaChannel& aChannel); |
148 virtual void StopTransfer(const TDmaChannel& aChannel); |
124 virtual TBool IsIdle(const TDmaChannel& aChannel); |
149 virtual TBool IsIdle(const TDmaChannel& aChannel); |
125 virtual TInt MaxTransferSize(TDmaChannel& aChannel, TUint aFlags, TUint32 aPslInfo); |
150 virtual TUint MaxTransferLength(TDmaChannel& aChannel, TUint aSrcFlags, |
126 virtual TUint MemAlignMask(TDmaChannel& aChannel, TUint aFlags, TUint32 aPslInfo); |
151 TUint aDstFlags, TUint32 aPslInfo); |
|
152 virtual TUint AddressAlignMask(TDmaChannel& aChannel, TUint aSrcFlags, |
|
153 TUint aDstFlags, TUint32 aPslInfo); |
127 // from TDmac (PIL virtual) |
154 // from TDmac (PIL virtual) |
128 virtual void InitHwDes(const SDmaDesHdr& aHdr, TUint32 aSrc, TUint32 aDest, TInt aCount, |
155 virtual void Transfer(const TDmaChannel& aChannel, const SDmaDesHdr& aHdr); |
129 TUint aFlags, TUint32 aPslInfo, TUint32 aCookie); |
156 virtual TInt InitHwDes(const SDmaDesHdr& aHdr, const TDmaTransferArgs& aTransferArgs); |
130 virtual void ChainHwDes(const SDmaDesHdr& aHdr, const SDmaDesHdr& aNextHdr); |
157 virtual void ChainHwDes(const SDmaDesHdr& aHdr, const SDmaDesHdr& aNextHdr); |
131 virtual void AppendHwDes(const TDmaChannel& aChannel, const SDmaDesHdr& aLastHdr, |
158 virtual void AppendHwDes(const TDmaChannel& aChannel, const SDmaDesHdr& aLastHdr, |
132 const SDmaDesHdr& aNewHdr); |
159 const SDmaDesHdr& aNewHdr); |
133 virtual void UnlinkHwDes(const TDmaChannel& aChannel, SDmaDesHdr& aHdr); |
160 virtual void UnlinkHwDes(const TDmaChannel& aChannel, SDmaDesHdr& aHdr); |
134 // other |
161 // other |
138 static const SCreateInfo KInfo; |
165 static const SCreateInfo KInfo; |
139 public: |
166 public: |
140 TTemplateSgChannel iChannels[KChannelCount]; |
167 TTemplateSgChannel iChannels[KChannelCount]; |
141 }; |
168 }; |
142 |
169 |
|
170 |
143 static TTemplateDmac Controller; |
171 static TTemplateDmac Controller; |
144 |
172 |
|
173 |
145 const TDmac::SCreateInfo TTemplateDmac::KInfo = |
174 const TDmac::SCreateInfo TTemplateDmac::KInfo = |
146 { |
175 { |
147 KChannelCount, |
176 ETrue, // iCapsHwDes |
148 KDesCount, |
177 KDesCount, // iDesCount |
149 TDmac::KCapsBitHwDes, |
178 sizeof(TDmaDesc), // iDesSize |
150 sizeof(TDmaDesc), |
179 EMapAttrSupRw | EMapAttrFullyBlocking // iDesChunkAttribs |
151 EMapAttrSupRw | EMapAttrFullyBlocking |
|
152 }; |
180 }; |
153 |
181 |
154 |
182 |
155 TTemplateDmac::TTemplateDmac() |
183 TTemplateDmac::TTemplateDmac() |
156 // |
184 // |
171 __DMA_ASSERTA(ReserveSetOfDes(KChannelCount) == KErrNone); |
199 __DMA_ASSERTA(ReserveSetOfDes(KChannelCount) == KErrNone); |
172 for (TInt i=0; i < KChannelCount; ++i) |
200 for (TInt i=0; i < KChannelCount; ++i) |
173 { |
201 { |
174 TDmaDesc* pD = HdrToHwDes(*iFreeHdr); |
202 TDmaDesc* pD = HdrToHwDes(*iFreeHdr); |
175 iChannels[i].iTmpDes = pD; |
203 iChannels[i].iTmpDes = pD; |
176 iChannels[i].iTmpDesPhysAddr = DesLinToPhys(pD); |
204 iChannels[i].iTmpDesPhysAddr = HwDesLinToPhys(pD); |
177 iFreeHdr = iFreeHdr->iNext; |
205 iFreeHdr = iFreeHdr->iNext; |
178 } |
206 } |
179 r = Interrupt::Bind(EAsspIntIdDma, Isr, this); |
207 r = Interrupt::Bind(EAsspIntIdDma, Isr, this); |
180 if (r == KErrNone) |
208 if (r == KErrNone) |
181 { |
209 { |
235 |
263 |
236 return ETrue; |
264 return ETrue; |
237 } |
265 } |
238 |
266 |
239 |
267 |
240 TInt TTemplateDmac::MaxTransferSize(TDmaChannel& /*aChannel*/, TUint /*aFlags*/, TUint32 /*aPslInfo*/) |
268 TUint TTemplateDmac::MaxTransferLength(TDmaChannel& /*aChannel*/, TUint /*aSrcFlags*/, |
241 // |
269 TUint /*aDstFlags*/, TUint32 /*aPslInfo*/) |
242 // Returns the maximum transfer size for a given transfer. |
270 // |
|
271 // Returns the maximum transfer length in bytes for a given transfer. |
243 // |
272 // |
244 { |
273 { |
245 // TO DO: Determine the proper return value, based on the arguments. |
274 // TO DO: Determine the proper return value, based on the arguments. |
246 |
275 |
247 // For instance: |
276 // For instance: |
248 return KMaxTransferLen; |
277 return KMaxTransferLen; |
249 } |
278 } |
250 |
279 |
251 |
280 |
252 TUint TTemplateDmac::MemAlignMask(TDmaChannel& /*aChannel*/, TUint /*aFlags*/, TUint32 /*aPslInfo*/) |
281 TUint TTemplateDmac::AddressAlignMask(TDmaChannel& aChannel, TUint /*aSrcFlags*/, |
|
282 TUint /*aDstFlags*/, TUint32 /*aPslInfo*/) |
253 // |
283 // |
254 // Returns the memory buffer alignment restrictions mask for a given transfer. |
284 // Returns the memory buffer alignment restrictions mask for a given transfer. |
255 // |
285 // |
256 { |
286 { |
257 // TO DO: Determine the proper return value, based on the arguments. |
287 // TO DO: Determine the proper return value, based on the arguments. |
259 // For instance: |
289 // For instance: |
260 return KMemAlignMask; |
290 return KMemAlignMask; |
261 } |
291 } |
262 |
292 |
263 |
293 |
264 void TTemplateDmac::InitHwDes(const SDmaDesHdr& aHdr, TUint32 aSrc, TUint32 aDest, TInt aCount, |
294 TInt TTemplateDmac::InitHwDes(const SDmaDesHdr& aHdr, const TDmaTransferArgs& aTransferArgs) |
265 TUint aFlags, TUint32 aPslInfo, TUint32 /*aCookie*/) |
295 // |
266 // |
296 // Sets up (from a passed in request) the descriptor with that fragment's |
267 // Sets up (from a passed in request) the descriptor with that fragment's source and destination address, |
297 // source and destination address, the fragment size, and the (driver/DMA |
268 // the fragment size, and the (driver/DMA controller) specific transfer parameters (mem/peripheral, |
298 // controller) specific transfer parameters (mem/peripheral, burst size, |
269 // burst size, transfer width). |
299 // transfer width). |
270 // |
300 // |
271 { |
301 { |
272 TDmaDesc* pD = HdrToHwDes(aHdr); |
302 TDmaDesc* pD = HdrToHwDes(aHdr); |
273 |
303 |
274 __KTRACE_OPT(KDMA, Kern::Printf("TTemplateDmac::InitHwDes 0x%08X", pD)); |
304 __KTRACE_OPT(KDMA, Kern::Printf("TTemplateDmac::InitHwDes 0x%08X", pD)); |
275 |
305 |
276 // Unaligned descriptor? Bug in generic layer! |
306 // Unaligned descriptor? Bug in generic layer! |
277 __DMA_ASSERTD(IsHwDesAligned(pD)); |
307 __DMA_ASSERTD(IsHwDesAligned(pD)); |
278 |
308 |
279 pD->iSrcAddr = (aFlags & KDmaPhysAddrSrc) ? aSrc : Epoc::LinearToPhysical(aSrc); |
309 const TDmaTransferConfig& src = aTransferArgs.iSrcConfig; |
280 pD->iDestAddr = (aFlags & KDmaPhysAddrDest) ? aDest : Epoc::LinearToPhysical(aDest); |
310 const TDmaTransferConfig& dst = aTransferArgs.iDstConfig; |
281 pD->iCmd = DcmdReg(aCount, aFlags, aPslInfo); |
311 pD->iSrcAddr = (src.iFlags & KDmaPhysAddr) ? src.iAddr : Epoc::LinearToPhysical(src.iAddr); |
|
312 pD->iDestAddr = (dst.iFlags & KDmaPhysAddr) ? dst.iAddr : Epoc::LinearToPhysical(dst.iAddr); |
|
313 pD->iCmd = DmaCmdReg(aTransferArgs.iTransferCount, aTransferArgs.iFlags, |
|
314 src.iPslTargetInfo, dst.iPslTargetInfo); |
282 pD->iDescAddr = TDmaDesc::KStopBitMask; |
315 pD->iDescAddr = TDmaDesc::KStopBitMask; |
|
316 |
|
317 return KErrNone; |
283 } |
318 } |
284 |
319 |
285 |
320 |
286 void TTemplateDmac::ChainHwDes(const SDmaDesHdr& aHdr, const SDmaDesHdr& aNextHdr) |
321 void TTemplateDmac::ChainHwDes(const SDmaDesHdr& aHdr, const SDmaDesHdr& aNextHdr) |
287 // |
322 // |
297 // Unaligned descriptor? Bug in generic layer! |
332 // Unaligned descriptor? Bug in generic layer! |
298 __DMA_ASSERTD(IsHwDesAligned(pD) && IsHwDesAligned(pN)); |
333 __DMA_ASSERTD(IsHwDesAligned(pD) && IsHwDesAligned(pN)); |
299 |
334 |
300 // TO DO: Modify pD->iCmd so that no end-of-transfer interrupt gets raised any longer. |
335 // TO DO: Modify pD->iCmd so that no end-of-transfer interrupt gets raised any longer. |
301 |
336 |
302 pD->iDescAddr = DesLinToPhys(pN); |
337 pD->iDescAddr = HwDesLinToPhys(pN); |
303 } |
338 } |
304 |
339 |
305 |
340 |
306 void TTemplateDmac::AppendHwDes(const TDmaChannel& aChannel, const SDmaDesHdr& aLastHdr, |
341 void TTemplateDmac::AppendHwDes(const TDmaChannel& aChannel, const SDmaDesHdr& aLastHdr, |
307 const SDmaDesHdr& aNewHdr) |
342 const SDmaDesHdr& aNewHdr) |
317 __KTRACE_OPT(KDMA, Kern::Printf(">TTemplateDmac::AppendHwDes channel=%d last des=0x%08X new des=0x%08X", |
352 __KTRACE_OPT(KDMA, Kern::Printf(">TTemplateDmac::AppendHwDes channel=%d last des=0x%08X new des=0x%08X", |
318 i, pL, pN)); |
353 i, pL, pN)); |
319 // Unaligned descriptor? Bug in generic layer! |
354 // Unaligned descriptor? Bug in generic layer! |
320 __DMA_ASSERTD(IsHwDesAligned(pL) && IsHwDesAligned(pN)); |
355 __DMA_ASSERTD(IsHwDesAligned(pL) && IsHwDesAligned(pN)); |
321 |
356 |
322 TPhysAddr newPhys = DesLinToPhys(pN); |
357 TPhysAddr newPhys = HwDesLinToPhys(pN); |
323 |
358 |
324 const TInt irq = NKern::DisableAllInterrupts(); |
359 const TInt irq = NKern::DisableAllInterrupts(); |
325 StopTransfer(aChannel); |
360 StopTransfer(aChannel); |
326 |
361 |
327 pL->iDescAddr = newPhys; |
362 pL->iDescAddr = newPhys; |
361 { |
396 { |
362 TTemplateDmac& me = *static_cast<TTemplateDmac*>(aThis); |
397 TTemplateDmac& me = *static_cast<TTemplateDmac*>(aThis); |
363 |
398 |
364 // TO DO: Implement the behaviour described above, call HandleIsr(). |
399 // TO DO: Implement the behaviour described above, call HandleIsr(). |
365 |
400 |
366 HandleIsr(me.iChannels[5], 0); // Example |
401 HandleIsr(me.iChannels[5], EDmaCallbackRequestCompletion, ETrue); // Example |
367 |
402 |
368 } |
403 } |
369 |
404 |
370 |
405 |
371 inline TDmaDesc* TTemplateDmac::HdrToHwDes(const SDmaDesHdr& aHdr) |
406 inline TDmaDesc* TTemplateDmac::HdrToHwDes(const SDmaDesHdr& aHdr) |
379 |
414 |
380 ////////////////////////////////////////////////////////////////////////////// |
415 ////////////////////////////////////////////////////////////////////////////// |
381 // Channel Opening/Closing (Channel Allocator) |
416 // Channel Opening/Closing (Channel Allocator) |
382 ////////////////////////////////////////////////////////////////////////////// |
417 ////////////////////////////////////////////////////////////////////////////// |
383 |
418 |
384 TDmaChannel* DmaChannelMgr::Open(TUint32 aOpenId) |
419 TDmaChannel* DmaChannelMgr::Open(TUint32 aOpenId, TBool /*aDynChannel*/, TUint /*aPriority*/) |
385 // |
420 // |
386 // |
421 // |
387 // |
422 // |
388 { |
423 { |
389 __KTRACE_OPT(KDMA, Kern::Printf(">DmaChannelMgr::Open aOpenId=%d", aOpenId)); |
424 __KTRACE_OPT(KDMA, Kern::Printf(">DmaChannelMgr::Open aOpenId=%d", aOpenId)); |
390 |
425 |
391 __DMA_ASSERTA(aOpenId < static_cast<TUint32>(KChannelCount)); |
426 __DMA_ASSERTA(aOpenId < static_cast<TUint32>(KChannelCount)); |
392 |
427 |
393 TDmaChannel* pC = Controller.iChannels + aOpenId; |
428 TDmaChannel* pC = Controller.iChannels + aOpenId; |
394 if (pC->IsOpened()) |
429 if (pC->IsOpened()) |
|
430 { |
395 pC = NULL; |
431 pC = NULL; |
|
432 } |
396 else |
433 else |
397 { |
434 { |
398 pC->iController = &Controller; |
435 pC->iController = &Controller; |
399 pC->iPslId = aOpenId; |
436 pC->iPslId = aOpenId; |
400 } |
437 } |
401 |
438 |
402 return pC; |
439 return pC; |
403 } |
440 } |
404 |
441 |
405 |
442 |
406 void DmaChannelMgr::Close(TDmaChannel* /* aChannel */) |
443 void DmaChannelMgr::Close(TDmaChannel* /*aChannel*/) |
407 // |
444 // |
408 // |
445 // |
409 // |
446 // |
410 { |
447 { |
411 // NOP |
448 // NOP |
412 } |
449 } |
413 |
450 |
414 |
451 |
415 TInt DmaChannelMgr::StaticExtension(TInt /* aCmd */, TAny* /* aArg */) |
452 TInt DmaChannelMgr::StaticExtension(TInt /*aCmd*/, TAny* /*aArg*/) |
416 // |
453 // |
417 // |
454 // |
418 // |
455 // |
419 { |
456 { |
420 return KErrNotSupported; |
457 return KErrNotSupported; |