blob: 4bf0a4966c1724fcd62a82da952291b19d31c244 [file] [log] [blame]
developer02e65912023-08-17 16:33:10 +08001/* adapter_pec_dma.c
2 *
3 * Packet Engine Control (PEC) API Implementation
4 * using DMA mode.
5 */
6
7/*****************************************************************************
8* Copyright (c) 2011-2022 by Rambus, Inc. and/or its subsidiaries.
9*
10* This program is free software: you can redistribute it and/or modify
11* it under the terms of the GNU General Public License as published by
12* the Free Software Foundation, either version 2 of the License, or
13* any later version.
14*
15* This program is distributed in the hope that it will be useful,
16* but WITHOUT ANY WARRANTY; without even the implied warranty of
17* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18* GNU General Public License for more details.
19*
20* You should have received a copy of the GNU General Public License
21* along with this program. If not, see <http://www.gnu.org/licenses/>.
22******************************************************************************/
23
24/*----------------------------------------------------------------------------
25 * This module implements (provides) the following interface(s):
26 */
27
28#include "api_pec.h" // PEC_* (the API we implement here)
29
30
31/*----------------------------------------------------------------------------
32 * This module uses (requires) the following interface(s):
33 */
34
35// Default Adapter PEC configuration
36#include "c_adapter_pec.h"
37
38// DMABuf API
39#include "api_dmabuf.h" // DMABuf_*
40
41// Adapter DMABuf internal API
42#include "adapter_dmabuf.h"
43
44// Adapter PEC device API
45#include "adapter_pecdev_dma.h" // Adapter_PECDev_*
46
47// Adapter Locking internal API
48#include "adapter_lock.h" // Adapter_Lock_*
49
50#ifdef ADAPTER_PEC_ENABLE_SCATTERGATHER
51#include "api_pec_sg.h" // PEC_SG_* (the API we implement here)
52#endif
53
54// Runtime Power Management Device Macros API
55#include "rpm_device_macros.h" // RPM_*
56
57// Logging API
58#include "log.h"
59
60// Driver Framework DMAResource API
61#include "dmares_types.h" // DMAResource_Handle_t
62#include "dmares_mgmt.h" // DMAResource management functions
63#include "dmares_rw.h" // DMAResource buffer access.
64#include "dmares_addr.h" // DMAResource addr translation functions.
65#include "dmares_buf.h" // DMAResource buffer allocations
66
67// Standard IOToken API
68#include "iotoken.h"
69
70// Driver Framework C Run-Time Library API
71#include "clib.h" // memcpy, memset
72
73// Driver Framework Basic Definitions API
74#include "basic_defs.h" // bool, uint32_t
75
76
77#ifndef ADAPTER_PE_MODE_DHM
78/*----------------------------------------------------------------------------
79 * Definitions and macros
80 */
81
82typedef struct
83{
84 void * User_p;
85 DMABuf_Handle_t SrcPkt_Handle;
86 DMABuf_Handle_t DstPkt_Handle;
87 DMABuf_Handle_t Token_Handle;
88 unsigned int Bypass_WordCount;
89} Adapter_SideChannelRecord_t;
90
91
92/* Side channel FIFO
93 - Normal operation: PEC_Packet_Put adds a record containing several
94 words for each packet.
95 PEC_Packet_Get pops one record for each packet, fills
96 fields into result descriptor.
97 - Contiuous scatter mode: PEC_Scatter_Preload adds a record
98 with DestPkt_Handle only for each scatter
99 buffer.
100 PEC_Packet_Get pops a record for each scatter
101 buffer used. Can do PostDMA for each
102 scatter buffer, will not fill in fields
103 in result descriptor.
104*/
105typedef struct
106{
107 int Size;
108 int ReadIndex;
109 int WriteIndex;
110 Adapter_SideChannelRecord_t Records[1 + ADAPTER_PEC_MAX_PACKETS +
111 ADAPTER_PEC_MAX_LOGICDESCR];
112} AdapterPEC_SideChannelFIFO_t;
113
114
115/*----------------------------------------------------------------------------
116 * Local variables
117 */
118static volatile bool PEC_IsInitialized[ADAPTER_PEC_DEVICE_COUNT];
119static volatile bool PEC_ContinuousScatter[ADAPTER_PEC_DEVICE_COUNT];
120
121// Lock and critical section for PEC_Init/Uninit()
122static ADAPTER_LOCK_DEFINE(AdapterPEC_InitLock);
123static Adapter_Lock_CS_t AdapterPEC_InitCS;
124
125// Locks and critical sections for PEC_Packet_Put()
126static Adapter_Lock_t AdapterPEC_PutLock[ADAPTER_PEC_DEVICE_COUNT];
127static Adapter_Lock_CS_t AdapterPEC_PutCS[ADAPTER_PEC_DEVICE_COUNT];
128
129// Locks and critical sections for PEC_Packet_Get()
130static Adapter_Lock_t AdapterPEC_GetLock[ADAPTER_PEC_DEVICE_COUNT];
131static Adapter_Lock_CS_t AdapterPEC_GetCS[ADAPTER_PEC_DEVICE_COUNT];
132
133static AdapterPEC_SideChannelFIFO_t
134Adapter_SideChannelFIFO[ADAPTER_PEC_DEVICE_COUNT];
135
136static struct
137{
138 volatile PEC_NotifyFunction_t ResultNotifyCB_p;
139 volatile unsigned int ResultsCount;
140
141 volatile PEC_NotifyFunction_t CommandNotifyCB_p;
142 volatile unsigned int CommandsCount;
143
144} PEC_Notify[ADAPTER_PEC_DEVICE_COUNT];
145
146
147#ifdef ADAPTER_PEC_INTERRUPTS_ENABLE
148/*----------------------------------------------------------------------------
149 * AdapterPEC_InterruptHandlerResultNotify
150 *
151 * This function is the interrupt handler for the PEC interrupt
152 * sources that indicate the arrival of a a result descriptor..There
153 * may be several interrupt sources.
154 *
155 * This function is used to invoke the PEC result notification callback.
156 */
157static void
158AdapterPEC_InterruptHandlerResultNotify(
159 const int nIRQ,
160 const unsigned int flags)
161{
162 unsigned int InterfaceId = Adapter_PECDev_IRQToInferfaceId(nIRQ);
163
164 IDENTIFIER_NOT_USED(flags);
165
166 if (InterfaceId >= ADAPTER_PEC_DEVICE_COUNT)
167 {
168 LOG_CRIT("AdapterPEC_InterruptHandlerResultNotify"
169 "InterfaceId out of range\n");
170 return;
171 }
172
173 Adapter_PECDev_Disable_ResultIRQ(InterfaceId);
174
175 LOG_INFO("AdapterPEC_InterruptHandlerResultNotify: Enter\n");
176
177 if (PEC_Notify[InterfaceId].ResultNotifyCB_p != NULL)
178 {
179 PEC_NotifyFunction_t CBFunc_p;
180
181 // Keep the callback on stack to allow registration
182 // of another result notify request from callback
183 CBFunc_p = PEC_Notify[InterfaceId].ResultNotifyCB_p;
184
185 PEC_Notify[InterfaceId].ResultNotifyCB_p = NULL;
186 PEC_Notify[InterfaceId].ResultsCount = 0;
187
188 LOG_INFO(
189 "AdapterPEC_InterruptHandlerResultNotify: "
190 "Invoking PEC result notify callback for interface %d\n",
191 InterfaceId);
192
193 CBFunc_p();
194 }
195}
196
197
198/*----------------------------------------------------------------------------
199 * AdapterPEC_InterruptHandlerCommandNotify
200 *
201 * This function is the interrupt handler for the PEC interrupt sources.that
202 * indicate that there is again freee space for new command descriptors.
203 *
204 * This function is used to invoke the PEC command notification callback.
205 */
206static void
207AdapterPEC_InterruptHandlerCommandNotify(
208 const int nIRQ,
209 const unsigned int flags)
210{
211 unsigned int InterfaceId = Adapter_PECDev_IRQToInferfaceId(nIRQ);
212
213 IDENTIFIER_NOT_USED(flags);
214
215 if (InterfaceId >= ADAPTER_PEC_DEVICE_COUNT)
216 {
217 LOG_CRIT("AdapterPEC_InterruptHandlerCommandNotify"
218 "InterfaceId out of range\n");
219 return;
220 }
221
222 Adapter_PECDev_Disable_CommandIRQ(InterfaceId);
223
224 LOG_INFO("AdapterPEC_InterruptHandlerCommandNotify: Enter\n");
225
226 if (PEC_Notify[InterfaceId].CommandNotifyCB_p != NULL)
227 {
228 PEC_NotifyFunction_t CBFunc_p;
229
230 // Keep the callback on stack to allow registration
231 // of another command notify request from callback
232 CBFunc_p = PEC_Notify[InterfaceId].CommandNotifyCB_p;
233
234 PEC_Notify[InterfaceId].CommandNotifyCB_p = NULL;
235 PEC_Notify[InterfaceId].CommandsCount = 0;
236
237 LOG_INFO(
238 "AdapterPEC_InterruptHandlerCommandNotify: "
239 "Invoking PEC command notify callback interface=%d\n",
240 InterfaceId);
241
242 CBFunc_p();
243 }
244}
245#endif /* ADAPTER_PEC_INTERRUPTS_ENABLE */
246
247
248/*----------------------------------------------------------------------------
249 * Adapter_MakeCommandNotify_CallBack
250 */
251static inline void
252Adapter_MakeCommandNotify_CallBack(unsigned int InterfaceId)
253{
254 unsigned int PacketSlotsEmptyCount;
255
256 if (InterfaceId >= ADAPTER_PEC_DEVICE_COUNT)
257 return;
258
259 if (PEC_Notify[InterfaceId].CommandNotifyCB_p != NULL)
260 {
261 PacketSlotsEmptyCount = Adapter_PECDev_GetFreeSpace(InterfaceId);
262
263 if (PEC_Notify[InterfaceId].CommandsCount <= PacketSlotsEmptyCount)
264 {
265 PEC_NotifyFunction_t CBFunc_p;
266
267 // Keep the callback on stack to allow registeration
268 // of another result notify request from callback
269 CBFunc_p = PEC_Notify[InterfaceId].CommandNotifyCB_p;
270
271 PEC_Notify[InterfaceId].CommandNotifyCB_p = NULL;
272 PEC_Notify[InterfaceId].CommandsCount = 0;
273
274 LOG_INFO(
275 "PEC_Packet_Get: "
276 "Invoking command notify callback\n");
277
278 CBFunc_p();
279 }
280 }
281}
282
283
284/*----------------------------------------------------------------------------
285 * Adapter_PECResgisterSA_BounceIfRequired
286 *
287 * Returns false in case of error.
288 * Allocate a bounce buffer and copy the data in case this if required.
289 */
290#ifndef ADAPTER_PEC_REMOVE_BOUNCEBUFFERS
291static bool
292Adapter_PECRegisterSA_BounceIfRequired(
293 DMAResource_Handle_t *DMAHandle_p)
294{
295 DMAResource_Handle_t DMAHandle = *DMAHandle_p;
296 DMAResource_Record_t * Rec_p;
297 DMAResource_AddrPair_t BounceHostAddr;
298 void * HostAddr;
299 int dmares;
300
301 // skip null handles
302 if (!DMAResource_IsValidHandle(DMAHandle))
303 return true; // no error
304
305 Rec_p = DMAResource_Handle2RecordPtr(DMAHandle);
306
307
308 // skip proper buffers
309 if (!Adapter_DMAResource_IsForeignAllocated(DMAHandle))
310 {
311 Rec_p->bounce.Bounce_Handle = NULL;
312 return true; // no error
313 }
314
315 {
316 DMAResource_Properties_t BounceProperties;
317
318 // used as uint32_t array
319 BounceProperties.Alignment = Adapter_DMAResource_Alignment_Get();
320 BounceProperties.Bank = ADAPTER_PEC_BANK_SA;
321 BounceProperties.fCached = false;
322 BounceProperties.Size = Rec_p->Props.Size;
323
324 HostAddr = Adapter_DMAResource_HostAddr(DMAHandle);
325
326 dmares = DMAResource_Alloc(
327 BounceProperties,
328 &BounceHostAddr,
329 &Rec_p->bounce.Bounce_Handle);
330
331 // bounce buffer handle is stored in the DMA Resource Record
332 // of the original buffer, which links the two
333 // this will be used when freeing the buffer
334 // but also when the SA is referenced in packet put
335
336 if (dmares != 0)
337 {
338 LOG_CRIT(
339 "PEC_SA_Register: "
340 "Failed to alloc bounce buffer (error %d)\n",
341 dmares);
342 return false; // error!
343 }
344 LOG_INFO(
345 "PEC_SA_Register: "
346 "Bouncing SA: %p to %p\n",
347 DMAHandle,
348 Rec_p->bounce.Bounce_Handle);
349#ifdef ADAPTER_PEC_ARMRING_ENABLE_SWAP
350 DMAResource_SwapEndianness_Set(Rec_p->bounce.Bounce_Handle, true);
351#endif
352
353 }
354
355 // copy the data to the bounce buffer
356 memcpy(
357 BounceHostAddr.Address_p,
358 HostAddr,
359 Rec_p->Props.Size);
360
361 *DMAHandle_p = Rec_p->bounce.Bounce_Handle;
362 return true; // no error
363}
364#endif /* ADAPTER_PEC_REMOVE_BOUNCEBUFFERS */
365
366
367/*----------------------------------------------------------------------------
368 * Adapter_FIFO_Put
369 *
370 * Put packet information into the side channel FIFO
371 */
372static bool
373Adapter_FIFO_Put(AdapterPEC_SideChannelFIFO_t *FIFO,
374 void *User_p,
375 DMABuf_Handle_t SrcPkt_Handle,
376 DMABuf_Handle_t DstPkt_Handle,
377 DMABuf_Handle_t Token_Handle,
378 unsigned int Bypass_WordCount)
379{
380 int WriteIndex = FIFO->WriteIndex;
381 int ReadIndex = FIFO->ReadIndex;
382 if (WriteIndex == ReadIndex - 1 ||
383 (ReadIndex == 0 && WriteIndex == FIFO->Size - 1))
384 {
385 LOG_CRIT("Side channel FIFO full\n");
386 return false;
387 }
388 FIFO->Records[WriteIndex].User_p = User_p;
389 FIFO->Records[WriteIndex].SrcPkt_Handle = SrcPkt_Handle;
390 FIFO->Records[WriteIndex].DstPkt_Handle = DstPkt_Handle;
391
392 FIFO->Records[WriteIndex].Token_Handle = Token_Handle;
393 if (!DMABuf_Handle_IsSame(&Token_Handle, &DMABuf_NULLHandle))
394 {
395 FIFO->Records[WriteIndex].Bypass_WordCount = Bypass_WordCount;
396 }
397
398 WriteIndex += 1;
399 if (WriteIndex == FIFO->Size)
400 WriteIndex = 0;
401 FIFO->WriteIndex = WriteIndex;
402 return true;
403}
404
405
406/*----------------------------------------------------------------------------
407 * Adapter_FIFO_Get
408 *
409 * Get and remove the oldest entry from the side channel FIFO.
410 */
411static bool
412Adapter_FIFO_Get(AdapterPEC_SideChannelFIFO_t *FIFO,
413 void **User_p,
414 DMABuf_Handle_t *SrcPkt_Handle_p,
415 DMABuf_Handle_t *DstPkt_Handle_p,
416 DMABuf_Handle_t *Token_Handle_p,
417 unsigned int *Bypass_WordCount_p)
418{
419 int WriteIndex = FIFO->WriteIndex;
420 int ReadIndex = FIFO->ReadIndex;
421 if (WriteIndex == ReadIndex)
422 {
423 LOG_CRIT("Trying to read from empty FIFO\n");
424 return false;
425 }
426 if (User_p)
427 *User_p = FIFO->Records[ReadIndex].User_p;
428 if (SrcPkt_Handle_p)
429 *SrcPkt_Handle_p = FIFO->Records[ReadIndex].SrcPkt_Handle;
430 *DstPkt_Handle_p = FIFO->Records[ReadIndex].DstPkt_Handle;
431
432 if (Token_Handle_p)
433 *Token_Handle_p = FIFO->Records[ReadIndex].Token_Handle;
434 if (Token_Handle_p != NULL &&
435 !DMABuf_Handle_IsSame(Token_Handle_p, &DMABuf_NULLHandle) &&
436 Bypass_WordCount_p != NULL)
437 *Bypass_WordCount_p = FIFO->Records[ReadIndex].Bypass_WordCount;
438
439 ReadIndex += 1;
440 if (ReadIndex == FIFO->Size)
441 ReadIndex = 0;
442 FIFO->ReadIndex = ReadIndex;
443 return true;
444}
445
446
447/*----------------------------------------------------------------------------
448 * Adapter_FIFO_Withdraw
449 *
450 * Withdraw the most recently added record from the side channel FIFO.
451 */
452static void
453Adapter_FIFO_Withdraw(
454 AdapterPEC_SideChannelFIFO_t *FIFO)
455{
456 int WriteIndex = FIFO->WriteIndex;
457 if (WriteIndex == FIFO->ReadIndex)
458 {
459 LOG_CRIT("Adapter_FIFO_Withdraw: FIFO is empty\n");
460 }
461 if (WriteIndex == 0)
462 WriteIndex = FIFO->Size - 1;
463 else
464 WriteIndex -= 1;
465 FIFO->WriteIndex = WriteIndex;
466}
467
468
469/* Adapter_Packet_Prepare
470 *
471 * In case of bounce buffers, allocate bounce buffers for the packet and
472 * the packet token.
473 * Copy source packet and token into the bounce buffers.
474 * Perform PreDMA on all packet buffers (source, destination and token).
475 */
476static PEC_Status_t
477Adapter_Packet_Prepare(
478 const unsigned int InterfaceId,
479 const PEC_CommandDescriptor_t *Cmd_p)
480{
481 DMAResource_Handle_t SrcPkt_Handle, DstPkt_Handle, Token_Handle;
482#ifdef ADAPTER_PEC_ENABLE_SCATTERGATHER
483 unsigned int ParticleCount;
484 unsigned int i;
485 DMABuf_Handle_t ParticleHandle;
486 DMAResource_Handle_t DMARes_Handle;
487 uint8_t * DummyPtr;
488 unsigned int ParticleSize;
489#endif
490
491 SrcPkt_Handle =
492 Adapter_DMABuf_Handle2DMAResourceHandle(Cmd_p->SrcPkt_Handle);
493 DstPkt_Handle =
494 Adapter_DMABuf_Handle2DMAResourceHandle(Cmd_p->DstPkt_Handle);
495 Token_Handle = Adapter_DMABuf_Handle2DMAResourceHandle(Cmd_p->Token_Handle);
496
497 if (!DMAResource_IsValidHandle(SrcPkt_Handle) &&
498 !DMAResource_IsValidHandle(DstPkt_Handle))
499 return PEC_STATUS_OK; // For record invalidation in the Record Cache
500 else if (!DMAResource_IsValidHandle(SrcPkt_Handle) ||
501 (!DMAResource_IsValidHandle(DstPkt_Handle) &&
502 !PEC_ContinuousScatter[InterfaceId]))
503 {
504 LOG_CRIT("PEC_Packet_Put: invalid source or destination handle\n");
505 return PEC_ERROR_BAD_PARAMETER;
506 }
507
508 // Token handle
509 if (DMAResource_IsValidHandle(Token_Handle))
510 {
511#ifndef ADAPTER_PEC_REMOVE_BOUNCEBUFFERS
512 DMAResource_Record_t * Rec_p =
513 DMAResource_Handle2RecordPtr(Token_Handle);
514 if (Adapter_DMAResource_IsForeignAllocated(Token_Handle))
515 {
516 // Bounce buffer required.
517 DMAResource_AddrPair_t BounceHostAddr;
518 void * HostAddr;
519 int dmares;
520 DMAResource_Properties_t BounceProperties;
521
522 // used as uint32_t array
523 BounceProperties.Alignment = Adapter_DMAResource_Alignment_Get();
524 BounceProperties.Bank = ADAPTER_PEC_BANK_TOKEN;
525 BounceProperties.fCached = false;
526 BounceProperties.Size = Rec_p->Props.Size;
527
528 HostAddr = Adapter_DMAResource_HostAddr(Token_Handle);
529
530 dmares = DMAResource_Alloc(
531 BounceProperties,
532 &BounceHostAddr,
533 &Rec_p->bounce.Bounce_Handle);
534
535 // bounce buffer handle is stored in the DMA Resource Record
536 // of the original buffer, which links the two
537 // this will be used when freeing the buffer
538 // but also when obtaining the bus address.
539
540 if (dmares != 0)
541 {
542 LOG_CRIT(
543 "PEC_Packet_Put: "
544 "Failed to alloc bounce buffer (error %d)\n",
545 dmares);
546 return PEC_ERROR_INTERNAL; // error!
547 }
548
549 LOG_INFO(
550 "PEC_Packet_Putr: "
551 "Bouncing Token: %p to %p\n",
552 Token_Handle,
553 Rec_p->bounce.Bounce_Handle);
554
555 // copy the data to the bounce buffer
556 memcpy(
557 BounceHostAddr.Address_p,
558 HostAddr,
559 Rec_p->Props.Size);
560
561 Token_Handle = Rec_p->bounce.Bounce_Handle;
562 }
563 else
564 {
565 Rec_p->bounce.Bounce_Handle = NULL;
566 }
567#endif // !ADAPTER_PEC_REMOVE_BOUNCEBUFFERS
568
569#ifdef ADAPTER_PEC_ARMRING_ENABLE_SWAP
570 // Convert token data to packet engine endianness format
571 DMAResource_SwapEndianness_Set(Token_Handle, true);
572
573 DMAResource_Write32Array(
574 Token_Handle,
575 0,
576 Cmd_p->Token_WordCount,
577 Adapter_DMAResource_HostAddr(Token_Handle));
578#endif // ADAPTER_PEC_ARMRING_ENABLE_SWAP
579
580 DMAResource_PreDMA(Token_Handle, 0, 0);
581 }
582
583 // Source packet handle
584#ifdef ADAPTER_PEC_ENABLE_SCATTERGATHER
585 PEC_SGList_GetCapacity(Cmd_p->SrcPkt_Handle, &ParticleCount);
586
587 if (ParticleCount > 0)
588 {
589 for (i=0; i<ParticleCount; i++)
590 {
591 PEC_SGList_Read(Cmd_p->SrcPkt_Handle,
592 i,
593 &ParticleHandle,
594 &ParticleSize,
595 &DummyPtr);
596 DMARes_Handle =
597 Adapter_DMABuf_Handle2DMAResourceHandle(ParticleHandle);
598 DMAResource_PreDMA(DMARes_Handle, 0, 0);
599 }
600 }
601 else
602#endif
603 { // Not a gather packet,
604#ifndef ADAPTER_PEC_REMOVE_BOUNCEBUFFERS
605 DMAResource_Record_t * Rec_p =
606 DMAResource_Handle2RecordPtr(SrcPkt_Handle);
607 DMAResource_Record_t * Dst_Rec_p =
608 DMAResource_Handle2RecordPtr(DstPkt_Handle);
609 if (Adapter_DMAResource_IsForeignAllocated(SrcPkt_Handle) ||
610 Adapter_DMAResource_IsForeignAllocated(DstPkt_Handle))
611 {
612 // Bounce buffer required. Use a single bounce buffer for
613 // both the source and the destination packet.
614 DMAResource_AddrPair_t BounceHostAddr;
615 void * HostAddr;
616 int dmares;
617 DMAResource_Properties_t BounceProperties;
618
619 // used as uint32_t array
620 BounceProperties.Alignment = Adapter_DMAResource_Alignment_Get();
621 BounceProperties.Bank = ADAPTER_PEC_BANK_PACKET;
622 BounceProperties.fCached = false;
623 BounceProperties.Size = MAX(Rec_p->Props.Size,
624 Dst_Rec_p->Props.Size);
625
626 HostAddr = Adapter_DMAResource_HostAddr(SrcPkt_Handle);
627
628 dmares = DMAResource_Alloc(
629 BounceProperties,
630 &BounceHostAddr,
631 &Rec_p->bounce.Bounce_Handle);
632
633 // bounce buffer handle is stored in the DMA Resource Record
634 // of the original buffer, which links the two
635 // this will be used when freeing the buffer
636 // but also when obtaining the bus address.
637
638 if (dmares != 0)
639 {
640 LOG_CRIT(
641 "PEC_Packet_Put: "
642 "Failed to alloc bounce buffer (error %d)\n",
643 dmares);
644 return PEC_ERROR_INTERNAL; // error!
645 }
646 LOG_INFO(
647 "PEC_Packet_Putr: "
648 "Bouncing Packet: %p to %p\n",
649 SrcPkt_Handle,
650 Rec_p->bounce.Bounce_Handle);
651
652
653 // copy the data to the bounce buffer
654 memcpy(
655 BounceHostAddr.Address_p,
656 HostAddr,
657 Rec_p->Props.Size);
658
659 DstPkt_Handle = SrcPkt_Handle = Rec_p->bounce.Bounce_Handle;
660
661 Dst_Rec_p->bounce.Bounce_Handle = Rec_p->bounce.Bounce_Handle;
662 }
663 else
664 {
665 Rec_p->bounce.Bounce_Handle = NULL;
666 Dst_Rec_p->bounce.Bounce_Handle = NULL;
667 }
668#endif
669 DMAResource_PreDMA(SrcPkt_Handle, 0, 0);
670 }
671 // Destination packet handle, not for continuous scatter.
672 if (PEC_ContinuousScatter[InterfaceId])
673 return PEC_STATUS_OK;
674#ifdef ADAPTER_PEC_ENABLE_SCATTERGATHER
675 PEC_SGList_GetCapacity(Cmd_p->DstPkt_Handle, &ParticleCount);
676
677 if (ParticleCount > 0)
678 {
679 for (i=0; i<ParticleCount; i++)
680 {
681 PEC_SGList_Read(Cmd_p->DstPkt_Handle,
682 i,
683 &ParticleHandle,
684 &ParticleSize,
685 &DummyPtr);
686 DMARes_Handle =
687 Adapter_DMABuf_Handle2DMAResourceHandle(ParticleHandle);
688 DMAResource_PreDMA(DMARes_Handle, 0, 0);
689 }
690 }
691 else
692#endif
693 if (SrcPkt_Handle != DstPkt_Handle)
694 {
695 // Only if source and destination are distinct.
696 // When bounce buffers were used, these are not distinct.
697 DMAResource_PreDMA(DstPkt_Handle, 0, 0);
698 }
699 return PEC_STATUS_OK;
700}
701
702
703/* Adapter_Packet_Finalize
704 *
705 * Perform PostDMA on all DMA buffers (source, destination and token).
706 * Copy the destination packet from the bounce buffer into the final location.
707 * Deallocate any bounce buffers (packet and token).
708 */
709static PEC_Status_t
710Adapter_Packet_Finalize(
711 DMABuf_Handle_t DMABuf_SrcPkt_Handle,
712 DMABuf_Handle_t DMABuf_DstPkt_Handle,
713 DMABuf_Handle_t DMABuf_Token_Handle)
714{
715 DMAResource_Handle_t SrcPkt_Handle, DstPkt_Handle, Token_Handle;
716
717#ifdef ADAPTER_PEC_ENABLE_SCATTERGATHER
718 unsigned int ParticleCount;
719 unsigned int i;
720 DMABuf_Handle_t ParticleHandle;
721 DMAResource_Handle_t DMARes_Handle;
722 uint8_t * DummyPtr;
723 unsigned int ParticleSize;
724#endif
725
726 SrcPkt_Handle =
727 Adapter_DMABuf_Handle2DMAResourceHandle(DMABuf_SrcPkt_Handle);
728 DstPkt_Handle =
729 Adapter_DMABuf_Handle2DMAResourceHandle(DMABuf_DstPkt_Handle);
730
731 if (!DMAResource_IsValidHandle(SrcPkt_Handle) &&
732 !DMAResource_IsValidHandle(DstPkt_Handle))
733 return PEC_STATUS_OK; // For record invalidation in the Record Cache
734
735 Token_Handle = Adapter_DMABuf_Handle2DMAResourceHandle(DMABuf_Token_Handle);
736
737 // Token Handle.
738 if (DMAResource_IsValidHandle(Token_Handle))
739 {
740#ifndef ADAPTER_PEC_REMOVE_BOUNCEBUFFERS
741 DMAResource_Record_t * Rec_p =
742 DMAResource_Handle2RecordPtr(Token_Handle);
743 if (Rec_p->bounce.Bounce_Handle != NULL)
744 {
745 // Post DMA and release the bounce buffer.
746 DMAResource_PostDMA(Rec_p->bounce.Bounce_Handle, 0, 0);
747 DMAResource_Release(Rec_p->bounce.Bounce_Handle);
748 }
749 else
750#endif
751 {
752 DMAResource_PostDMA(Token_Handle, 0, 0);
753 }
754 }
755 // Destination packet handle
756
757#ifdef ADAPTER_PEC_ENABLE_SCATTERGATHER
758 PEC_SGList_GetCapacity(DMABuf_DstPkt_Handle, &ParticleCount);
759
760 if (ParticleCount > 0)
761 {
762 for (i=0; i<ParticleCount; i++)
763 {
764 PEC_SGList_Read(DMABuf_DstPkt_Handle,
765 i,
766 &ParticleHandle,
767 &ParticleSize,
768 &DummyPtr);
769 DMARes_Handle =
770 Adapter_DMABuf_Handle2DMAResourceHandle(ParticleHandle);
771 DMAResource_PostDMA(DMARes_Handle, 0, 0);
772 }
773 }
774 else
775#endif
776 {
777#ifndef ADAPTER_PEC_REMOVE_BOUNCEBUFFERS
778 DMAResource_Record_t * Rec_p =
779 DMAResource_Handle2RecordPtr(DstPkt_Handle);
780 void * HostAddr = Adapter_DMAResource_HostAddr(DstPkt_Handle);
781 if (Rec_p->bounce.Bounce_Handle != NULL)
782 {
783 void * BounceHostAddr =
784 Adapter_DMAResource_HostAddr(Rec_p->bounce.Bounce_Handle);
785 // Post DMA, copy and release the bounce buffer.
786 DMAResource_PostDMA(Rec_p->bounce.Bounce_Handle, 0, 0);
787
788 memcpy( HostAddr, BounceHostAddr, Rec_p->Props.Size);
789
790 DMAResource_Release(Rec_p->bounce.Bounce_Handle);
791 SrcPkt_Handle = DstPkt_Handle;
792 }
793 else
794#endif
795 {
796 DMAResource_PostDMA(DstPkt_Handle, 0, 0);
797 }
798
799 }
800 // Source packet handle
801#ifdef ADAPTER_PEC_ENABLE_SCATTERGATHER
802 PEC_SGList_GetCapacity(DMABuf_SrcPkt_Handle, &ParticleCount);
803
804 if (ParticleCount > 0)
805 {
806 for (i=0; i<ParticleCount; i++)
807 {
808 PEC_SGList_Read(DMABuf_SrcPkt_Handle,
809 i,
810 &ParticleHandle,
811 &ParticleSize,
812 &DummyPtr);
813 DMARes_Handle =
814 Adapter_DMABuf_Handle2DMAResourceHandle(ParticleHandle);
815 DMAResource_PostDMA(DMARes_Handle, 0, 0);
816 }
817 }
818 else
819#endif
820 if (SrcPkt_Handle != DstPkt_Handle)
821 {
822 // Only if source and destination are distinct.
823 // When bounce buffers were used, these are not distinct.
824 DMAResource_PostDMA(SrcPkt_Handle, 0, 0);
825 }
826
827 return PEC_STATUS_OK;
828}
829
830
831#ifdef ADAPTER_PEC_RPM_EIP202_DEVICE0_ID
832/*----------------------------------------------------------------------------
833 * AdapterPEC_Resume
834 */
835static int
836AdapterPEC_Resume(void * p)
837{
838 int InterfaceId = *(int *)p;
839
840 if (InterfaceId < 0 || InterfaceId < ADAPTER_PEC_RPM_EIP202_DEVICE0_ID)
841 return -3; // error
842
843 InterfaceId -= ADAPTER_PEC_RPM_EIP202_DEVICE0_ID;
844
845 return Adapter_PECDev_Resume(InterfaceId);
846}
847
848
849/*----------------------------------------------------------------------------
850 * AdapterPEC_Suspend
851 */
852static int
853AdapterPEC_Suspend(void * p)
854{
855 int InterfaceId = *(int *)p;
856
857 if (InterfaceId < 0 || InterfaceId < ADAPTER_PEC_RPM_EIP202_DEVICE0_ID)
858 return -3; // error
859
860 InterfaceId -= ADAPTER_PEC_RPM_EIP202_DEVICE0_ID;
861
862 return Adapter_PECDev_Suspend(InterfaceId);
863}
864#endif
865
866
867/*----------------------------------------------------------------------------
868 * PEC_Capabilities_Get
869 */
870PEC_Status_t
871PEC_Capabilities_Get(
872 PEC_Capabilities_t * const Capabilities_p)
873{
874 return Adapter_PECDev_Capabilities_Get(Capabilities_p);
875}
876
877
878/*----------------------------------------------------------------------------
879 * PEC_Init
880 */
881PEC_Status_t
882PEC_Init(
883 const unsigned int InterfaceId,
884 const PEC_InitBlock_t * const InitBlock_p)
885{
886 LOG_INFO("\n\t PEC_Init \n");
887
888 if (!InitBlock_p)
889 return PEC_ERROR_BAD_PARAMETER;
890
891 if (InterfaceId >= ADAPTER_PEC_DEVICE_COUNT)
892 return PEC_ERROR_BAD_PARAMETER;
893
894 Adapter_Lock_CS_Set(&AdapterPEC_InitCS, &AdapterPEC_InitLock);
895
896 if (!Adapter_Lock_CS_Enter(&AdapterPEC_InitCS))
897 return PEC_STATUS_BUSY;
898
899 // ensure we init only once
900 if (PEC_IsInitialized[InterfaceId])
901 {
902 Adapter_Lock_CS_Leave(&AdapterPEC_InitCS);
903 return PEC_STATUS_OK;
904 }
905 PEC_ContinuousScatter[InterfaceId] = InitBlock_p->fContinuousScatter;
906
907 // Allocate the Put lock
908 AdapterPEC_PutLock[InterfaceId] = Adapter_Lock_Alloc();
909 if (AdapterPEC_PutLock[InterfaceId] == NULL)
910 {
911 LOG_CRIT("PEC_Init: PutLock allocation failed\n");
912 Adapter_Lock_CS_Leave(&AdapterPEC_InitCS);
913 return PEC_ERROR_INTERNAL;
914 }
915 Adapter_Lock_CS_Set(&AdapterPEC_PutCS[InterfaceId],
916 AdapterPEC_PutLock[InterfaceId]);
917
918 // Allocate the Get lock
919 AdapterPEC_GetLock[InterfaceId] = Adapter_Lock_Alloc();
920 if (AdapterPEC_GetLock[InterfaceId] == NULL)
921 {
922 LOG_CRIT("PEC_Init: GetLock allocation failed\n");
923 Adapter_Lock_Free(AdapterPEC_PutLock[InterfaceId]);
924 Adapter_Lock_CS_Leave(&AdapterPEC_InitCS);
925 return PEC_ERROR_INTERNAL;
926 }
927 Adapter_Lock_CS_Set(&AdapterPEC_GetCS[InterfaceId],
928 AdapterPEC_GetLock[InterfaceId]);
929
930 ZEROINIT(PEC_Notify[InterfaceId]);
931
932 if (RPM_DEVICE_INIT_START_MACRO(ADAPTER_PEC_RPM_EIP202_DEVICE0_ID + InterfaceId,
933 AdapterPEC_Suspend,
934 AdapterPEC_Resume) != RPM_SUCCESS)
935 return PEC_ERROR_INTERNAL;
936
937 // Init the device
938 if (Adapter_PECDev_Init(InterfaceId, InitBlock_p) != PEC_STATUS_OK)
939 {
940 (void)RPM_DEVICE_INIT_STOP_MACRO(ADAPTER_PEC_RPM_EIP202_DEVICE0_ID + InterfaceId);
941 LOG_CRIT("PEC_Init: Adapter_PECDev_Init failed\n");
942 Adapter_Lock_Free(AdapterPEC_PutLock[InterfaceId]);
943 Adapter_Lock_Free(AdapterPEC_GetLock[InterfaceId]);
944 Adapter_Lock_CS_Leave(&AdapterPEC_InitCS);
945 return PEC_ERROR_INTERNAL;
946 }
947
948 (void)RPM_DEVICE_INIT_STOP_MACRO(ADAPTER_PEC_RPM_EIP202_DEVICE0_ID + InterfaceId);
949
950 Adapter_SideChannelFIFO[InterfaceId].Size =
951 sizeof(Adapter_SideChannelFIFO[InterfaceId].Records) /
952 sizeof(Adapter_SideChannelFIFO[InterfaceId].Records[0]);
953 Adapter_SideChannelFIFO[InterfaceId].WriteIndex = 0;
954 Adapter_SideChannelFIFO[InterfaceId].ReadIndex = 0;
955
956#ifdef ADAPTER_PEC_INTERRUPTS_ENABLE
957 // enable the descriptor done interrupt
958 LOG_INFO("PEC_Init: Registering interrupt handler\n");
959
960 Adapter_PECDev_SetResultHandler(
961 InterfaceId,
962 AdapterPEC_InterruptHandlerResultNotify);
963
964 Adapter_PECDev_SetCommandHandler(
965 InterfaceId,
966 AdapterPEC_InterruptHandlerCommandNotify);
967#endif /* ADAPTER_PEC_INTERRUPTS_ENABLE */
968
969 PEC_IsInitialized[InterfaceId] = true;
970
971 LOG_INFO("\n\t PEC_Init done \n");
972
973 Adapter_Lock_CS_Leave(&AdapterPEC_InitCS);
974
975 return PEC_STATUS_OK;
976}
977
978
979/*----------------------------------------------------------------------------
980 * PEC_UnInit
981 */
982PEC_Status_t
983PEC_UnInit(
984 const unsigned int InterfaceId)
985{
986 LOG_INFO("\n\t PEC_UnInit \n");
987
988 if (InterfaceId >= ADAPTER_PEC_DEVICE_COUNT)
989 return PEC_ERROR_BAD_PARAMETER;
990
991 Adapter_Lock_CS_Set(&AdapterPEC_InitCS, &AdapterPEC_InitLock);
992
993 if (!Adapter_Lock_CS_Enter(&AdapterPEC_InitCS))
994 return PEC_STATUS_BUSY;
995
996 // ensure we uninit only once
997 if (!PEC_IsInitialized[InterfaceId])
998 {
999 Adapter_Lock_CS_Leave(&AdapterPEC_InitCS);
1000 return PEC_STATUS_OK;
1001 }
1002
1003 if (!Adapter_Lock_CS_Enter(&AdapterPEC_PutCS[InterfaceId]))
1004 {
1005 Adapter_Lock_CS_Leave(&AdapterPEC_InitCS);
1006 return PEC_STATUS_BUSY;
1007 }
1008
1009 if (!Adapter_Lock_CS_Enter(&AdapterPEC_GetCS[InterfaceId]))
1010 {
1011 Adapter_Lock_CS_Leave(&AdapterPEC_PutCS[InterfaceId]);
1012 Adapter_Lock_CS_Leave(&AdapterPEC_InitCS);
1013 return PEC_STATUS_BUSY;
1014 }
1015
1016 if (RPM_DEVICE_UNINIT_START_MACRO(ADAPTER_PEC_RPM_EIP202_DEVICE0_ID + InterfaceId,
1017 true) != RPM_SUCCESS)
1018 {
1019 Adapter_Lock_CS_Leave(&AdapterPEC_PutCS[InterfaceId]);
1020 Adapter_Lock_CS_Leave(&AdapterPEC_InitCS);
1021 return PEC_ERROR_INTERNAL;
1022 }
1023
1024#ifdef ADAPTER_PEC_INTERRUPTS_ENABLE
1025 Adapter_PECDev_Disable_ResultIRQ(InterfaceId);
1026 Adapter_PECDev_Disable_CommandIRQ(InterfaceId);
1027#endif
1028
1029 Adapter_PECDev_UnInit(InterfaceId);
1030
1031 PEC_IsInitialized[InterfaceId] = false;
1032
1033 (void)RPM_DEVICE_UNINIT_STOP_MACRO(ADAPTER_PEC_RPM_EIP202_DEVICE0_ID + InterfaceId);
1034
1035 Adapter_Lock_CS_Leave(&AdapterPEC_GetCS[InterfaceId]);
1036 Adapter_Lock_CS_Leave(&AdapterPEC_PutCS[InterfaceId]);
1037
1038 // Free Get lock
1039 Adapter_Lock_Free(Adapter_Lock_CS_Get(&AdapterPEC_GetCS[InterfaceId]));
1040 Adapter_Lock_CS_Set(&AdapterPEC_GetCS[InterfaceId], Adapter_Lock_NULL);
1041
1042 // Free Put lock
1043 Adapter_Lock_Free(Adapter_Lock_CS_Get(&AdapterPEC_PutCS[InterfaceId]));
1044 Adapter_Lock_CS_Set(&AdapterPEC_PutCS[InterfaceId], Adapter_Lock_NULL);
1045
1046 LOG_INFO("\n\t PEC_UnInit done \n");
1047
1048 Adapter_Lock_CS_Leave(&AdapterPEC_InitCS);
1049
1050 return PEC_STATUS_OK;
1051}
1052
1053
1054/*----------------------------------------------------------------------------
1055 * PEC_SA_Register
1056 */
1057PEC_Status_t
1058PEC_SA_Register(
1059 const unsigned int InterfaceId,
1060 DMABuf_Handle_t SA_Handle1,
1061 DMABuf_Handle_t SA_Handle2,
1062 DMABuf_Handle_t SA_Handle3)
1063{
1064 DMAResource_Handle_t DMAHandle1, DMAHandle2, DMAHandle3;
1065 PEC_Status_t res;
1066
1067 LOG_INFO("\n\t PEC_SA_Register \n");
1068
1069 IDENTIFIER_NOT_USED(InterfaceId);
1070
1071 DMAHandle1 = Adapter_DMABuf_Handle2DMAResourceHandle(SA_Handle1);
1072 DMAHandle2 = Adapter_DMABuf_Handle2DMAResourceHandle(SA_Handle2);
1073 DMAHandle3 = Adapter_DMABuf_Handle2DMAResourceHandle(SA_Handle3);
1074
1075 // The SA, State Record and ARC4 State Record are arrays of uint32_t.
1076 // The caller provides them in host-native format.
1077 // This function converts them to device-native format
1078 // using DMAResource and in-place operations.
1079
1080 // Endianness conversion for the 1st SA memory block (Main SA Record)
1081#ifdef ADAPTER_PEC_ARMRING_ENABLE_SWAP
1082 {
1083 DMAResource_Record_t * const Rec_p =
1084 DMAResource_Handle2RecordPtr(DMAHandle1);
1085
1086 if (Rec_p == NULL)
1087 return PEC_ERROR_INTERNAL;
1088
1089 DMAResource_SwapEndianness_Set(DMAHandle1, true);
1090
1091 DMAResource_Write32Array(
1092 DMAHandle1,
1093 0,
1094 Rec_p->Props.Size / 4,
1095 Adapter_DMAResource_HostAddr(DMAHandle1));
1096 }
1097
1098 // Endianness conversion for the 2nd SA memory block (State Record)
1099 if (DMAHandle2 != NULL)
1100 {
1101 DMAResource_Record_t * const Rec_p =
1102 DMAResource_Handle2RecordPtr(DMAHandle2);
1103
1104 if (Rec_p == NULL)
1105 return PEC_ERROR_INTERNAL;
1106
1107 // The 2nd SA memory block can never be a subset of
1108 // the 1st SA memory block so it is safe to perform
1109 // the endianness conversion
1110 DMAResource_SwapEndianness_Set(DMAHandle2, true);
1111
1112 DMAResource_Write32Array(
1113 DMAHandle2,
1114 0,
1115 Rec_p->Props.Size / 4,
1116 Adapter_DMAResource_HostAddr(DMAHandle2));
1117 }
1118
1119 // Endianness conversion for the 3d SA memory block (ARC4 State Record)
1120 if (DMAHandle3 != NULL)
1121 {
1122 DMAResource_Record_t * const Rec_p =
1123 DMAResource_Handle2RecordPtr(DMAHandle3);
1124
1125 if (Rec_p == NULL)
1126 return PEC_ERROR_INTERNAL;
1127
1128 // The 3d SA memory block can never be a subset of
1129 // the 2nd SA memory block.
1130
1131 // Check if the 3d SA memory block is not a subset of the 1st one
1132 if (!Adapter_DMAResource_IsSubRangeOf(DMAHandle3, DMAHandle1))
1133 {
1134 // The 3d SA memory block is a separate buffer and does not
1135 // overlap with the 1st SA memory block,
1136 // so the endianness conversion must be done
1137 DMAResource_SwapEndianness_Set(DMAHandle3, true);
1138
1139 DMAResource_Write32Array(
1140 DMAHandle3,
1141 0,
1142 Rec_p->Props.Size / 4,
1143 Adapter_DMAResource_HostAddr(DMAHandle3));
1144 }
1145 }
1146#endif // ADAPTER_PEC_ARMRING_ENABLE_SWAP
1147
1148#ifndef ADAPTER_PEC_REMOVE_BOUNCEBUFFERS
1149 // Bounce the SA buffers if required
1150 // Check if the 3d SA memory block is not a subset of the 1st one
1151 if (DMAHandle3 != NULL &&
1152 !Adapter_DMAResource_IsSubRangeOf(DMAHandle3, DMAHandle1))
1153 {
1154 if (!Adapter_PECRegisterSA_BounceIfRequired(&DMAHandle3))
1155 return PEC_ERROR_INTERNAL;
1156 }
1157
1158 if (!Adapter_PECRegisterSA_BounceIfRequired(&DMAHandle1))
1159 return PEC_ERROR_INTERNAL;
1160
1161 if (!Adapter_PECRegisterSA_BounceIfRequired(&DMAHandle2))
1162 return PEC_ERROR_INTERNAL;
1163#endif
1164
1165 res = Adapter_PECDev_SA_Prepare(SA_Handle1, SA_Handle2, SA_Handle3);
1166 if (res != PEC_STATUS_OK)
1167 {
1168 LOG_WARN(
1169 "PEC_SA_Register: "
1170 "Adapter_PECDev_PrepareSA returned %d\n",
1171 res);
1172 return PEC_ERROR_INTERNAL;
1173 }
1174
1175 // now use DMAResource to ensure the engine
1176 // can read the memory blocks using DMA
1177 DMAResource_PreDMA(DMAHandle1, 0, 0); // 0,0 = "entire buffer"
1178
1179 if (DMAHandle2 != NULL)
1180 DMAResource_PreDMA(DMAHandle2, 0, 0);
1181
1182 // Check if the 3d SA memory block is not a subset of the 1st one
1183 if (DMAHandle3 != NULL &&
1184 !Adapter_DMAResource_IsSubRangeOf(DMAHandle3, DMAHandle1))
1185 DMAResource_PreDMA(DMAHandle3, 0, 0);
1186
1187 LOG_INFO("\n\t PEC_SA_Register done \n");
1188
1189 return PEC_STATUS_OK;
1190}
1191
1192
1193/*----------------------------------------------------------------------------
1194 * PEC_SA_UnRegister
1195 */
1196PEC_Status_t
1197PEC_SA_UnRegister(
1198 const unsigned int InterfaceId,
1199 DMABuf_Handle_t SA_Handle1,
1200 DMABuf_Handle_t SA_Handle2,
1201 DMABuf_Handle_t SA_Handle3)
1202{
1203 DMAResource_Handle_t SA_Handle[3];
1204 PEC_Status_t res;
1205 int i, MaxHandles;
1206
1207 LOG_INFO("\n\t PEC_SA_UnRegister \n");
1208
1209 IDENTIFIER_NOT_USED(InterfaceId);
1210
1211 res = Adapter_PECDev_SA_Remove(SA_Handle1, SA_Handle2, SA_Handle3);
1212 if (res != PEC_STATUS_OK)
1213 {
1214 LOG_CRIT(
1215 "PEC_SA_UnRegister: "
1216 "Adapter_PECDev_SA_Remove returned %d\n",
1217 res);
1218 return PEC_ERROR_INTERNAL;
1219 }
1220
1221 SA_Handle[0] = Adapter_DMABuf_Handle2DMAResourceHandle(SA_Handle1);
1222 SA_Handle[1] = Adapter_DMABuf_Handle2DMAResourceHandle(SA_Handle2);
1223 SA_Handle[2] = Adapter_DMABuf_Handle2DMAResourceHandle(SA_Handle3);
1224
1225 // Check if the 3d SA memory block is not a subset of the 1st one
1226 if (SA_Handle[0] != NULL &&
1227 SA_Handle[2] != NULL &&
1228 Adapter_DMAResource_IsSubRangeOf(SA_Handle[2], SA_Handle[0]))
1229 MaxHandles = 2;
1230 else
1231 MaxHandles = 3;
1232
1233 for (i = 0; i < MaxHandles; i++)
1234 {
1235 if (DMAResource_IsValidHandle(SA_Handle[i]))
1236 {
1237 DMAResource_Handle_t DMAHandle = SA_Handle[i];
1238 void *HostAddr;
1239 DMAResource_Record_t * Rec_p =
1240 DMAResource_Handle2RecordPtr(DMAHandle);
1241
1242 // Check if a bounce buffer is in use
1243#ifndef ADAPTER_PEC_REMOVE_BOUNCEBUFFERS
1244 void * OrigHostAddr;
1245 DMAResource_Record_t * HostRec_p = Rec_p;
1246
1247 OrigHostAddr = Adapter_DMAResource_HostAddr(DMAHandle);
1248
1249 if (Adapter_DMAResource_IsForeignAllocated(SA_Handle[i]))
1250 {
1251 // Get bounce buffer handle and its record
1252 DMAHandle = HostRec_p->bounce.Bounce_Handle;
1253 Rec_p = DMAResource_Handle2RecordPtr(DMAHandle);
1254 }
1255#endif /* ADAPTER_PEC_REMOVE_BOUNCEBUFFERS */
1256
1257 HostAddr = Adapter_DMAResource_HostAddr(DMAHandle);
1258 // ensure we look at valid engine-written data
1259 // 0,0 = "entire buffer"
1260 DMAResource_PostDMA(DMAHandle, 0, 0);
1261
1262 // convert to host format
1263 if (Rec_p != NULL)
1264 DMAResource_Read32Array(
1265 DMAHandle,
1266 0,
1267 Rec_p->Props.Size / 4,
1268 HostAddr);
1269
1270 // copy from bounce buffer to original buffer
1271#ifndef ADAPTER_PEC_REMOVE_BOUNCEBUFFERS
1272 if (Adapter_DMAResource_IsForeignAllocated(SA_Handle[i]) &&
1273 HostRec_p != NULL)
1274 {
1275 // copy the data from bounce to original buffer
1276 memcpy(
1277 OrigHostAddr,
1278 HostAddr,
1279 HostRec_p->Props.Size);
1280
1281 // free the bounce handle
1282 DMAResource_Release(HostRec_p->bounce.Bounce_Handle);
1283 HostRec_p->bounce.Bounce_Handle = NULL;
1284 }
1285#endif /* ADAPTER_PEC_REMOVE_BOUNCEBUFFERS */
1286 } // if handle valid
1287 } // for
1288
1289 LOG_INFO("\n\t PEC_SA_UnRegister done\n");
1290
1291 return PEC_STATUS_OK;
1292}
1293
1294
1295/*----------------------------------------------------------------------------
1296 * PEC_Packet_Put
1297 */
1298PEC_Status_t
1299PEC_Packet_Put(
1300 const unsigned int InterfaceId,
1301 const PEC_CommandDescriptor_t * Commands_p,
1302 const unsigned int CommandsCount,
1303 unsigned int * const PutCount_p)
1304{
1305 unsigned int CmdLp;
1306 unsigned int PktCnt;
1307 unsigned int CmdDescriptorCount;
1308 PEC_Status_t res = 0, res2, PEC_Rc = PEC_STATUS_OK;
1309 unsigned int FreeSlots;
1310
1311 LOG_INFO("\n\t PEC_Packet_Put \n");
1312
1313 if (InterfaceId >= ADAPTER_PEC_DEVICE_COUNT)
1314 return PEC_ERROR_BAD_PARAMETER;
1315
1316#ifdef ADAPTER_PEC_STRICT_ARGS
1317 if (Commands_p == NULL ||
1318 CommandsCount == 0 ||
1319 PutCount_p == NULL)
1320 {
1321 return PEC_ERROR_BAD_PARAMETER;
1322 }
1323#endif
1324
1325 // initialize the output parameters
1326 *PutCount_p = 0;
1327
1328#ifdef ADAPTER_PEC_STRICT_ARGS
1329 // validate the descriptors
1330 // (error out before bounce buffer allocation)
1331 for (CmdLp = 0; CmdLp < CommandsCount; CmdLp++)
1332 if (Commands_p[CmdLp].Bypass_WordCount > 255)
1333 return PEC_ERROR_BAD_PARAMETER;
1334#endif /* ADAPTER_PEC_STRICT_ARGS */
1335
1336 if (!Adapter_Lock_CS_Enter(&AdapterPEC_PutCS[InterfaceId]))
1337 return PEC_STATUS_BUSY;
1338
1339 if (!PEC_IsInitialized[InterfaceId])
1340 {
1341 Adapter_Lock_CS_Leave(&AdapterPEC_PutCS[InterfaceId]);
1342 return PEC_ERROR_BAD_USE_ORDER;
1343 }
1344
1345 CmdDescriptorCount = MIN(ADAPTER_PEC_MAX_LOGICDESCR, CommandsCount);
1346 FreeSlots = 0;
1347 CmdLp = 0;
1348 while (CmdLp < CmdDescriptorCount)
1349 {
1350 unsigned int j;
1351 unsigned int count;
1352 unsigned int NonSGPackets;
1353
1354#ifndef ADAPTER_PEC_ENABLE_SCATTERGATHER
1355 NonSGPackets = CmdDescriptorCount - CmdLp;
1356 // All remaining packets are non-SG.
1357#else
1358 unsigned int GatherParticles;
1359 unsigned int ScatterParticles;
1360 unsigned int i;
1361
1362 for (i = CmdLp; i < CmdDescriptorCount; i++)
1363 {
1364 PEC_SGList_GetCapacity(Commands_p[i].SrcPkt_Handle,
1365 &GatherParticles);
1366 if (PEC_ContinuousScatter[InterfaceId])
1367 ScatterParticles = 0;
1368 else
1369 PEC_SGList_GetCapacity(Commands_p[i].DstPkt_Handle,
1370 &ScatterParticles);
1371 if ( GatherParticles > 0 || ScatterParticles > 0)
1372 break;
1373 }
1374 NonSGPackets = i - CmdLp;
1375
1376 if (NonSGPackets == 0)
1377 {
1378 bool fSuccess;
1379
1380 if (RPM_DEVICE_IO_START_MACRO(ADAPTER_PEC_RPM_EIP202_DEVICE0_ID +
1381 InterfaceId,
1382 RPM_FLAG_SYNC) != RPM_SUCCESS)
1383 {
1384 PEC_Rc = PEC_ERROR_INTERNAL;
1385 break;
1386 }
1387
1388 // First packet found is scatter gather.
1389 fSuccess = Adapter_PECDev_TestSG(InterfaceId,
1390 GatherParticles,
1391 ScatterParticles);
1392
1393 (void)RPM_DEVICE_IO_STOP_MACRO(ADAPTER_PEC_RPM_EIP202_DEVICE0_ID +
1394 InterfaceId,
1395 RPM_FLAG_ASYNC);
1396
1397 if (!fSuccess)
1398 {
1399 PEC_Rc = PEC_ERROR_INTERNAL;
1400 break;
1401 }
1402
1403 // Process a single SG packet in this iteration.
1404 FreeSlots = 1;
1405 }
1406 else
1407#endif
1408 if (FreeSlots == 0)
1409 {
1410 if (RPM_DEVICE_IO_START_MACRO(ADAPTER_PEC_RPM_EIP202_DEVICE0_ID +
1411 InterfaceId,
1412 RPM_FLAG_SYNC) != RPM_SUCCESS)
1413 {
1414 PEC_Rc = PEC_ERROR_INTERNAL;
1415 break;
1416 }
1417
1418 // Allow all non-SG packets to be processed in this iteration,
1419 // but limited by the number of free slots in the ring(s).
1420 FreeSlots = Adapter_PECDev_GetFreeSpace(InterfaceId);
1421
1422 (void)RPM_DEVICE_IO_STOP_MACRO(ADAPTER_PEC_RPM_EIP202_DEVICE0_ID +
1423 InterfaceId,
1424 RPM_FLAG_ASYNC);
1425
1426 if (FreeSlots > NonSGPackets)
1427 FreeSlots = NonSGPackets;
1428
1429 if (FreeSlots == 0)
1430 break;
1431 }
1432
1433 for (PktCnt=0; PktCnt<FreeSlots; PktCnt++)
1434 {
1435 res = Adapter_Packet_Prepare(InterfaceId,
1436 Commands_p + CmdLp + PktCnt);
1437 if (res != PEC_STATUS_OK)
1438 {
1439 LOG_CRIT("%s: Adapter_Packet_Prepare error %d\n", __func__, res);
1440 PEC_Rc = res;
1441 break;
1442 }
1443
1444 if (!PEC_ContinuousScatter[InterfaceId])
1445 {
1446 Adapter_FIFO_Put(&(Adapter_SideChannelFIFO[InterfaceId]),
1447 Commands_p[CmdLp+PktCnt].User_p,
1448 Commands_p[CmdLp+PktCnt].SrcPkt_Handle,
1449 Commands_p[CmdLp+PktCnt].DstPkt_Handle,
1450 Commands_p[CmdLp+PktCnt].Token_Handle,
1451 Commands_p[CmdLp+PktCnt].Bypass_WordCount);
1452 }
1453 }
1454
1455 // RPM_Device_IO_Start() must be called for each successfully submitted
1456 // packet
1457 for (j = 0; j < PktCnt; j++)
1458 {
1459 // Skipped error checking to reduce code complexity
1460 (void)RPM_DEVICE_IO_START_MACRO(ADAPTER_PEC_RPM_EIP202_DEVICE0_ID +
1461 InterfaceId,
1462 RPM_FLAG_SYNC);
1463 }
1464
1465 res2 = Adapter_PECDev_Packet_Put(InterfaceId,
1466 Commands_p + CmdLp,
1467 PktCnt,
1468 &count);
1469 if (res2 != PEC_STATUS_OK)
1470 {
1471 LOG_CRIT("%s: Adapter_PECDev_Packet_Put error %d\n", __func__, res2);
1472 PEC_Rc = res2;
1473 }
1474
1475 FreeSlots -= count;
1476 *PutCount_p += count;
1477
1478 if (count < PktCnt)
1479 {
1480 LOG_WARN("PEC_Packet_Put: withdrawing %d prepared packets\n",
1481 PktCnt - count);
1482
1483 for (j = count; j < PktCnt; j++)
1484 {
1485 if (!PEC_ContinuousScatter[InterfaceId])
1486 {
1487 Adapter_FIFO_Withdraw(&(Adapter_SideChannelFIFO[InterfaceId]));
1488 Adapter_Packet_Finalize(Commands_p[CmdLp + j].SrcPkt_Handle,
1489 Commands_p[CmdLp + j].DstPkt_Handle,
1490 Commands_p[CmdLp + j].Token_Handle);
1491 }
1492
1493 // RPM_DEVICE_IO_STOP_MACRO() must be called here for packets
1494 // which could not be successfully submitted,
1495 // for example because device queue was full
1496 (void)RPM_DEVICE_IO_STOP_MACRO(ADAPTER_PEC_RPM_EIP202_DEVICE0_ID +
1497 InterfaceId,
1498 RPM_FLAG_ASYNC);
1499 }
1500 break;
1501 }
1502
1503 CmdLp += count;
1504
1505 if (res != PEC_STATUS_OK || res2 != PEC_STATUS_OK)
1506 {
1507 PEC_Rc = PEC_ERROR_INTERNAL;
1508 break;
1509 }
1510 } // while
1511
1512 LOG_INFO("\n\t PEC_Packet_Put done \n");
1513
1514 Adapter_Lock_CS_Leave(&AdapterPEC_PutCS[InterfaceId]);
1515
1516 return PEC_Rc;
1517}
1518
1519
1520/*----------------------------------------------------------------------------
1521 * PEC_Packet_Get
1522 */
1523PEC_Status_t
1524PEC_Packet_Get(
1525 const unsigned int InterfaceId,
1526 PEC_ResultDescriptor_t * Results_p,
1527 const unsigned int ResultsLimit,
1528 unsigned int * const GetCount_p)
1529{
1530 LOG_INFO("\n\t PEC_Packet_Get \n");
1531
1532 if (InterfaceId >= ADAPTER_PEC_DEVICE_COUNT)
1533 return PEC_ERROR_BAD_PARAMETER;
1534
1535#ifdef ADAPTER_PEC_STRICT_ARGS
1536 if (Results_p == NULL ||
1537 GetCount_p == NULL ||
1538 ResultsLimit == 0)
1539 {
1540 return PEC_ERROR_BAD_PARAMETER;
1541 }
1542#endif
1543
1544 // initialize the output parameter
1545 *GetCount_p = 0;
1546
1547 if (!Adapter_Lock_CS_Enter(&AdapterPEC_GetCS[InterfaceId]))
1548 return PEC_STATUS_BUSY;
1549
1550 if (!PEC_IsInitialized[InterfaceId])
1551 {
1552 Adapter_Lock_CS_Leave(&AdapterPEC_GetCS[InterfaceId]);
1553 return PEC_ERROR_BAD_USE_ORDER;
1554 }
1555
1556 // read descriptors from PEC device
1557 {
1558 PEC_Status_t res;
1559 unsigned int ResLp;
1560 unsigned int Limit = MIN(ResultsLimit, ADAPTER_PEC_MAX_LOGICDESCR);
1561 unsigned int count;
1562 DMABuf_Handle_t Token_Handle = DMABuf_NULLHandle;
1563
1564 res=Adapter_PECDev_Packet_Get(InterfaceId,
1565 Results_p,
1566 Limit,
1567 &count);
1568 if (res != PEC_STATUS_OK)
1569 {
1570 LOG_CRIT("PEC_Packet_Get() returned error: %d\n", res);
1571 Adapter_Lock_CS_Leave(&AdapterPEC_GetCS[InterfaceId]);
1572 return res;
1573 }
1574
1575 for (ResLp = 0; ResLp < count; ResLp++)
1576 {
1577 // To help CommandNotifyCB
1578 if (ResLp == count-1)
1579 Adapter_MakeCommandNotify_CallBack(InterfaceId);
1580
1581 (void)RPM_DEVICE_IO_STOP_MACRO(ADAPTER_PEC_RPM_EIP202_DEVICE0_ID +
1582 InterfaceId,
1583 RPM_FLAG_ASYNC);
1584 if (PEC_ContinuousScatter[InterfaceId])
1585 {
1586 unsigned int i;
1587 DMABuf_Handle_t DestHandle = DMABuf_NULLHandle;
1588 DMAResource_Handle_t DMARes_Handle;
1589 if (Results_p[ResLp].NumParticles == 1)
1590 {
1591 /* No real scatter, can fixup using single destination
1592 handle */
1593 Adapter_FIFO_Get(&Adapter_SideChannelFIFO[InterfaceId],
1594 NULL,
1595 NULL,
1596 &DestHandle,
1597 NULL,
1598 NULL);
1599 DMARes_Handle =
1600 Adapter_DMABuf_Handle2DMAResourceHandle(DestHandle);
1601 DMAResource_PostDMA(DMARes_Handle, 0, 0);
1602#ifdef ADAPTER_AUTO_FIXUP
1603 IOToken_Fixup(Results_p[ResLp].OutputToken_p,
1604 DestHandle);
1605#endif
1606 Results_p[ResLp].User_p = NULL;
1607 Results_p[ResLp].SrcPkt_Handle = DMABuf_NULLHandle;
1608 Results_p[ResLp].DstPkt_Handle = DestHandle;
1609 Results_p[ResLp].Bypass_WordCount = 0;
1610 if (!DMABuf_Handle_IsSame(&Results_p[ResLp].DstPkt_Handle,
1611 &DMABuf_NULLHandle))
1612 {
1613 Results_p[ResLp].DstPkt_p =
1614 Adapter_DMAResource_HostAddr(
1615 Adapter_DMABuf_Handle2DMAResourceHandle(
1616 Results_p[ResLp].DstPkt_Handle));
1617 }
1618 else
1619 {
1620 Results_p[ResLp].DstPkt_p = NULL;
1621 }
1622 }
1623 else
1624 {
1625#if defined(ADAPTER_PEC_ENABLE_SCATTERGATHER) && defined(ADAPTER_AUTO_FIXUP)
1626 DMAResource_Record_t * Rec_p;
1627 PEC_Status_t PEC_Rc;
1628 DMABuf_Handle_t Fixup_SGList; /* scatter list for Fixup in continuous scatter mode */
1629 PEC_Rc = PEC_SGList_Create(Results_p[ResLp].NumParticles,
1630 &Fixup_SGList);
1631#endif
1632 for (i = 0; i < Results_p[ResLp].NumParticles; i++)
1633 {
1634 Adapter_FIFO_Get(&Adapter_SideChannelFIFO[InterfaceId],
1635 NULL,
1636 NULL,
1637 &DestHandle,
1638 NULL,
1639 NULL);
1640 DMARes_Handle =
1641 Adapter_DMABuf_Handle2DMAResourceHandle(DestHandle);
1642 DMAResource_PostDMA(DMARes_Handle, 0, 0);
1643#if defined(ADAPTER_PEC_ENABLE_SCATTERGATHER) && defined(ADAPTER_AUTO_FIXUP)
1644 if (PEC_Rc == PEC_STATUS_OK)
1645 {
1646 Rec_p = DMAResource_Handle2RecordPtr(DMARes_Handle);
1647
1648 PEC_SGList_Write(Fixup_SGList,
1649 i,
1650 DestHandle,
1651 Rec_p->Props.Size);
1652 }
1653#endif
1654 }
1655#if defined(ADAPTER_PEC_ENABLE_SCATTERGATHER) && defined(ADAPTER_AUTO_FIXUP)
1656 if (PEC_Rc == PEC_STATUS_OK)
1657 {
1658 IOToken_Fixup(Results_p[ResLp].OutputToken_p,
1659 Fixup_SGList);
1660 PEC_SGList_Destroy(Fixup_SGList);
1661 }
1662
1663#endif
1664 Results_p[ResLp].User_p = NULL;
1665 Results_p[ResLp].SrcPkt_Handle = DMABuf_NULLHandle;
1666 Results_p[ResLp].DstPkt_Handle = DMABuf_NULLHandle;
1667 Results_p[ResLp].Bypass_WordCount = 0;
1668 }
1669 }
1670 else
1671 {
1672 Adapter_FIFO_Get(&(Adapter_SideChannelFIFO[InterfaceId]),
1673 &(Results_p[ResLp].User_p),
1674 &(Results_p[ResLp].SrcPkt_Handle),
1675 &(Results_p[ResLp].DstPkt_Handle),
1676 &Token_Handle,
1677 &(Results_p[ResLp].Bypass_WordCount));
1678
1679 Adapter_Packet_Finalize(Results_p[ResLp].SrcPkt_Handle,
1680 Results_p[ResLp].DstPkt_Handle,
1681 Token_Handle);
1682#ifdef ADAPTER_AUTO_FIXUP
1683 IOToken_Fixup(Results_p[ResLp].OutputToken_p,
1684 Results_p[ResLp].DstPkt_Handle);
1685#endif
1686
1687 if (!DMABuf_Handle_IsSame(&Results_p[ResLp].DstPkt_Handle,
1688 &DMABuf_NULLHandle))
1689 {
1690 Results_p[ResLp].DstPkt_p =
1691 Adapter_DMAResource_HostAddr(
1692 Adapter_DMABuf_Handle2DMAResourceHandle(
1693 Results_p[ResLp].DstPkt_Handle));
1694 }
1695 else
1696 {
1697 Results_p[ResLp].DstPkt_p = NULL;
1698 }
1699 }
1700 *GetCount_p += 1;
1701 } // for
1702 }
1703
1704 LOG_INFO("\n\t PEC_Packet_Get done \n");
1705
1706 Adapter_Lock_CS_Leave(&AdapterPEC_GetCS[InterfaceId]);
1707
1708 return PEC_STATUS_OK;
1709}
1710
1711
1712/*----------------------------------------------------------------------------
1713 * PEC_CD_Control_Write
1714 *
1715 * Write the Control1 and Control2 engine-specific fields in the
1716 * Command Descriptor The other fields (such as SrcPkt_ByteCount and
1717 * Bypass_WordCount must have been filled in already.
1718 *
1719 * Command_p (input, output)
1720 * Command descriptor whose Control1 and Control2 fields must be filled in.
1721 *
1722 * PacketParams_p (input)
1723 * Per-packet parameters.
1724 *
1725 * This function is not implemented for all engine types.
1726 */
1727PEC_Status_t
1728PEC_CD_Control_Write(
1729 PEC_CommandDescriptor_t *Command_p,
1730 const PEC_PacketParams_t *PacketParams_p)
1731{
1732 return Adapter_PECDev_CD_Control_Write(Command_p, PacketParams_p);
1733}
1734
1735
1736/*----------------------------------------------------------------------------
1737 * PEC_RD_Status_Read
1738 */
1739PEC_Status_t
1740PEC_RD_Status_Read(
1741 const PEC_ResultDescriptor_t * const Result_p,
1742 PEC_ResultStatus_t * const ResultStatus_p)
1743{
1744 return Adapter_PECDev_RD_Status_Read(Result_p, ResultStatus_p);
1745}
1746
1747
1748/*----------------------------------------------------------------------------
1749 * PEC_CommandNotify_Request
1750 */
1751PEC_Status_t
1752PEC_CommandNotify_Request(
1753 const unsigned int InterfaceId,
1754 PEC_NotifyFunction_t CBFunc_p,
1755 const unsigned int CommandsCount)
1756{
1757 unsigned int PacketSlotsEmptyCount;
1758
1759 LOG_INFO("\n\t PEC_CommandNotify_Request \n");
1760
1761 if (InterfaceId >= ADAPTER_PEC_DEVICE_COUNT)
1762 return PEC_ERROR_BAD_PARAMETER;
1763
1764 if (CBFunc_p == NULL ||
1765 CommandsCount == 0 ||
1766 CommandsCount > ADAPTER_PEC_MAX_PACKETS)
1767 {
1768 return PEC_ERROR_BAD_PARAMETER;
1769 }
1770
1771 if (!PEC_IsInitialized[InterfaceId])
1772 return PEC_ERROR_BAD_USE_ORDER;
1773
1774 if (RPM_DEVICE_IO_START_MACRO(ADAPTER_PEC_RPM_EIP202_DEVICE0_ID + InterfaceId,
1775 RPM_FLAG_SYNC) != RPM_SUCCESS)
1776 return PEC_ERROR_INTERNAL;
1777
1778 PacketSlotsEmptyCount = Adapter_PECDev_GetFreeSpace(InterfaceId);
1779
1780 (void)RPM_DEVICE_IO_STOP_MACRO(ADAPTER_PEC_RPM_EIP202_DEVICE0_ID + InterfaceId,
1781 RPM_FLAG_ASYNC);
1782
1783 if (CommandsCount <= PacketSlotsEmptyCount)
1784 {
1785 LOG_INFO(
1786 "PEC_CommandNotify_Request: "
1787 "Invoking command notify callback immediately\n");
1788
1789 CBFunc_p();
1790 }
1791 else
1792 {
1793 PEC_Notify[InterfaceId].CommandsCount = CommandsCount;
1794 PEC_Notify[InterfaceId].CommandNotifyCB_p = CBFunc_p;
1795
1796#ifdef ADAPTER_PEC_INTERRUPTS_ENABLE
1797 if (RPM_DEVICE_IO_START_MACRO(ADAPTER_PEC_RPM_EIP202_DEVICE0_ID + InterfaceId,
1798 RPM_FLAG_SYNC) != RPM_SUCCESS)
1799 return PEC_ERROR_INTERNAL;
1800
1801 /* Note that space for new commands may have become available before
1802 * the call to PEC_CommandNotify_Request and the associated interrupt
1803 * may already be pending. In this case the interrupt will occur
1804 * immediately.
1805 */
1806 Adapter_PECDev_Enable_CommandIRQ(InterfaceId);
1807
1808 (void)RPM_DEVICE_IO_STOP_MACRO(ADAPTER_PEC_RPM_EIP202_DEVICE0_ID + InterfaceId,
1809 RPM_FLAG_ASYNC);
1810#endif /* ADAPTER_PEC_INTERRUPTS_ENABLE */
1811 }
1812
1813 LOG_INFO("\n\t PEC_CommandNotify_Request done \n");
1814
1815 return PEC_STATUS_OK;
1816}
1817
1818
1819/*----------------------------------------------------------------------------
1820 * PEC_ResultNotify_Request
1821 */
1822PEC_Status_t
1823PEC_ResultNotify_Request(
1824 const unsigned int InterfaceId,
1825 PEC_NotifyFunction_t CBFunc_p,
1826 const unsigned int ResultsCount)
1827{
1828 LOG_INFO("\n\t PEC_ResultNotify_Request \n");
1829
1830 if (InterfaceId >= ADAPTER_PEC_DEVICE_COUNT)
1831 return PEC_ERROR_BAD_PARAMETER;
1832
1833 if (CBFunc_p == NULL ||
1834 ResultsCount == 0 ||
1835 ResultsCount > ADAPTER_PEC_MAX_PACKETS)
1836 {
1837 return PEC_ERROR_BAD_PARAMETER;
1838 }
1839
1840 if (!PEC_IsInitialized[InterfaceId])
1841 return PEC_ERROR_BAD_USE_ORDER;
1842
1843 // install it
1844 PEC_Notify[InterfaceId].ResultsCount = ResultsCount;
1845 PEC_Notify[InterfaceId].ResultNotifyCB_p = CBFunc_p;
1846
1847#ifdef ADAPTER_PEC_INTERRUPTS_ENABLE
1848 if (RPM_DEVICE_IO_START_MACRO(ADAPTER_PEC_RPM_EIP202_DEVICE0_ID + InterfaceId,
1849 RPM_FLAG_SYNC) != RPM_SUCCESS)
1850 return PEC_ERROR_INTERNAL;
1851
1852 /* Note that results may have become available before the call
1853 to PEC_ResultNotify_Request and the associated interrupts may already
1854 be pending. In this case the interrupt will occur immediately.
1855 */
1856 Adapter_PECDev_Enable_ResultIRQ(InterfaceId);
1857
1858 (void)RPM_DEVICE_IO_STOP_MACRO(ADAPTER_PEC_RPM_EIP202_DEVICE0_ID + InterfaceId,
1859 RPM_FLAG_ASYNC);
1860#endif /* ADAPTER_PEC_INTERRUPTS_ENABLE */
1861
1862 LOG_INFO("\n\t PEC_ResultNotify_Request done\n");
1863
1864 return PEC_STATUS_OK;
1865}
1866
1867
1868/*----------------------------------------------------------------------------
1869 * PEC_Scatter_Preload
1870 */
1871PEC_Status_t
1872PEC_Scatter_Preload(
1873 const unsigned int InterfaceId,
1874 DMABuf_Handle_t * Handles_p,
1875 const unsigned int HandlesCount,
1876 unsigned int * const AcceptedCount_p)
1877{
1878 PEC_Status_t rc;
1879 unsigned int i;
1880 unsigned int HandlesToUse,ri,wi;
1881 LOG_INFO("\n\t PEC_Scatter_Preload\n");
1882
1883 if (InterfaceId >= ADAPTER_PEC_DEVICE_COUNT)
1884 return PEC_ERROR_BAD_PARAMETER;
1885
1886 if (!Adapter_Lock_CS_Enter(&AdapterPEC_PutCS[InterfaceId]))
1887 return PEC_STATUS_BUSY;
1888
1889 if (!PEC_IsInitialized[InterfaceId] || !PEC_ContinuousScatter[InterfaceId])
1890 {
1891 Adapter_Lock_CS_Leave(&AdapterPEC_PutCS[InterfaceId]);
1892 return PEC_ERROR_BAD_USE_ORDER;
1893 }
1894 ri = Adapter_SideChannelFIFO[InterfaceId].ReadIndex;
1895 wi = Adapter_SideChannelFIFO[InterfaceId].WriteIndex;
1896 // Compute the number of free slots in the ring from the read/write index
1897 // of the side channel FIFO (which is larger than the ring)
1898 if (wi >= ri)
1899 HandlesToUse = ADAPTER_PEC_MAX_PACKETS - 1 - wi + ri ;
1900 else
1901 HandlesToUse = ADAPTER_PEC_MAX_PACKETS - 1
1902 - Adapter_SideChannelFIFO[InterfaceId].Size - wi + ri;
1903 if (HandlesToUse > ADAPTER_PEC_MAX_LOGICDESCR)
1904 HandlesToUse = ADAPTER_PEC_MAX_LOGICDESCR;
1905 if (HandlesToUse > HandlesCount)
1906 HandlesToUse = HandlesCount;
1907 for (i=0; i < HandlesToUse; i++)
1908 {
1909 DMAResource_Handle_t DMARes_Handle =
1910 Adapter_DMABuf_Handle2DMAResourceHandle(Handles_p[i]);
1911 DMAResource_PreDMA(DMARes_Handle, 0, 0);
1912 Adapter_FIFO_Put(&Adapter_SideChannelFIFO[InterfaceId],
1913 NULL,
1914 DMABuf_NULLHandle,
1915 Handles_p[i],
1916 DMABuf_NULLHandle,
1917 0);
1918 }
1919 rc = Adapter_PECDev_Scatter_Preload(InterfaceId,
1920 Handles_p,
1921 HandlesToUse);
1922
1923 *AcceptedCount_p = HandlesToUse;
1924 Adapter_Lock_CS_Leave(&AdapterPEC_PutCS[InterfaceId]);
1925 return rc;
1926}
1927
1928
1929/*----------------------------------------------------------------------------
1930 * PEC_Scatter_PreloadNotify_Request
1931 */
1932PEC_Status_t
1933PEC_Scatter_PreloadNotify_Request(
1934 const unsigned int InterfaceId,
1935 PEC_NotifyFunction_t CBFunc_p,
1936 const unsigned int ConsumedCount)
1937{
1938 IDENTIFIER_NOT_USED(InterfaceId);
1939 IDENTIFIER_NOT_USED(CBFunc_p);
1940 IDENTIFIER_NOT_USED(ConsumedCount);
1941
1942 return PEC_ERROR_NOT_IMPLEMENTED;
1943}
1944
1945
1946/*----------------------------------------------------------------------------
1947 * PEC_Put_Dump
1948 */
1949void
1950PEC_Put_Dump(
1951 const unsigned int InterfaceId,
1952 const unsigned int FirstSlotId,
1953 const unsigned int LastSlotId,
1954 const bool fDumpRDRAdmin,
1955 const bool fDumpRDRCache)
1956{
1957 Adapter_PECDev_Put_Dump(InterfaceId,
1958 FirstSlotId,
1959 LastSlotId,
1960 fDumpRDRAdmin,
1961 fDumpRDRCache);
1962}
1963
1964
1965
1966
1967/*----------------------------------------------------------------------------
1968 * PEC_Get_Dump
1969 */
1970void
1971PEC_Get_Dump(
1972 const unsigned int InterfaceId,
1973 const unsigned int FirstSlotId,
1974 const unsigned int LastSlotId,
1975 const bool fDumpRDRAdmin,
1976 const bool fDumpRDRCache)
1977{
1978 Adapter_PECDev_Get_Dump(InterfaceId,
1979 FirstSlotId,
1980 LastSlotId,
1981 fDumpRDRAdmin,
1982 fDumpRDRCache);
1983}
1984
1985
1986#endif /* ADAPTER_PE_MODE_DHM */
1987
1988
1989/* end of file adapter_pec_dma.c */