xref: /rk3399_rockchip-uboot/drivers/net/cs8900.c (revision 2439e4bfa111babf4bc07ba20efbf3e36036813e)
1*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
2*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * Cirrus Logic CS8900A Ethernet
3*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  *
4*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * (C) 2003 Wolfgang Denk, wd@denx.de
5*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  *     Extension to synchronize ethaddr environment variable
6*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  *     against value in EEPROM
7*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  *
8*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * (C) Copyright 2002
9*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
10*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * Marius Groeger <mgroeger@sysgo.de>
11*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  *
12*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * Copyright (C) 1999 Ben Williamson <benw@pobox.com>
13*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  *
14*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * See file CREDITS for list of people who contributed to this
15*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * project.
16*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  *
17*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * This program is loaded into SRAM in bootstrap mode, where it waits
18*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * for commands on UART1 to read and write memory, jump to code etc.
19*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * A design goal for this program is to be entirely independent of the
20*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * target board.  Anything with a CL-PS7111 or EP7211 should be able to run
21*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * this code in bootstrap mode.  All the board specifics can be handled on
22*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * the host.
23*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  *
24*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * This program is free software; you can redistribute it and/or modify
25*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * it under the terms of the GNU General Public License as published by
26*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * the Free Software Foundation; either version 2 of the License, or
27*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * (at your option) any later version.
28*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  *
29*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * This program is distributed in the hope that it will be useful,
30*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * but WITHOUT ANY WARRANTY; without even the implied warranty of
31*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
32*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * GNU General Public License for more details.
33*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  *
34*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * You should have received a copy of the GNU General Public License
35*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * along with this program; if not, write to the Free Software
36*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
37*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  */
38*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
39*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <common.h>
40*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <command.h>
41*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #include "cs8900.h"
42*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <net.h>
43*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
44*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_DRIVER_CS8900
45*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
46*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if defined(CONFIG_CMD_NET)
47*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
48*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #undef DEBUG
49*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
50*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* packet page register access functions */
51*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
52*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CS8900_BUS32
53*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* we don't need 16 bit initialisation on 32 bit bus */
54*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define get_reg_init_bus(x) get_reg((x))
55*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #else
56*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static unsigned short get_reg_init_bus (int regno)
57*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
58*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* force 16 bit busmode */
59*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	volatile unsigned char c;
60*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
61*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	c = CS8900_BUS16_0;
62*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	c = CS8900_BUS16_1;
63*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	c = CS8900_BUS16_0;
64*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	c = CS8900_BUS16_1;
65*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	c = CS8900_BUS16_0;
66*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
67*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	CS8900_PPTR = regno;
68*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return (unsigned short) CS8900_PDATA;
69*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
70*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
71*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
72*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static unsigned short get_reg (int regno)
73*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
74*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	CS8900_PPTR = regno;
75*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return (unsigned short) CS8900_PDATA;
76*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
77*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
78*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
79*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void put_reg (int regno, unsigned short val)
80*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
81*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	CS8900_PPTR = regno;
82*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	CS8900_PDATA = val;
83*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
84*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
85*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void eth_reset (void)
86*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
87*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int tmo;
88*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	unsigned short us;
89*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
90*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* reset NIC */
91*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	put_reg (PP_SelfCTL, get_reg (PP_SelfCTL) | PP_SelfCTL_Reset);
92*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
93*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* wait for 200ms */
94*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	udelay (200000);
95*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Wait until the chip is reset */
96*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
97*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	tmo = get_timer (0) + 1 * CFG_HZ;
98*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	while ((((us = get_reg_init_bus (PP_SelfSTAT)) & PP_SelfSTAT_InitD) == 0)
99*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		   && tmo < get_timer (0))
100*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/*NOP*/;
101*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
102*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
103*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void eth_reginit (void)
104*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
105*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* receive only error free packets addressed to this card */
106*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	put_reg (PP_RxCTL, PP_RxCTL_IA | PP_RxCTL_Broadcast | PP_RxCTL_RxOK);
107*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* do not generate any interrupts on receive operations */
108*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	put_reg (PP_RxCFG, 0);
109*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* do not generate any interrupts on transmit operations */
110*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	put_reg (PP_TxCFG, 0);
111*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* do not generate any interrupts on buffer operations */
112*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	put_reg (PP_BufCFG, 0);
113*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* enable transmitter/receiver mode */
114*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	put_reg (PP_LineCTL, PP_LineCTL_Rx | PP_LineCTL_Tx);
115*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
116*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
117*2439e4bfSJean-Christophe PLAGNIOL-VILLARD void cs8900_get_enetaddr (uchar * addr)
118*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
119*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int i;
120*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	unsigned char env_enetaddr[6];
121*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	char *tmp = getenv ("ethaddr");
122*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	char *end;
123*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
124*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for (i=0; i<6; i++) {
125*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		env_enetaddr[i] = tmp ? simple_strtoul(tmp, &end, 16) : 0;
126*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (tmp)
127*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			tmp = (*end) ? end+1 : end;
128*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
129*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
130*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* verify chip id */
131*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if (get_reg_init_bus (PP_ChipID) != 0x630e)
132*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		return;
133*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	eth_reset ();
134*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if ((get_reg (PP_SelfST) & (PP_SelfSTAT_EEPROM | PP_SelfSTAT_EEPROM_OK)) ==
135*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			(PP_SelfSTAT_EEPROM | PP_SelfSTAT_EEPROM_OK)) {
136*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
137*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* Load the MAC from EEPROM */
138*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		for (i = 0; i < 6 / 2; i++) {
139*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			unsigned int Addr;
140*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
141*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			Addr = get_reg (PP_IA + i * 2);
142*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			addr[i * 2] = Addr & 0xFF;
143*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			addr[i * 2 + 1] = Addr >> 8;
144*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		}
145*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
146*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (memcmp(env_enetaddr, "\0\0\0\0\0\0", 6) != 0 &&
147*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		    memcmp(env_enetaddr, addr, 6) != 0) {
148*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			printf ("\nWarning: MAC addresses don't match:\n");
149*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			printf ("\tHW MAC address:  "
150*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 				"%02X:%02X:%02X:%02X:%02X:%02X\n",
151*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 				addr[0], addr[1],
152*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 				addr[2], addr[3],
153*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 				addr[4], addr[5] );
154*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			printf ("\t\"ethaddr\" value: "
155*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 				"%02X:%02X:%02X:%02X:%02X:%02X\n",
156*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 				env_enetaddr[0], env_enetaddr[1],
157*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 				env_enetaddr[2], env_enetaddr[3],
158*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 				env_enetaddr[4], env_enetaddr[5]) ;
159*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			debug ("### Set MAC addr from environment\n");
160*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			memcpy (addr, env_enetaddr, 6);
161*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		}
162*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (!tmp) {
163*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			char ethaddr[20];
164*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			sprintf (ethaddr, "%02X:%02X:%02X:%02X:%02X:%02X",
165*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 				 addr[0], addr[1],
166*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 				 addr[2], addr[3],
167*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 				 addr[4], addr[5]) ;
168*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			debug ("### Set environment from HW MAC addr = \"%s\"\n",				ethaddr);
169*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			setenv ("ethaddr", ethaddr);
170*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		}
171*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
172*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
173*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
174*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
175*2439e4bfSJean-Christophe PLAGNIOL-VILLARD void eth_halt (void)
176*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
177*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* disable transmitter/receiver mode */
178*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	put_reg (PP_LineCTL, 0);
179*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
180*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* "shutdown" to show ChipID or kernel wouldn't find he cs8900 ... */
181*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	get_reg_init_bus (PP_ChipID);
182*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
183*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
184*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int eth_init (bd_t * bd)
185*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
186*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
187*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* verify chip id */
188*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if (get_reg_init_bus (PP_ChipID) != 0x630e) {
189*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		printf ("CS8900 Ethernet chip not found?!\n");
190*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		return 0;
191*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
192*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
193*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	eth_reset ();
194*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* set the ethernet address */
195*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	put_reg (PP_IA + 0, bd->bi_enetaddr[0] | (bd->bi_enetaddr[1] << 8));
196*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	put_reg (PP_IA + 2, bd->bi_enetaddr[2] | (bd->bi_enetaddr[3] << 8));
197*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	put_reg (PP_IA + 4, bd->bi_enetaddr[4] | (bd->bi_enetaddr[5] << 8));
198*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
199*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	eth_reginit ();
200*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return 0;
201*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
202*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
203*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Get a data block via Ethernet */
204*2439e4bfSJean-Christophe PLAGNIOL-VILLARD extern int eth_rx (void)
205*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
206*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int i;
207*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	unsigned short rxlen;
208*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	unsigned short *addr;
209*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	unsigned short status;
210*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
211*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	status = get_reg (PP_RER);
212*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
213*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if ((status & PP_RER_RxOK) == 0)
214*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		return 0;
215*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
216*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	status = CS8900_RTDATA;		/* stat */
217*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	rxlen = CS8900_RTDATA;		/* len */
218*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
219*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG
220*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if (rxlen > PKTSIZE_ALIGN + PKTALIGN)
221*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		printf ("packet too big!\n");
222*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
223*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for (addr = (unsigned short *) NetRxPackets[0], i = rxlen >> 1; i > 0;
224*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		 i--)
225*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		*addr++ = CS8900_RTDATA;
226*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if (rxlen & 1)
227*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		*addr++ = CS8900_RTDATA;
228*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
229*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Pass the packet up to the protocol layers. */
230*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	NetReceive (NetRxPackets[0], rxlen);
231*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
232*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return rxlen;
233*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
234*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
235*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Send a data block via Ethernet. */
236*2439e4bfSJean-Christophe PLAGNIOL-VILLARD extern int eth_send (volatile void *packet, int length)
237*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
238*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	volatile unsigned short *addr;
239*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int tmo;
240*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	unsigned short s;
241*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
242*2439e4bfSJean-Christophe PLAGNIOL-VILLARD retry:
243*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* initiate a transmit sequence */
244*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	CS8900_TxCMD = PP_TxCmd_TxStart_Full;
245*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	CS8900_TxLEN = length;
246*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
247*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Test to see if the chip has allocated memory for the packet */
248*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if ((get_reg (PP_BusSTAT) & PP_BusSTAT_TxRDY) == 0) {
249*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* Oops... this should not happen! */
250*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG
251*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		printf ("cs: unable to send packet; retrying...\n");
252*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
253*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		for (tmo = get_timer (0) + 5 * CFG_HZ; get_timer (0) < tmo;)
254*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			/*NOP*/;
255*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		eth_reset ();
256*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		eth_reginit ();
257*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		goto retry;
258*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
259*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
260*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Write the contents of the packet */
261*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* assume even number of bytes */
262*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for (addr = packet; length > 0; length -= 2)
263*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		CS8900_RTDATA = *addr++;
264*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
265*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* wait for transfer to succeed */
266*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	tmo = get_timer (0) + 5 * CFG_HZ;
267*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	while ((s = get_reg (PP_TER) & ~0x1F) == 0) {
268*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (get_timer (0) >= tmo)
269*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			break;
270*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
271*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
272*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* nothing */ ;
273*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if ((s & (PP_TER_CRS | PP_TER_TxOK)) != PP_TER_TxOK) {
274*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG
275*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		printf ("\ntransmission error %#x\n", s);
276*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
277*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
278*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
279*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return 0;
280*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
281*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
282*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void cs8900_e2prom_ready(void)
283*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
284*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	while(get_reg(PP_SelfST) & SI_BUSY);
285*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
286*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
287*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /***********************************************************/
288*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* read a 16-bit word out of the EEPROM                    */
289*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /***********************************************************/
290*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
291*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int cs8900_e2prom_read(unsigned char addr, unsigned short *value)
292*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
293*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	cs8900_e2prom_ready();
294*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	put_reg(PP_EECMD, EEPROM_READ_CMD | addr);
295*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	cs8900_e2prom_ready();
296*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	*value = get_reg(PP_EEData);
297*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
298*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return 0;
299*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
300*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
301*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
302*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /***********************************************************/
303*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* write a 16-bit word into the EEPROM                     */
304*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /***********************************************************/
305*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
306*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int cs8900_e2prom_write(unsigned char addr, unsigned short value)
307*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
308*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	cs8900_e2prom_ready();
309*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	put_reg(PP_EECMD, EEPROM_WRITE_EN);
310*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	cs8900_e2prom_ready();
311*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	put_reg(PP_EEData, value);
312*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	put_reg(PP_EECMD, EEPROM_WRITE_CMD | addr);
313*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	cs8900_e2prom_ready();
314*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	put_reg(PP_EECMD, EEPROM_WRITE_DIS);
315*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	cs8900_e2prom_ready();
316*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
317*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return 0;
318*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
319*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
320*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif	/* COMMANDS & CFG_NET */
321*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
322*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif	/* CONFIG_DRIVER_CS8900 */
323