1 /******************************************************************************
2 * Copyright (C) 2009 - 2020 Xilinx, Inc.  All rights reserved.
3 * SPDX-License-Identifier: MIT
4 ******************************************************************************/
5 
6 /*****************************************************************************/
7 /**
8  *
9  * @file xemacps_control.c
10 * @addtogroup emacps_v3_11
11 * @{
12  *
13  * Functions in this file implement general purpose command and control related
14  * functionality. See xemacps.h for a detailed description of the driver.
15  *
16  * <pre>
17  * MODIFICATION HISTORY:
18  *
19  * Ver   Who  Date     Changes
20  * ----- ---- -------- -------------------------------------------------------
21  * 1.00a wsy  01/10/10 First release
22  * 1.02a asa  11/05/12 Added a new API for deleting an entry from the HASH
23  *                       register. Added a new API for setting the BURST length
24  *                       in DMACR register.
25  * 2.1   srt  07/15/14 Add support for Zynq Ultrascale Mp architecture.
26  * 3.0   kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
27  * 3.0   hk   02/20/15 Added support for jumbo frames.
28  * 3.2   hk   02/22/16 Added SGMII support for Zynq Ultrascale+ MPSoC.
29  * </pre>
30  *****************************************************************************/
31 
32 /***************************** Include Files *********************************/
33 
34 #include "xemacps.h"
35 
36 /************************** Constant Definitions *****************************/
37 
38 
39 /**************************** Type Definitions *******************************/
40 
41 
42 /***************** Macros (Inline Functions) Definitions *********************/
43 
44 
45 /************************** Function Prototypes ******************************/
46 
47 
48 /************************** Variable Definitions *****************************/
49 
50 
51 /*****************************************************************************/
52 /**
53  * Set the MAC address for this driver/device.  The address is a 48-bit value.
54  * The device must be stopped before calling this function.
55  *
56  * @param InstancePtr is a pointer to the instance to be worked on.
57  * @param AddressPtr is a pointer to a 6-byte MAC address.
58  * @param Index is a index to which MAC (1-4) address.
59  *
60  * @return
61  * - XST_SUCCESS if the MAC address was set successfully
62  * - XST_DEVICE_IS_STARTED if the device has not yet been stopped
63  *
64  *****************************************************************************/
XEmacPs_SetMacAddress(XEmacPs * InstancePtr,void * AddressPtr,u8 Index)65 LONG XEmacPs_SetMacAddress(XEmacPs *InstancePtr, void *AddressPtr, u8 Index)
66 {
67     u32 MacAddr;
68     u8 *Aptr = (u8 *)(void *)AddressPtr;
69     u8 IndexLoc = Index;
70     LONG Status;
71     Xil_AssertNonvoid(InstancePtr != NULL);
72     Xil_AssertNonvoid(Aptr != NULL);
73     Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
74     Xil_AssertNonvoid((IndexLoc <= (u8)XEMACPS_MAX_MAC_ADDR) && (IndexLoc > 0x00U));
75 
76     /* Be sure device has been stopped */
77     if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) {
78         Status = (LONG)(XST_DEVICE_IS_STARTED);
79     }
80     else{
81     /* Index ranges 1 to 4, for offset calculation is 0 to 3. */
82         IndexLoc--;
83 
84     /* Set the MAC bits [31:0] in BOT */
85         MacAddr = *(Aptr);
86         MacAddr |= ((u32)(*(Aptr+1)) << 8U);
87         MacAddr |= ((u32)(*(Aptr+2)) << 16U);
88         MacAddr |= ((u32)(*(Aptr+3)) << 24U);
89     XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
90                 ((u32)XEMACPS_LADDR1L_OFFSET + ((u32)IndexLoc * (u32)8)), MacAddr);
91 
92     /* There are reserved bits in TOP so don't affect them */
93     MacAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
94                     ((u32)XEMACPS_LADDR1H_OFFSET + ((u32)IndexLoc * (u32)8)));
95 
96         MacAddr &= (u32)(~XEMACPS_LADDR_MACH_MASK);
97 
98     /* Set MAC bits [47:32] in TOP */
99         MacAddr |= (u32)(*(Aptr+4));
100         MacAddr |= (u32)(*(Aptr+5)) << 8U;
101 
102     XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
103                 ((u32)XEMACPS_LADDR1H_OFFSET + ((u32)IndexLoc * (u32)8)), MacAddr);
104 
105         Status = (LONG)(XST_SUCCESS);
106     }
107     return Status;
108 }
109 
110 
111 /*****************************************************************************/
112 /**
113  * Get the MAC address for this driver/device.
114  *
115  * @param InstancePtr is a pointer to the instance to be worked on.
116  * @param AddressPtr is an output parameter, and is a pointer to a buffer into
117  *        which the current MAC address will be copied.
118  * @param Index is a index to which MAC (1-4) address.
119  *
120  *****************************************************************************/
XEmacPs_GetMacAddress(XEmacPs * InstancePtr,void * AddressPtr,u8 Index)121 void XEmacPs_GetMacAddress(XEmacPs *InstancePtr, void *AddressPtr, u8 Index)
122 {
123     u32 MacAddr;
124     u8 *Aptr = (u8 *)(void *)AddressPtr;
125     u8 IndexLoc = Index;
126     Xil_AssertVoid(InstancePtr != NULL);
127     Xil_AssertVoid(Aptr != NULL);
128     Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
129     Xil_AssertVoid((IndexLoc <= (u8)XEMACPS_MAX_MAC_ADDR) && (IndexLoc > 0x00U));
130 
131     /* Index ranges 1 to 4, for offset calculation is 0 to 3. */
132     IndexLoc--;
133 
134     MacAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
135                     ((u32)XEMACPS_LADDR1L_OFFSET + ((u32)IndexLoc * (u32)8)));
136     *Aptr = (u8) MacAddr;
137     *(Aptr+1) = (u8) (MacAddr >> 8U);
138     *(Aptr+2) = (u8) (MacAddr >> 16U);
139     *(Aptr+3) = (u8) (MacAddr >> 24U);
140 
141     /* Read MAC bits [47:32] in TOP */
142     MacAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
143                     ((u32)XEMACPS_LADDR1H_OFFSET + ((u32)IndexLoc * (u32)8)));
144     *(Aptr+4) = (u8) MacAddr;
145     *(Aptr+5) = (u8) (MacAddr >> 8U);
146 }
147 
148 
149 /*****************************************************************************/
150 /**
151  * Set 48-bit MAC addresses in hash table.
152  * The device must be stopped before calling this function.
153  *
154  * The hash address register is 64 bits long and takes up two locations in
155  * the memory map. The least significant bits are stored in hash register
156  * bottom and the most significant bits in hash register top.
157  *
158  * The unicast hash enable and the multicast hash enable bits in the network
159  * configuration register enable the reception of hash matched frames. The
160  * destination address is reduced to a 6 bit index into the 64 bit hash
161  * register using the following hash function. The hash function is an XOR
162  * of every sixth bit of the destination address.
163  *
164  * <pre>
165  * hash_index[05] = da[05]^da[11]^da[17]^da[23]^da[29]^da[35]^da[41]^da[47]
166  * hash_index[04] = da[04]^da[10]^da[16]^da[22]^da[28]^da[34]^da[40]^da[46]
167  * hash_index[03] = da[03]^da[09]^da[15]^da[21]^da[27]^da[33]^da[39]^da[45]
168  * hash_index[02] = da[02]^da[08]^da[14]^da[20]^da[26]^da[32]^da[38]^da[44]
169  * hash_index[01] = da[01]^da[07]^da[13]^da[19]^da[25]^da[31]^da[37]^da[43]
170  * hash_index[00] = da[00]^da[06]^da[12]^da[18]^da[24]^da[30]^da[36]^da[42]
171  * </pre>
172  *
173  * da[0] represents the least significant bit of the first byte received,
174  * that is, the multicast/unicast indicator, and da[47] represents the most
175  * significant bit of the last byte received.
176  *
177  * If the hash index points to a bit that is set in the hash register then
178  * the frame will be matched according to whether the frame is multicast
179  * or unicast.
180  *
181  * A multicast match will be signaled if the multicast hash enable bit is
182  * set, da[0] is logic 1 and the hash index points to a bit set in the hash
183  * register.
184  *
185  * A unicast match will be signaled if the unicast hash enable bit is set,
186  * da[0] is logic 0 and the hash index points to a bit set in the hash
187  * register.
188  *
189  * To receive all multicast frames, the hash register should be set with
190  * all ones and the multicast hash enable bit should be set in the network
191  * configuration register.
192  *
193  *
194  * @param InstancePtr is a pointer to the instance to be worked on.
195  * @param AddressPtr is a pointer to a 6-byte MAC address.
196  *
197  * @return
198  * - XST_SUCCESS if the HASH MAC address was set successfully
199  * - XST_DEVICE_IS_STARTED if the device has not yet been stopped
200  * - XST_INVALID_PARAM if the HASH MAC address passed in does not meet
201  *   requirement after calculation
202  *
203  * @note
204  * Having Aptr be unsigned type prevents the following operations from sign
205  * extending.
206  *****************************************************************************/
XEmacPs_SetHash(XEmacPs * InstancePtr,void * AddressPtr)207 LONG XEmacPs_SetHash(XEmacPs *InstancePtr, void *AddressPtr)
208 {
209     u32 HashAddr;
210     u8 *Aptr = (u8 *)(void *)AddressPtr;
211     u8 Temp1, Temp2, Temp3, Temp4, Temp5, Temp6, Temp7, Temp8;
212     u32 Result;
213     LONG Status;
214 
215     Xil_AssertNonvoid(InstancePtr != NULL);
216     Xil_AssertNonvoid(AddressPtr != NULL);
217     Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
218 
219     /* Be sure device has been stopped */
220     if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) {
221         Status = (LONG)(XST_DEVICE_IS_STARTED);
222     } else {
223         Temp1 = (*(Aptr+0)) & 0x3FU;
224         Temp2 = ((*(Aptr+0) >> 6U) & 0x03U) | ((*(Aptr+1) & 0x0FU) << 2U);
225 
226         Temp3 = ((*(Aptr+1) >> 4U) & 0x0FU) | ((*(Aptr+2) & 0x3U) << 4U);
227         Temp4 = ((*(Aptr+2) >> 2U) & 0x3FU);
228         Temp5 =   (*(Aptr+3)) & 0x3FU;
229         Temp6 = ((*(Aptr+3) >> 6U) & 0x03U) | ((*(Aptr+4) & 0x0FU) << 2U);
230         Temp7 = ((*(Aptr+4) >> 4U) & 0x0FU) | ((*(Aptr+5) & 0x03U) << 4U);
231         Temp8 = ((*(Aptr+5) >> 2U) & 0x3FU);
232 
233         Result = (u32)((u32)Temp1 ^ (u32)Temp2 ^ (u32)Temp3 ^ (u32)Temp4 ^
234                 (u32)Temp5 ^ (u32)Temp6 ^ (u32)Temp7 ^ (u32)Temp8);
235 
236         if (Result >= (u32)XEMACPS_MAX_HASH_BITS) {
237             Status = (LONG)(XST_INVALID_PARAM);
238         } else {
239 
240             if (Result < (u32)32) {
241         HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
242                 XEMACPS_HASHL_OFFSET);
243                 HashAddr |= (u32)(0x00000001U << Result);
244         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
245             XEMACPS_HASHL_OFFSET, HashAddr);
246     } else {
247         HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
248                 XEMACPS_HASHH_OFFSET);
249                 HashAddr |= (u32)(0x00000001U << (u32)(Result - (u32)32));
250         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
251             XEMACPS_HASHH_OFFSET, HashAddr);
252     }
253             Status = (LONG)(XST_SUCCESS);
254         }
255     }
256     return Status;
257 }
258 
259 /*****************************************************************************/
260 /**
261  * Delete 48-bit MAC addresses in hash table.
262  * The device must be stopped before calling this function.
263  *
264  * @param InstancePtr is a pointer to the instance to be worked on.
265  * @param AddressPtr is a pointer to a 6-byte MAC address.
266  *
267  * @return
268  * - XST_SUCCESS if the HASH MAC address was deleted successfully
269  * - XST_DEVICE_IS_STARTED if the device has not yet been stopped
270  * - XST_INVALID_PARAM if the HASH MAC address passed in does not meet
271  *   requirement after calculation
272  *
273  * @note
274  * Having Aptr be unsigned type prevents the following operations from sign
275  * extending.
276  *****************************************************************************/
XEmacPs_DeleteHash(XEmacPs * InstancePtr,void * AddressPtr)277 LONG XEmacPs_DeleteHash(XEmacPs *InstancePtr, void *AddressPtr)
278 {
279     u32 HashAddr;
280     u8 *Aptr = (u8 *)(void *)AddressPtr;
281     u8 Temp1, Temp2, Temp3, Temp4, Temp5, Temp6, Temp7, Temp8;
282     u32 Result;
283     LONG Status;
284 
285     Xil_AssertNonvoid(InstancePtr != NULL);
286     Xil_AssertNonvoid(Aptr != NULL);
287     Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
288 
289     /* Be sure device has been stopped */
290     if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) {
291         Status = (LONG)(XST_DEVICE_IS_STARTED);
292     } else {
293         Temp1 = (*(Aptr+0)) & 0x3FU;
294         Temp2 = ((*(Aptr+0) >> 6U) & 0x03U) | ((*(Aptr+1) & 0x0FU) << 2U);
295         Temp3 = ((*(Aptr+1) >> 4U) & 0x0FU) | ((*(Aptr+2) & 0x03U) << 4U);
296         Temp4 = ((*(Aptr+2) >> 2U) & 0x3FU);
297         Temp5 =   (*(Aptr+3)) & 0x3FU;
298         Temp6 = ((*(Aptr+3) >> 6U) & 0x03U) | ((*(Aptr+4) & 0x0FU) << 2U);
299         Temp7 = ((*(Aptr+4) >> 4U) & 0x0FU) | ((*(Aptr+5) & 0x03U) << 4U);
300         Temp8 = ((*(Aptr+5) >> 2U) & 0x3FU);
301 
302         Result = (u32)((u32)Temp1 ^ (u32)Temp2 ^ (u32)Temp3 ^ (u32)Temp4 ^
303                     (u32)Temp5 ^ (u32)Temp6 ^ (u32)Temp7 ^ (u32)Temp8);
304 
305         if (Result >= (u32)(XEMACPS_MAX_HASH_BITS)) {
306             Status =  (LONG)(XST_INVALID_PARAM);
307         } else {
308             if (Result < (u32)32) {
309         HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
310                 XEMACPS_HASHL_OFFSET);
311                 HashAddr &= (u32)(~(0x00000001U << Result));
312         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
313                 XEMACPS_HASHL_OFFSET, HashAddr);
314     } else {
315         HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
316                 XEMACPS_HASHH_OFFSET);
317                 HashAddr &= (u32)(~(0x00000001U << (u32)(Result - (u32)32)));
318         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
319             XEMACPS_HASHH_OFFSET, HashAddr);
320     }
321             Status = (LONG)(XST_SUCCESS);
322         }
323     }
324     return Status;
325 }
326 /*****************************************************************************/
327 /**
328  * Clear the Hash registers for the mac address pointed by AddressPtr.
329  *
330  * @param InstancePtr is a pointer to the instance to be worked on.
331  *
332  *****************************************************************************/
XEmacPs_ClearHash(XEmacPs * InstancePtr)333 void XEmacPs_ClearHash(XEmacPs *InstancePtr)
334 {
335     Xil_AssertVoid(InstancePtr != NULL);
336     Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
337 
338     XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
339                     XEMACPS_HASHL_OFFSET, 0x0U);
340 
341     /* write bits [63:32] in TOP */
342     XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
343                     XEMACPS_HASHH_OFFSET, 0x0U);
344 }
345 
346 
347 /*****************************************************************************/
348 /**
349  * Get the Hash address for this driver/device.
350  *
351  * @param InstancePtr is a pointer to the instance to be worked on.
352  * @param AddressPtr is an output parameter, and is a pointer to a buffer into
353  *        which the current HASH MAC address will be copied.
354  *
355  *****************************************************************************/
XEmacPs_GetHash(XEmacPs * InstancePtr,void * AddressPtr)356 void XEmacPs_GetHash(XEmacPs *InstancePtr, void *AddressPtr)
357 {
358     u32 *Aptr = (u32 *)(void *)AddressPtr;
359 
360     Xil_AssertVoid(InstancePtr != NULL);
361     Xil_AssertVoid(AddressPtr != NULL);
362     Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
363 
364     *(Aptr+0) = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
365                     XEMACPS_HASHL_OFFSET);
366 
367     /* Read Hash bits [63:32] in TOP */
368     *(Aptr+1) = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
369                     XEMACPS_HASHH_OFFSET);
370 }
371 
372 
373 /*****************************************************************************/
374 /**
375  * Set the Type ID match for this driver/device.  The register is a 32-bit
376  * value. The device must be stopped before calling this function.
377  *
378  * @param InstancePtr is a pointer to the instance to be worked on.
379  * @param Id_Check is type ID to be configured.
380  * @param Index is a index to which Type ID (1-4).
381  *
382  * @return
383  * - XST_SUCCESS if the MAC address was set successfully
384  * - XST_DEVICE_IS_STARTED if the device has not yet been stopped
385  *
386  *****************************************************************************/
XEmacPs_SetTypeIdCheck(XEmacPs * InstancePtr,u32 Id_Check,u8 Index)387 LONG XEmacPs_SetTypeIdCheck(XEmacPs *InstancePtr, u32 Id_Check, u8 Index)
388 {
389     u8 IndexLoc = Index;
390     LONG Status;
391     Xil_AssertNonvoid(InstancePtr != NULL);
392     Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
393     Xil_AssertNonvoid((IndexLoc <= (u8)XEMACPS_MAX_TYPE_ID) && (IndexLoc > 0x00U));
394 
395     /* Be sure device has been stopped */
396     if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) {
397         Status = (LONG)(XST_DEVICE_IS_STARTED);
398     } else {
399 
400     /* Index ranges 1 to 4, for offset calculation is 0 to 3. */
401         IndexLoc--;
402 
403     /* Set the ID bits in MATCHx register */
404     XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
405                    ((u32)XEMACPS_MATCH1_OFFSET + ((u32)IndexLoc * (u32)4)), Id_Check);
406 
407         Status = (LONG)(XST_SUCCESS);
408     }
409     return Status;
410 }
411 
412 /*****************************************************************************/
413 /**
414  * Set options for the driver/device. The driver should be stopped with
415  * XEmacPs_Stop() before changing options.
416  *
417  * @param InstancePtr is a pointer to the instance to be worked on.
418  * @param Options are the options to set. Multiple options can be set by OR'ing
419  *        XTE_*_OPTIONS constants together. Options not specified are not
420  *        affected.
421  *
422  * @return
423  * - XST_SUCCESS if the options were set successfully
424  * - XST_DEVICE_IS_STARTED if the device has not yet been stopped
425  *
426  * @note
427  * See xemacps.h for a description of the available options.
428  *
429  *****************************************************************************/
XEmacPs_SetOptions(XEmacPs * InstancePtr,u32 Options)430 LONG XEmacPs_SetOptions(XEmacPs *InstancePtr, u32 Options)
431 {
432     u32 Reg;        /* Generic register contents */
433     u32 RegNetCfg;        /* Reflects original contents of NET_CONFIG */
434     u32 RegNewNetCfg;    /* Reflects new contents of NET_CONFIG */
435     LONG Status;
436     Xil_AssertNonvoid(InstancePtr != NULL);
437     Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
438 
439     /* Be sure device has been stopped */
440     if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) {
441         Status = (LONG)(XST_DEVICE_IS_STARTED);
442     } else {
443 
444     /* Many of these options will change the NET_CONFIG registers.
445      * To reduce the amount of IO to the device, group these options here
446      * and change them all at once.
447      */
448 
449     /* Grab current register contents */
450     RegNetCfg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
451                       XEMACPS_NWCFG_OFFSET);
452     RegNewNetCfg = RegNetCfg;
453 
454     /*
455      * It is configured to max 1536.
456      */
457         if ((Options & XEMACPS_FRAME1536_OPTION) != 0x00000000U) {
458         RegNewNetCfg |= (XEMACPS_NWCFG_1536RXEN_MASK);
459     }
460 
461     /* Turn on VLAN packet only, only VLAN tagged will be accepted */
462         if ((Options & XEMACPS_VLAN_OPTION) != 0x00000000U) {
463         RegNewNetCfg |= XEMACPS_NWCFG_NVLANDISC_MASK;
464     }
465 
466     /* Turn on FCS stripping on receive packets */
467         if ((Options & XEMACPS_FCS_STRIP_OPTION) != 0x00000000U) {
468         RegNewNetCfg |= XEMACPS_NWCFG_FCSREM_MASK;
469     }
470 
471     /* Turn on length/type field checking on receive packets */
472         if ((Options & XEMACPS_LENTYPE_ERR_OPTION) != 0x00000000U) {
473             RegNewNetCfg |= XEMACPS_NWCFG_LENERRDSCRD_MASK;
474     }
475 
476     /* Turn on flow control */
477         if ((Options & XEMACPS_FLOW_CONTROL_OPTION) != 0x00000000U) {
478         RegNewNetCfg |= XEMACPS_NWCFG_PAUSEEN_MASK;
479     }
480 
481     /* Turn on promiscuous frame filtering (all frames are received) */
482         if ((Options & XEMACPS_PROMISC_OPTION) != 0x00000000U) {
483         RegNewNetCfg |= XEMACPS_NWCFG_COPYALLEN_MASK;
484     }
485 
486     /* Allow broadcast address reception */
487         if ((Options & XEMACPS_BROADCAST_OPTION) != 0x00000000U) {
488             RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_BCASTDI_MASK);
489     }
490 
491     /* Allow multicast address filtering */
492         if ((Options & XEMACPS_MULTICAST_OPTION) != 0x00000000U) {
493         RegNewNetCfg |= XEMACPS_NWCFG_MCASTHASHEN_MASK;
494     }
495 
496     /* enable RX checksum offload */
497         if ((Options & XEMACPS_RX_CHKSUM_ENABLE_OPTION) != 0x00000000U) {
498         RegNewNetCfg |= XEMACPS_NWCFG_RXCHKSUMEN_MASK;
499     }
500 
501     /* Enable jumbo frames */
502     if (((Options & XEMACPS_JUMBO_ENABLE_OPTION) != 0x00000000U) &&
503         (InstancePtr->Version > 2)) {
504         RegNewNetCfg |= XEMACPS_NWCFG_JUMBO_MASK;
505         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
506             XEMACPS_JUMBOMAXLEN_OFFSET, XEMACPS_RX_BUF_SIZE_JUMBO);
507         Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
508                       XEMACPS_DMACR_OFFSET);
509         Reg &= ~XEMACPS_DMACR_RXBUF_MASK;
510         Reg |= (((((u32)XEMACPS_RX_BUF_SIZE_JUMBO / (u32)XEMACPS_RX_BUF_UNIT) +
511             (((((u32)XEMACPS_RX_BUF_SIZE_JUMBO %
512             (u32)XEMACPS_RX_BUF_UNIT))!=(u32)0) ? 1U : 0U)) <<
513             (u32)(XEMACPS_DMACR_RXBUF_SHIFT)) &
514             (u32)(XEMACPS_DMACR_RXBUF_MASK));
515         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
516             XEMACPS_DMACR_OFFSET, Reg);
517         InstancePtr->MaxMtuSize = XEMACPS_MTU_JUMBO;
518         InstancePtr->MaxFrameSize = XEMACPS_MTU_JUMBO +
519                     XEMACPS_HDR_SIZE + XEMACPS_TRL_SIZE;
520         InstancePtr->MaxVlanFrameSize = InstancePtr->MaxFrameSize +
521                     XEMACPS_HDR_VLAN_SIZE;
522         InstancePtr->RxBufMask = XEMACPS_RXBUF_LEN_JUMBO_MASK;
523     }
524 
525     if (((Options & XEMACPS_SGMII_ENABLE_OPTION) != 0x00000000U) &&
526         (InstancePtr->Version > 2)) {
527         RegNewNetCfg |= (XEMACPS_NWCFG_SGMIIEN_MASK |
528                         XEMACPS_NWCFG_PCSSEL_MASK);
529     }
530 
531     /* Officially change the NET_CONFIG registers if it needs to be
532      * modified.
533      */
534     if (RegNetCfg != RegNewNetCfg) {
535         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
536                    XEMACPS_NWCFG_OFFSET, RegNewNetCfg);
537     }
538 
539     /* Enable TX checksum offload */
540         if ((Options & XEMACPS_TX_CHKSUM_ENABLE_OPTION) != 0x00000000U) {
541         Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
542                     XEMACPS_DMACR_OFFSET);
543         Reg |= XEMACPS_DMACR_TCPCKSUM_MASK;
544         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
545                      XEMACPS_DMACR_OFFSET, Reg);
546     }
547 
548     /* Enable transmitter */
549         if ((Options & XEMACPS_TRANSMITTER_ENABLE_OPTION) != 0x00000000U) {
550         Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
551                     XEMACPS_NWCTRL_OFFSET);
552         Reg |= XEMACPS_NWCTRL_TXEN_MASK;
553         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
554                    XEMACPS_NWCTRL_OFFSET, Reg);
555     }
556 
557     /* Enable receiver */
558         if ((Options & XEMACPS_RECEIVER_ENABLE_OPTION) != 0x00000000U) {
559         Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
560                     XEMACPS_NWCTRL_OFFSET);
561         Reg |= XEMACPS_NWCTRL_RXEN_MASK;
562         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
563                    XEMACPS_NWCTRL_OFFSET, Reg);
564     }
565 
566     /* The remaining options not handled here are managed elsewhere in the
567      * driver. No register modifications are needed at this time. Reflecting
568      * the option in InstancePtr->Options is good enough for now.
569      */
570 
571     /* Set options word to its new value */
572     InstancePtr->Options |= Options;
573 
574         Status = (LONG)(XST_SUCCESS);
575     }
576     return Status;
577 }
578 
579 
580 /*****************************************************************************/
581 /**
582  * Clear options for the driver/device
583  *
584  * @param InstancePtr is a pointer to the instance to be worked on.
585  * @param Options are the options to clear. Multiple options can be cleared by
586  *        OR'ing XEMACPS_*_OPTIONS constants together. Options not specified
587  *        are not affected.
588  *
589  * @return
590  * - XST_SUCCESS if the options were set successfully
591  * - XST_DEVICE_IS_STARTED if the device has not yet been stopped
592  *
593  * @note
594  * See xemacps.h for a description of the available options.
595  *
596  *****************************************************************************/
XEmacPs_ClearOptions(XEmacPs * InstancePtr,u32 Options)597 LONG XEmacPs_ClearOptions(XEmacPs *InstancePtr, u32 Options)
598 {
599     u32 Reg;        /* Generic */
600     u32 RegNetCfg;        /* Reflects original contents of NET_CONFIG */
601     u32 RegNewNetCfg;    /* Reflects new contents of NET_CONFIG */
602     LONG Status;
603     Xil_AssertNonvoid(InstancePtr != NULL);
604     Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
605 
606     /* Be sure device has been stopped */
607     if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) {
608         Status = (LONG)(XST_DEVICE_IS_STARTED);
609     } else {
610 
611     /* Many of these options will change the NET_CONFIG registers.
612      * To reduce the amount of IO to the device, group these options here
613      * and change them all at once.
614      */
615 
616     /* Grab current register contents */
617     RegNetCfg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
618                       XEMACPS_NWCFG_OFFSET);
619     RegNewNetCfg = RegNetCfg;
620 
621     /* There is only RX configuration!?
622      * It is configured in two different length, up to 1536 and 10240 bytes
623      */
624         if ((Options & XEMACPS_FRAME1536_OPTION) != 0x00000000U) {
625             RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_1536RXEN_MASK);
626     }
627 
628     /* Turn off VLAN packet only */
629         if ((Options & XEMACPS_VLAN_OPTION) != 0x00000000U) {
630             RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_NVLANDISC_MASK);
631     }
632 
633     /* Turn off FCS stripping on receive packets */
634         if ((Options & XEMACPS_FCS_STRIP_OPTION) != 0x00000000U) {
635             RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_FCSREM_MASK);
636     }
637 
638     /* Turn off length/type field checking on receive packets */
639         if ((Options & XEMACPS_LENTYPE_ERR_OPTION) != 0x00000000U) {
640             RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_LENERRDSCRD_MASK);
641     }
642 
643     /* Turn off flow control */
644         if ((Options & XEMACPS_FLOW_CONTROL_OPTION) != 0x00000000U) {
645             RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_PAUSEEN_MASK);
646     }
647 
648     /* Turn off promiscuous frame filtering (all frames are received) */
649         if ((Options & XEMACPS_PROMISC_OPTION) != 0x00000000U) {
650             RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_COPYALLEN_MASK);
651     }
652 
653     /* Disallow broadcast address filtering => broadcast reception */
654         if ((Options & XEMACPS_BROADCAST_OPTION) != 0x00000000U) {
655         RegNewNetCfg |= XEMACPS_NWCFG_BCASTDI_MASK;
656     }
657 
658     /* Disallow multicast address filtering */
659         if ((Options & XEMACPS_MULTICAST_OPTION) != 0x00000000U) {
660             RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_MCASTHASHEN_MASK);
661     }
662 
663     /* Disable RX checksum offload */
664         if ((Options & XEMACPS_RX_CHKSUM_ENABLE_OPTION) != 0x00000000U) {
665             RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_RXCHKSUMEN_MASK);
666     }
667 
668     /* Disable jumbo frames */
669     if (((Options & XEMACPS_JUMBO_ENABLE_OPTION) != 0x00000000U) &&
670         (InstancePtr->Version > 2)) {
671         RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_JUMBO_MASK);
672         Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
673                       XEMACPS_DMACR_OFFSET);
674         Reg &= ~XEMACPS_DMACR_RXBUF_MASK;
675         Reg |= (((((u32)XEMACPS_RX_BUF_SIZE / (u32)XEMACPS_RX_BUF_UNIT) +
676             (((((u32)XEMACPS_RX_BUF_SIZE %
677             (u32)XEMACPS_RX_BUF_UNIT))!=(u32)0) ? 1U : 0U)) <<
678             (u32)(XEMACPS_DMACR_RXBUF_SHIFT)) &
679             (u32)(XEMACPS_DMACR_RXBUF_MASK));
680         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
681             XEMACPS_DMACR_OFFSET, Reg);
682         InstancePtr->MaxMtuSize = XEMACPS_MTU;
683         InstancePtr->MaxFrameSize = XEMACPS_MTU +
684                     XEMACPS_HDR_SIZE + XEMACPS_TRL_SIZE;
685         InstancePtr->MaxVlanFrameSize = InstancePtr->MaxFrameSize +
686                     XEMACPS_HDR_VLAN_SIZE;
687         InstancePtr->RxBufMask = XEMACPS_RXBUF_LEN_MASK;
688     }
689 
690     if (((Options & XEMACPS_SGMII_ENABLE_OPTION) != 0x00000000U) &&
691         (InstancePtr->Version > 2)) {
692         RegNewNetCfg &= (u32)(~(XEMACPS_NWCFG_SGMIIEN_MASK |
693                         XEMACPS_NWCFG_PCSSEL_MASK));
694     }
695 
696     /* Officially change the NET_CONFIG registers if it needs to be
697      * modified.
698      */
699     if (RegNetCfg != RegNewNetCfg) {
700         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
701                    XEMACPS_NWCFG_OFFSET, RegNewNetCfg);
702     }
703 
704     /* Disable TX checksum offload */
705         if ((Options & XEMACPS_TX_CHKSUM_ENABLE_OPTION) != 0x00000000U) {
706         Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
707                     XEMACPS_DMACR_OFFSET);
708             Reg &= (u32)(~XEMACPS_DMACR_TCPCKSUM_MASK);
709         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
710                      XEMACPS_DMACR_OFFSET, Reg);
711     }
712 
713     /* Disable transmitter */
714         if ((Options & XEMACPS_TRANSMITTER_ENABLE_OPTION) != 0x00000000U) {
715         Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
716                     XEMACPS_NWCTRL_OFFSET);
717             Reg &= (u32)(~XEMACPS_NWCTRL_TXEN_MASK);
718         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
719                    XEMACPS_NWCTRL_OFFSET, Reg);
720     }
721 
722     /* Disable receiver */
723         if ((Options & XEMACPS_RECEIVER_ENABLE_OPTION) != 0x00000000U) {
724         Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
725                     XEMACPS_NWCTRL_OFFSET);
726             Reg &= (u32)(~XEMACPS_NWCTRL_RXEN_MASK);
727         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
728                    XEMACPS_NWCTRL_OFFSET, Reg);
729     }
730 
731     /* The remaining options not handled here are managed elsewhere in the
732      * driver. No register modifications are needed at this time. Reflecting
733      * option in InstancePtr->Options is good enough for now.
734      */
735 
736     /* Set options word to its new value */
737     InstancePtr->Options &= ~Options;
738 
739         Status = (LONG)(XST_SUCCESS);
740     }
741     return Status;
742 }
743 
744 
745 /*****************************************************************************/
746 /**
747  * Get current option settings
748  *
749  * @param InstancePtr is a pointer to the instance to be worked on.
750  *
751  * @return
752  * A bitmask of XTE_*_OPTION constants. Any bit set to 1 is to be interpreted
753  * as a set option.
754  *
755  * @note
756  * See xemacps.h for a description of the available options.
757  *
758  *****************************************************************************/
XEmacPs_GetOptions(XEmacPs * InstancePtr)759 u32 XEmacPs_GetOptions(XEmacPs *InstancePtr)
760 {
761     Xil_AssertNonvoid(InstancePtr != NULL);
762     Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
763 
764     return (InstancePtr->Options);
765 }
766 
767 
768 /*****************************************************************************/
769 /**
770  * Send a pause packet
771  *
772  * @param InstancePtr is a pointer to the instance to be worked on.
773  *
774  * @return
775  * - XST_SUCCESS if pause frame transmission was initiated
776  * - XST_DEVICE_IS_STOPPED if the device has not been started.
777  *
778  *****************************************************************************/
XEmacPs_SendPausePacket(XEmacPs * InstancePtr)779 LONG XEmacPs_SendPausePacket(XEmacPs *InstancePtr)
780 {
781     u32 Reg;
782     LONG Status;
783 
784     Xil_AssertNonvoid(InstancePtr != NULL);
785     Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
786 
787     /* Make sure device is ready for this operation */
788     if (InstancePtr->IsStarted != (u32)XIL_COMPONENT_IS_STARTED) {
789         Status = (LONG)(XST_DEVICE_IS_STOPPED);
790     } else {
791     /* Send flow control frame */
792     Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
793                 XEMACPS_NWCTRL_OFFSET);
794     Reg |= XEMACPS_NWCTRL_PAUSETX_MASK;
795     XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
796                XEMACPS_NWCTRL_OFFSET, Reg);
797         Status = (LONG)(XST_SUCCESS);
798     }
799     return Status;
800 }
801 
802 /*****************************************************************************/
803 /**
804  * XEmacPs_GetOperatingSpeed gets the current operating link speed. This may
805  * be the value set by XEmacPs_SetOperatingSpeed() or a hardware default.
806  *
807  * @param InstancePtr references the TEMAC channel on which to operate.
808  *
809  * @return XEmacPs_GetOperatingSpeed returns the link speed in units of
810  *         megabits per second.
811  *
812  * @note
813  *
814  *****************************************************************************/
XEmacPs_GetOperatingSpeed(XEmacPs * InstancePtr)815 u16 XEmacPs_GetOperatingSpeed(XEmacPs *InstancePtr)
816 {
817     u32 Reg;
818     u16 Status;
819 
820     Xil_AssertNonvoid(InstancePtr != NULL);
821     Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
822 
823     Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
824             XEMACPS_NWCFG_OFFSET);
825 
826     if ((Reg & XEMACPS_NWCFG_1000_MASK) != 0x00000000U) {
827         Status = (u16)(1000);
828     } else {
829         if ((Reg & XEMACPS_NWCFG_100_MASK) != 0x00000000U) {
830             Status = (u16)(100);
831         } else {
832             Status = (u16)(10);
833         }
834     }
835     return Status;
836 }
837 
838 
839 /*****************************************************************************/
840 /**
841  * XEmacPs_SetOperatingSpeed sets the current operating link speed. For any
842  * traffic to be passed, this speed must match the current MII/GMII/SGMII/RGMII
843  * link speed.
844  *
845  * @param InstancePtr references the TEMAC channel on which to operate.
846  * @param Speed is the speed to set in units of Mbps. Valid values are 10, 100,
847  *        or 1000. XEmacPs_SetOperatingSpeed ignores invalid values.
848  *
849  * @note
850  *
851  *****************************************************************************/
XEmacPs_SetOperatingSpeed(XEmacPs * InstancePtr,u16 Speed)852 void XEmacPs_SetOperatingSpeed(XEmacPs *InstancePtr, u16 Speed)
853 {
854         u32 Reg;
855         Xil_AssertVoid(InstancePtr != NULL);
856     Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
857     Xil_AssertVoid((Speed == (u16)10) || (Speed == (u16)100) || (Speed == (u16)1000));
858 
859         Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
860             XEMACPS_NWCFG_OFFSET);
861     Reg &= (u32)(~(XEMACPS_NWCFG_1000_MASK | XEMACPS_NWCFG_100_MASK));
862 
863     switch (Speed) {
864         case (u16)10:
865                 break;
866 
867         case (u16)100:
868                 Reg |= XEMACPS_NWCFG_100_MASK;
869                 break;
870 
871         case (u16)1000:
872                 Reg |= XEMACPS_NWCFG_1000_MASK;
873                 break;
874     }
875 
876         /* Set register and return */
877         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
878                 XEMACPS_NWCFG_OFFSET, Reg);
879 }
880 
881 
882 /*****************************************************************************/
883 /**
884  * Set the MDIO clock divisor.
885  *
886  * Calculating the divisor:
887  *
888  * <pre>
889  *              f[HOSTCLK]
890  *   f[MDC] = -----------------
891  *            (1 + Divisor) * 2
892  * </pre>
893  *
894  * where f[HOSTCLK] is the bus clock frequency in MHz, and f[MDC] is the
895  * MDIO clock frequency in MHz to the PHY. Typically, f[MDC] should not
896  * exceed 2.5 MHz. Some PHYs can tolerate faster speeds which means faster
897  * access. Here is the table to show values to generate MDC,
898  *
899  * <pre>
900  * 000 : divide pclk by   8 (pclk up to  20 MHz)
901  * 001 : divide pclk by  16 (pclk up to  40 MHz)
902  * 010 : divide pclk by  32 (pclk up to  80 MHz)
903  * 011 : divide pclk by  48 (pclk up to 120 MHz)
904  * 100 : divide pclk by  64 (pclk up to 160 MHz)
905  * 101 : divide pclk by  96 (pclk up to 240 MHz)
906  * 110 : divide pclk by 128 (pclk up to 320 MHz)
907  * 111 : divide pclk by 224 (pclk up to 540 MHz)
908  * </pre>
909  *
910  * @param InstancePtr is a pointer to the instance to be worked on.
911  * @param Divisor is the divisor to set. Range is 0b000 to 0b111.
912  *
913  *****************************************************************************/
XEmacPs_SetMdioDivisor(XEmacPs * InstancePtr,XEmacPs_MdcDiv Divisor)914 void XEmacPs_SetMdioDivisor(XEmacPs *InstancePtr, XEmacPs_MdcDiv Divisor)
915 {
916     u32 Reg;
917     Xil_AssertVoid(InstancePtr != NULL);
918     Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
919     Xil_AssertVoid(Divisor <= (XEmacPs_MdcDiv)0x7); /* only last three bits are valid */
920 
921     Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
922                 XEMACPS_NWCFG_OFFSET);
923     /* clear these three bits, could be done with mask */
924     Reg &= (u32)(~XEMACPS_NWCFG_MDCCLKDIV_MASK);
925 
926     Reg |= ((u32)Divisor << XEMACPS_NWCFG_MDC_SHIFT_MASK);
927 
928     XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
929                XEMACPS_NWCFG_OFFSET, Reg);
930 }
931 
932 
933 /*****************************************************************************/
934 /**
935 * Read the current value of the PHY register indicated by the PhyAddress and
936 * the RegisterNum parameters. The MAC provides the driver with the ability to
937 * talk to a PHY that adheres to the Media Independent Interface (MII) as
938 * defined in the IEEE 802.3 standard.
939 *
940 * Prior to PHY access with this function, the user should have setup the MDIO
941 * clock with XEmacPs_SetMdioDivisor().
942 *
943 * @param InstancePtr is a pointer to the XEmacPs instance to be worked on.
944 * @param PhyAddress is the address of the PHY to be read (supports multiple
945 *        PHYs)
946 * @param RegisterNum is the register number, 0-31, of the specific PHY register
947 *        to read
948 * @param PhyDataPtr is an output parameter, and points to a 16-bit buffer into
949 *        which the current value of the register will be copied.
950 *
951 * @return
952 *
953 * - XST_SUCCESS if the PHY was read from successfully
954 * - XST_EMAC_MII_BUSY if there is another PHY operation in progress
955 *
956 * @note
957 *
958 * This function is not thread-safe. The user must provide mutually exclusive
959 * access to this function if there are to be multiple threads that can call it.
960 *
961 * There is the possibility that this function will not return if the hardware
962 * is broken (i.e., it never sets the status bit indicating that the read is
963 * done). If this is of concern to the user, the user should provide a mechanism
964 * suitable to their needs for recovery.
965 *
966 * For the duration of this function, all host interface reads and writes are
967 * blocked to the current XEmacPs instance.
968 *
969 ******************************************************************************/
XEmacPs_PhyRead(XEmacPs * InstancePtr,u32 PhyAddress,u32 RegisterNum,u16 * PhyDataPtr)970 LONG XEmacPs_PhyRead(XEmacPs *InstancePtr, u32 PhyAddress,
971              u32 RegisterNum, u16 *PhyDataPtr)
972 {
973     u32 Mgtcr;
974     volatile u32 Ipisr;
975     u32 IpReadTemp;
976     LONG Status;
977 
978     Xil_AssertNonvoid(InstancePtr != NULL);
979 
980     /* Make sure no other PHY operation is currently in progress */
981     if ((!(XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
982                 XEMACPS_NWSR_OFFSET) &
983           XEMACPS_NWSR_MDIOIDLE_MASK))==TRUE) {
984         Status = (LONG)(XST_EMAC_MII_BUSY);
985     } else {
986 
987     /* Construct Mgtcr mask for the operation */
988     Mgtcr = XEMACPS_PHYMNTNC_OP_MASK | XEMACPS_PHYMNTNC_OP_R_MASK |
989             (PhyAddress << XEMACPS_PHYMNTNC_PHAD_SHFT_MSK) |
990             (RegisterNum << XEMACPS_PHYMNTNC_PREG_SHFT_MSK);
991 
992     /* Write Mgtcr and wait for completion */
993     XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
994                XEMACPS_PHYMNTNC_OFFSET, Mgtcr);
995 
996     do {
997         Ipisr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
998                       XEMACPS_NWSR_OFFSET);
999             IpReadTemp = Ipisr;
1000         } while ((IpReadTemp & XEMACPS_NWSR_MDIOIDLE_MASK) == 0x00000000U);
1001 
1002     /* Read data */
1003         *PhyDataPtr = (u16)XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
1004                     XEMACPS_PHYMNTNC_OFFSET);
1005         Status = (LONG)(XST_SUCCESS);
1006     }
1007     return Status;
1008 }
1009 
1010 
1011 /*****************************************************************************/
1012 /**
1013 * Write data to the specified PHY register. The Ethernet driver does not
1014 * require the device to be stopped before writing to the PHY.  Although it is
1015 * probably a good idea to stop the device, it is the responsibility of the
1016 * application to deem this necessary. The MAC provides the driver with the
1017 * ability to talk to a PHY that adheres to the Media Independent Interface
1018 * (MII) as defined in the IEEE 802.3 standard.
1019 *
1020 * Prior to PHY access with this function, the user should have setup the MDIO
1021 * clock with XEmacPs_SetMdioDivisor().
1022 *
1023 * @param InstancePtr is a pointer to the XEmacPs instance to be worked on.
1024 * @param PhyAddress is the address of the PHY to be written (supports multiple
1025 *        PHYs)
1026 * @param RegisterNum is the register number, 0-31, of the specific PHY register
1027 *        to write
1028 * @param PhyData is the 16-bit value that will be written to the register
1029 *
1030 * @return
1031 *
1032 * - XST_SUCCESS if the PHY was written to successfully. Since there is no error
1033 *   status from the MAC on a write, the user should read the PHY to verify the
1034 *   write was successful.
1035 * - XST_EMAC_MII_BUSY if there is another PHY operation in progress
1036 *
1037 * @note
1038 *
1039 * This function is not thread-safe. The user must provide mutually exclusive
1040 * access to this function if there are to be multiple threads that can call it.
1041 *
1042 * There is the possibility that this function will not return if the hardware
1043 * is broken (i.e., it never sets the status bit indicating that the write is
1044 * done). If this is of concern to the user, the user should provide a mechanism
1045 * suitable to their needs for recovery.
1046 *
1047 * For the duration of this function, all host interface reads and writes are
1048 * blocked to the current XEmacPs instance.
1049 *
1050 ******************************************************************************/
XEmacPs_PhyWrite(XEmacPs * InstancePtr,u32 PhyAddress,u32 RegisterNum,u16 PhyData)1051 LONG XEmacPs_PhyWrite(XEmacPs *InstancePtr, u32 PhyAddress,
1052               u32 RegisterNum, u16 PhyData)
1053 {
1054     u32 Mgtcr;
1055     volatile u32 Ipisr;
1056     u32 IpWriteTemp;
1057     LONG Status;
1058 
1059     Xil_AssertNonvoid(InstancePtr != NULL);
1060 
1061     /* Make sure no other PHY operation is currently in progress */
1062     if ((!(XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
1063                 XEMACPS_NWSR_OFFSET) &
1064           XEMACPS_NWSR_MDIOIDLE_MASK))==TRUE) {
1065         Status = (LONG)(XST_EMAC_MII_BUSY);
1066     } else {
1067     /* Construct Mgtcr mask for the operation */
1068     Mgtcr = XEMACPS_PHYMNTNC_OP_MASK | XEMACPS_PHYMNTNC_OP_W_MASK |
1069             (PhyAddress << XEMACPS_PHYMNTNC_PHAD_SHFT_MSK) |
1070             (RegisterNum << XEMACPS_PHYMNTNC_PREG_SHFT_MSK) | (u32)PhyData;
1071 
1072     /* Write Mgtcr and wait for completion */
1073     XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
1074                XEMACPS_PHYMNTNC_OFFSET, Mgtcr);
1075 
1076     do {
1077         Ipisr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
1078                       XEMACPS_NWSR_OFFSET);
1079                 IpWriteTemp = Ipisr;
1080         } while ((IpWriteTemp & XEMACPS_NWSR_MDIOIDLE_MASK) == 0x00000000U);
1081 
1082         Status = (LONG)(XST_SUCCESS);
1083     }
1084     return Status;
1085 }
1086 
1087 /*****************************************************************************/
1088 /**
1089 * API to update the Burst length in the DMACR register.
1090 *
1091 * @param InstancePtr is a pointer to the XEmacPs instance to be worked on.
1092 * @param BLength is the length in bytes for the dma burst.
1093 *
1094 * @return None
1095 *
1096 ******************************************************************************/
XEmacPs_DMABLengthUpdate(XEmacPs * InstancePtr,s32 BLength)1097 void XEmacPs_DMABLengthUpdate(XEmacPs *InstancePtr, s32 BLength)
1098 {
1099     u32 Reg;
1100     u32 RegUpdateVal = 0;
1101 
1102     Xil_AssertVoid(InstancePtr != NULL);
1103     Xil_AssertVoid((BLength == XEMACPS_SINGLE_BURST) ||
1104                     (BLength == XEMACPS_4BYTE_BURST) ||
1105                     (BLength == XEMACPS_8BYTE_BURST) ||
1106                     (BLength == XEMACPS_16BYTE_BURST));
1107 
1108     switch (BLength) {
1109         case XEMACPS_SINGLE_BURST:
1110             RegUpdateVal = XEMACPS_DMACR_SINGLE_AHB_BURST;
1111             break;
1112 
1113         case XEMACPS_4BYTE_BURST:
1114             RegUpdateVal = XEMACPS_DMACR_INCR4_AHB_BURST;
1115             break;
1116 
1117         case XEMACPS_8BYTE_BURST:
1118             RegUpdateVal = XEMACPS_DMACR_INCR8_AHB_BURST;
1119             break;
1120 
1121         case XEMACPS_16BYTE_BURST:
1122             RegUpdateVal = XEMACPS_DMACR_INCR16_AHB_BURST;
1123             break;
1124     }
1125     Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
1126                         XEMACPS_DMACR_OFFSET);
1127 
1128     Reg &= (u32)(~XEMACPS_DMACR_BLENGTH_MASK);
1129     Reg |= RegUpdateVal;
1130     XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_DMACR_OFFSET,
1131                                                                     Reg);
1132 }
1133 /** @} */
1134