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