xref: /freebsd/sys/contrib/ncsw/Peripherals/FM/MAC/memac.c (revision 852ba100)
1 /*
2  * Copyright 2008-2012 Freescale Semiconductor Inc.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *     * Redistributions of source code must retain the above copyright
7  *       notice, this list of conditions and the following disclaimer.
8  *     * Redistributions in binary form must reproduce the above copyright
9  *       notice, this list of conditions and the following disclaimer in the
10  *       documentation and/or other materials provided with the distribution.
11  *     * Neither the name of Freescale Semiconductor nor the
12  *       names of its contributors may be used to endorse or promote products
13  *       derived from this software without specific prior written permission.
14  *
15  *
16  * ALTERNATIVELY, this software may be distributed under the terms of the
17  * GNU General Public License ("GPL") as published by the Free Software
18  * Foundation, either version 2 of that License or (at your option) any
19  * later version.
20  *
21  * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
22  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24  * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
25  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 
34 /******************************************************************************
35  @File          memac.c
36 
37  @Description   FM mEMAC driver
38 *//***************************************************************************/
39 
40 #include "std_ext.h"
41 #include "string_ext.h"
42 #include "error_ext.h"
43 #include "xx_ext.h"
44 #include "endian_ext.h"
45 #include "debug_ext.h"
46 
47 #include "fm_common.h"
48 #include "memac.h"
49 
50 
51 /*****************************************************************************/
52 /*                      Internal routines                                    */
53 /*****************************************************************************/
54 
55 /* ......................................................................... */
56 
GetMacAddrHashCode(uint64_t ethAddr)57 static uint32_t GetMacAddrHashCode(uint64_t ethAddr)
58 {
59     uint64_t    mask1, mask2;
60     uint32_t    xorVal = 0;
61     uint8_t     i, j;
62 
63     for (i=0; i<6; i++)
64     {
65         mask1 = ethAddr & (uint64_t)0x01;
66         ethAddr >>= 1;
67 
68         for (j=0; j<7; j++)
69         {
70             mask2 = ethAddr & (uint64_t)0x01;
71             mask1 ^= mask2;
72             ethAddr >>= 1;
73         }
74 
75         xorVal |= (mask1 << (5-i));
76     }
77 
78     return xorVal;
79 }
80 
81 /* ......................................................................... */
82 
SetupSgmiiInternalPhy(t_Memac * p_Memac,uint8_t phyAddr)83 static void SetupSgmiiInternalPhy(t_Memac *p_Memac, uint8_t phyAddr)
84 {
85     uint16_t    tmpReg16;
86     e_EnetMode  enetMode;
87 
88      /* In case the higher MACs are used (i.e. the MACs that should support 10G),
89         speed=10000 is provided for SGMII ports. Temporary modify enet mode
90         to 1G one, so MII functions can work correctly. */
91     enetMode = p_Memac->enetMode;
92 
93     /* SGMII mode + AN enable */
94     tmpReg16 = PHY_SGMII_IF_MODE_AN | PHY_SGMII_IF_MODE_SGMII;
95     if ((p_Memac->enetMode) == e_ENET_MODE_SGMII_2500)
96         tmpReg16 = PHY_SGMII_CR_PHY_RESET | PHY_SGMII_IF_SPEED_GIGABIT | PHY_SGMII_IF_MODE_SGMII;
97 
98     p_Memac->enetMode = MAKE_ENET_MODE(ENET_INTERFACE_FROM_MODE(p_Memac->enetMode), e_ENET_SPEED_1000);
99     MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x14, tmpReg16);
100 
101     /* Device ability according to SGMII specification */
102     tmpReg16 = PHY_SGMII_DEV_ABILITY_SGMII;
103     MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x4, tmpReg16);
104 
105     /* Adjust link timer for SGMII  -
106        According to Cisco SGMII specification the timer should be 1.6 ms.
107        The link_timer register is configured in units of the clock.
108        - When running as 1G SGMII, Serdes clock is 125 MHz, so
109          unit = 1 / (125*10^6 Hz) = 8 ns.
110          1.6 ms in units of 8 ns = 1.6ms / 8ns = 2 * 10^5 = 0x30d40
111        - When running as 2.5G SGMII, Serdes clock is 312.5 MHz, so
112          unit = 1 / (312.5*10^6 Hz) = 3.2 ns.
113          1.6 ms in units of 3.2 ns = 1.6ms / 3.2ns = 5 * 10^5 = 0x7a120.
114        Since link_timer value of 1G SGMII will be too short for 2.5 SGMII,
115        we always set up here a value of 2.5 SGMII. */
116     MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x13, 0x0007);
117     MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x12, 0xa120);
118 
119     /* Restart AN */
120     tmpReg16 = PHY_SGMII_CR_DEF_VAL | PHY_SGMII_CR_RESET_AN;
121     MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x0, tmpReg16);
122 
123     /* Restore original enet mode */
124     p_Memac->enetMode = enetMode;
125 }
126 
127 /* ......................................................................... */
128 
SetupSgmiiInternalPhyBaseX(t_Memac * p_Memac,uint8_t phyAddr)129 static void SetupSgmiiInternalPhyBaseX(t_Memac *p_Memac, uint8_t phyAddr)
130 {
131     uint16_t    tmpReg16;
132     e_EnetMode  enetMode;
133 
134      /* In case the higher MACs are used (i.e. the MACs that should support 10G),
135         speed=10000 is provided for SGMII ports. Temporary modify enet mode
136         to 1G one, so MII functions can work correctly. */
137     enetMode = p_Memac->enetMode;
138     p_Memac->enetMode = MAKE_ENET_MODE(ENET_INTERFACE_FROM_MODE(p_Memac->enetMode), e_ENET_SPEED_1000);
139 
140     /* 1000BaseX mode */
141     tmpReg16 = PHY_SGMII_IF_MODE_1000X;
142     MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x14, tmpReg16);
143 
144     /* AN Device capability  */
145     tmpReg16 = PHY_SGMII_DEV_ABILITY_1000X;
146     MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x4, tmpReg16);
147 
148     /* Adjust link timer for SGMII  -
149        For Serdes 1000BaseX auto-negotiation the timer should be 10 ms.
150        The link_timer register is configured in units of the clock.
151        - When running as 1G SGMII, Serdes clock is 125 MHz, so
152          unit = 1 / (125*10^6 Hz) = 8 ns.
153          10 ms in units of 8 ns = 10ms / 8ns = 1250000 = 0x1312d0
154        - When running as 2.5G SGMII, Serdes clock is 312.5 MHz, so
155          unit = 1 / (312.5*10^6 Hz) = 3.2 ns.
156          10 ms in units of 3.2 ns = 10ms / 3.2ns = 3125000 = 0x2faf08.
157        Since link_timer value of 1G SGMII will be too short for 2.5 SGMII,
158        we always set up here a value of 2.5 SGMII. */
159     MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x13, 0x002f);
160     MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x12, 0xaf08);
161 
162     /* Restart AN */
163     tmpReg16 = PHY_SGMII_CR_DEF_VAL | PHY_SGMII_CR_RESET_AN;
164     MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x0, tmpReg16);
165 
166     /* Restore original enet mode */
167     p_Memac->enetMode = enetMode;
168 }
169 
170 /* ......................................................................... */
171 
CheckInitParameters(t_Memac * p_Memac)172 static t_Error CheckInitParameters(t_Memac *p_Memac)
173 {
174     e_FmMacType portType;
175 
176     portType = ((ENET_SPEED_FROM_MODE(p_Memac->enetMode) < e_ENET_SPEED_10000) ? e_FM_MAC_1G : e_FM_MAC_10G);
177 
178 #if (FM_MAX_NUM_OF_10G_MACS > 0)
179     if ((portType == e_FM_MAC_10G) && (p_Memac->macId >= FM_MAX_NUM_OF_10G_MACS))
180         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("10G MAC ID must be less than %d", FM_MAX_NUM_OF_10G_MACS));
181 #endif /* (FM_MAX_NUM_OF_10G_MACS > 0) */
182 
183     if ((portType == e_FM_MAC_1G) && (p_Memac->macId >= FM_MAX_NUM_OF_1G_MACS))
184         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("1G MAC ID must be less than %d", FM_MAX_NUM_OF_1G_MACS));
185     if (p_Memac->addr == 0)
186         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Ethernet MAC must have a valid MAC address"));
187     if (!p_Memac->f_Exception)
188         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Uninitialized f_Exception"));
189     if (!p_Memac->f_Event)
190         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Uninitialized f_Event"));
191 #ifdef FM_LEN_CHECK_ERRATA_FMAN_SW002
192     if (!p_Memac->p_MemacDriverParam->no_length_check_enable)
193        RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("LengthCheck!"));
194 #endif /* FM_LEN_CHECK_ERRATA_FMAN_SW002 */
195 
196     return E_OK;
197 }
198 
199 /* ........................................................................... */
200 
MemacErrException(t_Handle h_Memac)201 static void MemacErrException(t_Handle h_Memac)
202 {
203     t_Memac     *p_Memac = (t_Memac *)h_Memac;
204     uint32_t    event, imask;
205 
206     event = fman_memac_get_event(p_Memac->p_MemMap, 0xffffffff);
207     imask = fman_memac_get_interrupt_mask(p_Memac->p_MemMap);
208 
209     /* Imask include both error and notification/event bits.
210        Leaving only error bits enabled by imask.
211        The imask error bits are shifted by 16 bits offset from
212        their corresponding location in the ievent - hence the >> 16 */
213     event &= ((imask & MEMAC_ALL_ERRS_IMASK) >> 16);
214 
215     fman_memac_ack_event(p_Memac->p_MemMap, event);
216 
217     if (event & MEMAC_IEVNT_TS_ECC_ER)
218         p_Memac->f_Exception(p_Memac->h_App, e_FM_MAC_EX_TS_FIFO_ECC_ERR);
219     if (event & MEMAC_IEVNT_TX_ECC_ER)
220         p_Memac->f_Exception(p_Memac->h_App, e_FM_MAC_EX_10G_1TX_ECC_ER);
221     if (event & MEMAC_IEVNT_RX_ECC_ER)
222         p_Memac->f_Exception(p_Memac->h_App, e_FM_MAC_EX_10G_RX_ECC_ER);
223 }
224 
MemacException(t_Handle h_Memac)225 static void MemacException(t_Handle h_Memac)
226 {
227     t_Memac     *p_Memac = (t_Memac *)h_Memac;
228     uint32_t    event, imask;
229 
230     event = fman_memac_get_event(p_Memac->p_MemMap, 0xffffffff);
231     imask = fman_memac_get_interrupt_mask(p_Memac->p_MemMap);
232 
233     /* Imask include both error and notification/event bits.
234        Leaving only error bits enabled by imask.
235        The imask error bits are shifted by 16 bits offset from
236        their corresponding location in the ievent - hence the >> 16 */
237     event &= ((imask & MEMAC_ALL_ERRS_IMASK) >> 16);
238 
239     fman_memac_ack_event(p_Memac->p_MemMap, event);
240 
241     if (event & MEMAC_IEVNT_MGI)
242         p_Memac->f_Exception(p_Memac->h_App, e_FM_MAC_EX_MAGIC_PACKET_INDICATION);
243 }
244 
245 /* ......................................................................... */
246 
FreeInitResources(t_Memac * p_Memac)247 static void FreeInitResources(t_Memac *p_Memac)
248 {
249     e_FmMacType portType;
250 
251     portType =
252         ((ENET_SPEED_FROM_MODE(p_Memac->enetMode) < e_ENET_SPEED_10000) ? e_FM_MAC_1G : e_FM_MAC_10G);
253 
254     if (portType == e_FM_MAC_10G)
255         FmUnregisterIntr(p_Memac->fmMacControllerDriver.h_Fm, e_FM_MOD_10G_MAC, p_Memac->macId, e_FM_INTR_TYPE_ERR);
256     else
257         FmUnregisterIntr(p_Memac->fmMacControllerDriver.h_Fm, e_FM_MOD_1G_MAC, p_Memac->macId, e_FM_INTR_TYPE_ERR);
258 
259     /* release the driver's group hash table */
260     FreeHashTable(p_Memac->p_MulticastAddrHash);
261     p_Memac->p_MulticastAddrHash =   NULL;
262 
263     /* release the driver's individual hash table */
264     FreeHashTable(p_Memac->p_UnicastAddrHash);
265     p_Memac->p_UnicastAddrHash =     NULL;
266 }
267 
268 
269 /*****************************************************************************/
270 /*                     mEMAC API routines                                    */
271 /*****************************************************************************/
272 
273 /* ......................................................................... */
274 
MemacEnable(t_Handle h_Memac,e_CommMode mode)275 static t_Error MemacEnable(t_Handle h_Memac,  e_CommMode mode)
276 {
277     t_Memac     *p_Memac = (t_Memac *)h_Memac;
278 
279     SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
280     SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
281 
282     fman_memac_enable(p_Memac->p_MemMap, (mode & e_COMM_MODE_RX), (mode & e_COMM_MODE_TX));
283 
284     return E_OK;
285 }
286 
287 /* ......................................................................... */
288 
MemacDisable(t_Handle h_Memac,e_CommMode mode)289 static t_Error MemacDisable (t_Handle h_Memac, e_CommMode mode)
290 {
291     t_Memac     *p_Memac = (t_Memac *)h_Memac;
292 
293     SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
294     SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
295 
296     fman_memac_disable(p_Memac->p_MemMap, (mode & e_COMM_MODE_RX), (mode & e_COMM_MODE_TX));
297 
298     return E_OK;
299 }
300 
301 /* ......................................................................... */
302 
MemacSetPromiscuous(t_Handle h_Memac,bool newVal)303 static t_Error MemacSetPromiscuous(t_Handle h_Memac, bool newVal)
304 {
305     t_Memac     *p_Memac = (t_Memac *)h_Memac;
306 
307     SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
308     SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
309 
310     fman_memac_set_promiscuous(p_Memac->p_MemMap, newVal);
311 
312     return E_OK;
313 }
314 
315 /* .............................................................................. */
316 
MemacAdjustLink(t_Handle h_Memac,e_EnetSpeed speed,bool fullDuplex)317 static t_Error MemacAdjustLink(t_Handle h_Memac, e_EnetSpeed speed, bool fullDuplex)
318 {
319     t_Memac     *p_Memac = (t_Memac *)h_Memac;
320 
321     SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
322     SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
323 
324     if ((speed >= e_ENET_SPEED_1000) && (!fullDuplex))
325         RETURN_ERROR(MAJOR, E_CONFLICT,
326                      ("Ethernet MAC 1G or 10G does not support half-duplex"));
327 
328     fman_memac_adjust_link(p_Memac->p_MemMap,
329                            (enum enet_interface)ENET_INTERFACE_FROM_MODE(p_Memac->enetMode),
330                            (enum enet_speed)speed,
331                            fullDuplex);
332     return E_OK;
333 }
334 
335 
336 /*****************************************************************************/
337 /*                      Memac Configs modification functions                 */
338 /*****************************************************************************/
339 
340 /* ......................................................................... */
341 
MemacConfigLoopback(t_Handle h_Memac,bool newVal)342 static t_Error MemacConfigLoopback(t_Handle h_Memac, bool newVal)
343 {
344     t_Memac     *p_Memac = (t_Memac *)h_Memac;
345 
346     SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
347     SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE);
348 
349     p_Memac->p_MemacDriverParam->loopback_enable = newVal;
350 
351     return E_OK;
352 }
353 
354 /* ......................................................................... */
355 
MemacConfigWan(t_Handle h_Memac,bool newVal)356 static t_Error MemacConfigWan(t_Handle h_Memac, bool newVal)
357 {
358     t_Memac     *p_Memac = (t_Memac *)h_Memac;
359 
360     SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
361     SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE);
362 
363     p_Memac->p_MemacDriverParam->wan_mode_enable = newVal;
364 
365     return E_OK;
366 }
367 
368 /* ......................................................................... */
369 
MemacConfigMaxFrameLength(t_Handle h_Memac,uint16_t newVal)370 static t_Error MemacConfigMaxFrameLength(t_Handle h_Memac, uint16_t newVal)
371 {
372     t_Memac     *p_Memac = (t_Memac *)h_Memac;
373 
374     SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
375     SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE);
376 
377     p_Memac->p_MemacDriverParam->max_frame_length = newVal;
378 
379     return E_OK;
380 }
381 
382 /* ......................................................................... */
383 
MemacConfigPad(t_Handle h_Memac,bool newVal)384 static t_Error MemacConfigPad(t_Handle h_Memac, bool newVal)
385 {
386     t_Memac     *p_Memac = (t_Memac *)h_Memac;
387 
388     SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
389     SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE);
390 
391     p_Memac->p_MemacDriverParam->pad_enable = newVal;
392 
393     return E_OK;
394 }
395 
396 /* ......................................................................... */
397 
MemacConfigLengthCheck(t_Handle h_Memac,bool newVal)398 static t_Error MemacConfigLengthCheck(t_Handle h_Memac, bool newVal)
399 {
400     t_Memac     *p_Memac = (t_Memac *)h_Memac;
401 
402     SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
403     SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE);
404 
405     p_Memac->p_MemacDriverParam->no_length_check_enable = !newVal;
406 
407     return E_OK;
408 }
409 
410 /* ......................................................................... */
411 
MemacConfigException(t_Handle h_Memac,e_FmMacExceptions exception,bool enable)412 static t_Error MemacConfigException(t_Handle h_Memac, e_FmMacExceptions exception, bool enable)
413 {
414     t_Memac     *p_Memac = (t_Memac *)h_Memac;
415     uint32_t    bitMask = 0;
416 
417     SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
418     SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE);
419 
420     GET_EXCEPTION_FLAG(bitMask, exception);
421     if (bitMask)
422     {
423         if (enable)
424             p_Memac->exceptions |= bitMask;
425         else
426             p_Memac->exceptions &= ~bitMask;
427     }
428     else
429         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception"));
430 
431     return E_OK;
432 }
433 
434 /* ......................................................................... */
435 
MemacConfigResetOnInit(t_Handle h_Memac,bool enable)436 static t_Error MemacConfigResetOnInit(t_Handle h_Memac, bool enable)
437 {
438     t_Memac     *p_Memac = (t_Memac *)h_Memac;
439 
440     SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
441     SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE);
442 
443     p_Memac->p_MemacDriverParam->reset_on_init = enable;
444 
445     return E_OK;
446 }
447 
448 
449 /*****************************************************************************/
450 /*                      Memac Run Time API functions                         */
451 /*****************************************************************************/
452 
453 /* ......................................................................... */
454 
MemacSetTxPauseFrames(t_Handle h_Memac,uint8_t priority,uint16_t pauseTime,uint16_t threshTime)455 static t_Error MemacSetTxPauseFrames(t_Handle h_Memac,
456                                      uint8_t  priority,
457                                      uint16_t pauseTime,
458                                      uint16_t threshTime)
459 {
460     t_Memac     *p_Memac = (t_Memac *)h_Memac;
461 
462     SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_STATE);
463     SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
464 
465     if (priority != 0xFF)
466     {
467         bool   PortConfigured, PreFetchEnabled;
468 
469         if (FmGetTnumAgingPeriod(p_Memac->fmMacControllerDriver.h_Fm) == 0)
470             RETURN_ERROR(MAJOR, E_CONFLICT, ("For PFC operation, TNUM aging must be enabled"));
471 
472         FmGetPortPreFetchConfiguration(p_Memac->fmMacControllerDriver.h_Fm,
473                                        p_Memac->fmMacControllerDriver.macId,
474                                        &PortConfigured,
475                                        &PreFetchEnabled);
476 
477         if ((ENET_SPEED_FROM_MODE(p_Memac->fmMacControllerDriver.enetMode) == e_ENET_SPEED_1000) && !PortConfigured)
478             DBG(INFO, ("For PFC correct operation, prefetch must be configured on the FM Tx PORT"));
479 
480         if ((ENET_SPEED_FROM_MODE(p_Memac->fmMacControllerDriver.enetMode) == e_ENET_SPEED_1000) && PortConfigured && !PreFetchEnabled)
481             DBG(WARNING, ("For PFC correct operation, prefetch must be configured on the FM Tx PORT"));
482     }
483 
484     fman_memac_set_tx_pause_frames(p_Memac->p_MemMap, priority, pauseTime, threshTime);
485 
486     return E_OK;
487 }
488 
489 /* ......................................................................... */
490 
MemacSetTxAutoPauseFrames(t_Handle h_Memac,uint16_t pauseTime)491 static t_Error MemacSetTxAutoPauseFrames(t_Handle h_Memac,
492                                          uint16_t pauseTime)
493 {
494     return MemacSetTxPauseFrames(h_Memac, FM_MAC_NO_PFC, pauseTime, 0);
495 }
496 
497 /* ......................................................................... */
498 
MemacSetRxIgnorePauseFrames(t_Handle h_Memac,bool en)499 static t_Error MemacSetRxIgnorePauseFrames(t_Handle h_Memac, bool en)
500 {
501     t_Memac     *p_Memac = (t_Memac *)h_Memac;
502 
503     SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_STATE);
504     SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
505 
506     fman_memac_set_rx_ignore_pause_frames(p_Memac->p_MemMap, en);
507 
508     return E_OK;
509 }
510 
511 /* ......................................................................... */
512 
MemacSetWakeOnLan(t_Handle h_Memac,bool en)513 static t_Error MemacSetWakeOnLan(t_Handle h_Memac, bool en)
514 {
515     t_Memac     *p_Memac = (t_Memac *)h_Memac;
516 
517     SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_STATE);
518     SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
519 
520     fman_memac_set_wol(p_Memac->p_MemMap, en);
521 
522     return E_OK;
523 }
524 
525 /* .............................................................................. */
526 
MemacEnable1588TimeStamp(t_Handle h_Memac)527 static t_Error MemacEnable1588TimeStamp(t_Handle h_Memac)
528 {
529     t_Memac     *p_Memac = (t_Memac *)h_Memac;
530 
531     SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
532     SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
533 UNUSED(p_Memac);
534 DBG(WARNING, ("mEMAC has 1588 always enabled!"));
535 
536     return E_OK;
537 }
538 
539 /* Counters handling */
540 /* ......................................................................... */
541 
MemacGetStatistics(t_Handle h_Memac,t_FmMacStatistics * p_Statistics)542 static t_Error MemacGetStatistics(t_Handle h_Memac, t_FmMacStatistics *p_Statistics)
543 {
544     t_Memac     *p_Memac = (t_Memac *)h_Memac;
545 
546     SANITY_CHECK_RETURN_ERROR(p_Memac, E_NULL_POINTER);
547     SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
548     SANITY_CHECK_RETURN_ERROR(p_Statistics, E_NULL_POINTER);
549 
550     p_Statistics->eStatPkts64           = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R64);
551     p_Statistics->eStatPkts65to127      = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R127);
552     p_Statistics->eStatPkts128to255     = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R255);
553     p_Statistics->eStatPkts256to511     = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R511);
554     p_Statistics->eStatPkts512to1023    = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R1023);
555     p_Statistics->eStatPkts1024to1518   = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R1518);
556     p_Statistics->eStatPkts1519to1522   = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R1519X);
557 /* */
558     p_Statistics->eStatFragments        = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RFRG);
559     p_Statistics->eStatJabbers          = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RJBR);
560 
561     p_Statistics->eStatsDropEvents      = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RDRP);
562     p_Statistics->eStatCRCAlignErrors   = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RALN);
563 
564     p_Statistics->eStatUndersizePkts    = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TUND);
565     p_Statistics->eStatOversizePkts     = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_ROVR);
566 /* Pause */
567     p_Statistics->reStatPause           = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RXPF);
568     p_Statistics->teStatPause           = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TXPF);
569 
570 /* MIB II */
571     p_Statistics->ifInOctets            = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_ROCT);
572     p_Statistics->ifInUcastPkts         = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RUCA);
573     p_Statistics->ifInMcastPkts         = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RMCA);
574     p_Statistics->ifInBcastPkts         = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RBCA);
575     p_Statistics->ifInPkts              = p_Statistics->ifInUcastPkts
576                                         + p_Statistics->ifInMcastPkts
577                                         + p_Statistics->ifInBcastPkts;
578     p_Statistics->ifInDiscards          = 0;
579     p_Statistics->ifInErrors            = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RERR);
580 
581     p_Statistics->ifOutOctets           = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TOCT);
582     p_Statistics->ifOutUcastPkts        = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TUCA);
583     p_Statistics->ifOutMcastPkts        = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TMCA);
584     p_Statistics->ifOutBcastPkts        = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TBCA);
585     p_Statistics->ifOutPkts             = p_Statistics->ifOutUcastPkts
586                                         + p_Statistics->ifOutMcastPkts
587                                         + p_Statistics->ifOutBcastPkts;
588     p_Statistics->ifOutDiscards         = 0;
589     p_Statistics->ifOutErrors           = fman_memac_get_counter(p_Memac->p_MemMap,  E_MEMAC_COUNTER_TERR);
590 
591     return E_OK;
592 }
593 
594 /* ......................................................................... */
595 
MemacModifyMacAddress(t_Handle h_Memac,t_EnetAddr * p_EnetAddr)596 static t_Error MemacModifyMacAddress (t_Handle h_Memac, t_EnetAddr *p_EnetAddr)
597 {
598     t_Memac     *p_Memac = (t_Memac *)h_Memac;
599 
600     SANITY_CHECK_RETURN_ERROR(p_Memac, E_NULL_POINTER);
601     SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
602 
603     fman_memac_add_addr_in_paddr(p_Memac->p_MemMap, (uint8_t *)(*p_EnetAddr), 0);
604 
605     return E_OK;
606 }
607 
608 /* ......................................................................... */
609 
MemacResetCounters(t_Handle h_Memac)610 static t_Error MemacResetCounters (t_Handle h_Memac)
611 {
612     t_Memac     *p_Memac = (t_Memac *)h_Memac;
613 
614     SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
615     SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
616 
617     fman_memac_reset_stat(p_Memac->p_MemMap);
618 
619     return E_OK;
620 }
621 
622 /* ......................................................................... */
623 
MemacAddExactMatchMacAddress(t_Handle h_Memac,t_EnetAddr * p_EthAddr)624 static t_Error MemacAddExactMatchMacAddress(t_Handle h_Memac, t_EnetAddr *p_EthAddr)
625 {
626     t_Memac     *p_Memac = (t_Memac *) h_Memac;
627     uint64_t    ethAddr;
628     uint8_t     paddrNum;
629 
630     SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
631     SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
632 
633     ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);
634 
635     if (ethAddr & GROUP_ADDRESS)
636         /* Multicast address has no effect in PADDR */
637         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Multicast address"));
638 
639     /* Make sure no PADDR contains this address */
640     for (paddrNum = 0; paddrNum < MEMAC_NUM_OF_PADDRS; paddrNum++)
641         if (p_Memac->indAddrRegUsed[paddrNum])
642             if (p_Memac->paddr[paddrNum] == ethAddr)
643                 RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, NO_MSG);
644 
645     /* Find first unused PADDR */
646     for (paddrNum = 0; paddrNum < MEMAC_NUM_OF_PADDRS; paddrNum++)
647         if (!(p_Memac->indAddrRegUsed[paddrNum]))
648         {
649             /* mark this PADDR as used */
650             p_Memac->indAddrRegUsed[paddrNum] = TRUE;
651             /* store address */
652             p_Memac->paddr[paddrNum] = ethAddr;
653 
654             /* put in hardware */
655             fman_memac_add_addr_in_paddr(p_Memac->p_MemMap, (uint8_t*)(*p_EthAddr), paddrNum);
656             p_Memac->numOfIndAddrInRegs++;
657 
658             return E_OK;
659         }
660 
661     /* No free PADDR */
662     RETURN_ERROR(MAJOR, E_FULL, NO_MSG);
663 }
664 
665 /* ......................................................................... */
666 
MemacDelExactMatchMacAddress(t_Handle h_Memac,t_EnetAddr * p_EthAddr)667 static t_Error MemacDelExactMatchMacAddress(t_Handle h_Memac, t_EnetAddr *p_EthAddr)
668 {
669     t_Memac     *p_Memac = (t_Memac *) h_Memac;
670     uint64_t    ethAddr;
671     uint8_t     paddrNum;
672 
673     SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
674     SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
675 
676     ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);
677 
678     /* Find used PADDR containing this address */
679     for (paddrNum = 0; paddrNum < MEMAC_NUM_OF_PADDRS; paddrNum++)
680     {
681         if ((p_Memac->indAddrRegUsed[paddrNum]) &&
682             (p_Memac->paddr[paddrNum] == ethAddr))
683         {
684             /* mark this PADDR as not used */
685             p_Memac->indAddrRegUsed[paddrNum] = FALSE;
686             /* clear in hardware */
687             fman_memac_clear_addr_in_paddr(p_Memac->p_MemMap, paddrNum);
688             p_Memac->numOfIndAddrInRegs--;
689 
690             return E_OK;
691         }
692     }
693 
694     RETURN_ERROR(MAJOR, E_NOT_FOUND, NO_MSG);
695 }
696 
697 /* ......................................................................... */
698 
MemacGetId(t_Handle h_Memac,uint32_t * macId)699 static t_Error MemacGetId(t_Handle h_Memac, uint32_t *macId)
700 {
701     t_Memac     *p_Memac = (t_Memac *)h_Memac;
702 
703     SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
704     SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
705 
706     *macId = p_Memac->macId;
707 
708     return E_OK;
709 }
710 
711 /* ......................................................................... */
712 
713 
MemacAddHashMacAddress(t_Handle h_Memac,t_EnetAddr * p_EthAddr)714 static t_Error MemacAddHashMacAddress(t_Handle h_Memac, t_EnetAddr *p_EthAddr)
715 {
716     t_Memac             *p_Memac = (t_Memac *)h_Memac;
717     t_EthHashEntry      *p_HashEntry;
718     uint32_t            hash;
719     uint64_t            ethAddr;
720 
721     SANITY_CHECK_RETURN_ERROR(p_Memac, E_NULL_POINTER);
722     SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
723 
724     ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);
725 
726     if (!(ethAddr & GROUP_ADDRESS))
727         /* Unicast addresses not supported in hash */
728         RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Unicast Address"));
729 
730     hash = GetMacAddrHashCode(ethAddr) & HASH_CTRL_ADDR_MASK;
731 
732     /* Create element to be added to the driver hash table */
733     p_HashEntry = (t_EthHashEntry *)XX_Malloc(sizeof(t_EthHashEntry));
734     p_HashEntry->addr = ethAddr;
735     INIT_LIST(&p_HashEntry->node);
736 
737     LIST_AddToTail(&(p_HashEntry->node), &(p_Memac->p_MulticastAddrHash->p_Lsts[hash]));
738     fman_memac_set_hash_table(p_Memac->p_MemMap, (hash | HASH_CTRL_MCAST_EN));
739 
740     return E_OK;
741 }
742 
743 /* ......................................................................... */
744 
MemacDelHashMacAddress(t_Handle h_Memac,t_EnetAddr * p_EthAddr)745 static t_Error MemacDelHashMacAddress(t_Handle h_Memac, t_EnetAddr *p_EthAddr)
746 {
747     t_Memac             *p_Memac = (t_Memac *)h_Memac;
748     t_EthHashEntry      *p_HashEntry = NULL;
749     t_List              *p_Pos;
750     uint32_t            hash;
751     uint64_t            ethAddr;
752 
753     SANITY_CHECK_RETURN_ERROR(p_Memac, E_NULL_POINTER);
754     SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
755 
756     ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);
757 
758     hash = GetMacAddrHashCode(ethAddr) & HASH_CTRL_ADDR_MASK;
759 
760     LIST_FOR_EACH(p_Pos, &(p_Memac->p_MulticastAddrHash->p_Lsts[hash]))
761     {
762         p_HashEntry = ETH_HASH_ENTRY_OBJ(p_Pos);
763         if (p_HashEntry->addr == ethAddr)
764         {
765             LIST_DelAndInit(&p_HashEntry->node);
766             XX_Free(p_HashEntry);
767             break;
768         }
769     }
770     if (LIST_IsEmpty(&p_Memac->p_MulticastAddrHash->p_Lsts[hash]))
771         fman_memac_set_hash_table(p_Memac->p_MemMap, (hash & ~HASH_CTRL_MCAST_EN));
772 
773     return E_OK;
774 }
775 
776 
777 /* ......................................................................... */
778 
MemacSetException(t_Handle h_Memac,e_FmMacExceptions exception,bool enable)779 static t_Error MemacSetException(t_Handle h_Memac, e_FmMacExceptions exception, bool enable)
780 {
781     t_Memac     *p_Memac = (t_Memac *)h_Memac;
782     uint32_t    bitMask = 0;
783 
784     SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
785     SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
786 
787     GET_EXCEPTION_FLAG(bitMask, exception);
788     if (bitMask)
789     {
790         if (enable)
791             p_Memac->exceptions |= bitMask;
792         else
793             p_Memac->exceptions &= ~bitMask;
794     }
795     else
796         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception"));
797 
798     fman_memac_set_exception(p_Memac->p_MemMap, bitMask, enable);
799 
800     return E_OK;
801 }
802 
803 /* ......................................................................... */
804 
MemacGetMaxFrameLength(t_Handle h_Memac)805 static uint16_t MemacGetMaxFrameLength(t_Handle h_Memac)
806 {
807     t_Memac     *p_Memac = (t_Memac *)h_Memac;
808 
809     SANITY_CHECK_RETURN_VALUE(p_Memac, E_INVALID_HANDLE, 0);
810     SANITY_CHECK_RETURN_VALUE(!p_Memac->p_MemacDriverParam, E_INVALID_STATE, 0);
811 
812     return fman_memac_get_max_frame_len(p_Memac->p_MemMap);
813 }
814 
MemacInitInternalPhy(t_Handle h_Memac)815 static t_Error MemacInitInternalPhy(t_Handle h_Memac)
816 {
817     t_Memac *p_Memac = (t_Memac *)h_Memac;
818     uint8_t i, phyAddr;
819 
820     if (ENET_INTERFACE_FROM_MODE(p_Memac->enetMode) == e_ENET_IF_SGMII)
821     {
822         /* Configure internal SGMII PHY */
823         if (p_Memac->enetMode & ENET_IF_SGMII_BASEX)
824             SetupSgmiiInternalPhyBaseX(p_Memac, PHY_MDIO_ADDR);
825         else
826             SetupSgmiiInternalPhy(p_Memac, PHY_MDIO_ADDR);
827     }
828     else if (ENET_INTERFACE_FROM_MODE(p_Memac->enetMode) == e_ENET_IF_QSGMII)
829     {
830         /* Configure 4 internal SGMII PHYs */
831         for (i = 0; i < 4; i++)
832         {
833             /* QSGMII PHY address occupies 3 upper bits of 5-bit
834                phyAddress; the lower 2 bits are used to extend
835                register address space and access each one of 4
836                ports inside QSGMII. */
837             phyAddr = (uint8_t)((PHY_MDIO_ADDR << 2) | i);
838             if (p_Memac->enetMode & ENET_IF_SGMII_BASEX)
839                 SetupSgmiiInternalPhyBaseX(p_Memac, phyAddr);
840             else
841                 SetupSgmiiInternalPhy(p_Memac, phyAddr);
842         }
843     }
844     return E_OK;
845 }
846 
847 /*****************************************************************************/
848 /*                      mEMAC Init & Free API                                   */
849 /*****************************************************************************/
850 
851 /* ......................................................................... */
852 void *g_MemacRegs;
MemacInit(t_Handle h_Memac)853 static t_Error MemacInit(t_Handle h_Memac)
854 {
855     t_Memac                 *p_Memac = (t_Memac *)h_Memac;
856     struct memac_cfg        *p_MemacDriverParam;
857     enum enet_interface     enet_interface;
858     enum enet_speed         enet_speed;
859     t_EnetAddr              ethAddr;
860     e_FmMacType             portType;
861     t_Error                 err;
862     bool                    slow_10g_if = FALSE;
863     if (p_Memac->macId == 3) /* This is a quick WA */
864 		g_MemacRegs = p_Memac->p_MemMap;
865 
866     SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
867     SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE);
868     SANITY_CHECK_RETURN_ERROR(p_Memac->fmMacControllerDriver.h_Fm, E_INVALID_HANDLE);
869 
870     FM_GetRevision(p_Memac->fmMacControllerDriver.h_Fm, &p_Memac->fmMacControllerDriver.fmRevInfo);
871     if (p_Memac->fmMacControllerDriver.fmRevInfo.majorRev == 6 &&
872         p_Memac->fmMacControllerDriver.fmRevInfo.minorRev == 4)
873         slow_10g_if = TRUE;
874 
875     CHECK_INIT_PARAMETERS(p_Memac, CheckInitParameters);
876 
877     p_MemacDriverParam = p_Memac->p_MemacDriverParam;
878 
879     portType =
880         ((ENET_SPEED_FROM_MODE(p_Memac->enetMode) < e_ENET_SPEED_10000) ? e_FM_MAC_1G : e_FM_MAC_10G);
881 
882     /* First, reset the MAC if desired. */
883     if (p_MemacDriverParam->reset_on_init)
884         fman_memac_reset(p_Memac->p_MemMap);
885 
886     /* MAC Address */
887     MAKE_ENET_ADDR_FROM_UINT64(p_Memac->addr, ethAddr);
888     fman_memac_add_addr_in_paddr(p_Memac->p_MemMap, (uint8_t*)ethAddr, 0);
889 
890     enet_interface = (enum enet_interface) ENET_INTERFACE_FROM_MODE(p_Memac->enetMode);
891     enet_speed = (enum enet_speed) ENET_SPEED_FROM_MODE(p_Memac->enetMode);
892 
893     fman_memac_init(p_Memac->p_MemMap,
894                p_Memac->p_MemacDriverParam,
895                enet_interface,
896                enet_speed,
897                slow_10g_if,
898                p_Memac->exceptions);
899 
900 #ifdef FM_RX_FIFO_CORRUPT_ERRATA_10GMAC_A006320
901     {
902     	uint32_t tmpReg = 0;
903 
904     	FM_GetRevision(p_Memac->fmMacControllerDriver.h_Fm, &p_Memac->fmMacControllerDriver.fmRevInfo);
905         /* check the FMAN version - the bug exists only in rev1 */
906         if ((p_Memac->fmMacControllerDriver.fmRevInfo.majorRev == 6) &&
907         	(p_Memac->fmMacControllerDriver.fmRevInfo.minorRev == 0))
908         {
909         	/* MAC strips CRC from received frames - this workaround should
910         	   decrease the likelihood of bug appearance
911             */
912 			tmpReg = GET_UINT32(p_Memac->p_MemMap->command_config);
913 			tmpReg &= ~CMD_CFG_CRC_FWD;
914 			WRITE_UINT32(p_Memac->p_MemMap->command_config, tmpReg);
915 			/* DBG(WARNING, ("mEMAC strips CRC from received frames as part of A006320 errata workaround"));*/
916         }
917     }
918 #endif /* FM_RX_FIFO_CORRUPT_ERRATA_10GMAC_A006320 */
919 
920     MemacInitInternalPhy(h_Memac);
921 
922     /* Max Frame Length */
923     err = FmSetMacMaxFrame(p_Memac->fmMacControllerDriver.h_Fm,
924                            portType,
925                            p_Memac->fmMacControllerDriver.macId,
926                            p_MemacDriverParam->max_frame_length);
927     if (err)
928         RETURN_ERROR(MAJOR, err, ("settings Mac max frame length is FAILED"));
929 
930     p_Memac->p_MulticastAddrHash = AllocHashTable(HASH_TABLE_SIZE);
931     if (!p_Memac->p_MulticastAddrHash)
932     {
933         FreeInitResources(p_Memac);
934         RETURN_ERROR(MAJOR, E_NO_MEMORY, ("allocation hash table is FAILED"));
935     }
936 
937     p_Memac->p_UnicastAddrHash = AllocHashTable(HASH_TABLE_SIZE);
938     if (!p_Memac->p_UnicastAddrHash)
939     {
940         FreeInitResources(p_Memac);
941         RETURN_ERROR(MAJOR, E_NO_MEMORY, ("allocation hash table is FAILED"));
942     }
943 
944     FmRegisterIntr(p_Memac->fmMacControllerDriver.h_Fm,
945                    (portType == e_FM_MAC_10G) ? e_FM_MOD_10G_MAC : e_FM_MOD_1G_MAC,
946                    p_Memac->macId,
947                    e_FM_INTR_TYPE_ERR,
948                    MemacErrException,
949                    p_Memac);
950 
951     FmRegisterIntr(p_Memac->fmMacControllerDriver.h_Fm,
952                    (portType == e_FM_MAC_10G) ? e_FM_MOD_10G_MAC : e_FM_MOD_1G_MAC,
953                    p_Memac->macId,
954                    e_FM_INTR_TYPE_NORMAL,
955                    MemacException,
956                    p_Memac);
957 
958     XX_Free(p_MemacDriverParam);
959     p_Memac->p_MemacDriverParam = NULL;
960 
961     return E_OK;
962 }
963 
964 /* ......................................................................... */
965 
MemacFree(t_Handle h_Memac)966 static t_Error MemacFree(t_Handle h_Memac)
967 {
968     t_Memac     *p_Memac = (t_Memac *)h_Memac;
969 
970     SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
971 
972     if (p_Memac->p_MemacDriverParam)
973     {
974         /* Called after config */
975         XX_Free(p_Memac->p_MemacDriverParam);
976         p_Memac->p_MemacDriverParam = NULL;
977     }
978     else
979         /* Called after init */
980         FreeInitResources(p_Memac);
981 
982     XX_Free(p_Memac);
983 
984     return E_OK;
985 }
986 
987 /* ......................................................................... */
988 
InitFmMacControllerDriver(t_FmMacControllerDriver * p_FmMacControllerDriver)989 static void InitFmMacControllerDriver(t_FmMacControllerDriver *p_FmMacControllerDriver)
990 {
991     p_FmMacControllerDriver->f_FM_MAC_Init                      = MemacInit;
992     p_FmMacControllerDriver->f_FM_MAC_Free                      = MemacFree;
993 
994     p_FmMacControllerDriver->f_FM_MAC_SetStatistics             = NULL;
995     p_FmMacControllerDriver->f_FM_MAC_ConfigLoopback            = MemacConfigLoopback;
996     p_FmMacControllerDriver->f_FM_MAC_ConfigMaxFrameLength      = MemacConfigMaxFrameLength;
997 
998     p_FmMacControllerDriver->f_FM_MAC_ConfigWan                 = MemacConfigWan;
999 
1000     p_FmMacControllerDriver->f_FM_MAC_ConfigPadAndCrc           = MemacConfigPad;
1001     p_FmMacControllerDriver->f_FM_MAC_ConfigHalfDuplex          = NULL; /* half-duplex is detected automatically */
1002     p_FmMacControllerDriver->f_FM_MAC_ConfigLengthCheck         = MemacConfigLengthCheck;
1003 
1004     p_FmMacControllerDriver->f_FM_MAC_ConfigException           = MemacConfigException;
1005     p_FmMacControllerDriver->f_FM_MAC_ConfigResetOnInit         = MemacConfigResetOnInit;
1006 
1007     p_FmMacControllerDriver->f_FM_MAC_SetException              = MemacSetException;
1008 
1009     p_FmMacControllerDriver->f_FM_MAC_Enable1588TimeStamp       = MemacEnable1588TimeStamp; /* always enabled */
1010     p_FmMacControllerDriver->f_FM_MAC_Disable1588TimeStamp      = NULL;
1011 
1012     p_FmMacControllerDriver->f_FM_MAC_SetPromiscuous            = MemacSetPromiscuous;
1013     p_FmMacControllerDriver->f_FM_MAC_AdjustLink                = MemacAdjustLink;
1014     p_FmMacControllerDriver->f_FM_MAC_RestartAutoneg            = NULL;
1015 
1016     p_FmMacControllerDriver->f_FM_MAC_Enable                    = MemacEnable;
1017     p_FmMacControllerDriver->f_FM_MAC_Disable                   = MemacDisable;
1018     p_FmMacControllerDriver->f_FM_MAC_Resume                    = MemacInitInternalPhy;
1019 
1020     p_FmMacControllerDriver->f_FM_MAC_SetTxAutoPauseFrames      = MemacSetTxAutoPauseFrames;
1021     p_FmMacControllerDriver->f_FM_MAC_SetTxPauseFrames          = MemacSetTxPauseFrames;
1022     p_FmMacControllerDriver->f_FM_MAC_SetRxIgnorePauseFrames    = MemacSetRxIgnorePauseFrames;
1023 
1024     p_FmMacControllerDriver->f_FM_MAC_SetWakeOnLan              = MemacSetWakeOnLan;
1025 
1026     p_FmMacControllerDriver->f_FM_MAC_ResetCounters             = MemacResetCounters;
1027     p_FmMacControllerDriver->f_FM_MAC_GetStatistics             = MemacGetStatistics;
1028 
1029     p_FmMacControllerDriver->f_FM_MAC_ModifyMacAddr             = MemacModifyMacAddress;
1030     p_FmMacControllerDriver->f_FM_MAC_AddHashMacAddr            = MemacAddHashMacAddress;
1031     p_FmMacControllerDriver->f_FM_MAC_RemoveHashMacAddr         = MemacDelHashMacAddress;
1032     p_FmMacControllerDriver->f_FM_MAC_AddExactMatchMacAddr      = MemacAddExactMatchMacAddress;
1033     p_FmMacControllerDriver->f_FM_MAC_RemovelExactMatchMacAddr  = MemacDelExactMatchMacAddress;
1034     p_FmMacControllerDriver->f_FM_MAC_GetId                     = MemacGetId;
1035     p_FmMacControllerDriver->f_FM_MAC_GetVersion                = NULL;
1036     p_FmMacControllerDriver->f_FM_MAC_GetMaxFrameLength         = MemacGetMaxFrameLength;
1037 
1038     p_FmMacControllerDriver->f_FM_MAC_MII_WritePhyReg           = MEMAC_MII_WritePhyReg;
1039     p_FmMacControllerDriver->f_FM_MAC_MII_ReadPhyReg            = MEMAC_MII_ReadPhyReg;
1040 }
1041 
1042 
1043 /*****************************************************************************/
1044 /*                      mEMAC Config Main Entry                             */
1045 /*****************************************************************************/
1046 
1047 /* ......................................................................... */
1048 
MEMAC_Config(t_FmMacParams * p_FmMacParam)1049 t_Handle MEMAC_Config(t_FmMacParams *p_FmMacParam)
1050 {
1051     t_Memac             *p_Memac;
1052     struct memac_cfg    *p_MemacDriverParam;
1053     uintptr_t           baseAddr;
1054 
1055     SANITY_CHECK_RETURN_VALUE(p_FmMacParam, E_NULL_POINTER, NULL);
1056 
1057     baseAddr = p_FmMacParam->baseAddr;
1058     /* Allocate memory for the mEMAC data structure */
1059     p_Memac = (t_Memac *)XX_Malloc(sizeof(t_Memac));
1060     if (!p_Memac)
1061     {
1062         REPORT_ERROR(MAJOR, E_NO_MEMORY, ("mEMAC driver structure"));
1063         return NULL;
1064     }
1065     memset(p_Memac, 0, sizeof(t_Memac));
1066     InitFmMacControllerDriver(&p_Memac->fmMacControllerDriver);
1067 
1068     /* Allocate memory for the mEMAC driver parameters data structure */
1069     p_MemacDriverParam = (struct memac_cfg *)XX_Malloc(sizeof(struct memac_cfg));
1070     if (!p_MemacDriverParam)
1071     {
1072         REPORT_ERROR(MAJOR, E_NO_MEMORY, ("mEMAC driver parameters"));
1073         XX_Free(p_Memac);
1074         return NULL;
1075     }
1076     memset(p_MemacDriverParam, 0, sizeof(struct memac_cfg));
1077 
1078     /* Plant parameter structure pointer */
1079     p_Memac->p_MemacDriverParam = p_MemacDriverParam;
1080 
1081     fman_memac_defconfig(p_MemacDriverParam);
1082 
1083     p_Memac->addr           = ENET_ADDR_TO_UINT64(p_FmMacParam->addr);
1084 
1085     p_Memac->p_MemMap       = (struct memac_regs *)UINT_TO_PTR(baseAddr);
1086     p_Memac->p_MiiMemMap    = (struct memac_mii_access_mem_map*)UINT_TO_PTR(baseAddr + MEMAC_TO_MII_OFFSET);
1087 
1088     p_Memac->enetMode       = p_FmMacParam->enetMode;
1089     p_Memac->macId          = p_FmMacParam->macId;
1090     p_Memac->exceptions     = MEMAC_default_exceptions;
1091     p_Memac->f_Exception    = p_FmMacParam->f_Exception;
1092     p_Memac->f_Event        = p_FmMacParam->f_Event;
1093     p_Memac->h_App          = p_FmMacParam->h_App;
1094 
1095     return p_Memac;
1096 }
1097