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