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