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