Update QCA956x GPIO OUT functions list
[oweals/u-boot_mod.git] / u-boot / net / eth.c
1 /*
2  * (C) Copyright 2001-2004
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 #include <common.h>
25 #include <command.h>
26 #include <net.h>
27 #include <miiphy.h>
28
29 #if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI)
30
31 #if defined(CONFIG_ATHEROS)
32         extern int ath_gmac_enet_initialize(bd_t * bis);
33 #else
34         extern int ag7240_enet_initialize(bd_t * bis);
35 #endif
36
37 /*
38 static struct eth_device *eth_devices, *eth_current;
39
40 struct eth_device *eth_get_dev(void){
41         return eth_current;
42 }
43 */
44
45 static struct eth_device *eth_devices;
46 struct eth_device *eth_current;
47
48
49 struct eth_device *eth_get_dev_by_name(char *devname){
50         struct eth_device *dev, *target_dev;
51
52         if(!eth_devices){
53                 return NULL;
54         }
55
56         dev = eth_devices;
57         target_dev = NULL;
58
59         do {
60                 if(strcmp(devname, dev->name) == 0){
61                         target_dev = dev;
62                         break;
63                 }
64                 dev = dev->next;
65         } while(dev != eth_devices);
66
67         return(target_dev);
68 }
69
70 int eth_get_dev_index(void){
71         struct eth_device *dev;
72         int num = 0;
73
74         if (!eth_devices){
75                 return(-1);
76         }
77
78         for(dev = eth_devices; dev; dev = dev->next){
79                 if(dev == eth_current){
80                         break;
81                 }
82                 ++num;
83         }
84
85         if(dev){
86                 return(num);
87         }
88
89         return(0);
90 }
91
92 int eth_register(struct eth_device* dev){
93         struct eth_device *d;
94
95         if(!eth_devices){
96                 eth_current = eth_devices = dev;
97 #ifdef CONFIG_NET_MULTI
98                 /* update current ethernet name */
99                 char *act = getenv("ethact");
100                 if(act == NULL || strcmp(act, eth_current->name) != 0){
101                         setenv("ethact", eth_current->name);
102                 }
103 #endif
104         } else {
105                 for (d = eth_devices; d->next != eth_devices; d = d->next);
106                 d->next = dev;
107         }
108
109         dev->state = ETH_STATE_INIT;
110         dev->next = eth_devices;
111
112         return(0);
113 }
114
115 int eth_initialize(bd_t *bis){
116         char enetvar[32];
117         int i, eth_number = 0;
118         char *tmp = NULL, *end = NULL;
119
120         eth_devices = NULL;
121         eth_current = NULL;
122
123 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
124         miiphy_init();
125 #endif
126
127         // ag7240 initialization
128 #if defined(CONFIG_ATHEROS)
129         ath_gmac_enet_initialize(bis);
130 #else
131         ag7240_enet_initialize(bis);
132 #endif
133
134         if(!eth_devices){
135                 printf_err("no ethernet found\n");
136         } else {
137                 struct eth_device *dev = eth_devices;
138                 char *ethprime = getenv("ethprime");
139
140                 do {
141                         /*
142                         if (eth_number) {
143                                 puts(", ");
144                         }
145
146                         printf("%s", dev->name);
147                         */
148
149                         if(ethprime && strcmp(dev->name, ethprime) == 0){
150                                 eth_current = dev;
151                                 //puts(" [PRIME]");
152                         }
153
154                         sprintf(enetvar, eth_number ? "eth%daddr" : "ethaddr", eth_number);
155                         tmp = getenv(enetvar);
156
157                         for(i = 0; i < 6; i++){
158                                 if(tmp){
159                                         tmp = (*end) ? end + 1 : end;
160                                 }
161                         }
162
163                         eth_number++;
164                         dev = dev->next;
165
166                 } while(dev != eth_devices);
167
168 #ifdef CONFIG_NET_MULTI
169                 /* update current ethernet name */
170                 if(eth_current){
171                         char *act = getenv("ethact");
172                         if(act == NULL || strcmp(act, eth_current->name) != 0){
173                                 setenv("ethact", eth_current->name);
174                         }
175                 } else {
176                         setenv("ethact", NULL);
177                 }
178 #endif
179
180                 //putc('\n');
181         }
182
183         return(eth_number);
184 }
185
186 void eth_set_enetaddr(int num, char *addr){
187         struct eth_device *dev;
188         unsigned char enetaddr[6];
189         char *end;
190         int i;
191
192         //debug("eth_set_enetaddr(num=%d, addr=%s)\n", num, addr);
193
194         if(!eth_devices){
195                 return;
196         }
197
198         for(i = 0; i < 6; i++){
199                 enetaddr[i] = addr ? simple_strtoul(addr, &end, 16) : 0;
200                 if (addr){
201                         addr = (*end) ? end + 1 : end;
202                 }
203         }
204
205         dev = eth_devices;
206         while(num-- > 0){
207                 dev = dev->next;
208
209                 if(dev == eth_devices){
210                         return;
211                 }
212         }
213
214         //debug("Setting new HW address on %s\nNew Address is %02X:%02X:%02X:%02X:%02X:%02X\n", dev->name, enetaddr[0], enetaddr[1], enetaddr[2], enetaddr[3], enetaddr[4], enetaddr[5]);
215         memcpy(dev->enetaddr, enetaddr, 6);
216 }
217
218 int eth_init(bd_t *bis){
219         struct eth_device* old_current;
220
221         if (!eth_current){
222                 return(0);
223         }
224
225         old_current = eth_current;
226
227         do {
228 #if !defined(CFG_ATHRS26_PHY) && !defined(CFG_ATHRHDR_EN)
229                 //debug("Trying %s\n", eth_current->name);
230 #endif
231                 if(eth_current->init(eth_current, bis)){
232                         eth_current->state = ETH_STATE_ACTIVE;
233                         return(1);
234                 }
235
236                 //debug("FAIL\n");
237
238                 eth_try_another(0);
239         } while(old_current != eth_current);
240
241         return(0);
242 }
243
244 void eth_halt(void){
245         if(!eth_current){
246                 return;
247         }
248
249         eth_current->halt(eth_current);
250         eth_current->state = ETH_STATE_PASSIVE;
251 }
252
253 int eth_send(volatile void *packet, int length){
254         if(!eth_current){
255                 return(-1);
256         }
257
258         return(eth_current->send(eth_current, packet, length));
259 }
260
261 int eth_rx(void){
262         if(!eth_current){
263                 return(-1);
264         }
265
266         return(eth_current->recv(eth_current));
267 }
268
269 void eth_try_another(int first_restart){
270         static struct eth_device *first_failed = NULL;
271
272         if(!eth_current){
273                 return;
274         }
275
276         if(first_restart){
277                 first_failed = eth_current;
278         }
279
280         eth_current = eth_current->next;
281
282 #ifdef CONFIG_NET_MULTI
283         /* update current ethernet name */
284         char *act = getenv("ethact");
285         if(act == NULL || strcmp(act, eth_current->name) != 0){
286                 setenv("ethact", eth_current->name);
287         }
288 #endif
289
290         if (first_failed == eth_current){
291                 NetRestartWrap = 1;
292         }
293 }
294
295 #ifdef CONFIG_NET_MULTI
296 void eth_set_current(void){
297
298         char *act;
299         struct eth_device* old_current;
300
301         if (!eth_current){
302                 return;
303         }
304
305         act = getenv("ethact");
306
307         if(act != NULL){
308                 old_current = eth_current;
309                 do {
310                         if(strcmp(eth_current->name, act) == 0){
311                                 return;
312                         }
313                         eth_current = eth_current->next;
314                 } while(old_current != eth_current);
315         }
316
317         setenv("ethact", eth_current->name);
318 }
319 #endif
320
321 char *eth_get_name(void){
322         return(eth_current ? eth_current->name : "unknown");
323 }
324 #elif defined(CONFIG_CMD_NET) && !defined(CONFIG_NET_MULTI)
325
326 int eth_initialize(bd_t *bis){
327 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
328         miiphy_init();
329 #endif
330         return 0;
331 }
332 #endif