xref: /rk3399_rockchip-uboot/drivers/net/xilinx_emaclite.c (revision 89c53891b18cbafd29ab8931b40e27ad231b6085)
1*89c53891SMichal Simek /******************************************************************************
2*89c53891SMichal Simek  *
3*89c53891SMichal Simek  * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
4*89c53891SMichal Simek  * AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND
5*89c53891SMichal Simek  * SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE,
6*89c53891SMichal Simek  * OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,
7*89c53891SMichal Simek  * APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION
8*89c53891SMichal Simek  * THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,
9*89c53891SMichal Simek  * AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
10*89c53891SMichal Simek  * FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY
11*89c53891SMichal Simek  * WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE
12*89c53891SMichal Simek  * IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR
13*89c53891SMichal Simek  * REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF
14*89c53891SMichal Simek  * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
15*89c53891SMichal Simek  * FOR A PARTICULAR PURPOSE.
16*89c53891SMichal Simek  *
17*89c53891SMichal Simek  * (C) Copyright 2007-2008 Michal Simek
18*89c53891SMichal Simek  * Michal SIMEK <monstr@monstr.eu>
19*89c53891SMichal Simek  *
20*89c53891SMichal Simek  * (c) Copyright 2003 Xilinx Inc.
21*89c53891SMichal Simek  * All rights reserved.
22*89c53891SMichal Simek  *
23*89c53891SMichal Simek  ******************************************************************************/
24*89c53891SMichal Simek 
25*89c53891SMichal Simek #include <common.h>
26*89c53891SMichal Simek #include <net.h>
27*89c53891SMichal Simek #include <config.h>
28*89c53891SMichal Simek #include <asm/io.h>
29*89c53891SMichal Simek 
30*89c53891SMichal Simek #undef DEBUG
31*89c53891SMichal Simek 
32*89c53891SMichal Simek #define ENET_MAX_MTU		PKTSIZE
33*89c53891SMichal Simek #define ENET_MAX_MTU_ALIGNED	PKTSIZE_ALIGN
34*89c53891SMichal Simek #define ENET_ADDR_LENGTH	6
35*89c53891SMichal Simek 
36*89c53891SMichal Simek /* EmacLite constants */
37*89c53891SMichal Simek #define XEL_BUFFER_OFFSET	0x0800	/* Next buffer's offset */
38*89c53891SMichal Simek #define XEL_TPLR_OFFSET		0x07F4	/* Tx packet length */
39*89c53891SMichal Simek #define XEL_TSR_OFFSET		0x07FC	/* Tx status */
40*89c53891SMichal Simek #define XEL_RSR_OFFSET		0x17FC	/* Rx status */
41*89c53891SMichal Simek #define XEL_RXBUFF_OFFSET	0x1000	/* Receive Buffer */
42*89c53891SMichal Simek 
43*89c53891SMichal Simek /* Xmit complete */
44*89c53891SMichal Simek #define XEL_TSR_XMIT_BUSY_MASK		0x00000001UL
45*89c53891SMichal Simek /* Xmit interrupt enable bit */
46*89c53891SMichal Simek #define XEL_TSR_XMIT_IE_MASK		0x00000008UL
47*89c53891SMichal Simek /* Buffer is active, SW bit only */
48*89c53891SMichal Simek #define XEL_TSR_XMIT_ACTIVE_MASK	0x80000000UL
49*89c53891SMichal Simek /* Program the MAC address */
50*89c53891SMichal Simek #define XEL_TSR_PROGRAM_MASK		0x00000002UL
51*89c53891SMichal Simek /* define for programming the MAC address into the EMAC Lite */
52*89c53891SMichal Simek #define XEL_TSR_PROG_MAC_ADDR	(XEL_TSR_XMIT_BUSY_MASK | XEL_TSR_PROGRAM_MASK)
53*89c53891SMichal Simek 
54*89c53891SMichal Simek /* Transmit packet length upper byte */
55*89c53891SMichal Simek #define XEL_TPLR_LENGTH_MASK_HI		0x0000FF00UL
56*89c53891SMichal Simek /* Transmit packet length lower byte */
57*89c53891SMichal Simek #define XEL_TPLR_LENGTH_MASK_LO		0x000000FFUL
58*89c53891SMichal Simek 
59*89c53891SMichal Simek /* Recv complete */
60*89c53891SMichal Simek #define XEL_RSR_RECV_DONE_MASK		0x00000001UL
61*89c53891SMichal Simek /* Recv interrupt enable bit */
62*89c53891SMichal Simek #define XEL_RSR_RECV_IE_MASK		0x00000008UL
63*89c53891SMichal Simek 
64*89c53891SMichal Simek typedef struct {
65*89c53891SMichal Simek 	unsigned int baseaddress;	/* Base address for device (IPIF) */
66*89c53891SMichal Simek 	unsigned int nexttxbuffertouse;	/* Next TX buffer to write to */
67*89c53891SMichal Simek 	unsigned int nextrxbuffertouse;	/* Next RX buffer to read from */
68*89c53891SMichal Simek 	unsigned char deviceid;		/* Unique ID of device - for future */
69*89c53891SMichal Simek } xemaclite;
70*89c53891SMichal Simek 
71*89c53891SMichal Simek static xemaclite emaclite;
72*89c53891SMichal Simek 
73*89c53891SMichal Simek static char etherrxbuff[PKTSIZE_ALIGN/4]; /* Receive buffer */
74*89c53891SMichal Simek 
75*89c53891SMichal Simek /* hardcoded MAC address for the Xilinx EMAC Core when env is nowhere*/
76*89c53891SMichal Simek #ifdef CFG_ENV_IS_NOWHERE
77*89c53891SMichal Simek static u8 emacaddr[ENET_ADDR_LENGTH] = { 0x00, 0x0a, 0x35, 0x00, 0x22, 0x01 };
78*89c53891SMichal Simek #else
79*89c53891SMichal Simek static u8 emacaddr[ENET_ADDR_LENGTH];
80*89c53891SMichal Simek #endif
81*89c53891SMichal Simek 
82*89c53891SMichal Simek void xemaclite_alignedread (u32 * srcptr, void *destptr, unsigned bytecount)
83*89c53891SMichal Simek {
84*89c53891SMichal Simek 	unsigned int i;
85*89c53891SMichal Simek 	u32 alignbuffer;
86*89c53891SMichal Simek 	u32 *to32ptr;
87*89c53891SMichal Simek 	u32 *from32ptr;
88*89c53891SMichal Simek 	u8 *to8ptr;
89*89c53891SMichal Simek 	u8 *from8ptr;
90*89c53891SMichal Simek 
91*89c53891SMichal Simek 	from32ptr = (u32 *) srcptr;
92*89c53891SMichal Simek 
93*89c53891SMichal Simek 	/* Word aligned buffer, no correction needed. */
94*89c53891SMichal Simek 	to32ptr = (u32 *) destptr;
95*89c53891SMichal Simek 	while (bytecount > 3) {
96*89c53891SMichal Simek 		*to32ptr++ = *from32ptr++;
97*89c53891SMichal Simek 		bytecount -= 4;
98*89c53891SMichal Simek 	}
99*89c53891SMichal Simek 	to8ptr = (u8 *) to32ptr;
100*89c53891SMichal Simek 
101*89c53891SMichal Simek 	alignbuffer = *from32ptr++;
102*89c53891SMichal Simek 	from8ptr = (u8 *) & alignbuffer;
103*89c53891SMichal Simek 
104*89c53891SMichal Simek 	for (i = 0; i < bytecount; i++) {
105*89c53891SMichal Simek 		*to8ptr++ = *from8ptr++;
106*89c53891SMichal Simek 	}
107*89c53891SMichal Simek }
108*89c53891SMichal Simek 
109*89c53891SMichal Simek void xemaclite_alignedwrite (void *srcptr, u32 destptr, unsigned bytecount)
110*89c53891SMichal Simek {
111*89c53891SMichal Simek 	unsigned i;
112*89c53891SMichal Simek 	u32 alignbuffer;
113*89c53891SMichal Simek 	u32 *to32ptr = (u32 *) destptr;
114*89c53891SMichal Simek 	u32 *from32ptr;
115*89c53891SMichal Simek 	u8 *to8ptr;
116*89c53891SMichal Simek 	u8 *from8ptr;
117*89c53891SMichal Simek 
118*89c53891SMichal Simek 	from32ptr = (u32 *) srcptr;
119*89c53891SMichal Simek 	while (bytecount > 3) {
120*89c53891SMichal Simek 
121*89c53891SMichal Simek 		*to32ptr++ = *from32ptr++;
122*89c53891SMichal Simek 		bytecount -= 4;
123*89c53891SMichal Simek 	}
124*89c53891SMichal Simek 
125*89c53891SMichal Simek 	alignbuffer = 0;
126*89c53891SMichal Simek 	to8ptr = (u8 *) & alignbuffer;
127*89c53891SMichal Simek 	from8ptr = (u8 *) from32ptr;
128*89c53891SMichal Simek 
129*89c53891SMichal Simek 	for (i = 0; i < bytecount; i++) {
130*89c53891SMichal Simek 		*to8ptr++ = *from8ptr++;
131*89c53891SMichal Simek 	}
132*89c53891SMichal Simek 
133*89c53891SMichal Simek 	*to32ptr++ = alignbuffer;
134*89c53891SMichal Simek }
135*89c53891SMichal Simek 
136*89c53891SMichal Simek void eth_halt (void)
137*89c53891SMichal Simek {
138*89c53891SMichal Simek 	debug ("eth_halt\n");
139*89c53891SMichal Simek }
140*89c53891SMichal Simek 
141*89c53891SMichal Simek int eth_init (bd_t * bis)
142*89c53891SMichal Simek {
143*89c53891SMichal Simek 	debug ("EmacLite Initialization Started\n");
144*89c53891SMichal Simek 	memset (&emaclite, 0, sizeof (xemaclite));
145*89c53891SMichal Simek 	emaclite.baseaddress = XILINX_EMACLITE_BASEADDR;
146*89c53891SMichal Simek 
147*89c53891SMichal Simek 	if (!getenv("ethaddr")) {
148*89c53891SMichal Simek 		memcpy(bis->bi_enetaddr, emacaddr, ENET_ADDR_LENGTH);
149*89c53891SMichal Simek 	}
150*89c53891SMichal Simek 
151*89c53891SMichal Simek /*
152*89c53891SMichal Simek  * TX - TX_PING & TX_PONG initialization
153*89c53891SMichal Simek  */
154*89c53891SMichal Simek 	/* Restart PING TX */
155*89c53891SMichal Simek 	out_be32 (emaclite.baseaddress + XEL_TSR_OFFSET, 0);
156*89c53891SMichal Simek 	/* Copy MAC address */
157*89c53891SMichal Simek 	xemaclite_alignedwrite (bis->bi_enetaddr,
158*89c53891SMichal Simek 		emaclite.baseaddress, ENET_ADDR_LENGTH);
159*89c53891SMichal Simek 	/* Set the length */
160*89c53891SMichal Simek 	out_be32 (emaclite.baseaddress + XEL_TPLR_OFFSET, ENET_ADDR_LENGTH);
161*89c53891SMichal Simek 	/* Update the MAC address in the EMAC Lite */
162*89c53891SMichal Simek 	out_be32 (emaclite.baseaddress + XEL_TSR_OFFSET, XEL_TSR_PROG_MAC_ADDR);
163*89c53891SMichal Simek 	/* Wait for EMAC Lite to finish with the MAC address update */
164*89c53891SMichal Simek 	while ((in_be32 (emaclite.baseaddress + XEL_TSR_OFFSET) &
165*89c53891SMichal Simek 		XEL_TSR_PROG_MAC_ADDR) != 0) ;
166*89c53891SMichal Simek 
167*89c53891SMichal Simek #ifdef CONFIG_XILINX_EMACLITE_TX_PING_PONG
168*89c53891SMichal Simek 	/* The same operation with PONG TX */
169*89c53891SMichal Simek 	out_be32 (emaclite.baseaddress + XEL_TSR_OFFSET + XEL_BUFFER_OFFSET, 0);
170*89c53891SMichal Simek 	xemaclite_alignedwrite (bis->bi_enetaddr, emaclite.baseaddress +
171*89c53891SMichal Simek 		XEL_BUFFER_OFFSET, ENET_ADDR_LENGTH);
172*89c53891SMichal Simek 	out_be32 (emaclite.baseaddress + XEL_TPLR_OFFSET, ENET_ADDR_LENGTH);
173*89c53891SMichal Simek 	out_be32 (emaclite.baseaddress + XEL_TSR_OFFSET + XEL_BUFFER_OFFSET,
174*89c53891SMichal Simek 		XEL_TSR_PROG_MAC_ADDR);
175*89c53891SMichal Simek 	while ((in_be32 (emaclite.baseaddress + XEL_TSR_OFFSET +
176*89c53891SMichal Simek 		XEL_BUFFER_OFFSET) & XEL_TSR_PROG_MAC_ADDR) != 0) ;
177*89c53891SMichal Simek #endif
178*89c53891SMichal Simek 
179*89c53891SMichal Simek /*
180*89c53891SMichal Simek  * RX - RX_PING & RX_PONG initialization
181*89c53891SMichal Simek  */
182*89c53891SMichal Simek 	/* Write out the value to flush the RX buffer */
183*89c53891SMichal Simek 	out_be32 (emaclite.baseaddress + XEL_RSR_OFFSET, XEL_RSR_RECV_IE_MASK);
184*89c53891SMichal Simek #ifdef CONFIG_XILINX_EMACLITE_RX_PING_PONG
185*89c53891SMichal Simek 	out_be32 (emaclite.baseaddress + XEL_RSR_OFFSET + XEL_BUFFER_OFFSET,
186*89c53891SMichal Simek 		XEL_RSR_RECV_IE_MASK);
187*89c53891SMichal Simek #endif
188*89c53891SMichal Simek 
189*89c53891SMichal Simek 	debug ("EmacLite Initialization complete\n");
190*89c53891SMichal Simek 	return 0;
191*89c53891SMichal Simek }
192*89c53891SMichal Simek 
193*89c53891SMichal Simek int xemaclite_txbufferavailable (xemaclite * instanceptr)
194*89c53891SMichal Simek {
195*89c53891SMichal Simek 	u32 reg;
196*89c53891SMichal Simek 	u32 txpingbusy;
197*89c53891SMichal Simek 	u32 txpongbusy;
198*89c53891SMichal Simek 	/*
199*89c53891SMichal Simek 	 * Read the other buffer register
200*89c53891SMichal Simek 	 * and determine if the other buffer is available
201*89c53891SMichal Simek 	 */
202*89c53891SMichal Simek 	reg = in_be32 (instanceptr->baseaddress +
203*89c53891SMichal Simek 			instanceptr->nexttxbuffertouse + 0);
204*89c53891SMichal Simek 	txpingbusy = ((reg & XEL_TSR_XMIT_BUSY_MASK) ==
205*89c53891SMichal Simek 			XEL_TSR_XMIT_BUSY_MASK);
206*89c53891SMichal Simek 
207*89c53891SMichal Simek 	reg = in_be32 (instanceptr->baseaddress +
208*89c53891SMichal Simek 			(instanceptr->nexttxbuffertouse ^ XEL_TSR_OFFSET) + 0);
209*89c53891SMichal Simek 	txpongbusy = ((reg & XEL_TSR_XMIT_BUSY_MASK) ==
210*89c53891SMichal Simek 			XEL_TSR_XMIT_BUSY_MASK);
211*89c53891SMichal Simek 
212*89c53891SMichal Simek 	return (!(txpingbusy && txpongbusy));
213*89c53891SMichal Simek }
214*89c53891SMichal Simek 
215*89c53891SMichal Simek int eth_send (volatile void *ptr, int len) {
216*89c53891SMichal Simek 
217*89c53891SMichal Simek 	unsigned int reg;
218*89c53891SMichal Simek 	unsigned int baseaddress;
219*89c53891SMichal Simek 
220*89c53891SMichal Simek 	unsigned maxtry = 1000;
221*89c53891SMichal Simek 
222*89c53891SMichal Simek 	if (len > ENET_MAX_MTU)
223*89c53891SMichal Simek 		len = ENET_MAX_MTU;
224*89c53891SMichal Simek 
225*89c53891SMichal Simek 	while (!xemaclite_txbufferavailable (&emaclite) && maxtry) {
226*89c53891SMichal Simek 		udelay (10);
227*89c53891SMichal Simek 		maxtry--;
228*89c53891SMichal Simek 	}
229*89c53891SMichal Simek 
230*89c53891SMichal Simek 	if (!maxtry) {
231*89c53891SMichal Simek 		printf ("Error: Timeout waiting for ethernet TX buffer\n");
232*89c53891SMichal Simek 		/* Restart PING TX */
233*89c53891SMichal Simek 		out_be32 (emaclite.baseaddress + XEL_TSR_OFFSET, 0);
234*89c53891SMichal Simek #ifdef CONFIG_XILINX_EMACLITE_TX_PING_PONG
235*89c53891SMichal Simek 		out_be32 (emaclite.baseaddress + XEL_TSR_OFFSET +
236*89c53891SMichal Simek 		XEL_BUFFER_OFFSET, 0);
237*89c53891SMichal Simek #endif
238*89c53891SMichal Simek 		return 0;
239*89c53891SMichal Simek 	}
240*89c53891SMichal Simek 
241*89c53891SMichal Simek 	/* Determine the expected TX buffer address */
242*89c53891SMichal Simek 	baseaddress = (emaclite.baseaddress + emaclite.nexttxbuffertouse);
243*89c53891SMichal Simek 
244*89c53891SMichal Simek 	/* Determine if the expected buffer address is empty */
245*89c53891SMichal Simek 	reg = in_be32 (baseaddress + XEL_TSR_OFFSET);
246*89c53891SMichal Simek 	if (((reg & XEL_TSR_XMIT_BUSY_MASK) == 0)
247*89c53891SMichal Simek 		&& ((in_be32 ((baseaddress) + XEL_TSR_OFFSET)
248*89c53891SMichal Simek 			& XEL_TSR_XMIT_ACTIVE_MASK) == 0)) {
249*89c53891SMichal Simek 
250*89c53891SMichal Simek #ifdef CONFIG_XILINX_EMACLITE_TX_PING_PONG
251*89c53891SMichal Simek 		emaclite.nexttxbuffertouse ^= XEL_BUFFER_OFFSET;
252*89c53891SMichal Simek #endif
253*89c53891SMichal Simek 		debug ("Send packet from 0x%x\n", baseaddress);
254*89c53891SMichal Simek 		/* Write the frame to the buffer */
255*89c53891SMichal Simek 		xemaclite_alignedwrite ((void *) ptr, baseaddress, len);
256*89c53891SMichal Simek 		out_be32 (baseaddress + XEL_TPLR_OFFSET,(len &
257*89c53891SMichal Simek 			(XEL_TPLR_LENGTH_MASK_HI | XEL_TPLR_LENGTH_MASK_LO)));
258*89c53891SMichal Simek 		reg = in_be32 (baseaddress + XEL_TSR_OFFSET);
259*89c53891SMichal Simek 		reg |= XEL_TSR_XMIT_BUSY_MASK;
260*89c53891SMichal Simek 		if ((reg & XEL_TSR_XMIT_IE_MASK) != 0) {
261*89c53891SMichal Simek 			reg |= XEL_TSR_XMIT_ACTIVE_MASK;
262*89c53891SMichal Simek 		}
263*89c53891SMichal Simek 		out_be32 (baseaddress + XEL_TSR_OFFSET, reg);
264*89c53891SMichal Simek 		return 1;
265*89c53891SMichal Simek 	}
266*89c53891SMichal Simek #ifdef CONFIG_XILINX_EMACLITE_TX_PING_PONG
267*89c53891SMichal Simek 	/* Switch to second buffer */
268*89c53891SMichal Simek 	baseaddress ^= XEL_BUFFER_OFFSET;
269*89c53891SMichal Simek 	/* Determine if the expected buffer address is empty */
270*89c53891SMichal Simek 	reg = in_be32 (baseaddress + XEL_TSR_OFFSET);
271*89c53891SMichal Simek 	if (((reg & XEL_TSR_XMIT_BUSY_MASK) == 0)
272*89c53891SMichal Simek 		&& ((in_be32 ((baseaddress) + XEL_TSR_OFFSET)
273*89c53891SMichal Simek 			& XEL_TSR_XMIT_ACTIVE_MASK) == 0)) {
274*89c53891SMichal Simek 		debug ("Send packet from 0x%x\n", baseaddress);
275*89c53891SMichal Simek 		/* Write the frame to the buffer */
276*89c53891SMichal Simek 		xemaclite_alignedwrite ((void *) ptr, baseaddress, len);
277*89c53891SMichal Simek 		out_be32 (baseaddress + XEL_TPLR_OFFSET,(len &
278*89c53891SMichal Simek 			(XEL_TPLR_LENGTH_MASK_HI | XEL_TPLR_LENGTH_MASK_LO)));
279*89c53891SMichal Simek 		reg = in_be32 (baseaddress + XEL_TSR_OFFSET);
280*89c53891SMichal Simek 		reg |= XEL_TSR_XMIT_BUSY_MASK;
281*89c53891SMichal Simek 		if ((reg & XEL_TSR_XMIT_IE_MASK) != 0) {
282*89c53891SMichal Simek 			reg |= XEL_TSR_XMIT_ACTIVE_MASK;
283*89c53891SMichal Simek 		}
284*89c53891SMichal Simek 		out_be32 (baseaddress + XEL_TSR_OFFSET, reg);
285*89c53891SMichal Simek 		return 1;
286*89c53891SMichal Simek 	}
287*89c53891SMichal Simek #endif
288*89c53891SMichal Simek 	puts ("Error while sending frame\n");
289*89c53891SMichal Simek 	return 0;
290*89c53891SMichal Simek }
291*89c53891SMichal Simek 
292*89c53891SMichal Simek int eth_rx (void)
293*89c53891SMichal Simek {
294*89c53891SMichal Simek 	unsigned int length;
295*89c53891SMichal Simek 	unsigned int reg;
296*89c53891SMichal Simek 	unsigned int baseaddress;
297*89c53891SMichal Simek 
298*89c53891SMichal Simek 	baseaddress = emaclite.baseaddress + emaclite.nextrxbuffertouse;
299*89c53891SMichal Simek 	reg = in_be32 (baseaddress + XEL_RSR_OFFSET);
300*89c53891SMichal Simek 	debug ("Testing data at address 0x%x\n", baseaddress);
301*89c53891SMichal Simek 	if ((reg & XEL_RSR_RECV_DONE_MASK) == XEL_RSR_RECV_DONE_MASK) {
302*89c53891SMichal Simek #ifdef CONFIG_XILINX_EMACLITE_RX_PING_PONG
303*89c53891SMichal Simek 		emaclite.nextrxbuffertouse ^= XEL_BUFFER_OFFSET;
304*89c53891SMichal Simek #endif
305*89c53891SMichal Simek 	} else {
306*89c53891SMichal Simek #ifndef CONFIG_XILINX_EMACLITE_RX_PING_PONG
307*89c53891SMichal Simek 		debug ("No data was available - address 0x%x\n", baseaddress);
308*89c53891SMichal Simek 		return 0;
309*89c53891SMichal Simek #else
310*89c53891SMichal Simek 		baseaddress ^= XEL_BUFFER_OFFSET;
311*89c53891SMichal Simek 		reg = in_be32 (baseaddress + XEL_RSR_OFFSET);
312*89c53891SMichal Simek 		if ((reg & XEL_RSR_RECV_DONE_MASK) !=
313*89c53891SMichal Simek 					XEL_RSR_RECV_DONE_MASK) {
314*89c53891SMichal Simek 			debug ("No data was available - address 0x%x\n",
315*89c53891SMichal Simek 					baseaddress);
316*89c53891SMichal Simek 			return 0;
317*89c53891SMichal Simek 		}
318*89c53891SMichal Simek #endif
319*89c53891SMichal Simek 	}
320*89c53891SMichal Simek 	/* Get the length of the frame that arrived */
321*89c53891SMichal Simek 	switch(((in_be32 (baseaddress + XEL_RXBUFF_OFFSET + 0xC)) &
322*89c53891SMichal Simek 			0xFFFF0000 ) >> 16) {
323*89c53891SMichal Simek 		case 0x806:
324*89c53891SMichal Simek 			length = 42 + 20; /* FIXME size of ARP */
325*89c53891SMichal Simek 			debug ("ARP Packet\n");
326*89c53891SMichal Simek 			break;
327*89c53891SMichal Simek 		case 0x800:
328*89c53891SMichal Simek 			length = 14 + 14 +
329*89c53891SMichal Simek 			(((in_be32 (baseaddress + XEL_RXBUFF_OFFSET + 0x10)) &
330*89c53891SMichal Simek 			0xFFFF0000) >> 16); /* FIXME size of IP packet */
331*89c53891SMichal Simek 			debug ("IP Packet\n");
332*89c53891SMichal Simek 			break;
333*89c53891SMichal Simek 		default:
334*89c53891SMichal Simek 			debug ("Other Packet\n");
335*89c53891SMichal Simek 			length = ENET_MAX_MTU;
336*89c53891SMichal Simek 			break;
337*89c53891SMichal Simek 	}
338*89c53891SMichal Simek 
339*89c53891SMichal Simek 	xemaclite_alignedread ((u32 *) (baseaddress + XEL_RXBUFF_OFFSET),
340*89c53891SMichal Simek 			etherrxbuff, length);
341*89c53891SMichal Simek 
342*89c53891SMichal Simek 	/* Acknowledge the frame */
343*89c53891SMichal Simek 	reg = in_be32 (baseaddress + XEL_RSR_OFFSET);
344*89c53891SMichal Simek 	reg &= ~XEL_RSR_RECV_DONE_MASK;
345*89c53891SMichal Simek 	out_be32 (baseaddress + XEL_RSR_OFFSET, reg);
346*89c53891SMichal Simek 
347*89c53891SMichal Simek 	debug ("Packet receive from 0x%x, length %dB\n", baseaddress, length);
348*89c53891SMichal Simek 	NetReceive ((uchar *) etherrxbuff, length);
349*89c53891SMichal Simek 	return 1;
350*89c53891SMichal Simek 
351*89c53891SMichal Simek }
352