xref: /freebsd/sys/contrib/ncsw/Peripherals/FM/Pcd/fm_replic.c (revision c2c014f24c10f90d85126ac5fbd4d8524de32b1c)
1*852ba100SJustin Hibbits /*
2*852ba100SJustin Hibbits  * Copyright 2008-2012 Freescale Semiconductor Inc.
3*852ba100SJustin Hibbits  *
4*852ba100SJustin Hibbits  * Redistribution and use in source and binary forms, with or without
5*852ba100SJustin Hibbits  * modification, are permitted provided that the following conditions are met:
6*852ba100SJustin Hibbits  *     * Redistributions of source code must retain the above copyright
7*852ba100SJustin Hibbits  *       notice, this list of conditions and the following disclaimer.
8*852ba100SJustin Hibbits  *     * Redistributions in binary form must reproduce the above copyright
9*852ba100SJustin Hibbits  *       notice, this list of conditions and the following disclaimer in the
10*852ba100SJustin Hibbits  *       documentation and/or other materials provided with the distribution.
11*852ba100SJustin Hibbits  *     * Neither the name of Freescale Semiconductor nor the
12*852ba100SJustin Hibbits  *       names of its contributors may be used to endorse or promote products
13*852ba100SJustin Hibbits  *       derived from this software without specific prior written permission.
14*852ba100SJustin Hibbits  *
15*852ba100SJustin Hibbits  *
16*852ba100SJustin Hibbits  * ALTERNATIVELY, this software may be distributed under the terms of the
17*852ba100SJustin Hibbits  * GNU General Public License ("GPL") as published by the Free Software
18*852ba100SJustin Hibbits  * Foundation, either version 2 of that License or (at your option) any
19*852ba100SJustin Hibbits  * later version.
20*852ba100SJustin Hibbits  *
21*852ba100SJustin Hibbits  * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
22*852ba100SJustin Hibbits  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23*852ba100SJustin Hibbits  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24*852ba100SJustin Hibbits  * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
25*852ba100SJustin Hibbits  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26*852ba100SJustin Hibbits  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27*852ba100SJustin Hibbits  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28*852ba100SJustin Hibbits  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29*852ba100SJustin Hibbits  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30*852ba100SJustin Hibbits  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31*852ba100SJustin Hibbits  */
32*852ba100SJustin Hibbits 
33*852ba100SJustin Hibbits 
34*852ba100SJustin Hibbits /******************************************************************************
35*852ba100SJustin Hibbits  @File          fm_replic.c
36*852ba100SJustin Hibbits 
37*852ba100SJustin Hibbits  @Description   FM frame replicator
38*852ba100SJustin Hibbits *//***************************************************************************/
39*852ba100SJustin Hibbits #include "std_ext.h"
40*852ba100SJustin Hibbits #include "error_ext.h"
41*852ba100SJustin Hibbits #include "string_ext.h"
42*852ba100SJustin Hibbits #include "debug_ext.h"
43*852ba100SJustin Hibbits #include "fm_pcd_ext.h"
44*852ba100SJustin Hibbits #include "fm_muram_ext.h"
45*852ba100SJustin Hibbits #include "fm_common.h"
46*852ba100SJustin Hibbits #include "fm_hc.h"
47*852ba100SJustin Hibbits #include "fm_replic.h"
48*852ba100SJustin Hibbits #include "fm_cc.h"
49*852ba100SJustin Hibbits #include "list_ext.h"
50*852ba100SJustin Hibbits 
51*852ba100SJustin Hibbits 
52*852ba100SJustin Hibbits /****************************************/
53*852ba100SJustin Hibbits /*       static functions               */
54*852ba100SJustin Hibbits /****************************************/
GetMemberPosition(t_FmPcdFrmReplicGroup * p_ReplicGroup,uint32_t memberIndex,bool isAddOperation)55*852ba100SJustin Hibbits static uint8_t  GetMemberPosition(t_FmPcdFrmReplicGroup *p_ReplicGroup,
56*852ba100SJustin Hibbits                                   uint32_t              memberIndex,
57*852ba100SJustin Hibbits                                   bool                  isAddOperation)
58*852ba100SJustin Hibbits {
59*852ba100SJustin Hibbits     uint8_t     memberPosition;
60*852ba100SJustin Hibbits     uint32_t    lastMemberIndex;
61*852ba100SJustin Hibbits 
62*852ba100SJustin Hibbits     ASSERT_COND(p_ReplicGroup);
63*852ba100SJustin Hibbits 
64*852ba100SJustin Hibbits     /* the last member index is different between add and remove operation -
65*852ba100SJustin Hibbits     in case of remove - this is exactly the last member index
66*852ba100SJustin Hibbits     in case of add - this is the last member index + 1 - e.g.
67*852ba100SJustin Hibbits     if we have 4 members, the index of the actual last member is 3(because the
68*852ba100SJustin Hibbits     index starts from 0) therefore in order to add a new member as the last
69*852ba100SJustin Hibbits     member we shall use memberIndex = 4 and not 3
70*852ba100SJustin Hibbits     */
71*852ba100SJustin Hibbits     if (isAddOperation)
72*852ba100SJustin Hibbits         lastMemberIndex = p_ReplicGroup->numOfEntries;
73*852ba100SJustin Hibbits     else
74*852ba100SJustin Hibbits         lastMemberIndex = p_ReplicGroup->numOfEntries-1;
75*852ba100SJustin Hibbits 
76*852ba100SJustin Hibbits     /* last */
77*852ba100SJustin Hibbits     if (memberIndex == lastMemberIndex)
78*852ba100SJustin Hibbits         memberPosition = FRM_REPLIC_LAST_MEMBER_INDEX;
79*852ba100SJustin Hibbits     else
80*852ba100SJustin Hibbits     {
81*852ba100SJustin Hibbits         /* first */
82*852ba100SJustin Hibbits         if (memberIndex == 0)
83*852ba100SJustin Hibbits             memberPosition = FRM_REPLIC_FIRST_MEMBER_INDEX;
84*852ba100SJustin Hibbits         else
85*852ba100SJustin Hibbits         {
86*852ba100SJustin Hibbits             /* middle */
87*852ba100SJustin Hibbits             ASSERT_COND(memberIndex < lastMemberIndex);
88*852ba100SJustin Hibbits             memberPosition = FRM_REPLIC_MIDDLE_MEMBER_INDEX;
89*852ba100SJustin Hibbits         }
90*852ba100SJustin Hibbits     }
91*852ba100SJustin Hibbits     return memberPosition;
92*852ba100SJustin Hibbits }
93*852ba100SJustin Hibbits 
MemberCheckParams(t_Handle h_FmPcd,t_FmPcdCcNextEngineParams * p_MemberParams)94*852ba100SJustin Hibbits static t_Error MemberCheckParams(t_Handle                  h_FmPcd,
95*852ba100SJustin Hibbits                                  t_FmPcdCcNextEngineParams *p_MemberParams)
96*852ba100SJustin Hibbits {
97*852ba100SJustin Hibbits     t_Error         err;
98*852ba100SJustin Hibbits 
99*852ba100SJustin Hibbits 
100*852ba100SJustin Hibbits     if ((p_MemberParams->nextEngine != e_FM_PCD_DONE) &&
101*852ba100SJustin Hibbits         (p_MemberParams->nextEngine != e_FM_PCD_KG)   &&
102*852ba100SJustin Hibbits         (p_MemberParams->nextEngine != e_FM_PCD_PLCR))
103*852ba100SJustin Hibbits         RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Next engine of a member should be MatchTable(cc) or Done or Policer"));
104*852ba100SJustin Hibbits 
105*852ba100SJustin Hibbits     /* check the regular parameters of the next engine */
106*852ba100SJustin Hibbits     err = ValidateNextEngineParams(h_FmPcd, p_MemberParams, e_FM_PCD_CC_STATS_MODE_NONE);
107*852ba100SJustin Hibbits     if (err)
108*852ba100SJustin Hibbits         RETURN_ERROR(MAJOR, err, ("member next engine parameters"));
109*852ba100SJustin Hibbits 
110*852ba100SJustin Hibbits     return E_OK;
111*852ba100SJustin Hibbits }
112*852ba100SJustin Hibbits 
CheckParams(t_Handle h_FmPcd,t_FmPcdFrmReplicGroupParams * p_ReplicGroupParam)113*852ba100SJustin Hibbits static t_Error CheckParams(t_Handle                     h_FmPcd,
114*852ba100SJustin Hibbits                            t_FmPcdFrmReplicGroupParams *p_ReplicGroupParam)
115*852ba100SJustin Hibbits {
116*852ba100SJustin Hibbits     int             i;
117*852ba100SJustin Hibbits     t_Error         err;
118*852ba100SJustin Hibbits 
119*852ba100SJustin Hibbits     /* check that max num of entries is at least 2 */
120*852ba100SJustin Hibbits     if (!IN_RANGE(2, p_ReplicGroupParam->maxNumOfEntries, FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES))
121*852ba100SJustin Hibbits         RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, ("maxNumOfEntries in the frame replicator parameters should be 2-%d",FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES));
122*852ba100SJustin Hibbits 
123*852ba100SJustin Hibbits     /* check that number of entries is greater than zero */
124*852ba100SJustin Hibbits     if (!p_ReplicGroupParam->numOfEntries)
125*852ba100SJustin Hibbits         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOFEntries in the frame replicator group should be greater than zero"));
126*852ba100SJustin Hibbits 
127*852ba100SJustin Hibbits     /* check that max num of entries is equal or greater than number of entries */
128*852ba100SJustin Hibbits     if (p_ReplicGroupParam->maxNumOfEntries < p_ReplicGroupParam->numOfEntries)
129*852ba100SJustin Hibbits         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("maxNumOfEntries should be equal or greater than numOfEntries"));
130*852ba100SJustin Hibbits 
131*852ba100SJustin Hibbits     for (i=0; i<p_ReplicGroupParam->numOfEntries; i++)
132*852ba100SJustin Hibbits     {
133*852ba100SJustin Hibbits         err = MemberCheckParams(h_FmPcd, &p_ReplicGroupParam->nextEngineParams[i]);
134*852ba100SJustin Hibbits         if (err)
135*852ba100SJustin Hibbits             RETURN_ERROR(MAJOR, err, ("member check parameters"));
136*852ba100SJustin Hibbits     }
137*852ba100SJustin Hibbits     return E_OK;
138*852ba100SJustin Hibbits }
139*852ba100SJustin Hibbits 
GetAvailableMember(t_FmPcdFrmReplicGroup * p_ReplicGroup)140*852ba100SJustin Hibbits static t_FmPcdFrmReplicMember *GetAvailableMember(t_FmPcdFrmReplicGroup *p_ReplicGroup)
141*852ba100SJustin Hibbits {
142*852ba100SJustin Hibbits     t_FmPcdFrmReplicMember  *p_ReplicMember = NULL;
143*852ba100SJustin Hibbits     t_List                  *p_Next;
144*852ba100SJustin Hibbits 
145*852ba100SJustin Hibbits     if (!LIST_IsEmpty(&p_ReplicGroup->availableMembersList))
146*852ba100SJustin Hibbits     {
147*852ba100SJustin Hibbits         p_Next = LIST_FIRST(&p_ReplicGroup->availableMembersList);
148*852ba100SJustin Hibbits         p_ReplicMember = LIST_OBJECT(p_Next, t_FmPcdFrmReplicMember, node);
149*852ba100SJustin Hibbits         ASSERT_COND(p_ReplicMember);
150*852ba100SJustin Hibbits         LIST_DelAndInit(p_Next);
151*852ba100SJustin Hibbits     }
152*852ba100SJustin Hibbits     return p_ReplicMember;
153*852ba100SJustin Hibbits }
154*852ba100SJustin Hibbits 
PutAvailableMember(t_FmPcdFrmReplicGroup * p_ReplicGroup,t_FmPcdFrmReplicMember * p_ReplicMember)155*852ba100SJustin Hibbits static void PutAvailableMember(t_FmPcdFrmReplicGroup    *p_ReplicGroup,
156*852ba100SJustin Hibbits                                t_FmPcdFrmReplicMember   *p_ReplicMember)
157*852ba100SJustin Hibbits {
158*852ba100SJustin Hibbits     LIST_AddToTail(&p_ReplicMember->node, &p_ReplicGroup->availableMembersList);
159*852ba100SJustin Hibbits }
160*852ba100SJustin Hibbits 
AddMemberToList(t_FmPcdFrmReplicGroup * p_ReplicGroup,t_FmPcdFrmReplicMember * p_CurrentMember,t_List * p_ListHead)161*852ba100SJustin Hibbits static void AddMemberToList(t_FmPcdFrmReplicGroup   *p_ReplicGroup,
162*852ba100SJustin Hibbits                             t_FmPcdFrmReplicMember  *p_CurrentMember,
163*852ba100SJustin Hibbits                             t_List                  *p_ListHead)
164*852ba100SJustin Hibbits {
165*852ba100SJustin Hibbits     LIST_Add(&p_CurrentMember->node, p_ListHead);
166*852ba100SJustin Hibbits 
167*852ba100SJustin Hibbits     p_ReplicGroup->numOfEntries++;
168*852ba100SJustin Hibbits }
169*852ba100SJustin Hibbits 
RemoveMemberFromList(t_FmPcdFrmReplicGroup * p_ReplicGroup,t_FmPcdFrmReplicMember * p_CurrentMember)170*852ba100SJustin Hibbits static void RemoveMemberFromList(t_FmPcdFrmReplicGroup  *p_ReplicGroup,
171*852ba100SJustin Hibbits                                  t_FmPcdFrmReplicMember *p_CurrentMember)
172*852ba100SJustin Hibbits {
173*852ba100SJustin Hibbits     ASSERT_COND(p_ReplicGroup->numOfEntries);
174*852ba100SJustin Hibbits     LIST_DelAndInit(&p_CurrentMember->node);
175*852ba100SJustin Hibbits     p_ReplicGroup->numOfEntries--;
176*852ba100SJustin Hibbits }
177*852ba100SJustin Hibbits 
LinkSourceToMember(t_FmPcdFrmReplicGroup * p_ReplicGroup,t_AdOfTypeContLookup * p_SourceTd,t_FmPcdFrmReplicMember * p_ReplicMember)178*852ba100SJustin Hibbits static void LinkSourceToMember(t_FmPcdFrmReplicGroup    *p_ReplicGroup,
179*852ba100SJustin Hibbits                                t_AdOfTypeContLookup     *p_SourceTd,
180*852ba100SJustin Hibbits                                t_FmPcdFrmReplicMember   *p_ReplicMember)
181*852ba100SJustin Hibbits {
182*852ba100SJustin Hibbits     t_FmPcd             *p_FmPcd;
183*852ba100SJustin Hibbits 
184*852ba100SJustin Hibbits     ASSERT_COND(p_SourceTd);
185*852ba100SJustin Hibbits     ASSERT_COND(p_ReplicMember);
186*852ba100SJustin Hibbits     ASSERT_COND(p_ReplicGroup);
187*852ba100SJustin Hibbits     ASSERT_COND(p_ReplicGroup->h_FmPcd);
188*852ba100SJustin Hibbits 
189*852ba100SJustin Hibbits     /* Link the first member in the group to the source TD */
190*852ba100SJustin Hibbits     p_FmPcd = p_ReplicGroup->h_FmPcd;
191*852ba100SJustin Hibbits 
192*852ba100SJustin Hibbits     WRITE_UINT32(p_SourceTd->matchTblPtr,
193*852ba100SJustin Hibbits         (uint32_t)(XX_VirtToPhys(p_ReplicMember->p_MemberAd) -
194*852ba100SJustin Hibbits                         p_FmPcd->physicalMuramBase));
195*852ba100SJustin Hibbits }
196*852ba100SJustin Hibbits 
LinkMemberToMember(t_FmPcdFrmReplicGroup * p_ReplicGroup,t_FmPcdFrmReplicMember * p_CurrentMember,t_FmPcdFrmReplicMember * p_NextMember)197*852ba100SJustin Hibbits static void LinkMemberToMember(t_FmPcdFrmReplicGroup    *p_ReplicGroup,
198*852ba100SJustin Hibbits                                t_FmPcdFrmReplicMember   *p_CurrentMember,
199*852ba100SJustin Hibbits                                t_FmPcdFrmReplicMember   *p_NextMember)
200*852ba100SJustin Hibbits {
201*852ba100SJustin Hibbits     t_AdOfTypeResult    *p_CurrReplicAd = (t_AdOfTypeResult*)p_CurrentMember->p_MemberAd;
202*852ba100SJustin Hibbits     t_AdOfTypeResult    *p_NextReplicAd = NULL;
203*852ba100SJustin Hibbits     t_FmPcd             *p_FmPcd;
204*852ba100SJustin Hibbits     uint32_t            offset = 0;
205*852ba100SJustin Hibbits 
206*852ba100SJustin Hibbits     /* Check if the next member exists or it's NULL (- means that this is the last member) */
207*852ba100SJustin Hibbits     if (p_NextMember)
208*852ba100SJustin Hibbits     {
209*852ba100SJustin Hibbits         p_NextReplicAd = (t_AdOfTypeResult*)p_NextMember->p_MemberAd;
210*852ba100SJustin Hibbits         p_FmPcd = p_ReplicGroup->h_FmPcd;
211*852ba100SJustin Hibbits         offset = (XX_VirtToPhys(p_NextReplicAd) - (p_FmPcd->physicalMuramBase));
212*852ba100SJustin Hibbits         offset = ((offset>>NEXT_FRM_REPLIC_ADDR_SHIFT)<< NEXT_FRM_REPLIC_MEMBER_INDEX_SHIFT);
213*852ba100SJustin Hibbits     }
214*852ba100SJustin Hibbits 
215*852ba100SJustin Hibbits     /* link the current AD to point to the AD of the next member */
216*852ba100SJustin Hibbits     WRITE_UINT32(p_CurrReplicAd->res, offset);
217*852ba100SJustin Hibbits }
218*852ba100SJustin Hibbits 
ModifyDescriptor(t_FmPcdFrmReplicGroup * p_ReplicGroup,void * p_OldDescriptor,void * p_NewDescriptor)219*852ba100SJustin Hibbits static t_Error ModifyDescriptor(t_FmPcdFrmReplicGroup   *p_ReplicGroup,
220*852ba100SJustin Hibbits                                 void                    *p_OldDescriptor,
221*852ba100SJustin Hibbits                                 void                    *p_NewDescriptor)
222*852ba100SJustin Hibbits {
223*852ba100SJustin Hibbits     t_Handle            h_Hc;
224*852ba100SJustin Hibbits     t_Error             err;
225*852ba100SJustin Hibbits     t_FmPcd             *p_FmPcd;
226*852ba100SJustin Hibbits 
227*852ba100SJustin Hibbits     ASSERT_COND(p_ReplicGroup);
228*852ba100SJustin Hibbits     ASSERT_COND(p_ReplicGroup->h_FmPcd);
229*852ba100SJustin Hibbits     ASSERT_COND(p_OldDescriptor);
230*852ba100SJustin Hibbits     ASSERT_COND(p_NewDescriptor);
231*852ba100SJustin Hibbits 
232*852ba100SJustin Hibbits     p_FmPcd = p_ReplicGroup->h_FmPcd;
233*852ba100SJustin Hibbits     h_Hc = FmPcdGetHcHandle(p_FmPcd);
234*852ba100SJustin Hibbits     if (!h_Hc)
235*852ba100SJustin Hibbits         RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("Host command"));
236*852ba100SJustin Hibbits 
237*852ba100SJustin Hibbits     err = FmHcPcdCcDoDynamicChange(h_Hc,
238*852ba100SJustin Hibbits                                    (uint32_t)(XX_VirtToPhys(p_OldDescriptor) - p_FmPcd->physicalMuramBase),
239*852ba100SJustin Hibbits                                    (uint32_t)(XX_VirtToPhys(p_NewDescriptor) - p_FmPcd->physicalMuramBase));
240*852ba100SJustin Hibbits     if (err)
241*852ba100SJustin Hibbits         RETURN_ERROR(MAJOR, err, ("Dynamic change host command"));
242*852ba100SJustin Hibbits 
243*852ba100SJustin Hibbits     return E_OK;
244*852ba100SJustin Hibbits }
245*852ba100SJustin Hibbits 
FillReplicAdOfTypeResult(void * p_ReplicAd,bool last)246*852ba100SJustin Hibbits static void FillReplicAdOfTypeResult(void *p_ReplicAd, bool last)
247*852ba100SJustin Hibbits {
248*852ba100SJustin Hibbits     t_AdOfTypeResult    *p_CurrReplicAd = (t_AdOfTypeResult*)p_ReplicAd;
249*852ba100SJustin Hibbits     uint32_t            tmp;
250*852ba100SJustin Hibbits 
251*852ba100SJustin Hibbits     tmp = GET_UINT32(p_CurrReplicAd->plcrProfile);
252*852ba100SJustin Hibbits     if (last)
253*852ba100SJustin Hibbits         /* clear the NL bit in case it's the last member in the group*/
254*852ba100SJustin Hibbits         WRITE_UINT32(p_CurrReplicAd->plcrProfile,(tmp & ~FRM_REPLIC_NL_BIT));
255*852ba100SJustin Hibbits     else
256*852ba100SJustin Hibbits         /* set the NL bit in case it's not the last member in the group */
257*852ba100SJustin Hibbits         WRITE_UINT32(p_CurrReplicAd->plcrProfile, (tmp |FRM_REPLIC_NL_BIT));
258*852ba100SJustin Hibbits 
259*852ba100SJustin Hibbits     /* set FR bit in the action descriptor */
260*852ba100SJustin Hibbits     tmp = GET_UINT32(p_CurrReplicAd->nia);
261*852ba100SJustin Hibbits     WRITE_UINT32(p_CurrReplicAd->nia,
262*852ba100SJustin Hibbits         (tmp | FRM_REPLIC_FR_BIT | FM_PCD_AD_RESULT_EXTENDED_MODE ));
263*852ba100SJustin Hibbits }
264*852ba100SJustin Hibbits 
BuildSourceTd(void * p_Ad)265*852ba100SJustin Hibbits static void BuildSourceTd(void *p_Ad)
266*852ba100SJustin Hibbits {
267*852ba100SJustin Hibbits     t_AdOfTypeContLookup    *p_SourceTd;
268*852ba100SJustin Hibbits 
269*852ba100SJustin Hibbits     ASSERT_COND(p_Ad);
270*852ba100SJustin Hibbits 
271*852ba100SJustin Hibbits     p_SourceTd = (t_AdOfTypeContLookup *)p_Ad;
272*852ba100SJustin Hibbits 
273*852ba100SJustin Hibbits     IOMemSet32((uint8_t*)p_SourceTd, 0, FM_PCD_CC_AD_ENTRY_SIZE);
274*852ba100SJustin Hibbits 
275*852ba100SJustin Hibbits     /* initialize the source table descriptor */
276*852ba100SJustin Hibbits     WRITE_UINT32(p_SourceTd->ccAdBase,     FM_PCD_AD_CONT_LOOKUP_TYPE);
277*852ba100SJustin Hibbits     WRITE_UINT32(p_SourceTd->pcAndOffsets, FRM_REPLIC_SOURCE_TD_OPCODE);
278*852ba100SJustin Hibbits }
279*852ba100SJustin Hibbits 
BuildShadowAndModifyDescriptor(t_FmPcdFrmReplicGroup * p_ReplicGroup,t_FmPcdFrmReplicMember * p_NextMember,t_FmPcdFrmReplicMember * p_CurrentMember,bool sourceDescriptor,bool last)280*852ba100SJustin Hibbits static t_Error BuildShadowAndModifyDescriptor(t_FmPcdFrmReplicGroup   *p_ReplicGroup,
281*852ba100SJustin Hibbits                                               t_FmPcdFrmReplicMember  *p_NextMember,
282*852ba100SJustin Hibbits                                               t_FmPcdFrmReplicMember  *p_CurrentMember,
283*852ba100SJustin Hibbits                                               bool                    sourceDescriptor,
284*852ba100SJustin Hibbits                                               bool                    last)
285*852ba100SJustin Hibbits {
286*852ba100SJustin Hibbits     t_FmPcd                 *p_FmPcd;
287*852ba100SJustin Hibbits     t_FmPcdFrmReplicMember  shadowMember;
288*852ba100SJustin Hibbits     t_Error                 err;
289*852ba100SJustin Hibbits 
290*852ba100SJustin Hibbits     ASSERT_COND(p_ReplicGroup);
291*852ba100SJustin Hibbits     ASSERT_COND(p_ReplicGroup->h_FmPcd);
292*852ba100SJustin Hibbits 
293*852ba100SJustin Hibbits     p_FmPcd = p_ReplicGroup->h_FmPcd;
294*852ba100SJustin Hibbits     ASSERT_COND(p_FmPcd->p_CcShadow);
295*852ba100SJustin Hibbits 
296*852ba100SJustin Hibbits     if (!TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock))
297*852ba100SJustin Hibbits         return ERROR_CODE(E_BUSY);
298*852ba100SJustin Hibbits 
299*852ba100SJustin Hibbits     if (sourceDescriptor)
300*852ba100SJustin Hibbits     {
301*852ba100SJustin Hibbits         BuildSourceTd(p_FmPcd->p_CcShadow);
302*852ba100SJustin Hibbits         LinkSourceToMember(p_ReplicGroup, p_FmPcd->p_CcShadow, p_NextMember);
303*852ba100SJustin Hibbits 
304*852ba100SJustin Hibbits         /* Modify the source table descriptor according to the prepared shadow descriptor */
305*852ba100SJustin Hibbits         err = ModifyDescriptor(p_ReplicGroup,
306*852ba100SJustin Hibbits                                p_ReplicGroup->p_SourceTd,
307*852ba100SJustin Hibbits                                p_FmPcd->p_CcShadow/* new prepared source td */);
308*852ba100SJustin Hibbits 
309*852ba100SJustin Hibbits         RELEASE_LOCK(p_FmPcd->shadowLock);
310*852ba100SJustin Hibbits         if (err)
311*852ba100SJustin Hibbits             RETURN_ERROR(MAJOR, err, ("Modify source Descriptor in BuildShadowAndModifyDescriptor"));
312*852ba100SJustin Hibbits 
313*852ba100SJustin Hibbits     }
314*852ba100SJustin Hibbits     else
315*852ba100SJustin Hibbits     {
316*852ba100SJustin Hibbits         IO2IOCpy32(p_FmPcd->p_CcShadow,
317*852ba100SJustin Hibbits                    p_CurrentMember->p_MemberAd,
318*852ba100SJustin Hibbits                    FM_PCD_CC_AD_ENTRY_SIZE);
319*852ba100SJustin Hibbits 
320*852ba100SJustin Hibbits         /* update the last bit in the shadow ad */
321*852ba100SJustin Hibbits         FillReplicAdOfTypeResult(p_FmPcd->p_CcShadow, last);
322*852ba100SJustin Hibbits 
323*852ba100SJustin Hibbits         shadowMember.p_MemberAd = p_FmPcd->p_CcShadow;
324*852ba100SJustin Hibbits 
325*852ba100SJustin Hibbits         /* update the next FR member index */
326*852ba100SJustin Hibbits         LinkMemberToMember(p_ReplicGroup, &shadowMember, p_NextMember);
327*852ba100SJustin Hibbits 
328*852ba100SJustin Hibbits         /* Modify the next member according to the prepared shadow descriptor */
329*852ba100SJustin Hibbits         err = ModifyDescriptor(p_ReplicGroup,
330*852ba100SJustin Hibbits                                p_CurrentMember->p_MemberAd,
331*852ba100SJustin Hibbits                                p_FmPcd->p_CcShadow);
332*852ba100SJustin Hibbits 
333*852ba100SJustin Hibbits         RELEASE_LOCK(p_FmPcd->shadowLock);
334*852ba100SJustin Hibbits         if (err)
335*852ba100SJustin Hibbits             RETURN_ERROR(MAJOR, err, ("Modify Descriptor in BuildShadowAndModifyDescriptor"));
336*852ba100SJustin Hibbits     }
337*852ba100SJustin Hibbits 
338*852ba100SJustin Hibbits 
339*852ba100SJustin Hibbits     return E_OK;
340*852ba100SJustin Hibbits }
341*852ba100SJustin Hibbits 
GetMemberByIndex(t_FmPcdFrmReplicGroup * p_ReplicGroup,uint16_t memberIndex)342*852ba100SJustin Hibbits static t_FmPcdFrmReplicMember* GetMemberByIndex(t_FmPcdFrmReplicGroup   *p_ReplicGroup,
343*852ba100SJustin Hibbits                                                 uint16_t                memberIndex)
344*852ba100SJustin Hibbits {
345*852ba100SJustin Hibbits     int                     i=0;
346*852ba100SJustin Hibbits     t_List                  *p_Pos;
347*852ba100SJustin Hibbits     t_FmPcdFrmReplicMember  *p_Member = NULL;
348*852ba100SJustin Hibbits 
349*852ba100SJustin Hibbits     LIST_FOR_EACH(p_Pos, &p_ReplicGroup->membersList)
350*852ba100SJustin Hibbits     {
351*852ba100SJustin Hibbits         if (i == memberIndex)
352*852ba100SJustin Hibbits         {
353*852ba100SJustin Hibbits             p_Member = LIST_OBJECT(p_Pos, t_FmPcdFrmReplicMember, node);
354*852ba100SJustin Hibbits             return p_Member;
355*852ba100SJustin Hibbits         }
356*852ba100SJustin Hibbits         i++;
357*852ba100SJustin Hibbits     }
358*852ba100SJustin Hibbits     return p_Member;
359*852ba100SJustin Hibbits }
360*852ba100SJustin Hibbits 
AllocMember(t_FmPcdFrmReplicGroup * p_ReplicGroup)361*852ba100SJustin Hibbits static t_Error AllocMember(t_FmPcdFrmReplicGroup *p_ReplicGroup)
362*852ba100SJustin Hibbits {
363*852ba100SJustin Hibbits     t_FmPcdFrmReplicMember  *p_CurrentMember;
364*852ba100SJustin Hibbits     t_Handle                h_Muram;
365*852ba100SJustin Hibbits 
366*852ba100SJustin Hibbits     ASSERT_COND(p_ReplicGroup);
367*852ba100SJustin Hibbits 
368*852ba100SJustin Hibbits     h_Muram = FmPcdGetMuramHandle(p_ReplicGroup->h_FmPcd);
369*852ba100SJustin Hibbits     ASSERT_COND(h_Muram);
370*852ba100SJustin Hibbits 
371*852ba100SJustin Hibbits     /* Initialize an internal structure of a member to add to the available members list */
372*852ba100SJustin Hibbits     p_CurrentMember = (t_FmPcdFrmReplicMember *)XX_Malloc(sizeof(t_FmPcdFrmReplicMember));
373*852ba100SJustin Hibbits     if (!p_CurrentMember)
374*852ba100SJustin Hibbits         RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Frame replicator member"));
375*852ba100SJustin Hibbits 
376*852ba100SJustin Hibbits     memset(p_CurrentMember, 0 ,sizeof(t_FmPcdFrmReplicMember));
377*852ba100SJustin Hibbits 
378*852ba100SJustin Hibbits     /* Allocate the member AD */
379*852ba100SJustin Hibbits     p_CurrentMember->p_MemberAd =
380*852ba100SJustin Hibbits         (t_AdOfTypeResult*)FM_MURAM_AllocMem(h_Muram,
381*852ba100SJustin Hibbits                                              FM_PCD_CC_AD_ENTRY_SIZE,
382*852ba100SJustin Hibbits                                              FM_PCD_CC_AD_TABLE_ALIGN);
383*852ba100SJustin Hibbits     if (!p_CurrentMember->p_MemberAd)
384*852ba100SJustin Hibbits     {
385*852ba100SJustin Hibbits         XX_Free(p_CurrentMember);
386*852ba100SJustin Hibbits         RETURN_ERROR(MAJOR, E_NO_MEMORY, ("member AD table"));
387*852ba100SJustin Hibbits     }
388*852ba100SJustin Hibbits     IOMemSet32((uint8_t*)p_CurrentMember->p_MemberAd, 0, FM_PCD_CC_AD_ENTRY_SIZE);
389*852ba100SJustin Hibbits 
390*852ba100SJustin Hibbits     /* Add the new member to the available members list */
391*852ba100SJustin Hibbits     LIST_AddToTail(&p_CurrentMember->node, &(p_ReplicGroup->availableMembersList));
392*852ba100SJustin Hibbits 
393*852ba100SJustin Hibbits     return E_OK;
394*852ba100SJustin Hibbits }
395*852ba100SJustin Hibbits 
InitMember(t_FmPcdFrmReplicGroup * p_ReplicGroup,t_FmPcdCcNextEngineParams * p_MemberParams,bool last)396*852ba100SJustin Hibbits static t_FmPcdFrmReplicMember* InitMember(t_FmPcdFrmReplicGroup     *p_ReplicGroup,
397*852ba100SJustin Hibbits                                           t_FmPcdCcNextEngineParams *p_MemberParams,
398*852ba100SJustin Hibbits                                           bool                      last)
399*852ba100SJustin Hibbits {
400*852ba100SJustin Hibbits     t_FmPcdFrmReplicMember  *p_CurrentMember = NULL;
401*852ba100SJustin Hibbits 
402*852ba100SJustin Hibbits     ASSERT_COND(p_ReplicGroup);
403*852ba100SJustin Hibbits 
404*852ba100SJustin Hibbits     /* Get an available member from the internal members list */
405*852ba100SJustin Hibbits     p_CurrentMember = GetAvailableMember(p_ReplicGroup);
406*852ba100SJustin Hibbits     if (!p_CurrentMember)
407*852ba100SJustin Hibbits     {
408*852ba100SJustin Hibbits         REPORT_ERROR(MAJOR, E_NOT_FOUND, ("Available member"));
409*852ba100SJustin Hibbits         return NULL;
410*852ba100SJustin Hibbits     }
411*852ba100SJustin Hibbits     p_CurrentMember->h_Manip = NULL;
412*852ba100SJustin Hibbits 
413*852ba100SJustin Hibbits     /* clear the Ad of the new member */
414*852ba100SJustin Hibbits     IOMemSet32((uint8_t*)p_CurrentMember->p_MemberAd, 0, FM_PCD_CC_AD_ENTRY_SIZE);
415*852ba100SJustin Hibbits 
416*852ba100SJustin Hibbits     INIT_LIST(&p_CurrentMember->node);
417*852ba100SJustin Hibbits 
418*852ba100SJustin Hibbits     /* Initialize the Ad of the member */
419*852ba100SJustin Hibbits     NextStepAd(p_CurrentMember->p_MemberAd,
420*852ba100SJustin Hibbits                NULL,
421*852ba100SJustin Hibbits                p_MemberParams,
422*852ba100SJustin Hibbits                p_ReplicGroup->h_FmPcd);
423*852ba100SJustin Hibbits 
424*852ba100SJustin Hibbits     /* save Manip handle (for free needs) */
425*852ba100SJustin Hibbits     if (p_MemberParams->h_Manip)
426*852ba100SJustin Hibbits         p_CurrentMember->h_Manip = p_MemberParams->h_Manip;
427*852ba100SJustin Hibbits 
428*852ba100SJustin Hibbits     /* Initialize the relevant frame replicator fields in the AD */
429*852ba100SJustin Hibbits     FillReplicAdOfTypeResult(p_CurrentMember->p_MemberAd, last);
430*852ba100SJustin Hibbits 
431*852ba100SJustin Hibbits     return p_CurrentMember;
432*852ba100SJustin Hibbits }
433*852ba100SJustin Hibbits 
FreeMember(t_FmPcdFrmReplicGroup * p_ReplicGroup,t_FmPcdFrmReplicMember * p_Member)434*852ba100SJustin Hibbits static void FreeMember(t_FmPcdFrmReplicGroup    *p_ReplicGroup,
435*852ba100SJustin Hibbits                        t_FmPcdFrmReplicMember   *p_Member)
436*852ba100SJustin Hibbits {
437*852ba100SJustin Hibbits     /* Note: Can't free the member AD just returns the member to the available
438*852ba100SJustin Hibbits        member list - therefore only memset the AD */
439*852ba100SJustin Hibbits 
440*852ba100SJustin Hibbits     /* zero the AD */
441*852ba100SJustin Hibbits     IOMemSet32(p_Member->p_MemberAd, 0, FM_PCD_CC_AD_ENTRY_SIZE);
442*852ba100SJustin Hibbits 
443*852ba100SJustin Hibbits 
444*852ba100SJustin Hibbits     /* return the member to the available members list */
445*852ba100SJustin Hibbits     PutAvailableMember(p_ReplicGroup, p_Member);
446*852ba100SJustin Hibbits }
447*852ba100SJustin Hibbits 
RemoveMember(t_FmPcdFrmReplicGroup * p_ReplicGroup,uint16_t memberIndex)448*852ba100SJustin Hibbits static t_Error RemoveMember(t_FmPcdFrmReplicGroup   *p_ReplicGroup,
449*852ba100SJustin Hibbits                             uint16_t                memberIndex)
450*852ba100SJustin Hibbits {
451*852ba100SJustin Hibbits     t_FmPcd                 *p_FmPcd = NULL;
452*852ba100SJustin Hibbits     t_FmPcdFrmReplicMember  *p_CurrentMember = NULL, *p_PreviousMember = NULL, *p_NextMember = NULL;
453*852ba100SJustin Hibbits     t_Error                 err;
454*852ba100SJustin Hibbits     uint8_t                 memberPosition;
455*852ba100SJustin Hibbits 
456*852ba100SJustin Hibbits     p_FmPcd         = p_ReplicGroup->h_FmPcd;
457*852ba100SJustin Hibbits     ASSERT_COND(p_FmPcd);
458*852ba100SJustin Hibbits     UNUSED(p_FmPcd);
459*852ba100SJustin Hibbits 
460*852ba100SJustin Hibbits     p_CurrentMember = GetMemberByIndex(p_ReplicGroup, memberIndex);
461*852ba100SJustin Hibbits     ASSERT_COND(p_CurrentMember);
462*852ba100SJustin Hibbits 
463*852ba100SJustin Hibbits     /* determine the member position in the group */
464*852ba100SJustin Hibbits     memberPosition = GetMemberPosition(p_ReplicGroup,
465*852ba100SJustin Hibbits                                        memberIndex,
466*852ba100SJustin Hibbits                                        FALSE/*remove operation*/);
467*852ba100SJustin Hibbits 
468*852ba100SJustin Hibbits     switch (memberPosition)
469*852ba100SJustin Hibbits     {
470*852ba100SJustin Hibbits         case FRM_REPLIC_FIRST_MEMBER_INDEX:
471*852ba100SJustin Hibbits             p_NextMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)(memberIndex+1));
472*852ba100SJustin Hibbits             ASSERT_COND(p_NextMember);
473*852ba100SJustin Hibbits 
474*852ba100SJustin Hibbits             /* update the source td itself by using a host command */
475*852ba100SJustin Hibbits             err = BuildShadowAndModifyDescriptor(p_ReplicGroup,
476*852ba100SJustin Hibbits                                                  p_NextMember,
477*852ba100SJustin Hibbits                                                  NULL,
478*852ba100SJustin Hibbits                                                  TRUE/*sourceDescriptor*/,
479*852ba100SJustin Hibbits                                                  FALSE/*last*/);
480*852ba100SJustin Hibbits             break;
481*852ba100SJustin Hibbits 
482*852ba100SJustin Hibbits         case FRM_REPLIC_MIDDLE_MEMBER_INDEX:
483*852ba100SJustin Hibbits             p_PreviousMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)(memberIndex-1));
484*852ba100SJustin Hibbits             ASSERT_COND(p_PreviousMember);
485*852ba100SJustin Hibbits 
486*852ba100SJustin Hibbits             p_NextMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)(memberIndex+1));
487*852ba100SJustin Hibbits             ASSERT_COND(p_NextMember);
488*852ba100SJustin Hibbits 
489*852ba100SJustin Hibbits             err = BuildShadowAndModifyDescriptor(p_ReplicGroup,
490*852ba100SJustin Hibbits                                                  p_NextMember,
491*852ba100SJustin Hibbits                                                  p_PreviousMember,
492*852ba100SJustin Hibbits                                                  FALSE/*sourceDescriptor*/,
493*852ba100SJustin Hibbits                                                  FALSE/*last*/);
494*852ba100SJustin Hibbits 
495*852ba100SJustin Hibbits             break;
496*852ba100SJustin Hibbits 
497*852ba100SJustin Hibbits         case FRM_REPLIC_LAST_MEMBER_INDEX:
498*852ba100SJustin Hibbits             p_PreviousMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)(memberIndex-1));
499*852ba100SJustin Hibbits             ASSERT_COND(p_PreviousMember);
500*852ba100SJustin Hibbits 
501*852ba100SJustin Hibbits             err = BuildShadowAndModifyDescriptor(p_ReplicGroup,
502*852ba100SJustin Hibbits                                                  NULL,
503*852ba100SJustin Hibbits                                                  p_PreviousMember,
504*852ba100SJustin Hibbits                                                  FALSE/*sourceDescriptor*/,
505*852ba100SJustin Hibbits                                                  TRUE/*last*/);
506*852ba100SJustin Hibbits             break;
507*852ba100SJustin Hibbits 
508*852ba100SJustin Hibbits         default:
509*852ba100SJustin Hibbits             RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("member position in remove member"));
510*852ba100SJustin Hibbits     }
511*852ba100SJustin Hibbits 
512*852ba100SJustin Hibbits     if (err)
513*852ba100SJustin Hibbits         RETURN_ERROR(MAJOR, err, NO_MSG);
514*852ba100SJustin Hibbits 
515*852ba100SJustin Hibbits     if (p_CurrentMember->h_Manip)
516*852ba100SJustin Hibbits     {
517*852ba100SJustin Hibbits         FmPcdManipUpdateOwner(p_CurrentMember->h_Manip, FALSE);
518*852ba100SJustin Hibbits         p_CurrentMember->h_Manip = NULL;
519*852ba100SJustin Hibbits     }
520*852ba100SJustin Hibbits 
521*852ba100SJustin Hibbits     /* remove the member from the driver internal members list */
522*852ba100SJustin Hibbits     RemoveMemberFromList(p_ReplicGroup, p_CurrentMember);
523*852ba100SJustin Hibbits 
524*852ba100SJustin Hibbits     /* return the member to the available members list */
525*852ba100SJustin Hibbits     FreeMember(p_ReplicGroup, p_CurrentMember);
526*852ba100SJustin Hibbits 
527*852ba100SJustin Hibbits     return E_OK;
528*852ba100SJustin Hibbits }
529*852ba100SJustin Hibbits 
DeleteGroup(t_FmPcdFrmReplicGroup * p_ReplicGroup)530*852ba100SJustin Hibbits static void DeleteGroup(t_FmPcdFrmReplicGroup *p_ReplicGroup)
531*852ba100SJustin Hibbits {
532*852ba100SJustin Hibbits     int                     i, j;
533*852ba100SJustin Hibbits     t_Handle                h_Muram;
534*852ba100SJustin Hibbits     t_FmPcdFrmReplicMember  *p_Member, *p_CurrentMember;
535*852ba100SJustin Hibbits 
536*852ba100SJustin Hibbits     if (p_ReplicGroup)
537*852ba100SJustin Hibbits     {
538*852ba100SJustin Hibbits         ASSERT_COND(p_ReplicGroup->h_FmPcd);
539*852ba100SJustin Hibbits         h_Muram = FmPcdGetMuramHandle(p_ReplicGroup->h_FmPcd);
540*852ba100SJustin Hibbits         ASSERT_COND(h_Muram);
541*852ba100SJustin Hibbits 
542*852ba100SJustin Hibbits         /* free the source table descriptor */
543*852ba100SJustin Hibbits         if (p_ReplicGroup->p_SourceTd)
544*852ba100SJustin Hibbits         {
545*852ba100SJustin Hibbits             FM_MURAM_FreeMem(h_Muram, p_ReplicGroup->p_SourceTd);
546*852ba100SJustin Hibbits             p_ReplicGroup->p_SourceTd = NULL;
547*852ba100SJustin Hibbits         }
548*852ba100SJustin Hibbits 
549*852ba100SJustin Hibbits         /* Remove all members from the members linked list (hw and sw) and
550*852ba100SJustin Hibbits            return the members to the available members list */
551*852ba100SJustin Hibbits         if (p_ReplicGroup->numOfEntries)
552*852ba100SJustin Hibbits         {
553*852ba100SJustin Hibbits             j = p_ReplicGroup->numOfEntries-1;
554*852ba100SJustin Hibbits 
555*852ba100SJustin Hibbits             /* manually removal of the member because there are no owners of
556*852ba100SJustin Hibbits                this group */
557*852ba100SJustin Hibbits             for (i=j; i>=0; i--)
558*852ba100SJustin Hibbits             {
559*852ba100SJustin Hibbits                 p_CurrentMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)i/*memberIndex*/);
560*852ba100SJustin Hibbits                 ASSERT_COND(p_CurrentMember);
561*852ba100SJustin Hibbits 
562*852ba100SJustin Hibbits                 if (p_CurrentMember->h_Manip)
563*852ba100SJustin Hibbits                 {
564*852ba100SJustin Hibbits                     FmPcdManipUpdateOwner(p_CurrentMember->h_Manip, FALSE);
565*852ba100SJustin Hibbits                     p_CurrentMember->h_Manip = NULL;
566*852ba100SJustin Hibbits                 }
567*852ba100SJustin Hibbits 
568*852ba100SJustin Hibbits                 /* remove the member from the internal driver members list */
569*852ba100SJustin Hibbits                 RemoveMemberFromList(p_ReplicGroup, p_CurrentMember);
570*852ba100SJustin Hibbits 
571*852ba100SJustin Hibbits                 /* return the member to the available members list */
572*852ba100SJustin Hibbits                 FreeMember(p_ReplicGroup, p_CurrentMember);
573*852ba100SJustin Hibbits             }
574*852ba100SJustin Hibbits         }
575*852ba100SJustin Hibbits 
576*852ba100SJustin Hibbits         /* Free members AD */
577*852ba100SJustin Hibbits         for (i=0; i<p_ReplicGroup->maxNumOfEntries; i++)
578*852ba100SJustin Hibbits         {
579*852ba100SJustin Hibbits             p_Member = GetAvailableMember(p_ReplicGroup);
580*852ba100SJustin Hibbits             ASSERT_COND(p_Member);
581*852ba100SJustin Hibbits             if (p_Member->p_MemberAd)
582*852ba100SJustin Hibbits             {
583*852ba100SJustin Hibbits                 FM_MURAM_FreeMem(h_Muram, p_Member->p_MemberAd);
584*852ba100SJustin Hibbits                 p_Member->p_MemberAd = NULL;
585*852ba100SJustin Hibbits             }
586*852ba100SJustin Hibbits             XX_Free(p_Member);
587*852ba100SJustin Hibbits         }
588*852ba100SJustin Hibbits 
589*852ba100SJustin Hibbits         /* release the group lock */
590*852ba100SJustin Hibbits         if (p_ReplicGroup->p_Lock)
591*852ba100SJustin Hibbits             FmPcdReleaseLock(p_ReplicGroup->h_FmPcd, p_ReplicGroup->p_Lock);
592*852ba100SJustin Hibbits 
593*852ba100SJustin Hibbits         /* free the replicator group */
594*852ba100SJustin Hibbits         XX_Free(p_ReplicGroup);
595*852ba100SJustin Hibbits     }
596*852ba100SJustin Hibbits }
597*852ba100SJustin Hibbits 
598*852ba100SJustin Hibbits 
599*852ba100SJustin Hibbits /*****************************************************************************/
600*852ba100SJustin Hibbits /*              Inter-module API routines                                    */
601*852ba100SJustin Hibbits /*****************************************************************************/
602*852ba100SJustin Hibbits 
603*852ba100SJustin Hibbits /* NOTE: the inter-module routines are locked by cc in case of using them */
FrmReplicGroupGetSourceTableDescriptor(t_Handle h_ReplicGroup)604*852ba100SJustin Hibbits void * FrmReplicGroupGetSourceTableDescriptor(t_Handle h_ReplicGroup)
605*852ba100SJustin Hibbits {
606*852ba100SJustin Hibbits     t_FmPcdFrmReplicGroup   *p_ReplicGroup = (t_FmPcdFrmReplicGroup *)h_ReplicGroup;
607*852ba100SJustin Hibbits     ASSERT_COND(p_ReplicGroup);
608*852ba100SJustin Hibbits 
609*852ba100SJustin Hibbits     return (p_ReplicGroup->p_SourceTd);
610*852ba100SJustin Hibbits }
611*852ba100SJustin Hibbits 
FrmReplicGroupUpdateAd(t_Handle h_ReplicGroup,void * p_Ad,t_Handle * h_AdNew)612*852ba100SJustin Hibbits void FrmReplicGroupUpdateAd(t_Handle  h_ReplicGroup,
613*852ba100SJustin Hibbits                             void      *p_Ad,
614*852ba100SJustin Hibbits                             t_Handle  *h_AdNew)
615*852ba100SJustin Hibbits {
616*852ba100SJustin Hibbits     t_FmPcdFrmReplicGroup   *p_ReplicGroup = (t_FmPcdFrmReplicGroup *)h_ReplicGroup;
617*852ba100SJustin Hibbits     t_AdOfTypeResult    *p_AdResult = (t_AdOfTypeResult*)p_Ad;
618*852ba100SJustin Hibbits     t_FmPcd             *p_FmPcd;
619*852ba100SJustin Hibbits 
620*852ba100SJustin Hibbits     ASSERT_COND(p_ReplicGroup);
621*852ba100SJustin Hibbits     p_FmPcd = p_ReplicGroup->h_FmPcd;
622*852ba100SJustin Hibbits 
623*852ba100SJustin Hibbits     /* build a bypass ad */
624*852ba100SJustin Hibbits     WRITE_UINT32(p_AdResult->fqid, FM_PCD_AD_BYPASS_TYPE |
625*852ba100SJustin Hibbits         (uint32_t)((XX_VirtToPhys(p_ReplicGroup->p_SourceTd)) - p_FmPcd->physicalMuramBase));
626*852ba100SJustin Hibbits 
627*852ba100SJustin Hibbits     *h_AdNew = NULL;
628*852ba100SJustin Hibbits }
629*852ba100SJustin Hibbits 
FrmReplicGroupUpdateOwner(t_Handle h_ReplicGroup,bool add)630*852ba100SJustin Hibbits void  FrmReplicGroupUpdateOwner(t_Handle                   h_ReplicGroup,
631*852ba100SJustin Hibbits                                 bool                       add)
632*852ba100SJustin Hibbits {
633*852ba100SJustin Hibbits     t_FmPcdFrmReplicGroup   *p_ReplicGroup = (t_FmPcdFrmReplicGroup *)h_ReplicGroup;
634*852ba100SJustin Hibbits     ASSERT_COND(p_ReplicGroup);
635*852ba100SJustin Hibbits 
636*852ba100SJustin Hibbits     /* update the group owner counter */
637*852ba100SJustin Hibbits     if (add)
638*852ba100SJustin Hibbits         p_ReplicGroup->owners++;
639*852ba100SJustin Hibbits     else
640*852ba100SJustin Hibbits     {
641*852ba100SJustin Hibbits         ASSERT_COND(p_ReplicGroup->owners);
642*852ba100SJustin Hibbits         p_ReplicGroup->owners--;
643*852ba100SJustin Hibbits     }
644*852ba100SJustin Hibbits }
645*852ba100SJustin Hibbits 
FrmReplicGroupTryLock(t_Handle h_ReplicGroup)646*852ba100SJustin Hibbits t_Error FrmReplicGroupTryLock(t_Handle h_ReplicGroup)
647*852ba100SJustin Hibbits {
648*852ba100SJustin Hibbits     t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup *)h_ReplicGroup;
649*852ba100SJustin Hibbits 
650*852ba100SJustin Hibbits     ASSERT_COND(h_ReplicGroup);
651*852ba100SJustin Hibbits 
652*852ba100SJustin Hibbits     if (FmPcdLockTryLock(p_ReplicGroup->p_Lock))
653*852ba100SJustin Hibbits         return E_OK;
654*852ba100SJustin Hibbits 
655*852ba100SJustin Hibbits     return ERROR_CODE(E_BUSY);
656*852ba100SJustin Hibbits }
657*852ba100SJustin Hibbits 
FrmReplicGroupUnlock(t_Handle h_ReplicGroup)658*852ba100SJustin Hibbits void FrmReplicGroupUnlock(t_Handle h_ReplicGroup)
659*852ba100SJustin Hibbits {
660*852ba100SJustin Hibbits     t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup *)h_ReplicGroup;
661*852ba100SJustin Hibbits 
662*852ba100SJustin Hibbits     ASSERT_COND(h_ReplicGroup);
663*852ba100SJustin Hibbits 
664*852ba100SJustin Hibbits     FmPcdLockUnlock(p_ReplicGroup->p_Lock);
665*852ba100SJustin Hibbits }
666*852ba100SJustin Hibbits /*********************** End of inter-module routines ************************/
667*852ba100SJustin Hibbits 
668*852ba100SJustin Hibbits 
669*852ba100SJustin Hibbits /****************************************/
670*852ba100SJustin Hibbits /*       API Init unit functions        */
671*852ba100SJustin Hibbits /****************************************/
FM_PCD_FrmReplicSetGroup(t_Handle h_FmPcd,t_FmPcdFrmReplicGroupParams * p_ReplicGroupParam)672*852ba100SJustin Hibbits t_Handle FM_PCD_FrmReplicSetGroup(t_Handle                    h_FmPcd,
673*852ba100SJustin Hibbits                                   t_FmPcdFrmReplicGroupParams *p_ReplicGroupParam)
674*852ba100SJustin Hibbits {
675*852ba100SJustin Hibbits     t_FmPcdFrmReplicGroup       *p_ReplicGroup;
676*852ba100SJustin Hibbits     t_FmPcdFrmReplicMember      *p_CurrentMember, *p_NextMember = NULL;
677*852ba100SJustin Hibbits     int                         i;
678*852ba100SJustin Hibbits     t_Error                     err;
679*852ba100SJustin Hibbits     bool                        last = FALSE;
680*852ba100SJustin Hibbits     t_Handle                    h_Muram;
681*852ba100SJustin Hibbits 
682*852ba100SJustin Hibbits     SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, NULL);
683*852ba100SJustin Hibbits     SANITY_CHECK_RETURN_VALUE(p_ReplicGroupParam, E_INVALID_HANDLE, NULL);
684*852ba100SJustin Hibbits 
685*852ba100SJustin Hibbits     if (!FmPcdIsAdvancedOffloadSupported(h_FmPcd))
686*852ba100SJustin Hibbits     {
687*852ba100SJustin Hibbits         REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Advanced-offload must be enabled"));
688*852ba100SJustin Hibbits         return NULL;
689*852ba100SJustin Hibbits     }
690*852ba100SJustin Hibbits 
691*852ba100SJustin Hibbits     err = CheckParams(h_FmPcd, p_ReplicGroupParam);
692*852ba100SJustin Hibbits     if (err)
693*852ba100SJustin Hibbits     {
694*852ba100SJustin Hibbits         REPORT_ERROR(MAJOR, err, (NO_MSG));
695*852ba100SJustin Hibbits         return NULL;
696*852ba100SJustin Hibbits     }
697*852ba100SJustin Hibbits 
698*852ba100SJustin Hibbits     p_ReplicGroup = (t_FmPcdFrmReplicGroup*)XX_Malloc(sizeof(t_FmPcdFrmReplicGroup));
699*852ba100SJustin Hibbits     if (!p_ReplicGroup)
700*852ba100SJustin Hibbits     {
701*852ba100SJustin Hibbits         REPORT_ERROR(MAJOR, E_NO_MEMORY, ("No memory"));
702*852ba100SJustin Hibbits         return NULL;
703*852ba100SJustin Hibbits     }
704*852ba100SJustin Hibbits     memset(p_ReplicGroup, 0, sizeof(t_FmPcdFrmReplicGroup));
705*852ba100SJustin Hibbits 
706*852ba100SJustin Hibbits     /* initialize lists for internal driver use */
707*852ba100SJustin Hibbits     INIT_LIST(&p_ReplicGroup->availableMembersList);
708*852ba100SJustin Hibbits     INIT_LIST(&p_ReplicGroup->membersList);
709*852ba100SJustin Hibbits 
710*852ba100SJustin Hibbits     p_ReplicGroup->h_FmPcd = h_FmPcd;
711*852ba100SJustin Hibbits 
712*852ba100SJustin Hibbits     h_Muram = FmPcdGetMuramHandle(p_ReplicGroup->h_FmPcd);
713*852ba100SJustin Hibbits     ASSERT_COND(h_Muram);
714*852ba100SJustin Hibbits 
715*852ba100SJustin Hibbits     /* initialize the group lock */
716*852ba100SJustin Hibbits     p_ReplicGroup->p_Lock = FmPcdAcquireLock(p_ReplicGroup->h_FmPcd);
717*852ba100SJustin Hibbits     if (!p_ReplicGroup->p_Lock)
718*852ba100SJustin Hibbits     {
719*852ba100SJustin Hibbits         REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Replic group lock"));
720*852ba100SJustin Hibbits         DeleteGroup(p_ReplicGroup);
721*852ba100SJustin Hibbits         return NULL;
722*852ba100SJustin Hibbits     }
723*852ba100SJustin Hibbits 
724*852ba100SJustin Hibbits     /* Allocate the frame replicator source table descriptor */
725*852ba100SJustin Hibbits     p_ReplicGroup->p_SourceTd =
726*852ba100SJustin Hibbits         (t_Handle)FM_MURAM_AllocMem(h_Muram,
727*852ba100SJustin Hibbits                                     FM_PCD_CC_AD_ENTRY_SIZE,
728*852ba100SJustin Hibbits                                     FM_PCD_CC_AD_TABLE_ALIGN);
729*852ba100SJustin Hibbits     if (!p_ReplicGroup->p_SourceTd)
730*852ba100SJustin Hibbits     {
731*852ba100SJustin Hibbits         REPORT_ERROR(MAJOR, E_NO_MEMORY, ("frame replicator source table descriptor"));
732*852ba100SJustin Hibbits         DeleteGroup(p_ReplicGroup);
733*852ba100SJustin Hibbits         return NULL;
734*852ba100SJustin Hibbits     }
735*852ba100SJustin Hibbits 
736*852ba100SJustin Hibbits     /* update the shadow size - required for the host commands */
737*852ba100SJustin Hibbits     err = FmPcdUpdateCcShadow(p_ReplicGroup->h_FmPcd,
738*852ba100SJustin Hibbits                               FM_PCD_CC_AD_ENTRY_SIZE,
739*852ba100SJustin Hibbits                               FM_PCD_CC_AD_TABLE_ALIGN);
740*852ba100SJustin Hibbits     if (err)
741*852ba100SJustin Hibbits     {
742*852ba100SJustin Hibbits         REPORT_ERROR(MAJOR, err, ("Update CC shadow"));
743*852ba100SJustin Hibbits         DeleteGroup(p_ReplicGroup);
744*852ba100SJustin Hibbits         return NULL;
745*852ba100SJustin Hibbits     }
746*852ba100SJustin Hibbits 
747*852ba100SJustin Hibbits     p_ReplicGroup->maxNumOfEntries  = p_ReplicGroupParam->maxNumOfEntries;
748*852ba100SJustin Hibbits 
749*852ba100SJustin Hibbits     /* Allocate the maximal number of members ADs and Statistics AD for the group
750*852ba100SJustin Hibbits        It prevents allocation of Muram in run-time */
751*852ba100SJustin Hibbits     for (i=0; i<p_ReplicGroup->maxNumOfEntries; i++)
752*852ba100SJustin Hibbits     {
753*852ba100SJustin Hibbits         err = AllocMember(p_ReplicGroup);
754*852ba100SJustin Hibbits         if (err)
755*852ba100SJustin Hibbits         {
756*852ba100SJustin Hibbits             REPORT_ERROR(MAJOR, err, ("allocate a new member"));
757*852ba100SJustin Hibbits             DeleteGroup(p_ReplicGroup);
758*852ba100SJustin Hibbits             return NULL;
759*852ba100SJustin Hibbits         }
760*852ba100SJustin Hibbits     }
761*852ba100SJustin Hibbits 
762*852ba100SJustin Hibbits     /* Initialize the members linked lists:
763*852ba100SJustin Hibbits       (hw - the one that is used by the FMan controller and
764*852ba100SJustin Hibbits        sw - the one that is managed by the driver internally) */
765*852ba100SJustin Hibbits     for (i=(p_ReplicGroupParam->numOfEntries-1); i>=0; i--)
766*852ba100SJustin Hibbits     {
767*852ba100SJustin Hibbits         /* check if this is the last member in the group */
768*852ba100SJustin Hibbits         if (i == (p_ReplicGroupParam->numOfEntries-1))
769*852ba100SJustin Hibbits             last = TRUE;
770*852ba100SJustin Hibbits         else
771*852ba100SJustin Hibbits             last = FALSE;
772*852ba100SJustin Hibbits 
773*852ba100SJustin Hibbits         /* Initialize a new member */
774*852ba100SJustin Hibbits         p_CurrentMember = InitMember(p_ReplicGroup,
775*852ba100SJustin Hibbits                                      &(p_ReplicGroupParam->nextEngineParams[i]),
776*852ba100SJustin Hibbits                                      last);
777*852ba100SJustin Hibbits         if (!p_CurrentMember)
778*852ba100SJustin Hibbits         {
779*852ba100SJustin Hibbits             REPORT_ERROR(MAJOR, E_INVALID_HANDLE, ("No available member"));
780*852ba100SJustin Hibbits             DeleteGroup(p_ReplicGroup);
781*852ba100SJustin Hibbits             return NULL;
782*852ba100SJustin Hibbits         }
783*852ba100SJustin Hibbits 
784*852ba100SJustin Hibbits         /* Build the members group - link two consecutive members in the hw linked list */
785*852ba100SJustin Hibbits         LinkMemberToMember(p_ReplicGroup, p_CurrentMember, p_NextMember);
786*852ba100SJustin Hibbits 
787*852ba100SJustin Hibbits         /* update the driver internal members list to be compatible to the hw members linked list */
788*852ba100SJustin Hibbits         AddMemberToList(p_ReplicGroup, p_CurrentMember, &p_ReplicGroup->membersList);
789*852ba100SJustin Hibbits 
790*852ba100SJustin Hibbits         p_NextMember = p_CurrentMember;
791*852ba100SJustin Hibbits     }
792*852ba100SJustin Hibbits 
793*852ba100SJustin Hibbits     /* initialize the source table descriptor */
794*852ba100SJustin Hibbits     BuildSourceTd(p_ReplicGroup->p_SourceTd);
795*852ba100SJustin Hibbits 
796*852ba100SJustin Hibbits     /* link the source table descriptor to point to the first member in the group */
797*852ba100SJustin Hibbits     LinkSourceToMember(p_ReplicGroup, p_ReplicGroup->p_SourceTd, p_NextMember);
798*852ba100SJustin Hibbits 
799*852ba100SJustin Hibbits     return p_ReplicGroup;
800*852ba100SJustin Hibbits }
801*852ba100SJustin Hibbits 
FM_PCD_FrmReplicDeleteGroup(t_Handle h_ReplicGroup)802*852ba100SJustin Hibbits t_Error FM_PCD_FrmReplicDeleteGroup(t_Handle h_ReplicGroup)
803*852ba100SJustin Hibbits {
804*852ba100SJustin Hibbits     t_FmPcdFrmReplicGroup   *p_ReplicGroup = (t_FmPcdFrmReplicGroup *)h_ReplicGroup;
805*852ba100SJustin Hibbits 
806*852ba100SJustin Hibbits     SANITY_CHECK_RETURN_ERROR(p_ReplicGroup, E_INVALID_HANDLE);
807*852ba100SJustin Hibbits 
808*852ba100SJustin Hibbits     if (p_ReplicGroup->owners)
809*852ba100SJustin Hibbits         RETURN_ERROR(MAJOR,
810*852ba100SJustin Hibbits                      E_INVALID_STATE,
811*852ba100SJustin Hibbits                      ("the group has owners and can't be deleted"));
812*852ba100SJustin Hibbits 
813*852ba100SJustin Hibbits     DeleteGroup(p_ReplicGroup);
814*852ba100SJustin Hibbits 
815*852ba100SJustin Hibbits     return E_OK;
816*852ba100SJustin Hibbits }
817*852ba100SJustin Hibbits 
818*852ba100SJustin Hibbits 
819*852ba100SJustin Hibbits /*****************************************************************************/
820*852ba100SJustin Hibbits /*       API Run-time Frame replicator Control unit functions                */
821*852ba100SJustin Hibbits /*****************************************************************************/
FM_PCD_FrmReplicAddMember(t_Handle h_ReplicGroup,uint16_t memberIndex,t_FmPcdCcNextEngineParams * p_MemberParams)822*852ba100SJustin Hibbits t_Error FM_PCD_FrmReplicAddMember(t_Handle                  h_ReplicGroup,
823*852ba100SJustin Hibbits                                   uint16_t                  memberIndex,
824*852ba100SJustin Hibbits                                   t_FmPcdCcNextEngineParams *p_MemberParams)
825*852ba100SJustin Hibbits {
826*852ba100SJustin Hibbits     t_FmPcdFrmReplicGroup       *p_ReplicGroup = (t_FmPcdFrmReplicGroup*) h_ReplicGroup;
827*852ba100SJustin Hibbits     t_FmPcdFrmReplicMember      *p_NewMember, *p_CurrentMember = NULL, *p_PreviousMember = NULL;
828*852ba100SJustin Hibbits     t_Error                     err;
829*852ba100SJustin Hibbits     uint8_t                     memberPosition;
830*852ba100SJustin Hibbits 
831*852ba100SJustin Hibbits     SANITY_CHECK_RETURN_ERROR(p_ReplicGroup, E_INVALID_HANDLE);
832*852ba100SJustin Hibbits     SANITY_CHECK_RETURN_ERROR(p_MemberParams, E_INVALID_HANDLE);
833*852ba100SJustin Hibbits 
834*852ba100SJustin Hibbits     /* group lock */
835*852ba100SJustin Hibbits     err = FrmReplicGroupTryLock(p_ReplicGroup);
836*852ba100SJustin Hibbits     if (GET_ERROR_TYPE(err) == E_BUSY)
837*852ba100SJustin Hibbits         return ERROR_CODE(E_BUSY);
838*852ba100SJustin Hibbits 
839*852ba100SJustin Hibbits     if (memberIndex > p_ReplicGroup->numOfEntries)
840*852ba100SJustin Hibbits     {
841*852ba100SJustin Hibbits         /* unlock */
842*852ba100SJustin Hibbits         FrmReplicGroupUnlock(p_ReplicGroup);
843*852ba100SJustin Hibbits         RETURN_ERROR(MAJOR, E_INVALID_SELECTION,
844*852ba100SJustin Hibbits                      ("memberIndex is greater than the members in the list"));
845*852ba100SJustin Hibbits     }
846*852ba100SJustin Hibbits 
847*852ba100SJustin Hibbits     if (memberIndex >= p_ReplicGroup->maxNumOfEntries)
848*852ba100SJustin Hibbits     {
849*852ba100SJustin Hibbits         /* unlock */
850*852ba100SJustin Hibbits         FrmReplicGroupUnlock(p_ReplicGroup);
851*852ba100SJustin Hibbits         RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("memberIndex is greater than the allowed number of members in the group"));
852*852ba100SJustin Hibbits     }
853*852ba100SJustin Hibbits 
854*852ba100SJustin Hibbits     if ((p_ReplicGroup->numOfEntries + 1) > FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES)
855*852ba100SJustin Hibbits     {
856*852ba100SJustin Hibbits         /* unlock */
857*852ba100SJustin Hibbits         FrmReplicGroupUnlock(p_ReplicGroup);
858*852ba100SJustin Hibbits         RETURN_ERROR(MAJOR, E_INVALID_VALUE,
859*852ba100SJustin Hibbits                      ("numOfEntries with new entry can not be larger than %d\n",
860*852ba100SJustin Hibbits                       FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES));
861*852ba100SJustin Hibbits     }
862*852ba100SJustin Hibbits 
863*852ba100SJustin Hibbits     err = MemberCheckParams(p_ReplicGroup->h_FmPcd, p_MemberParams);
864*852ba100SJustin Hibbits     if (err)
865*852ba100SJustin Hibbits     {
866*852ba100SJustin Hibbits         /* unlock */
867*852ba100SJustin Hibbits         FrmReplicGroupUnlock(p_ReplicGroup);
868*852ba100SJustin Hibbits         RETURN_ERROR(MAJOR, err, ("member check parameters in add operation"));
869*852ba100SJustin Hibbits     }
870*852ba100SJustin Hibbits     /* determine the member position in the group */
871*852ba100SJustin Hibbits     memberPosition = GetMemberPosition(p_ReplicGroup,
872*852ba100SJustin Hibbits                                        memberIndex,
873*852ba100SJustin Hibbits                                        TRUE/* add operation */);
874*852ba100SJustin Hibbits 
875*852ba100SJustin Hibbits     /* Initialize a new member */
876*852ba100SJustin Hibbits     p_NewMember = InitMember(p_ReplicGroup,
877*852ba100SJustin Hibbits                              p_MemberParams,
878*852ba100SJustin Hibbits                              (memberPosition == FRM_REPLIC_LAST_MEMBER_INDEX ? TRUE : FALSE));
879*852ba100SJustin Hibbits     if (!p_NewMember)
880*852ba100SJustin Hibbits     {
881*852ba100SJustin Hibbits         /* unlock */
882*852ba100SJustin Hibbits         FrmReplicGroupUnlock(p_ReplicGroup);
883*852ba100SJustin Hibbits         RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("No available member"));
884*852ba100SJustin Hibbits     }
885*852ba100SJustin Hibbits 
886*852ba100SJustin Hibbits     switch (memberPosition)
887*852ba100SJustin Hibbits     {
888*852ba100SJustin Hibbits         case FRM_REPLIC_FIRST_MEMBER_INDEX:
889*852ba100SJustin Hibbits             p_CurrentMember = GetMemberByIndex(p_ReplicGroup, memberIndex);
890*852ba100SJustin Hibbits             ASSERT_COND(p_CurrentMember);
891*852ba100SJustin Hibbits 
892*852ba100SJustin Hibbits             LinkMemberToMember(p_ReplicGroup, p_NewMember, p_CurrentMember);
893*852ba100SJustin Hibbits 
894*852ba100SJustin Hibbits             /* update the internal group source TD */
895*852ba100SJustin Hibbits             LinkSourceToMember(p_ReplicGroup,
896*852ba100SJustin Hibbits                                p_ReplicGroup->p_SourceTd,
897*852ba100SJustin Hibbits                                p_NewMember);
898*852ba100SJustin Hibbits 
899*852ba100SJustin Hibbits             /* add member to the internal sw member list */
900*852ba100SJustin Hibbits             AddMemberToList(p_ReplicGroup,
901*852ba100SJustin Hibbits                             p_NewMember,
902*852ba100SJustin Hibbits                             &p_ReplicGroup->membersList);
903*852ba100SJustin Hibbits             break;
904*852ba100SJustin Hibbits 
905*852ba100SJustin Hibbits         case FRM_REPLIC_MIDDLE_MEMBER_INDEX:
906*852ba100SJustin Hibbits             p_CurrentMember = GetMemberByIndex(p_ReplicGroup, memberIndex);
907*852ba100SJustin Hibbits             ASSERT_COND(p_CurrentMember);
908*852ba100SJustin Hibbits 
909*852ba100SJustin Hibbits             p_PreviousMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)(memberIndex-1));
910*852ba100SJustin Hibbits             ASSERT_COND(p_PreviousMember);
911*852ba100SJustin Hibbits 
912*852ba100SJustin Hibbits             LinkMemberToMember(p_ReplicGroup, p_NewMember, p_CurrentMember);
913*852ba100SJustin Hibbits             LinkMemberToMember(p_ReplicGroup, p_PreviousMember, p_NewMember);
914*852ba100SJustin Hibbits 
915*852ba100SJustin Hibbits             AddMemberToList(p_ReplicGroup, p_NewMember, &p_PreviousMember->node);
916*852ba100SJustin Hibbits             break;
917*852ba100SJustin Hibbits 
918*852ba100SJustin Hibbits         case FRM_REPLIC_LAST_MEMBER_INDEX:
919*852ba100SJustin Hibbits             p_PreviousMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)(memberIndex-1));
920*852ba100SJustin Hibbits             ASSERT_COND(p_PreviousMember);
921*852ba100SJustin Hibbits 
922*852ba100SJustin Hibbits             LinkMemberToMember(p_ReplicGroup, p_PreviousMember, p_NewMember);
923*852ba100SJustin Hibbits             FillReplicAdOfTypeResult(p_PreviousMember->p_MemberAd, FALSE/*last*/);
924*852ba100SJustin Hibbits 
925*852ba100SJustin Hibbits             /* add the new member to the internal sw member list */
926*852ba100SJustin Hibbits             AddMemberToList(p_ReplicGroup, p_NewMember, &p_PreviousMember->node);
927*852ba100SJustin Hibbits            break;
928*852ba100SJustin Hibbits 
929*852ba100SJustin Hibbits         default:
930*852ba100SJustin Hibbits             /* unlock */
931*852ba100SJustin Hibbits             FrmReplicGroupUnlock(p_ReplicGroup);
932*852ba100SJustin Hibbits             RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("member position in add member"));
933*852ba100SJustin Hibbits 
934*852ba100SJustin Hibbits     }
935*852ba100SJustin Hibbits 
936*852ba100SJustin Hibbits     /* unlock */
937*852ba100SJustin Hibbits     FrmReplicGroupUnlock(p_ReplicGroup);
938*852ba100SJustin Hibbits 
939*852ba100SJustin Hibbits     return E_OK;
940*852ba100SJustin Hibbits }
941*852ba100SJustin Hibbits 
FM_PCD_FrmReplicRemoveMember(t_Handle h_ReplicGroup,uint16_t memberIndex)942*852ba100SJustin Hibbits t_Error FM_PCD_FrmReplicRemoveMember(t_Handle   h_ReplicGroup,
943*852ba100SJustin Hibbits                                      uint16_t   memberIndex)
944*852ba100SJustin Hibbits {
945*852ba100SJustin Hibbits     t_FmPcdFrmReplicGroup   *p_ReplicGroup = (t_FmPcdFrmReplicGroup*) h_ReplicGroup;
946*852ba100SJustin Hibbits     t_Error                 err;
947*852ba100SJustin Hibbits 
948*852ba100SJustin Hibbits     SANITY_CHECK_RETURN_ERROR(p_ReplicGroup, E_INVALID_HANDLE);
949*852ba100SJustin Hibbits 
950*852ba100SJustin Hibbits     /* lock */
951*852ba100SJustin Hibbits     err = FrmReplicGroupTryLock(p_ReplicGroup);
952*852ba100SJustin Hibbits     if (GET_ERROR_TYPE(err) == E_BUSY)
953*852ba100SJustin Hibbits         return ERROR_CODE(E_BUSY);
954*852ba100SJustin Hibbits 
955*852ba100SJustin Hibbits     if (memberIndex >= p_ReplicGroup->numOfEntries)
956*852ba100SJustin Hibbits         RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("member index to remove"));
957*852ba100SJustin Hibbits 
958*852ba100SJustin Hibbits     /* Design decision: group must contain at least one member
959*852ba100SJustin Hibbits        No possibility to remove the last member from the group */
960*852ba100SJustin Hibbits     if (p_ReplicGroup->numOfEntries == 1)
961*852ba100SJustin Hibbits         RETURN_ERROR(MAJOR, E_CONFLICT, ("Can't remove the last member. At least one member should be related to a group."));
962*852ba100SJustin Hibbits 
963*852ba100SJustin Hibbits     err = RemoveMember(p_ReplicGroup, memberIndex);
964*852ba100SJustin Hibbits 
965*852ba100SJustin Hibbits     /* unlock */
966*852ba100SJustin Hibbits     FrmReplicGroupUnlock(p_ReplicGroup);
967*852ba100SJustin Hibbits 
968*852ba100SJustin Hibbits     switch (GET_ERROR_TYPE(err))
969*852ba100SJustin Hibbits     {
970*852ba100SJustin Hibbits         case E_OK:
971*852ba100SJustin Hibbits             return E_OK;
972*852ba100SJustin Hibbits 
973*852ba100SJustin Hibbits         case E_BUSY:
974*852ba100SJustin Hibbits             DBG(TRACE, ("E_BUSY error"));
975*852ba100SJustin Hibbits             return ERROR_CODE(E_BUSY);
976*852ba100SJustin Hibbits 
977*852ba100SJustin Hibbits         default:
978*852ba100SJustin Hibbits             RETURN_ERROR(MAJOR, err, NO_MSG);
979*852ba100SJustin Hibbits     }
980*852ba100SJustin Hibbits }
981*852ba100SJustin Hibbits 
982*852ba100SJustin Hibbits /*********************** End of API routines ************************/
983*852ba100SJustin Hibbits 
984*852ba100SJustin Hibbits 
985