1 /******************************************************************************
3 * Copyright (C) 2009 - 2015 Xilinx, Inc. All rights reserved.
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * Use of the Software is limited solely to applications:
16 * (a) running on a Xilinx device, or
17 * (b) that interact with a Xilinx device through a bus or interconnect.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
24 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 * Except as contained in this notice, the name of the Xilinx shall not be used
28 * in advertising or otherwise to promote the sale, use or other dealings in
29 * this Software without prior written authorization from Xilinx.
31 ******************************************************************************/
32 /*****************************************************************************/
35 * @file xemacps_control.c
37 * Functions in this file implement general purpose command and control related
38 * functionality. See xemacps.h for a detailed description of the driver.
41 * MODIFICATION HISTORY:
43 * Ver Who Date Changes
44 * ----- ---- -------- -------------------------------------------------------
45 * 1.00a wsy 01/10/10 First release
46 * 1.02a asa 11/05/12 Added a new API for deleting an entry from the HASH
47 * register. Added a new API for setting the BURST length
49 * 2.1 srt 07/15/14 Add support for Zynq Ultrascale Mp architecture.
50 * 3.0 kvn 02/13/15 Modified code for MISRA-C:2012 compliance.
51 * 3.0 hk 02/20/15 Added support for jumbo frames.
53 *****************************************************************************/
55 /***************************** Include Files *********************************/
59 /************************** Constant Definitions *****************************/
62 /**************************** Type Definitions *******************************/
65 /***************** Macros (Inline Functions) Definitions *********************/
68 /************************** Function Prototypes ******************************/
71 /************************** Variable Definitions *****************************/
74 /*****************************************************************************/
76 * Set the MAC address for this driver/device. The address is a 48-bit value.
77 * The device must be stopped before calling this function.
79 * @param InstancePtr is a pointer to the instance to be worked on.
80 * @param AddressPtr is a pointer to a 6-byte MAC address.
81 * @param Index is a index to which MAC (1-4) address.
84 * - XST_SUCCESS if the MAC address was set successfully
85 * - XST_DEVICE_IS_STARTED if the device has not yet been stopped
87 *****************************************************************************/
88 LONG XEmacPs_SetMacAddress(XEmacPs *InstancePtr, void *AddressPtr, u8 Index)
91 u8 *Aptr = (u8 *)(void *)AddressPtr;
94 Xil_AssertNonvoid(InstancePtr != NULL);
95 Xil_AssertNonvoid(Aptr != NULL);
96 Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
97 Xil_AssertNonvoid((IndexLoc <= (u8)XEMACPS_MAX_MAC_ADDR) && (IndexLoc > 0x00U));
99 /* Be sure device has been stopped */
100 if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) {
101 Status = (LONG)(XST_DEVICE_IS_STARTED);
104 /* Index ranges 1 to 4, for offset calculation is 0 to 3. */
107 /* Set the MAC bits [31:0] in BOT */
109 MacAddr |= ((u32)(*(Aptr+1)) << 8U);
110 MacAddr |= ((u32)(*(Aptr+2)) << 16U);
111 MacAddr |= ((u32)(*(Aptr+3)) << 24U);
112 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
113 ((u32)XEMACPS_LADDR1L_OFFSET + ((u32)IndexLoc * (u32)8)), MacAddr);
115 /* There are reserved bits in TOP so don't affect them */
116 MacAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
117 ((u32)XEMACPS_LADDR1H_OFFSET + ((u32)IndexLoc * (u32)8)));
119 MacAddr &= (u32)(~XEMACPS_LADDR_MACH_MASK);
121 /* Set MAC bits [47:32] in TOP */
122 MacAddr |= (u32)(*(Aptr+4));
123 MacAddr |= (u32)(*(Aptr+5)) << 8U;
125 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
126 ((u32)XEMACPS_LADDR1H_OFFSET + ((u32)IndexLoc * (u32)8)), MacAddr);
128 Status = (LONG)(XST_SUCCESS);
134 /*****************************************************************************/
136 * Get the MAC address for this driver/device.
138 * @param InstancePtr is a pointer to the instance to be worked on.
139 * @param AddressPtr is an output parameter, and is a pointer to a buffer into
140 * which the current MAC address will be copied.
141 * @param Index is a index to which MAC (1-4) address.
143 *****************************************************************************/
144 void XEmacPs_GetMacAddress(XEmacPs *InstancePtr, void *AddressPtr, u8 Index)
147 u8 *Aptr = (u8 *)(void *)AddressPtr;
149 Xil_AssertVoid(InstancePtr != NULL);
150 Xil_AssertVoid(Aptr != NULL);
151 Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
152 Xil_AssertVoid((IndexLoc <= (u8)XEMACPS_MAX_MAC_ADDR) && (IndexLoc > 0x00U));
154 /* Index ranges 1 to 4, for offset calculation is 0 to 3. */
157 MacAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
158 ((u32)XEMACPS_LADDR1L_OFFSET + ((u32)IndexLoc * (u32)8)));
159 *Aptr = (u8) MacAddr;
160 *(Aptr+1) = (u8) (MacAddr >> 8U);
161 *(Aptr+2) = (u8) (MacAddr >> 16U);
162 *(Aptr+3) = (u8) (MacAddr >> 24U);
164 /* Read MAC bits [47:32] in TOP */
165 MacAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
166 ((u32)XEMACPS_LADDR1H_OFFSET + ((u32)IndexLoc * (u32)8)));
167 *(Aptr+4) = (u8) MacAddr;
168 *(Aptr+5) = (u8) (MacAddr >> 8U);
172 /*****************************************************************************/
174 * Set 48-bit MAC addresses in hash table.
175 * The device must be stopped before calling this function.
177 * The hash address register is 64 bits long and takes up two locations in
178 * the memory map. The least significant bits are stored in hash register
179 * bottom and the most significant bits in hash register top.
181 * The unicast hash enable and the multicast hash enable bits in the network
182 * configuration register enable the reception of hash matched frames. The
183 * destination address is reduced to a 6 bit index into the 64 bit hash
184 * register using the following hash function. The hash function is an XOR
185 * of every sixth bit of the destination address.
188 * hash_index[05] = da[05]^da[11]^da[17]^da[23]^da[29]^da[35]^da[41]^da[47]
189 * hash_index[04] = da[04]^da[10]^da[16]^da[22]^da[28]^da[34]^da[40]^da[46]
190 * hash_index[03] = da[03]^da[09]^da[15]^da[21]^da[27]^da[33]^da[39]^da[45]
191 * hash_index[02] = da[02]^da[08]^da[14]^da[20]^da[26]^da[32]^da[38]^da[44]
192 * hash_index[01] = da[01]^da[07]^da[13]^da[19]^da[25]^da[31]^da[37]^da[43]
193 * hash_index[00] = da[00]^da[06]^da[12]^da[18]^da[24]^da[30]^da[36]^da[42]
196 * da[0] represents the least significant bit of the first byte received,
197 * that is, the multicast/unicast indicator, and da[47] represents the most
198 * significant bit of the last byte received.
200 * If the hash index points to a bit that is set in the hash register then
201 * the frame will be matched according to whether the frame is multicast
204 * A multicast match will be signaled if the multicast hash enable bit is
205 * set, da[0] is logic 1 and the hash index points to a bit set in the hash
208 * A unicast match will be signaled if the unicast hash enable bit is set,
209 * da[0] is logic 0 and the hash index points to a bit set in the hash
212 * To receive all multicast frames, the hash register should be set with
213 * all ones and the multicast hash enable bit should be set in the network
214 * configuration register.
217 * @param InstancePtr is a pointer to the instance to be worked on.
218 * @param AddressPtr is a pointer to a 6-byte MAC address.
221 * - XST_SUCCESS if the HASH MAC address was set successfully
222 * - XST_DEVICE_IS_STARTED if the device has not yet been stopped
223 * - XST_INVALID_PARAM if the HASH MAC address passed in does not meet
224 * requirement after calculation
227 * Having Aptr be unsigned type prevents the following operations from sign
229 *****************************************************************************/
230 LONG XEmacPs_SetHash(XEmacPs *InstancePtr, void *AddressPtr)
233 u8 *Aptr = (u8 *)(void *)AddressPtr;
234 u8 Temp1, Temp2, Temp3, Temp4, Temp5, Temp6, Temp7, Temp8;
238 Xil_AssertNonvoid(InstancePtr != NULL);
239 Xil_AssertNonvoid(AddressPtr != NULL);
240 Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
242 /* Be sure device has been stopped */
243 if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) {
244 Status = (LONG)(XST_DEVICE_IS_STARTED);
246 Temp1 = (*(Aptr+0)) & 0x3FU;
247 Temp2 = ((*(Aptr+0) >> 6U) & 0x03U) | ((*(Aptr+1) & 0x0FU) << 2U);
249 Temp3 = ((*(Aptr+1) >> 4U) & 0x0FU) | ((*(Aptr+2) & 0x3U) << 4U);
250 Temp4 = ((*(Aptr+2) >> 2U) & 0x3FU);
251 Temp5 = (*(Aptr+3)) & 0x3FU;
252 Temp6 = ((*(Aptr+3) >> 6U) & 0x03U) | ((*(Aptr+4) & 0x0FU) << 2U);
253 Temp7 = ((*(Aptr+4) >> 4U) & 0x0FU) | ((*(Aptr+5) & 0x03U) << 4U);
254 Temp8 = ((*(Aptr+5) >> 2U) & 0x3FU);
256 Result = (u32)((u32)Temp1 ^ (u32)Temp2 ^ (u32)Temp3 ^ (u32)Temp4 ^
257 (u32)Temp5 ^ (u32)Temp6 ^ (u32)Temp7 ^ (u32)Temp8);
259 if (Result >= (u32)XEMACPS_MAX_HASH_BITS) {
260 Status = (LONG)(XST_INVALID_PARAM);
263 if (Result < (u32)32) {
264 HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
265 XEMACPS_HASHL_OFFSET);
266 HashAddr |= (u32)(0x00000001U << Result);
267 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
268 XEMACPS_HASHL_OFFSET, HashAddr);
270 HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
271 XEMACPS_HASHH_OFFSET);
272 HashAddr |= (u32)(0x00000001U << (u32)(Result - (u32)32));
273 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
274 XEMACPS_HASHH_OFFSET, HashAddr);
276 Status = (LONG)(XST_SUCCESS);
282 /*****************************************************************************/
284 * Delete 48-bit MAC addresses in hash table.
285 * The device must be stopped before calling this function.
287 * @param InstancePtr is a pointer to the instance to be worked on.
288 * @param AddressPtr is a pointer to a 6-byte MAC address.
291 * - XST_SUCCESS if the HASH MAC address was deleted successfully
292 * - XST_DEVICE_IS_STARTED if the device has not yet been stopped
293 * - XST_INVALID_PARAM if the HASH MAC address passed in does not meet
294 * requirement after calculation
297 * Having Aptr be unsigned type prevents the following operations from sign
299 *****************************************************************************/
300 LONG XEmacPs_DeleteHash(XEmacPs *InstancePtr, void *AddressPtr)
303 u8 *Aptr = (u8 *)(void *)AddressPtr;
304 u8 Temp1, Temp2, Temp3, Temp4, Temp5, Temp6, Temp7, Temp8;
308 Xil_AssertNonvoid(InstancePtr != NULL);
309 Xil_AssertNonvoid(Aptr != NULL);
310 Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
312 /* Be sure device has been stopped */
313 if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) {
314 Status = (LONG)(XST_DEVICE_IS_STARTED);
316 Temp1 = (*(Aptr+0)) & 0x3FU;
317 Temp2 = ((*(Aptr+0) >> 6U) & 0x03U) | ((*(Aptr+1) & 0x0FU) << 2U);
318 Temp3 = ((*(Aptr+1) >> 4U) & 0x0FU) | ((*(Aptr+2) & 0x03U) << 4U);
319 Temp4 = ((*(Aptr+2) >> 2U) & 0x3FU);
320 Temp5 = (*(Aptr+3)) & 0x3FU;
321 Temp6 = ((*(Aptr+3) >> 6U) & 0x03U) | ((*(Aptr+4) & 0x0FU) << 2U);
322 Temp7 = ((*(Aptr+4) >> 4U) & 0x0FU) | ((*(Aptr+5) & 0x03U) << 4U);
323 Temp8 = ((*(Aptr+5) >> 2U) & 0x3FU);
325 Result = (u32)((u32)Temp1 ^ (u32)Temp2 ^ (u32)Temp3 ^ (u32)Temp4 ^
326 (u32)Temp5 ^ (u32)Temp6 ^ (u32)Temp7 ^ (u32)Temp8);
328 if (Result >= (u32)(XEMACPS_MAX_HASH_BITS)) {
329 Status = (LONG)(XST_INVALID_PARAM);
331 if (Result < (u32)32) {
332 HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
333 XEMACPS_HASHL_OFFSET);
334 HashAddr &= (u32)(~(0x00000001U << Result));
335 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
336 XEMACPS_HASHL_OFFSET, HashAddr);
338 HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
339 XEMACPS_HASHH_OFFSET);
340 HashAddr &= (u32)(~(0x00000001U << (u32)(Result - (u32)32)));
341 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
342 XEMACPS_HASHH_OFFSET, HashAddr);
344 Status = (LONG)(XST_SUCCESS);
349 /*****************************************************************************/
351 * Clear the Hash registers for the mac address pointed by AddressPtr.
353 * @param InstancePtr is a pointer to the instance to be worked on.
355 *****************************************************************************/
356 void XEmacPs_ClearHash(XEmacPs *InstancePtr)
358 Xil_AssertVoid(InstancePtr != NULL);
359 Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
361 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
362 XEMACPS_HASHL_OFFSET, 0x0U);
364 /* write bits [63:32] in TOP */
365 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
366 XEMACPS_HASHH_OFFSET, 0x0U);
370 /*****************************************************************************/
372 * Get the Hash address for this driver/device.
374 * @param InstancePtr is a pointer to the instance to be worked on.
375 * @param AddressPtr is an output parameter, and is a pointer to a buffer into
376 * which the current HASH MAC address will be copied.
378 *****************************************************************************/
379 void XEmacPs_GetHash(XEmacPs *InstancePtr, void *AddressPtr)
381 u32 *Aptr = (u32 *)(void *)AddressPtr;
383 Xil_AssertVoid(InstancePtr != NULL);
384 Xil_AssertVoid(AddressPtr != NULL);
385 Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
387 *(Aptr+0) = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
388 XEMACPS_HASHL_OFFSET);
390 /* Read Hash bits [63:32] in TOP */
391 *(Aptr+1) = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
392 XEMACPS_HASHH_OFFSET);
396 /*****************************************************************************/
398 * Set the Type ID match for this driver/device. The register is a 32-bit
399 * value. The device must be stopped before calling this function.
401 * @param InstancePtr is a pointer to the instance to be worked on.
402 * @param Id_Check is type ID to be configured.
403 * @param Index is a index to which Type ID (1-4).
406 * - XST_SUCCESS if the MAC address was set successfully
407 * - XST_DEVICE_IS_STARTED if the device has not yet been stopped
409 *****************************************************************************/
410 LONG XEmacPs_SetTypeIdCheck(XEmacPs *InstancePtr, u32 Id_Check, u8 Index)
414 Xil_AssertNonvoid(InstancePtr != NULL);
415 Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
416 Xil_AssertNonvoid((IndexLoc <= (u8)XEMACPS_MAX_TYPE_ID) && (IndexLoc > 0x00U));
418 /* Be sure device has been stopped */
419 if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) {
420 Status = (LONG)(XST_DEVICE_IS_STARTED);
423 /* Index ranges 1 to 4, for offset calculation is 0 to 3. */
426 /* Set the ID bits in MATCHx register */
427 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
428 ((u32)XEMACPS_MATCH1_OFFSET + ((u32)IndexLoc * (u32)4)), Id_Check);
430 Status = (LONG)(XST_SUCCESS);
435 /*****************************************************************************/
437 * Set options for the driver/device. The driver should be stopped with
438 * XEmacPs_Stop() before changing options.
440 * @param InstancePtr is a pointer to the instance to be worked on.
441 * @param Options are the options to set. Multiple options can be set by OR'ing
442 * XTE_*_OPTIONS constants together. Options not specified are not
446 * - XST_SUCCESS if the options were set successfully
447 * - XST_DEVICE_IS_STARTED if the device has not yet been stopped
450 * See xemacps.h for a description of the available options.
452 *****************************************************************************/
453 LONG XEmacPs_SetOptions(XEmacPs *InstancePtr, u32 Options)
455 u32 Reg; /* Generic register contents */
456 u32 RegNetCfg; /* Reflects original contents of NET_CONFIG */
457 u32 RegNewNetCfg; /* Reflects new contents of NET_CONFIG */
459 Xil_AssertNonvoid(InstancePtr != NULL);
460 Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
462 /* Be sure device has been stopped */
463 if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) {
464 Status = (LONG)(XST_DEVICE_IS_STARTED);
467 /* Many of these options will change the NET_CONFIG registers.
468 * To reduce the amount of IO to the device, group these options here
469 * and change them all at once.
472 /* Grab current register contents */
473 RegNetCfg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
474 XEMACPS_NWCFG_OFFSET);
475 RegNewNetCfg = RegNetCfg;
478 * It is configured to max 1536.
480 if ((Options & XEMACPS_FRAME1536_OPTION) != 0x00000000U) {
481 RegNewNetCfg |= (XEMACPS_NWCFG_1536RXEN_MASK);
484 /* Turn on VLAN packet only, only VLAN tagged will be accepted */
485 if ((Options & XEMACPS_VLAN_OPTION) != 0x00000000U) {
486 RegNewNetCfg |= XEMACPS_NWCFG_NVLANDISC_MASK;
489 /* Turn on FCS stripping on receive packets */
490 if ((Options & XEMACPS_FCS_STRIP_OPTION) != 0x00000000U) {
491 RegNewNetCfg |= XEMACPS_NWCFG_FCSREM_MASK;
494 /* Turn on length/type field checking on receive packets */
495 if ((Options & XEMACPS_LENTYPE_ERR_OPTION) != 0x00000000U) {
496 RegNewNetCfg |= XEMACPS_NWCFG_LENERRDSCRD_MASK;
499 /* Turn on flow control */
500 if ((Options & XEMACPS_FLOW_CONTROL_OPTION) != 0x00000000U) {
501 RegNewNetCfg |= XEMACPS_NWCFG_PAUSEEN_MASK;
504 /* Turn on promiscuous frame filtering (all frames are received) */
505 if ((Options & XEMACPS_PROMISC_OPTION) != 0x00000000U) {
506 RegNewNetCfg |= XEMACPS_NWCFG_COPYALLEN_MASK;
509 /* Allow broadcast address reception */
510 if ((Options & XEMACPS_BROADCAST_OPTION) != 0x00000000U) {
511 RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_BCASTDI_MASK);
514 /* Allow multicast address filtering */
515 if ((Options & XEMACPS_MULTICAST_OPTION) != 0x00000000U) {
516 RegNewNetCfg |= XEMACPS_NWCFG_MCASTHASHEN_MASK;
519 /* enable RX checksum offload */
520 if ((Options & XEMACPS_RX_CHKSUM_ENABLE_OPTION) != 0x00000000U) {
521 RegNewNetCfg |= XEMACPS_NWCFG_RXCHKSUMEN_MASK;
524 /* Enable jumbo frames */
525 if (((Options & XEMACPS_JUMBO_ENABLE_OPTION) != 0x00000000U) &&
526 (InstancePtr->Version > 2)) {
527 RegNewNetCfg |= XEMACPS_NWCFG_JUMBO_MASK;
528 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
529 XEMACPS_JUMBOMAXLEN_OFFSET, XEMACPS_RX_BUF_SIZE_JUMBO);
530 Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
531 XEMACPS_DMACR_OFFSET);
532 Reg &= ~XEMACPS_DMACR_RXBUF_MASK;
533 Reg |= (((((u32)XEMACPS_RX_BUF_SIZE_JUMBO / (u32)XEMACPS_RX_BUF_UNIT) +
534 (((((u32)XEMACPS_RX_BUF_SIZE_JUMBO %
535 (u32)XEMACPS_RX_BUF_UNIT))!=(u32)0) ? 1U : 0U)) <<
536 (u32)(XEMACPS_DMACR_RXBUF_SHIFT)) &
537 (u32)(XEMACPS_DMACR_RXBUF_MASK));
538 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
539 XEMACPS_DMACR_OFFSET, Reg);
540 InstancePtr->MaxMtuSize = XEMACPS_MTU_JUMBO;
541 InstancePtr->MaxFrameSize = XEMACPS_MTU_JUMBO +
542 XEMACPS_HDR_SIZE + XEMACPS_TRL_SIZE;
543 InstancePtr->MaxVlanFrameSize = InstancePtr->MaxFrameSize +
544 XEMACPS_HDR_VLAN_SIZE;
545 InstancePtr->RxBufMask = XEMACPS_RXBUF_LEN_JUMBO_MASK;
548 /* Officially change the NET_CONFIG registers if it needs to be
551 if (RegNetCfg != RegNewNetCfg) {
552 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
553 XEMACPS_NWCFG_OFFSET, RegNewNetCfg);
556 /* Enable TX checksum offload */
557 if ((Options & XEMACPS_TX_CHKSUM_ENABLE_OPTION) != 0x00000000U) {
558 Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
559 XEMACPS_DMACR_OFFSET);
560 Reg |= XEMACPS_DMACR_TCPCKSUM_MASK;
561 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
562 XEMACPS_DMACR_OFFSET, Reg);
565 /* Enable transmitter */
566 if ((Options & XEMACPS_TRANSMITTER_ENABLE_OPTION) != 0x00000000U) {
567 Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
568 XEMACPS_NWCTRL_OFFSET);
569 Reg |= XEMACPS_NWCTRL_TXEN_MASK;
570 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
571 XEMACPS_NWCTRL_OFFSET, Reg);
574 /* Enable receiver */
575 if ((Options & XEMACPS_RECEIVER_ENABLE_OPTION) != 0x00000000U) {
576 Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
577 XEMACPS_NWCTRL_OFFSET);
578 Reg |= XEMACPS_NWCTRL_RXEN_MASK;
579 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
580 XEMACPS_NWCTRL_OFFSET, Reg);
583 /* The remaining options not handled here are managed elsewhere in the
584 * driver. No register modifications are needed at this time. Reflecting
585 * the option in InstancePtr->Options is good enough for now.
588 /* Set options word to its new value */
589 InstancePtr->Options |= Options;
591 Status = (LONG)(XST_SUCCESS);
597 /*****************************************************************************/
599 * Clear options for the driver/device
601 * @param InstancePtr is a pointer to the instance to be worked on.
602 * @param Options are the options to clear. Multiple options can be cleared by
603 * OR'ing XEMACPS_*_OPTIONS constants together. Options not specified
607 * - XST_SUCCESS if the options were set successfully
608 * - XST_DEVICE_IS_STARTED if the device has not yet been stopped
611 * See xemacps.h for a description of the available options.
613 *****************************************************************************/
614 LONG XEmacPs_ClearOptions(XEmacPs *InstancePtr, u32 Options)
616 u32 Reg; /* Generic */
617 u32 RegNetCfg; /* Reflects original contents of NET_CONFIG */
618 u32 RegNewNetCfg; /* Reflects new contents of NET_CONFIG */
620 Xil_AssertNonvoid(InstancePtr != NULL);
621 Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
623 /* Be sure device has been stopped */
624 if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) {
625 Status = (LONG)(XST_DEVICE_IS_STARTED);
628 /* Many of these options will change the NET_CONFIG registers.
629 * To reduce the amount of IO to the device, group these options here
630 * and change them all at once.
633 /* Grab current register contents */
634 RegNetCfg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
635 XEMACPS_NWCFG_OFFSET);
636 RegNewNetCfg = RegNetCfg;
638 /* There is only RX configuration!?
639 * It is configured in two different length, upto 1536 and 10240 bytes
641 if ((Options & XEMACPS_FRAME1536_OPTION) != 0x00000000U) {
642 RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_1536RXEN_MASK);
645 /* Turn off VLAN packet only */
646 if ((Options & XEMACPS_VLAN_OPTION) != 0x00000000U) {
647 RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_NVLANDISC_MASK);
650 /* Turn off FCS stripping on receive packets */
651 if ((Options & XEMACPS_FCS_STRIP_OPTION) != 0x00000000U) {
652 RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_FCSREM_MASK);
655 /* Turn off length/type field checking on receive packets */
656 if ((Options & XEMACPS_LENTYPE_ERR_OPTION) != 0x00000000U) {
657 RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_LENERRDSCRD_MASK);
660 /* Turn off flow control */
661 if ((Options & XEMACPS_FLOW_CONTROL_OPTION) != 0x00000000U) {
662 RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_PAUSEEN_MASK);
665 /* Turn off promiscuous frame filtering (all frames are received) */
666 if ((Options & XEMACPS_PROMISC_OPTION) != 0x00000000U) {
667 RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_COPYALLEN_MASK);
670 /* Disallow broadcast address filtering => broadcast reception */
671 if ((Options & XEMACPS_BROADCAST_OPTION) != 0x00000000U) {
672 RegNewNetCfg |= XEMACPS_NWCFG_BCASTDI_MASK;
675 /* Disallow multicast address filtering */
676 if ((Options & XEMACPS_MULTICAST_OPTION) != 0x00000000U) {
677 RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_MCASTHASHEN_MASK);
680 /* Disable RX checksum offload */
681 if ((Options & XEMACPS_RX_CHKSUM_ENABLE_OPTION) != 0x00000000U) {
682 RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_RXCHKSUMEN_MASK);
685 /* Disable jumbo frames */
686 if (((Options & XEMACPS_JUMBO_ENABLE_OPTION) != 0x00000000U) &&
687 (InstancePtr->Version > 2)) {
688 RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_JUMBO_MASK);
689 Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
690 XEMACPS_DMACR_OFFSET);
691 Reg &= ~XEMACPS_DMACR_RXBUF_MASK;
692 Reg |= (((((u32)XEMACPS_RX_BUF_SIZE / (u32)XEMACPS_RX_BUF_UNIT) +
693 (((((u32)XEMACPS_RX_BUF_SIZE %
694 (u32)XEMACPS_RX_BUF_UNIT))!=(u32)0) ? 1U : 0U)) <<
695 (u32)(XEMACPS_DMACR_RXBUF_SHIFT)) &
696 (u32)(XEMACPS_DMACR_RXBUF_MASK));
697 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
698 XEMACPS_DMACR_OFFSET, Reg);
699 InstancePtr->MaxMtuSize = XEMACPS_MTU;
700 InstancePtr->MaxFrameSize = XEMACPS_MTU +
701 XEMACPS_HDR_SIZE + XEMACPS_TRL_SIZE;
702 InstancePtr->MaxVlanFrameSize = InstancePtr->MaxFrameSize +
703 XEMACPS_HDR_VLAN_SIZE;
704 InstancePtr->RxBufMask = XEMACPS_RXBUF_LEN_MASK;
707 /* Officially change the NET_CONFIG registers if it needs to be
710 if (RegNetCfg != RegNewNetCfg) {
711 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
712 XEMACPS_NWCFG_OFFSET, RegNewNetCfg);
715 /* Disable TX checksum offload */
716 if ((Options & XEMACPS_TX_CHKSUM_ENABLE_OPTION) != 0x00000000U) {
717 Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
718 XEMACPS_DMACR_OFFSET);
719 Reg &= (u32)(~XEMACPS_DMACR_TCPCKSUM_MASK);
720 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
721 XEMACPS_DMACR_OFFSET, Reg);
724 /* Disable transmitter */
725 if ((Options & XEMACPS_TRANSMITTER_ENABLE_OPTION) != 0x00000000U) {
726 Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
727 XEMACPS_NWCTRL_OFFSET);
728 Reg &= (u32)(~XEMACPS_NWCTRL_TXEN_MASK);
729 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
730 XEMACPS_NWCTRL_OFFSET, Reg);
733 /* Disable receiver */
734 if ((Options & XEMACPS_RECEIVER_ENABLE_OPTION) != 0x00000000U) {
735 Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
736 XEMACPS_NWCTRL_OFFSET);
737 Reg &= (u32)(~XEMACPS_NWCTRL_RXEN_MASK);
738 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
739 XEMACPS_NWCTRL_OFFSET, Reg);
742 /* The remaining options not handled here are managed elsewhere in the
743 * driver. No register modifications are needed at this time. Reflecting
744 * option in InstancePtr->Options is good enough for now.
747 /* Set options word to its new value */
748 InstancePtr->Options &= ~Options;
750 Status = (LONG)(XST_SUCCESS);
756 /*****************************************************************************/
758 * Get current option settings
760 * @param InstancePtr is a pointer to the instance to be worked on.
763 * A bitmask of XTE_*_OPTION constants. Any bit set to 1 is to be interpreted
767 * See xemacps.h for a description of the available options.
769 *****************************************************************************/
770 u32 XEmacPs_GetOptions(XEmacPs *InstancePtr)
772 Xil_AssertNonvoid(InstancePtr != NULL);
773 Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
775 return (InstancePtr->Options);
779 /*****************************************************************************/
781 * Send a pause packet
783 * @param InstancePtr is a pointer to the instance to be worked on.
786 * - XST_SUCCESS if pause frame transmission was initiated
787 * - XST_DEVICE_IS_STOPPED if the device has not been started.
789 *****************************************************************************/
790 LONG XEmacPs_SendPausePacket(XEmacPs *InstancePtr)
795 Xil_AssertNonvoid(InstancePtr != NULL);
796 Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
798 /* Make sure device is ready for this operation */
799 if (InstancePtr->IsStarted != (u32)XIL_COMPONENT_IS_STARTED) {
800 Status = (LONG)(XST_DEVICE_IS_STOPPED);
802 /* Send flow control frame */
803 Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
804 XEMACPS_NWCTRL_OFFSET);
805 Reg |= XEMACPS_NWCTRL_PAUSETX_MASK;
806 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
807 XEMACPS_NWCTRL_OFFSET, Reg);
808 Status = (LONG)(XST_SUCCESS);
813 /*****************************************************************************/
815 * XEmacPs_GetOperatingSpeed gets the current operating link speed. This may
816 * be the value set by XEmacPs_SetOperatingSpeed() or a hardware default.
818 * @param InstancePtr references the TEMAC channel on which to operate.
820 * @return XEmacPs_GetOperatingSpeed returns the link speed in units of
821 * megabits per second.
825 *****************************************************************************/
826 u16 XEmacPs_GetOperatingSpeed(XEmacPs *InstancePtr)
831 Xil_AssertNonvoid(InstancePtr != NULL);
832 Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
834 Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
835 XEMACPS_NWCFG_OFFSET);
837 if ((Reg & XEMACPS_NWCFG_1000_MASK) != 0x00000000U) {
838 Status = (u16)(1000);
840 if ((Reg & XEMACPS_NWCFG_100_MASK) != 0x00000000U) {
850 /*****************************************************************************/
852 * XEmacPs_SetOperatingSpeed sets the current operating link speed. For any
853 * traffic to be passed, this speed must match the current MII/GMII/SGMII/RGMII
856 * @param InstancePtr references the TEMAC channel on which to operate.
857 * @param Speed is the speed to set in units of Mbps. Valid values are 10, 100,
858 * or 1000. XEmacPs_SetOperatingSpeed ignores invalid values.
862 *****************************************************************************/
863 void XEmacPs_SetOperatingSpeed(XEmacPs *InstancePtr, u16 Speed)
867 Xil_AssertVoid(InstancePtr != NULL);
868 Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
869 Xil_AssertVoid((Speed == (u16)10) || (Speed == (u16)100) || (Speed == (u16)1000));
871 Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
872 XEMACPS_NWCFG_OFFSET);
873 Reg &= (u32)(~(XEMACPS_NWCFG_1000_MASK | XEMACPS_NWCFG_100_MASK));
882 Reg |= XEMACPS_NWCFG_100_MASK;
887 Reg |= XEMACPS_NWCFG_1000_MASK;
894 if(Status == (u16)1){
898 /* Set register and return */
899 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
900 XEMACPS_NWCFG_OFFSET, Reg);
904 /*****************************************************************************/
906 * Set the MDIO clock divisor.
908 * Calculating the divisor:
912 * f[MDC] = -----------------
916 * where f[HOSTCLK] is the bus clock frequency in MHz, and f[MDC] is the
917 * MDIO clock frequency in MHz to the PHY. Typically, f[MDC] should not
918 * exceed 2.5 MHz. Some PHYs can tolerate faster speeds which means faster
919 * access. Here is the table to show values to generate MDC,
922 * 000 : divide pclk by 8 (pclk up to 20 MHz)
923 * 001 : divide pclk by 16 (pclk up to 40 MHz)
924 * 010 : divide pclk by 32 (pclk up to 80 MHz)
925 * 011 : divide pclk by 48 (pclk up to 120 MHz)
926 * 100 : divide pclk by 64 (pclk up to 160 MHz)
927 * 101 : divide pclk by 96 (pclk up to 240 MHz)
928 * 110 : divide pclk by 128 (pclk up to 320 MHz)
929 * 111 : divide pclk by 224 (pclk up to 540 MHz)
932 * @param InstancePtr is a pointer to the instance to be worked on.
933 * @param Divisor is the divisor to set. Range is 0b000 to 0b111.
935 *****************************************************************************/
936 void XEmacPs_SetMdioDivisor(XEmacPs *InstancePtr, XEmacPs_MdcDiv Divisor)
939 Xil_AssertVoid(InstancePtr != NULL);
940 Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
941 Xil_AssertVoid(Divisor <= (XEmacPs_MdcDiv)0x7); /* only last three bits are valid */
943 Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
944 XEMACPS_NWCFG_OFFSET);
945 /* clear these three bits, could be done with mask */
946 Reg &= (u32)(~XEMACPS_NWCFG_MDCCLKDIV_MASK);
948 Reg |= ((u32)Divisor << XEMACPS_NWCFG_MDC_SHIFT_MASK);
950 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
951 XEMACPS_NWCFG_OFFSET, Reg);
955 /*****************************************************************************/
957 * Read the current value of the PHY register indicated by the PhyAddress and
958 * the RegisterNum parameters. The MAC provides the driver with the ability to
959 * talk to a PHY that adheres to the Media Independent Interface (MII) as
960 * defined in the IEEE 802.3 standard.
962 * Prior to PHY access with this function, the user should have setup the MDIO
963 * clock with XEmacPs_SetMdioDivisor().
965 * @param InstancePtr is a pointer to the XEmacPs instance to be worked on.
966 * @param PhyAddress is the address of the PHY to be read (supports multiple
968 * @param RegisterNum is the register number, 0-31, of the specific PHY register
970 * @param PhyDataPtr is an output parameter, and points to a 16-bit buffer into
971 * which the current value of the register will be copied.
975 * - XST_SUCCESS if the PHY was read from successfully
976 * - XST_EMAC_MII_BUSY if there is another PHY operation in progress
980 * This function is not thread-safe. The user must provide mutually exclusive
981 * access to this function if there are to be multiple threads that can call it.
983 * There is the possibility that this function will not return if the hardware
984 * is broken (i.e., it never sets the status bit indicating that the read is
985 * done). If this is of concern to the user, the user should provide a mechanism
986 * suitable to their needs for recovery.
988 * For the duration of this function, all host interface reads and writes are
989 * blocked to the current XEmacPs instance.
991 ******************************************************************************/
992 LONG XEmacPs_PhyRead(XEmacPs *InstancePtr, u32 PhyAddress,
993 u32 RegisterNum, u16 *PhyDataPtr)
1000 Xil_AssertNonvoid(InstancePtr != NULL);
1002 /* Make sure no other PHY operation is currently in progress */
1003 if ((!(XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
1004 XEMACPS_NWSR_OFFSET) &
1005 XEMACPS_NWSR_MDIOIDLE_MASK))==TRUE) {
1006 Status = (LONG)(XST_EMAC_MII_BUSY);
1009 /* Construct Mgtcr mask for the operation */
1010 Mgtcr = XEMACPS_PHYMNTNC_OP_MASK | XEMACPS_PHYMNTNC_OP_R_MASK |
1011 (PhyAddress << XEMACPS_PHYMNTNC_PHAD_SHFT_MSK) |
1012 (RegisterNum << XEMACPS_PHYMNTNC_PREG_SHFT_MSK);
1014 /* Write Mgtcr and wait for completion */
1015 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
1016 XEMACPS_PHYMNTNC_OFFSET, Mgtcr);
1019 Ipisr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
1020 XEMACPS_NWSR_OFFSET);
1022 } while ((IpReadTemp & XEMACPS_NWSR_MDIOIDLE_MASK) == 0x00000000U);
1025 *PhyDataPtr = (u16)XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
1026 XEMACPS_PHYMNTNC_OFFSET);
1027 Status = (LONG)(XST_SUCCESS);
1033 /*****************************************************************************/
1035 * Write data to the specified PHY register. The Ethernet driver does not
1036 * require the device to be stopped before writing to the PHY. Although it is
1037 * probably a good idea to stop the device, it is the responsibility of the
1038 * application to deem this necessary. The MAC provides the driver with the
1039 * ability to talk to a PHY that adheres to the Media Independent Interface
1040 * (MII) as defined in the IEEE 802.3 standard.
1042 * Prior to PHY access with this function, the user should have setup the MDIO
1043 * clock with XEmacPs_SetMdioDivisor().
1045 * @param InstancePtr is a pointer to the XEmacPs instance to be worked on.
1046 * @param PhyAddress is the address of the PHY to be written (supports multiple
1048 * @param RegisterNum is the register number, 0-31, of the specific PHY register
1050 * @param PhyData is the 16-bit value that will be written to the register
1054 * - XST_SUCCESS if the PHY was written to successfully. Since there is no error
1055 * status from the MAC on a write, the user should read the PHY to verify the
1056 * write was successful.
1057 * - XST_EMAC_MII_BUSY if there is another PHY operation in progress
1061 * This function is not thread-safe. The user must provide mutually exclusive
1062 * access to this function if there are to be multiple threads that can call it.
1064 * There is the possibility that this function will not return if the hardware
1065 * is broken (i.e., it never sets the status bit indicating that the write is
1066 * done). If this is of concern to the user, the user should provide a mechanism
1067 * suitable to their needs for recovery.
1069 * For the duration of this function, all host interface reads and writes are
1070 * blocked to the current XEmacPs instance.
1072 ******************************************************************************/
1073 LONG XEmacPs_PhyWrite(XEmacPs *InstancePtr, u32 PhyAddress,
1074 u32 RegisterNum, u16 PhyData)
1081 Xil_AssertNonvoid(InstancePtr != NULL);
1083 /* Make sure no other PHY operation is currently in progress */
1084 if ((!(XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
1085 XEMACPS_NWSR_OFFSET) &
1086 XEMACPS_NWSR_MDIOIDLE_MASK))==TRUE) {
1087 Status = (LONG)(XST_EMAC_MII_BUSY);
1089 /* Construct Mgtcr mask for the operation */
1090 Mgtcr = XEMACPS_PHYMNTNC_OP_MASK | XEMACPS_PHYMNTNC_OP_W_MASK |
1091 (PhyAddress << XEMACPS_PHYMNTNC_PHAD_SHFT_MSK) |
1092 (RegisterNum << XEMACPS_PHYMNTNC_PREG_SHFT_MSK) | (u32)PhyData;
1094 /* Write Mgtcr and wait for completion */
1095 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
1096 XEMACPS_PHYMNTNC_OFFSET, Mgtcr);
1099 Ipisr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
1100 XEMACPS_NWSR_OFFSET);
1101 IpWriteTemp = Ipisr;
1102 } while ((IpWriteTemp & XEMACPS_NWSR_MDIOIDLE_MASK) == 0x00000000U);
1104 Status = (LONG)(XST_SUCCESS);
1109 /*****************************************************************************/
1111 * API to update the Burst length in the DMACR register.
1113 * @param InstancePtr is a pointer to the XEmacPs instance to be worked on.
1114 * @param BLength is the length in bytes for the dma burst.
1118 ******************************************************************************/
1119 void XEmacPs_DMABLengthUpdate(XEmacPs *InstancePtr, s32 BLength)
1124 Xil_AssertVoid(InstancePtr != NULL);
1125 Xil_AssertVoid((BLength == XEMACPS_SINGLE_BURST) ||
1126 (BLength == XEMACPS_4BYTE_BURST) ||
1127 (BLength == XEMACPS_8BYTE_BURST) ||
1128 (BLength == XEMACPS_16BYTE_BURST));
1131 case XEMACPS_SINGLE_BURST:
1132 RegUpdateVal = XEMACPS_DMACR_SINGLE_AHB_BURST;
1135 case XEMACPS_4BYTE_BURST:
1136 RegUpdateVal = XEMACPS_DMACR_INCR4_AHB_BURST;
1139 case XEMACPS_8BYTE_BURST:
1140 RegUpdateVal = XEMACPS_DMACR_INCR8_AHB_BURST;
1143 case XEMACPS_16BYTE_BURST:
1144 RegUpdateVal = XEMACPS_DMACR_INCR16_AHB_BURST;
1148 RegUpdateVal = 0x00000000U;
1151 Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
1152 XEMACPS_DMACR_OFFSET);
1154 Reg &= (u32)(~XEMACPS_DMACR_BLENGTH_MASK);
1155 Reg |= RegUpdateVal;
1156 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_DMACR_OFFSET,