1 /* $Id: xemacps_control.c,v 1.1.2.1 2011/01/20 03:39:02 sadanan Exp $ */
2 /******************************************************************************
4 * (c) Copyright 2009-2010 Xilinx, Inc. All rights reserved.
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.
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.
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.
38 * THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART OF THIS FILE
41 ******************************************************************************/
42 /*****************************************************************************/
45 * @file xemacps_control.c
47 * Functions in this file implement general purpose command and control related
48 * functionality. See xemacps.h for a detailed description of the driver.
51 * MODIFICATION HISTORY:
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
60 *****************************************************************************/
62 /***************************** Include Files *********************************/
66 /************************** Constant Definitions *****************************/
69 /**************************** Type Definitions *******************************/
72 /***************** Macros (Inline Functions) Definitions *********************/
75 /************************** Function Prototypes ******************************/
78 /************************** Variable Definitions *****************************/
81 /*****************************************************************************/
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.
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.
91 * - XST_SUCCESS if the MAC address was set successfully
92 * - XST_DEVICE_IS_STARTED if the device has not yet been stopped
94 *****************************************************************************/
95 int XEmacPs_SetMacAddress(XEmacPs *InstancePtr, void *AddressPtr, u8 Index)
98 u8 *Aptr = (u8 *) AddressPtr;
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));
105 /* Be sure device has been stopped */
106 if (InstancePtr->IsStarted == XIL_COMPONENT_IS_STARTED) {
107 return (XST_DEVICE_IS_STARTED);
110 /* Index ranges 1 to 4, for offset calculation is 0 to 3. */
113 /* Set the MAC bits [31:0] in BOT */
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);
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)));
125 MacAddr &= ~XEMACPS_LADDR_MACH_MASK;
127 /* Set MAC bits [47:32] in TOP */
129 MacAddr |= Aptr[5] << 8;
131 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
132 (XEMACPS_LADDR1H_OFFSET + (Index * 8)), MacAddr);
134 return (XST_SUCCESS);
138 /*****************************************************************************/
140 * Get the MAC address for this driver/device.
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.
147 *****************************************************************************/
148 void XEmacPs_GetMacAddress(XEmacPs *InstancePtr, void *AddressPtr, u8 Index)
151 u8 *Aptr = (u8 *) AddressPtr;
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));
158 /* Index ranges 1 to 4, for offset calculation is 0 to 3. */
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);
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);
176 /*****************************************************************************/
178 * Set 48-bit MAC addresses in hash table.
179 * The device must be stopped before calling this function.
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.
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.
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]
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.
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
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
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
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.
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.
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
231 * Having Aptr be unsigned type prevents the following operations from sign
233 *****************************************************************************/
234 int XEmacPs_SetHash(XEmacPs *InstancePtr, void *AddressPtr)
237 u8 *Aptr = (u8 *) AddressPtr;
238 u8 Temp1, Temp2, Temp3, Temp4, Temp5, Temp6, Temp7, Temp8;
241 Xil_AssertNonvoid(InstancePtr != NULL);
242 Xil_AssertNonvoid(AddressPtr != NULL);
243 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
245 /* Be sure device has been stopped */
246 if (InstancePtr->IsStarted == XIL_COMPONENT_IS_STARTED) {
247 return (XST_DEVICE_IS_STARTED);
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);
258 Result = Temp1 ^ Temp2 ^ Temp3 ^ Temp4 ^ Temp5 ^ Temp6 ^ Temp7 ^ Temp8;
260 if (Result >= XEMACPS_MAX_HASH_BITS) {
261 return (XST_INVALID_PARAM);
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);
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);
278 return (XST_SUCCESS);
281 /*****************************************************************************/
283 * Delete 48-bit MAC addresses in hash table.
284 * The device must be stopped before calling this function.
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.
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
296 * Having Aptr be unsigned type prevents the following operations from sign
298 *****************************************************************************/
299 int XEmacPs_DeleteHash(XEmacPs *InstancePtr, void *AddressPtr)
302 u8 *Aptr = (u8 *) AddressPtr;
303 u8 Temp1, Temp2, Temp3, Temp4, Temp5, Temp6, Temp7, Temp8;
306 Xil_AssertNonvoid(InstancePtr != NULL);
307 Xil_AssertNonvoid(AddressPtr != NULL);
308 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
310 /* Be sure device has been stopped */
311 if (InstancePtr->IsStarted == XIL_COMPONENT_IS_STARTED) {
312 return (XST_DEVICE_IS_STARTED);
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);
323 Result = Temp1 ^ Temp2 ^ Temp3 ^ Temp4 ^ Temp5 ^ Temp6 ^ Temp7 ^ Temp8;
325 if (Result >= XEMACPS_MAX_HASH_BITS) {
326 return (XST_INVALID_PARAM);
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);
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);
343 return (XST_SUCCESS);
347 /*****************************************************************************/
349 * Clear the Hash registers for the mac address pointed by AddressPtr.
351 * @param InstancePtr is a pointer to the instance to be worked on.
353 *****************************************************************************/
354 void XEmacPs_ClearHash(XEmacPs *InstancePtr)
356 Xil_AssertVoid(InstancePtr != NULL);
357 Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
359 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
360 XEMACPS_HASHL_OFFSET, 0x0);
362 /* write bits [63:32] in TOP */
363 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
364 XEMACPS_HASHH_OFFSET, 0x0);
368 /*****************************************************************************/
370 * Get the Hash address for this driver/device.
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.
376 *****************************************************************************/
377 void XEmacPs_GetHash(XEmacPs *InstancePtr, void *AddressPtr)
379 u32 *Aptr = (u32 *) AddressPtr;
381 Xil_AssertVoid(InstancePtr != NULL);
382 Xil_AssertVoid(AddressPtr != NULL);
383 Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
385 Aptr[0] = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
386 XEMACPS_HASHL_OFFSET);
388 /* Read Hash bits [63:32] in TOP */
389 Aptr[1] = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
390 XEMACPS_HASHH_OFFSET);
394 /*****************************************************************************/
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.
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).
404 * - XST_SUCCESS if the MAC address was set successfully
405 * - XST_DEVICE_IS_STARTED if the device has not yet been stopped
407 *****************************************************************************/
408 int XEmacPs_SetTypeIdCheck(XEmacPs *InstancePtr, u32 Id_Check, u8 Index)
410 Xil_AssertNonvoid(InstancePtr != NULL);
411 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
412 Xil_AssertNonvoid((Index <= XEMACPS_MAX_TYPE_ID) && (Index > 0));
414 /* Be sure device has been stopped */
415 if (InstancePtr->IsStarted == XIL_COMPONENT_IS_STARTED) {
416 return (XST_DEVICE_IS_STARTED);
419 /* Index ranges 1 to 4, for offset calculation is 0 to 3. */
422 /* Set the ID bits in MATCHx register */
423 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
424 (XEMACPS_MATCH1_OFFSET + (Index * 4)), Id_Check);
426 return (XST_SUCCESS);
429 /*****************************************************************************/
431 * Set options for the driver/device. The driver should be stopped with
432 * XEmacPs_Stop() before changing options.
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
440 * - XST_SUCCESS if the options were set successfully
441 * - XST_DEVICE_IS_STARTED if the device has not yet been stopped
444 * See xemacps.h for a description of the available options.
446 *****************************************************************************/
447 int XEmacPs_SetOptions(XEmacPs *InstancePtr, u32 Options)
449 u32 Reg; /* Generic register contents */
450 u32 RegNetCfg; /* Reflects original contents of NET_CONFIG */
451 u32 RegNewNetCfg; /* Reflects new contents of NET_CONFIG */
453 Xil_AssertNonvoid(InstancePtr != NULL);
454 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
456 /* Be sure device has been stopped */
457 if (InstancePtr->IsStarted == XIL_COMPONENT_IS_STARTED) {
458 return (XST_DEVICE_IS_STARTED);
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.
466 /* Grab current register contents */
467 RegNetCfg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
468 XEMACPS_NWCFG_OFFSET);
469 RegNewNetCfg = RegNetCfg;
472 * It is configured to max 1536.
474 if (Options & XEMACPS_FRAME1536_OPTION) {
475 RegNewNetCfg |= (XEMACPS_NWCFG_1536RXEN_MASK);
478 /* Turn on VLAN packet only, only VLAN tagged will be accepted */
479 if (Options & XEMACPS_VLAN_OPTION) {
480 RegNewNetCfg |= XEMACPS_NWCFG_NVLANDISC_MASK;
483 /* Turn on FCS stripping on receive packets */
484 if (Options & XEMACPS_FCS_STRIP_OPTION) {
485 RegNewNetCfg |= XEMACPS_NWCFG_FCSREM_MASK;
488 /* Turn on length/type field checking on receive packets */
489 if (Options & XEMACPS_LENTYPE_ERR_OPTION) {
490 RegNewNetCfg |= XEMACPS_NWCFG_LENGTHERRDSCRD_MASK;
493 /* Turn on flow control */
494 if (Options & XEMACPS_FLOW_CONTROL_OPTION) {
495 RegNewNetCfg |= XEMACPS_NWCFG_PAUSEEN_MASK;
498 /* Turn on promiscuous frame filtering (all frames are received) */
499 if (Options & XEMACPS_PROMISC_OPTION) {
500 RegNewNetCfg |= XEMACPS_NWCFG_COPYALLEN_MASK;
503 /* Allow broadcast address reception */
504 if (Options & XEMACPS_BROADCAST_OPTION) {
505 RegNewNetCfg &= ~XEMACPS_NWCFG_BCASTDI_MASK;
508 /* Allow multicast address filtering */
509 if (Options & XEMACPS_MULTICAST_OPTION) {
510 RegNewNetCfg |= XEMACPS_NWCFG_MCASTHASHEN_MASK;
513 /* enable RX checksum offload */
514 if (Options & XEMACPS_RX_CHKSUM_ENABLE_OPTION) {
515 RegNewNetCfg |= XEMACPS_NWCFG_RXCHKSUMEN_MASK;
518 /* Officially change the NET_CONFIG registers if it needs to be
521 if (RegNetCfg != RegNewNetCfg) {
522 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
523 XEMACPS_NWCFG_OFFSET, RegNewNetCfg);
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);
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);
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);
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.
558 /* Set options word to its new value */
559 InstancePtr->Options |= Options;
561 return (XST_SUCCESS);
565 /*****************************************************************************/
567 * Clear options for the driver/device
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
575 * - XST_SUCCESS if the options were set successfully
576 * - XST_DEVICE_IS_STARTED if the device has not yet been stopped
579 * See xemacps.h for a description of the available options.
581 *****************************************************************************/
582 int XEmacPs_ClearOptions(XEmacPs *InstancePtr, u32 Options)
584 u32 Reg; /* Generic */
585 u32 RegNetCfg; /* Reflects original contents of NET_CONFIG */
586 u32 RegNewNetCfg; /* Reflects new contents of NET_CONFIG */
588 Xil_AssertNonvoid(InstancePtr != NULL);
589 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
591 /* Be sure device has been stopped */
592 if (InstancePtr->IsStarted == XIL_COMPONENT_IS_STARTED) {
593 return (XST_DEVICE_IS_STARTED);
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.
601 /* Grab current register contents */
602 RegNetCfg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
603 XEMACPS_NWCFG_OFFSET);
604 RegNewNetCfg = RegNetCfg;
606 /* There is only RX configuration!?
607 * It is configured in two different length, upto 1536 and 10240 bytes
609 if (Options & XEMACPS_FRAME1536_OPTION) {
610 RegNewNetCfg &= ~XEMACPS_NWCFG_1536RXEN_MASK;
613 /* Turn off VLAN packet only */
614 if (Options & XEMACPS_VLAN_OPTION) {
615 RegNewNetCfg &= ~XEMACPS_NWCFG_NVLANDISC_MASK;
618 /* Turn off FCS stripping on receive packets */
619 if (Options & XEMACPS_FCS_STRIP_OPTION) {
620 RegNewNetCfg &= ~XEMACPS_NWCFG_FCSREM_MASK;
623 /* Turn off length/type field checking on receive packets */
624 if (Options & XEMACPS_LENTYPE_ERR_OPTION) {
625 RegNewNetCfg &= ~XEMACPS_NWCFG_LENGTHERRDSCRD_MASK;
628 /* Turn off flow control */
629 if (Options & XEMACPS_FLOW_CONTROL_OPTION) {
630 RegNewNetCfg &= ~XEMACPS_NWCFG_PAUSEEN_MASK;
633 /* Turn off promiscuous frame filtering (all frames are received) */
634 if (Options & XEMACPS_PROMISC_OPTION) {
635 RegNewNetCfg &= ~XEMACPS_NWCFG_COPYALLEN_MASK;
638 /* Disallow broadcast address filtering => broadcast reception */
639 if (Options & XEMACPS_BROADCAST_OPTION) {
640 RegNewNetCfg |= XEMACPS_NWCFG_BCASTDI_MASK;
643 /* Disallow multicast address filtering */
644 if (Options & XEMACPS_MULTICAST_OPTION) {
645 RegNewNetCfg &= ~XEMACPS_NWCFG_MCASTHASHEN_MASK;
648 /* Disable RX checksum offload */
649 if (Options & XEMACPS_RX_CHKSUM_ENABLE_OPTION) {
650 RegNewNetCfg &= ~XEMACPS_NWCFG_RXCHKSUMEN_MASK;
653 /* Officially change the NET_CONFIG registers if it needs to be
656 if (RegNetCfg != RegNewNetCfg) {
657 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
658 XEMACPS_NWCFG_OFFSET, RegNewNetCfg);
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);
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);
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);
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.
693 /* Set options word to its new value */
694 InstancePtr->Options &= ~Options;
696 return (XST_SUCCESS);
700 /*****************************************************************************/
702 * Get current option settings
704 * @param InstancePtr is a pointer to the instance to be worked on.
707 * A bitmask of XTE_*_OPTION constants. Any bit set to 1 is to be interpreted
711 * See xemacps.h for a description of the available options.
713 *****************************************************************************/
714 u32 XEmacPs_GetOptions(XEmacPs *InstancePtr)
716 Xil_AssertNonvoid(InstancePtr != NULL);
717 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
719 return (InstancePtr->Options);
723 /*****************************************************************************/
725 * Send a pause packet
727 * @param InstancePtr is a pointer to the instance to be worked on.
730 * - XST_SUCCESS if pause frame transmission was initiated
731 * - XST_DEVICE_IS_STOPPED if the device has not been started.
733 *****************************************************************************/
734 int XEmacPs_SendPausePacket(XEmacPs *InstancePtr)
738 Xil_AssertNonvoid(InstancePtr != NULL);
739 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
741 /* Make sure device is ready for this operation */
742 if (InstancePtr->IsStarted != XIL_COMPONENT_IS_STARTED) {
743 return (XST_DEVICE_IS_STOPPED);
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);
755 /*****************************************************************************/
757 * XEmacPs_GetOperatingSpeed gets the current operating link speed. This may
758 * be the value set by XEmacPs_SetOperatingSpeed() or a hardware default.
760 * @param InstancePtr references the TEMAC channel on which to operate.
762 * @return XEmacPs_GetOperatingSpeed returns the link speed in units of
763 * megabits per second.
767 *****************************************************************************/
768 u16 XEmacPs_GetOperatingSpeed(XEmacPs *InstancePtr)
772 Xil_AssertNonvoid(InstancePtr != NULL);
773 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
775 Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
776 XEMACPS_NWCFG_OFFSET);
778 if (Reg & XEMACPS_NWCFG_1000_MASK) {
781 if (Reg & XEMACPS_NWCFG_100_MASK) {
790 /*****************************************************************************/
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
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.
802 *****************************************************************************/
803 void XEmacPs_SetOperatingSpeed(XEmacPs *InstancePtr, u16 Speed)
807 Xil_AssertVoid(InstancePtr != NULL);
808 Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
809 Xil_AssertVoid((Speed == 10) || (Speed == 100) || (Speed == 1000));
811 Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
812 XEMACPS_NWCFG_OFFSET);
813 Reg &= ~(XEMACPS_NWCFG_1000_MASK | XEMACPS_NWCFG_100_MASK);
820 Reg |= XEMACPS_NWCFG_100_MASK;
824 Reg |= XEMACPS_NWCFG_1000_MASK;
831 /* Set register and return */
832 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
833 XEMACPS_NWCFG_OFFSET, Reg);
837 /*****************************************************************************/
839 * Set the MDIO clock divisor.
841 * Calculating the divisor:
845 * f[MDC] = -----------------
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,
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)
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.
868 *****************************************************************************/
869 void XEmacPs_SetMdioDivisor(XEmacPs *InstancePtr, XEmacPs_MdcDiv Divisor)
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 */
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;
882 Reg |= (Divisor << XEMACPS_NWCFG_MDC_SHIFT_MASK);
884 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
885 XEMACPS_NWCFG_OFFSET, Reg);
890 /*****************************************************************************/
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.
897 * Prior to PHY access with this function, the user should have setup the MDIO
898 * clock with XEmacPs_SetMdioDivisor().
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
903 * @param RegisterNum is the register number, 0-31, of the specific PHY register
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.
910 * - XST_SUCCESS if the PHY was read from successfully
911 * - XST_EMAC_MII_BUSY if there is another PHY operation in progress
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.
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.
923 * For the duration of this function, all host interface reads and writes are
924 * blocked to the current XEmacPs instance.
926 ******************************************************************************/
927 int XEmacPs_PhyRead(XEmacPs *InstancePtr, u32 PhyAddress,
928 u32 RegisterNum, u16 *PhyDataPtr)
933 Xil_AssertNonvoid(InstancePtr != NULL);
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);
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);
947 /* Write Mgtcr and wait for completion */
948 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
949 XEMACPS_PHYMNTNC_OFFSET, Mgtcr);
952 Ipisr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
953 XEMACPS_NWSR_OFFSET);
954 } while ((Ipisr & XEMACPS_NWSR_MDIOIDLE_MASK) == 0);
957 *PhyDataPtr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
958 XEMACPS_PHYMNTNC_OFFSET);
960 return (XST_SUCCESS);
964 /*****************************************************************************/
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.
973 * Prior to PHY access with this function, the user should have setup the MDIO
974 * clock with XEmacPs_SetMdioDivisor().
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
979 * @param RegisterNum is the register number, 0-31, of the specific PHY register
981 * @param PhyData is the 16-bit value that will be written to the register
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
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.
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.
1000 * For the duration of this function, all host interface reads and writes are
1001 * blocked to the current XEmacPs instance.
1003 ******************************************************************************/
1004 int XEmacPs_PhyWrite(XEmacPs *InstancePtr, u32 PhyAddress,
1005 u32 RegisterNum, u16 PhyData)
1010 Xil_AssertNonvoid(InstancePtr != NULL);
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);
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;
1024 /* Write Mgtcr and wait for completion */
1025 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
1026 XEMACPS_PHYMNTNC_OFFSET, Mgtcr);
1029 Ipisr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
1030 XEMACPS_NWSR_OFFSET);
1031 } while ((Ipisr & XEMACPS_NWSR_MDIOIDLE_MASK) == 0);
1033 return (XST_SUCCESS);
1036 /*****************************************************************************/
1038 * API to update the Burst length in the DMACR register.
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.
1045 ******************************************************************************/
1046 void XEmacPs_DMABLengthUpdate(XEmacPs *InstancePtr, int BLength)
1049 u32 RegUpdateVal = 0;
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));
1058 case XEMACPS_SINGLE_BURST:
1059 RegUpdateVal = XEMACPS_DMACR_SINGLE_AHB_BURST;
1062 case XEMACPS_4BYTE_BURST:
1063 RegUpdateVal = XEMACPS_DMACR_INCR4_AHB_BURST;
1066 case XEMACPS_8BYTE_BURST:
1067 RegUpdateVal = XEMACPS_DMACR_INCR8_AHB_BURST;
1070 case XEMACPS_16BYTE_BURST:
1071 RegUpdateVal = XEMACPS_DMACR_INCR16_AHB_BURST;
1077 Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
1078 XEMACPS_DMACR_OFFSET);
1080 Reg &= (~XEMACPS_DMACR_BLENGTH_MASK);
1081 Reg |= RegUpdateVal;
1082 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_DMACR_OFFSET,