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