Ticket #731: network.c

File network.c, 36.0 KB (added by yanjun.luo, on Dec 3, 2006 at 1:31:12 PM)

network.c

Line 
1/*
2*  AT91RM9200 ethernet driver
3*
4*  Copyright (c) 2003 by Cogent Computer Systems
5*  Written by Mike Kelly <mike@cogcomp.com>
6*         and Jay Monkman <jtm@lopingdog.com>
7*  Ported by Luo Yanjun <linux_arm_kernel@yahoo.com>
8*
9*  $Id$
10*/
11
12#include <rtems.h>
13#include <rtems/rtems_bsdnet.h>
14#include <at91rm9200.h>
15#include <at91rm9200_emac.h>
16
17#include <dm9161.h>
18
19#include <stdio.h>
20#include <string.h>
21
22#include <errno.h>
23#include <rtems/error.h>
24
25#include <sys/param.h>
26#include <sys/mbuf.h>
27#include <sys/socket.h>
28#include <sys/sockio.h>
29
30#include <net/if.h>
31
32#include <netinet/in.h>
33#include <netinet/if_ether.h>
34
35#include <irq.h>
36
37typedef unsigned char UCHAR;
38
39#define PHY_WAIT        100
40
41typedef volatile unsigned int AT91_REG;/* Hardware register definition */
42
43#define AT91C_PIOA_PDR  ((AT91_REG *)   0xFFFFF404) /* (PIOA) PIO Disable Register */
44
45#define AT91C_PIO_PA30          ((unsigned int) 1 << 30) /* Pin Controlled by PA30 */
46#define AT91C_PIO_PC0           ((unsigned int) 1 <<  0) /* Pin Controlled by PC0 */
47#define AT91C_PC0_BFCK          ((unsigned int) AT91C_PIO_PC0) /*  Burst Flash Clock */
48#define AT91C_PA30_DRXD         ((unsigned int) AT91C_PIO_PA30) /*  DBGU Debug Receive Data */
49#define AT91C_PIO_PA31          ((unsigned int) 1 << 31) /* Pin Controlled by PA31 */
50#define AT91C_PA31_DTXD         ((unsigned int) AT91C_PIO_PA31) /*  DBGU Debug Transmit Data */
51
52#define AT91C_ID_SYS            ((unsigned int)  1) /* System Peripheral */
53#define AT91C_ID_TC0            ((unsigned int) 17) /* Timer Counter 0 */
54#define AT91C_ID_EMAC           ((unsigned int) 24) /* Ethernet MAC */
55#define AT91C_ID_SPI            ((unsigned int) 13) /* Serial Peripheral Interface */
56
57#define AT91C_PIO_PC1           ((unsigned int) 1 <<  1) /* Pin Controlled by PC1 */
58#define AT91C_PC1_BFRDY_SMOE    ((unsigned int) AT91C_PIO_PC1) /*  Burst Flash Ready */
59#define AT91C_PIO_PC3           ((unsigned int) 1 <<  3) /* Pin Controlled by PC3 */
60#define AT91C_PC3_BFBAA_SMWE    ((unsigned int) AT91C_PIO_PC3) /*  Burst Flash Address Advance / SmartMedia Write Enable */
61#define AT91C_PIO_PC2           ((unsigned int) 1 <<  2) /* Pin Controlled by PC2 */
62#define AT91C_PC2_BFAVD         ((unsigned int) AT91C_PIO_PC2) /*  Burst Flash Address Valid */
63#define AT91C_PIO_PB1           ((unsigned int) 1 <<  1) /* Pin Controlled by PB1 */
64
65#define AT91C_PIO_PA23          ((unsigned int) 1 << 23) /* Pin Controlled by PA23 */
66#define AT91C_PA23_TXD2         ((unsigned int) AT91C_PIO_PA23) /* USART 2 Transmit Data */
67
68#define AT91C_PIO_PA0           ((unsigned int) 1 <<  0) /* Pin Controlled by PA0 */
69#define AT91C_PA0_MISO          ((unsigned int) AT91C_PIO_PA0) /* SPI Master In Slave */
70#define AT91C_PIO_PA1           ((unsigned int) 1 <<  1) /* Pin Controlled by PA1 */
71#define AT91C_PA1_MOSI          ((unsigned int) AT91C_PIO_PA1) /* SPI Master Out Slave */
72#define AT91C_PIO_PA2           ((unsigned int) 1 <<  2) /* Pin Controlled by PA2 */
73#define AT91C_PA2_SPCK          ((unsigned int) AT91C_PIO_PA2) /* SPI Serial Clock */
74#define AT91C_PIO_PA3           ((unsigned int) 1 <<  3) /* Pin Controlled by PA3 */
75#define AT91C_PA3_NPCS0         ((unsigned int) AT91C_PIO_PA3) /* SPI Peripheral Chip Select 0 */
76#define AT91C_PIO_PA4           ((unsigned int) 1 <<  4) /* Pin Controlled by PA4 */
77#define AT91C_PA4_NPCS1         ((unsigned int) AT91C_PIO_PA4) /* SPI Peripheral Chip Select 1 */
78#define AT91C_PIO_PA5           ((unsigned int) 1 <<  5) /* Pin Controlled by PA5 */
79#define AT91C_PA5_NPCS2         ((unsigned int) AT91C_PIO_PA5) /* SPI Peripheral Chip Select 2 */
80#define AT91C_PIO_PA6           ((unsigned int) 1 <<  6) /* Pin Controlled by PA6 */
81#define AT91C_PA6_NPCS3         ((unsigned int) AT91C_PIO_PA6) /* SPI Peripheral Chip Select 3 */
82
83
84#define AT91C_PIO_PA16          ((unsigned int) 1 << 16) /* Pin Controlled by PA16 */
85#define AT91C_PA16_EMDIO        ((unsigned int) AT91C_PIO_PA16) /*  Ethernet MAC Management Data Input/Output */
86#define AT91C_PIO_PA15          ((unsigned int) 1 << 15) /* Pin Controlled by PA15 */
87#define AT91C_PA15_EMDC         ((unsigned int) AT91C_PIO_PA15) /*  Ethernet MAC Management Data Clock */
88#define AT91C_PIO_PA14          ((unsigned int) 1 << 14) /* Pin Controlled by PA14 */
89#define AT91C_PA14_ERXER        ((unsigned int) AT91C_PIO_PA14) /*  Ethernet MAC Receive Error */
90#define AT91C_PIO_PA13          ((unsigned int) 1 << 13) /* Pin Controlled by PA13 */
91#define AT91C_PA13_ERX1         ((unsigned int) AT91C_PIO_PA13) /*  Ethernet MAC Receive Data 1 */
92#define AT91C_PIO_PA12          ((unsigned int) 1 << 12) /* Pin Controlled by PA12 */
93#define AT91C_PA12_ERX0         ((unsigned int) AT91C_PIO_PA12) /*  Ethernet MAC Receive Data 0 */
94#define AT91C_PIO_PA11          ((unsigned int) 1 << 11) /* Pin Controlled by PA11 */
95#define AT91C_PA11_ECRS_ECRSDV  ((unsigned int) AT91C_PIO_PA11) /*  Ethernet MAC Carrier Sense/Carrier Sense and Data Valid */
96#define AT91C_PIO_PA10          ((unsigned int) 1 << 10) /* Pin Controlled by PA10 */
97#define AT91C_PA10_ETX1         ((unsigned int) AT91C_PIO_PA10) /*  Ethernet MAC Transmit Data 1 */
98#define AT91C_PIO_PA9           ((unsigned int) 1 <<  9) /* Pin Controlled by PA9 */
99#define AT91C_PA9_ETX0          ((unsigned int) AT91C_PIO_PA9) /*  Ethernet MAC Transmit Data 0 */
100#define AT91C_PIO_PA8           ((unsigned int) 1 <<  8) /* Pin Controlled by PA8 */
101#define AT91C_PA8_ETXEN         ((unsigned int) AT91C_PIO_PA8) /*  Ethernet MAC Transmit Enable */
102#define AT91C_PIO_PA7           ((unsigned int) 1 <<  7) /* Pin Controlled by PA7 */
103#define AT91C_PA7_ETXCK_EREFCK  ((unsigned int) AT91C_PIO_PA7) /*  Ethernet MAC Transmit Clock/Reference Clock */
104
105#define AT91C_PIO_PB7           ((unsigned int) 1 <<  7) /* Pin Controlled by PB7 */
106#define AT91C_PIO_PB25          ((unsigned int) 1 << 25) /* Pin Controlled by PB25 */
107#define AT91C_PB25_DSR1         ((unsigned int) AT91C_PIO_PB25) /*  USART 1 Data Set ready */
108#define AT91C_PB25_EF100        ((unsigned int) AT91C_PIO_PB25) /*  Ethernet MAC Force 100 Mbits */
109#define AT91C_PIO_PB19          ((unsigned int) 1 << 19) /* Pin Controlled by PB19 */
110#define AT91C_PB19_DTR1         ((unsigned int) AT91C_PIO_PB19) /*  USART 1 Data Terminal ready */
111#define AT91C_PB19_ERXCK        ((unsigned int) AT91C_PIO_PB19) /*  Ethernet MAC Receive Clock */
112#define AT91C_PIO_PB18          ((unsigned int) 1 << 18) /* Pin Controlled by PB18 */
113#define AT91C_PB18_RI1          ((unsigned int) AT91C_PIO_PB18) /*  USART 1 Ring Indicator */
114#define AT91C_PB18_ECOL         ((unsigned int) AT91C_PIO_PB18) /*  Ethernet MAC Collision Detected */
115#define AT91C_PIO_PB17          ((unsigned int) 1 << 17) /* Pin Controlled by PB17 */
116#define AT91C_PB17_RF2          ((unsigned int) AT91C_PIO_PB17) /*  SSC Receive Frame Sync 2 */
117#define AT91C_PB17_ERXDV        ((unsigned int) AT91C_PIO_PB17) /*  Ethernet MAC Receive Data Valid */
118#define AT91C_PIO_PB16          ((unsigned int) 1 << 16) /* Pin Controlled by PB16 */
119#define AT91C_PB16_RK2          ((unsigned int) AT91C_PIO_PB16) /*  SSC Receive Clock 2 */
120#define AT91C_PB16_ERX3         ((unsigned int) AT91C_PIO_PB16) /*  Ethernet MAC Receive Data 3 */
121#define AT91C_PIO_PB15          ((unsigned int) 1 << 15) /* Pin Controlled by PB15 */
122#define AT91C_PB15_RD2          ((unsigned int) AT91C_PIO_PB15) /*  SSC Receive Data 2 */
123#define AT91C_PB15_ERX2         ((unsigned int) AT91C_PIO_PB15) /*  Ethernet MAC Receive Data 2 */
124#define AT91C_PIO_PB14          ((unsigned int) 1 << 14) /* Pin Controlled by PB14 */
125#define AT91C_PB14_TD2          ((unsigned int) AT91C_PIO_PB14) /*  SSC Transmit Data 2 */
126#define AT91C_PB14_ETXER        ((unsigned int) AT91C_PIO_PB14) /*  Ethernet MAC Transmikt Coding Error */
127#define AT91C_PIO_PB13          ((unsigned int) 1 << 13) /* Pin Controlled by PB13 */
128#define AT91C_PB13_TK2          ((unsigned int) AT91C_PIO_PB13) /*  SSC Transmit Clock 2 */
129#define AT91C_PB13_ETX3         ((unsigned int) AT91C_PIO_PB13) /*  Ethernet MAC Transmit Data 3 */
130#define AT91C_PIO_PB12          ((unsigned int) 1 << 12) /* Pin Controlled by PB12 */
131#define AT91C_PB12_TF2          ((unsigned int) AT91C_PIO_PB12) /*  SSC Transmit Frame Sync 2 */
132#define AT91C_PB12_ETX2         ((unsigned int) AT91C_PIO_PB12) /*  Ethernet MAC Transmit Data 2 */
133
134#define AT91C_PIOB_BSR          ((AT91_REG *)   0xFFFFF674) /* (PIOB) Select B Register */
135#define AT91C_PIOB_PDR          ((AT91_REG *)   0xFFFFF604) /* (PIOB) PIO Disable Register */
136
137#define AT91C_EBI_CS3A_SMC_SmartMedia       ((unsigned int) 0x1 <<  3) /* (EBI) Chip Select 3 is assigned to the Static Memory Controller and the SmartMedia Logic is activated. */
138#define AT91C_SMC2_ACSS_STANDARD ((unsigned int) 0x0 << 16) /* (SMC2) Standard, asserted at the beginning of the access and deasserted at the end. */
139#define AT91C_SMC2_DBW_8        ((unsigned int) 0x2 << 13) /* (SMC2) 8-bit. */
140#define AT91C_SMC2_WSEN         ((unsigned int) 0x1 <<  7) /* (SMC2) Wait State Enable */
141#define AT91C_PIOC_ASR          ((AT91_REG *)   0xFFFFF870) /* (PIOC) Select A Register */
142#define AT91C_PIOC_SODR         ((AT91_REG *)   0xFFFFF830) /* (PIOC) Set Output Data Register */
143#define AT91C_PIOC_CODR         ((AT91_REG *)   0xFFFFF834) /* (PIOC) Clear Output Data Register */
144#define AT91C_PIOC_PDSR         ((AT91_REG *)   0xFFFFF83C) /* (PIOC) Pin Data Status Register */
145
146#define AT91C_BASE_SPI          ((AT91PS_SPI)   0xFFFE0000) /* (SPI) Base Address */
147#define AT91C_BASE_EMAC         ((AT91PS_EMAC)  0xFFFBC000) /* (EMAC) Base Address */
148#define AT91C_BASE_PMC          ((AT91PS_PMC)   0xFFFFFC00) /* (PMC) Base Address */
149#define AT91C_BASE_TC0          ((AT91PS_TC)    0xFFFA0000) /* (TC0) Base Address */
150#define AT91C_BASE_DBGU         ((AT91PS_DBGU)  0xFFFFF200) /* (DBGU) Base Address */
151#define AT91C_BASE_PIOB         ((AT91PS_PIO)   0xFFFFF600) /* (PIOB) Base Address */
152#define AT91C_BASE_PIOA         ((AT91PS_PIO)   0xFFFFF400) /* (PIOA) Base Address */
153#define AT91C_EBI_CSA           ((AT91_REG *)   0xFFFFFF60) /* (EBI) Chip Select Assignment Register */
154#define AT91C_BASE_SMC2         ((AT91PS_SMC2)  0xFFFFFF70) /* (SMC2) Base Address */
155#define AT91C_BASE_US1          ((AT91PS_USART) 0xFFFC4000) /* (US1) Base Address */
156#define AT91C_TCB0_BMR          ((AT91_REG *)   0xFFFA00C4) /* (TCB0) TC Block Mode Register */
157#define AT91C_TCB0_BCR          ((AT91_REG *)   0xFFFA00C0) /* (TCB0) TC Block Control Register */
158#define AT91C_PIOC_PDR          ((AT91_REG *)   0xFFFFF804) /* (PIOC) PIO Disable Register */
159#define AT91C_PIOC_PER          ((AT91_REG *)   0xFFFFF800) /* (PIOC) PIO Enable Register */
160#define AT91C_PIOC_ODR          ((AT91_REG *)   0xFFFFF814) /* (PIOC) Output Disable Registerr */
161#define AT91C_PIOB_PER          ((AT91_REG *)   0xFFFFF600) /* (PIOB) PIO Enable Register */
162#define AT91C_PIOB_ODR          ((AT91_REG *)   0xFFFFF614) /* (PIOB) Output Disable Registerr */
163#define AT91C_PIOB_PDSR         ((AT91_REG *)   0xFFFFF63C) /* (PIOB) Pin Data Status Register */
164
165
166/* interrupt stuff */
167#define EMAC_INT_PRIORITY       7       
168
169/*  RTEMS event used by interrupt handler to start receive daemon. */
170#define START_RECEIVE_EVENT  RTEMS_EVENT_1
171
172/* RTEMS event used to start transmit daemon. */
173#define START_TRANSMIT_EVENT    RTEMS_EVENT_2
174
175rtems_isr at91rm9200_emac_isr(rtems_vector_number vector);
176static void at91rm9200_emac_isr_on(const rtems_irq_connect_data *unused);
177static void at91rm9200_emac_isr_off(const rtems_irq_connect_data *unused);
178static int at91rm9200_emac_isr_is_on(const rtems_irq_connect_data *irq);
179
180int  miiphy_read(unsigned char addr, unsigned char reg, unsigned short * value);
181int  miiphy_write(unsigned char addr, unsigned char reg, unsigned short value);
182static void at91rm9200_EmacEnableMDIO();
183static void at91rm9200_EmacDisableMDIO();
184static UCHAR at91rm9200_EmacReadPhy (unsigned char RegisterAddress,
185                                     unsigned short *pInput);
186static UCHAR at91rm9200_EmacWritePhy (unsigned char RegisterAddress,
187                                      unsigned short *pOutput);
188static unsigned int dm9161_IsPhyConnected();
189static UCHAR dm9161_GetLinkSpeed ();
190static UCHAR dm9161_InitPhy ();
191static UCHAR dm9161_AutoNegotiate (int *status);
192
193
194/* Replace the first value with the clock's interrupt name. */
195rtems_irq_connect_data at91rm9200_emac_isr_data = {
196 AT91RM9200_INT_EMAC,   
197 (rtems_irq_hdl)at91rm9200_emac_isr,
198 at91rm9200_emac_isr_on,
199 at91rm9200_emac_isr_off,
200 at91rm9200_emac_isr_is_on,
201 3,    /* unused for ARM */
202 0 };  /* unused for ARM */
203
204
205/* use the values defined in linkcmds for our use of SRAM */
206extern void * at91rm9200_emac_rxbuf_hdrs;
207extern void * at91rm9200_emac_txbuf;
208extern void * at91rm9200_emac_rxbufs;
209
210/* Set up EMAC hardware */
211/* Number of Receive and Transmit Buffers and Buffer Descriptors */
212#define NUM_RXBDS 8
213#define NUM_TXBDS 1
214#define RX_BUFFER_SIZE 0x600
215
216/* use internal SRAM for buffers and descriptors
217* also insure that the receive descriptors
218* start on a 64byte boundary
219* Receive Buffer Descriptor Header
220*/
221
222typedef struct
223{
224 unsigned long address;
225 unsigned long status;
226} RXBUF_HDR;
227
228RXBUF_HDR       *rxbuf_hdrs;
229unsigned char   *txbuf;
230unsigned char   *rxbuf;
231
232int delay_cnt;
233
234/*
235* Hardware-specific storage
236*/
237typedef struct
238{
239 /*
240  * Connection to networking code
241  * This entry *must* be the first in the sonic_softc structure.
242  */
243 struct arpcom                    arpcom;
244 
245 /*
246  * Interrupt vector
247  */
248 rtems_vector_number             vector;
249 
250 /*
251  *  Indicates configuration
252  */
253 int                             acceptBroadcast;
254 
255 /*
256  * Task waiting for interrupts
257  */
258 rtems_id                        rxDaemonTid;
259 rtems_id                        txDaemonTid;
260 
261 /*
262  * current receive header
263  */
264 int                rx_buf_idx;
265
266 /*
267  * Statistics
268  */
269 unsigned long                   Interrupts;
270 unsigned long                   rxInterrupts;
271 unsigned long                   rxMissed;
272 unsigned long                   rxGiant;
273 unsigned long                   rxNonOctet;
274 unsigned long                   rxBadCRC;
275 unsigned long                   rxCollision;
276 
277 unsigned long                   txInterrupts;
278 unsigned long                   txSingleCollision;
279 unsigned long                   txMultipleCollision;
280 unsigned long                   txCollision;
281 unsigned long                   txDeferred;
282 unsigned long                   txUnderrun;
283 unsigned long                   txLateCollision;
284 unsigned long                   txExcessiveCollision;
285 unsigned long                   txExcessiveDeferral;
286 unsigned long                   txLostCarrier;
287 unsigned long                   txRawWait;
288} at91rm9200_emac_softc_t;
289
290static at91rm9200_emac_softc_t softc;
291
292
293/* The AT91RM9200 ethernet fifos are very undersized. Therefore
294* we use the internal SRAM to hold 4 receive packets and one
295* transmit packet.  Note that the AT91RM9200 can only queue
296* one transmit packet at a time.
297*/
298
299/* function prototypes */
300int rtems_at91rm9200_emac_attach (struct rtems_bsdnet_ifconfig *config, 
301                               void *chip);
302void at91rm9200_emac_init(void *arg);
303void at91rm9200_emac_init_hw(at91rm9200_emac_softc_t *sc);
304void at91rm9200_emac_start(struct ifnet *ifp);
305void at91rm9200_emac_stop (at91rm9200_emac_softc_t *sc);
306void at91rm9200_emac_txDaemon (void *arg);
307void at91rm9200_emac_sendpacket (struct ifnet *ifp, struct mbuf *m);
308void at91rm9200_emac_rxDaemon(void *arg);
309void at91rm9200_emac_stats (at91rm9200_emac_softc_t *sc);
310static int at91rm9200_emac_ioctl (struct ifnet *ifp, 
311                               int command, 
312                               caddr_t data);
313
314int rtems_at91rm9200_emac_attach (
315 struct rtems_bsdnet_ifconfig *config,
316 void *chip  /* only one ethernet, so no chip number */
317 )
318{
319 struct ifnet *ifp;
320 int mtu;
321 int unitnumber;
322 char *unitname;
323
324 /* an array of receive buffer descriptors */
325 rxbuf_hdrs = (RXBUF_HDR *)&at91rm9200_emac_rxbuf_hdrs;
326
327 /* one transmit buffer, 1536 bytes maximum */
328 txbuf = (char *)&at91rm9200_emac_txbuf;
329
330 /* receive buffers starting address */
331 rxbuf = (char *)&at91rm9200_emac_rxbufs;
332 /*
333  * Parse driver name
334  */
335 if ((unitnumber = rtems_bsdnet_parse_driver_name (config, &unitname)) < 0)
336     return 0;
337 
338 /*
339  * Is driver free?
340  */
341 if (unitnumber != 0) {
342     printf ("Bad AT91RM9200 EMAC unit number.\n");
343     return 0;
344 }
345 ifp = &softc.arpcom.ac_if;
346 if (ifp->if_softc != NULL) {
347     printf ("Driver already in use.\n");
348     return 0;
349 }
350 
351 /*
352  *  zero out the control structure
353  */
354 
355 memset( &softc, 0, sizeof(softc) );
356 
357 /* get the MAC address from the chip */
358 softc.arpcom.ac_enaddr[0] = (EMAC_REG(EMAC_SA1L) >> 0) & 0xff;
359 softc.arpcom.ac_enaddr[1] = (EMAC_REG(EMAC_SA1L) >> 8) & 0xff;
360 softc.arpcom.ac_enaddr[2] = (EMAC_REG(EMAC_SA1L) >> 16) & 0xff;
361 softc.arpcom.ac_enaddr[3] = (EMAC_REG(EMAC_SA1L) >> 24) & 0xff;
362 softc.arpcom.ac_enaddr[4] = (EMAC_REG(EMAC_SA1H) >> 0) & 0xff;
363 softc.arpcom.ac_enaddr[5] = (EMAC_REG(EMAC_SA1H) >> 8) & 0xff;
364
365 if (config->mtu) {
366     mtu = config->mtu;
367 } else {
368     mtu = ETHERMTU;
369 }
370
371 softc.acceptBroadcast = !config->ignore_broadcast;
372 
373 /*
374  * Set up network interface values
375  */
376 ifp->if_softc = &softc;
377 ifp->if_unit = unitnumber;
378 ifp->if_name = unitname;
379 ifp->if_mtu = mtu;
380 ifp->if_init = at91rm9200_emac_init;
381 ifp->if_ioctl = at91rm9200_emac_ioctl;
382 ifp->if_start = at91rm9200_emac_start;
383 ifp->if_output = ether_output;
384 ifp->if_flags = IFF_BROADCAST;
385 if (ifp->if_snd.ifq_maxlen == 0) {
386     ifp->if_snd.ifq_maxlen = ifqmaxlen;
387 }
388 
389 softc.rx_buf_idx = 0;
390
391 /*
392  * Attach the interface
393  */
394 if_attach (ifp);
395 ether_ifattach (ifp);
396 return 1;
397}
398
399void at91rm9200_emac_init(void *arg)
400{
401 at91rm9200_emac_softc_t     *sc = arg;     
402 struct ifnet *ifp = &sc->arpcom.ac_if;
403
404 *AT91C_PIOA_PDR = AT91C_PA16_EMDIO | AT91C_PA15_EMDC | AT91C_PA14_ERXER |
405                          AT91C_PA13_ERX1 | AT91C_PA12_ERX0 | AT91C_PA11_ECRS_ECRSDV |
406                          AT91C_PA10_ETX1 | AT91C_PA9_ETX0 | AT91C_PA8_ETXEN |
407                          AT91C_PA7_ETXCK_EREFCK;
408
409 *AT91C_PIOB_PDR = AT91C_PB25_EF100 |
410                          AT91C_PB19_ERXCK | AT91C_PB18_ECOL | AT91C_PB17_ERXDV |
411                          AT91C_PB16_ERX3 | AT91C_PB15_ERX2 | AT91C_PB14_ETXER |
412                          AT91C_PB13_ETX3 | AT91C_PB12_ETX2;
413
414 *AT91C_PIOB_BSR = AT91C_PB25_EF100 | AT91C_PB19_ERXCK | AT91C_PB18_ECOL |
415                          AT91C_PB17_ERXDV | AT91C_PB16_ERX3 | AT91C_PB15_ERX2 |
416                          AT91C_PB14_ETXER | AT91C_PB13_ETX3 | AT91C_PB12_ETX2;
417/*
418 EMAC_REG(EMAC_CFG) |= AT91C_EMAC_CSR;
419*/
420 PMC_REG(PMC_PCER) |= BIT24;
421 
422 EMAC_REG(EMAC_CFG) |= EMAC_CFG_RMII;
423 
424 /*
425  *This is for stuff that only gets done once (at91rm9200_emac_init()
426  * gets called multiple times
427  */
428 if (sc->txDaemonTid == 0) {
429     /* Set up EMAC hardware */
430     at91rm9200_emac_init_hw(sc);
431     
432     /*      Start driver tasks */
433     sc->rxDaemonTid = rtems_bsdnet_newproc("ENrx", 
434                                            4096, 
435                                            at91rm9200_emac_rxDaemon, 
436                                            sc);
437     sc->txDaemonTid = rtems_bsdnet_newproc("ENtx", 
438                                            4096, 
439                                            at91rm9200_emac_txDaemon, 
440                                            sc);
441 } /* if txDaemonTid */
442 
443 /* set our priority in the AIC */
444 AIC_SMR_REG(AIC_SMR_EMAC) = AIC_SMR_PRIOR(EMAC_INT_PRIORITY);
445 
446 /* install the interrupt handler */
447 BSP_install_rtems_irq_handler(&at91rm9200_emac_isr_data);
448
449 /* EMAC doesn't support promiscuous, so ignore requests */
450 if (ifp->if_flags & IFF_PROMISC) {
451     printf ("Warning - AT91RM9200 Ethernet driver"
452             " doesn't support Promiscuous Mode!\n");
453 }
454
455 /*
456  * Tell the world that we're running.
457  */
458 ifp->if_flags |= IFF_RUNNING;
459 
460 /* Enable TX/RX and clear the statistics counters */
461 EMAC_REG(EMAC_CTL) = (EMAC_CTL_TE | EMAC_CTL_RE | EMAC_CTL_CSR);
462 
463 /* clear any pending interrupts */
464 EMAC_REG(EMAC_TSR) = 0xffffffff;
465 EMAC_REG(EMAC_RSR) = 0xffffffff;
466
467} /* at91rm9200_emac_init() */
468
469void  at91rm9200_emac_init_hw(at91rm9200_emac_softc_t *sc)
470{
471 int i;
472 
473 /* initialize our receive buffer descriptors */
474 for (i = 0; i < NUM_RXBDS-1; i++) {
475     rxbuf_hdrs[i].address = (unsigned long)(&rxbuf[i * RX_BUFFER_SIZE]);
476     rxbuf_hdrs[i].status = 0x00000000;
477 }
478
479 /* last one needs the wrapbit set as well  */
480 rxbuf_hdrs[i].address = ((unsigned long)(&rxbuf[i * RX_BUFFER_SIZE]) | 
481                          RXBUF_ADD_WRAP);
482 rxbuf_hdrs[i].status = 0x00000000;
483 
484 /* point to our receive buffer queue */
485 EMAC_REG(EMAC_RBQP) = (unsigned long)rxbuf_hdrs;
486 
487 /* clear any left over status bits */
488 EMAC_REG(EMAC_RSR)  &= ~(EMAC_RSR_OVR | EMAC_RSR_REC | EMAC_RSR_BNA);
489 
490 /* set the MII clock divder to MCK/64 */
491/*    EMAC_REG(EMAC_CFG) = (EMAC_CFG_CLK_64 | EMAC_CFG_BIG | EMAC_CFG_FD);*/
492 EMAC_REG(EMAC_CFG) = (EMAC_REG(EMAC_CFG) | AT91C_EMAC_CAF | AT91C_EMAC_NBC) & (~AT91C_EMAC_CLK);
493 
494 /* enable the MII interface */
495/*    EMAC_REG(EMAC_CTL) = EMAC_CTL_MPE;*/
496 EMAC_REG(EMAC_CTL) = AT91C_EMAC_TE | AT91C_EMAC_RE;
497
498#if 0   
499 /* Set PHY LED2 to combined Link/Activity and enable pulse stretching */
500 EMAC_REG(EMAC_MAN) = (0x01 << 30 |   /* Start of Frame Delimiter */
501                       0x01 << 28 |   /* Operation, 0x01 = Write */
502                       0x00 << 23 |   /* Phy Number */
503                       0x14 << 18 |   /* Phy Register */
504                       0x02 << 16 |   /* must be 0x02 */
505                       0x0D0A);       /* Write data (0x0000 if read) */
506#endif
507
508 if(!dm9161_IsPhyConnected()) printf("Can't find PHY...\n");
509 else printf("Find PHY, initializing...\n");
510 
511 dm9161_InitPhy();
512 
513/*    printf("PHY initialized.\n");*/
514
515} /* at91rm9200_emac_init_hw() */
516
517void at91rm9200_emac_start(struct ifnet *ifp)
518{
519 at91rm9200_emac_softc_t *sc = ifp->if_softc;
520 
521 rtems_event_send(sc->txDaemonTid, START_TRANSMIT_EVENT);
522 ifp->if_flags |= IFF_OACTIVE;
523}
524
525void at91rm9200_emac_stop (at91rm9200_emac_softc_t *sc)
526{
527 struct ifnet *ifp = &sc->arpcom.ac_if;
528
529 ifp->if_flags &= ~IFF_RUNNING;
530 
531 /*
532  * Stop the transmitter and receiver.
533  */
534 EMAC_REG(EMAC_CTL) &= ~(EMAC_CTL_TE | EMAC_CTL_RE);
535}
536
537/*
538* Driver transmit daemon
539*/
540void at91rm9200_emac_txDaemon (void *arg)
541{
542 at91rm9200_emac_softc_t *sc = (at91rm9200_emac_softc_t *)arg;
543 struct ifnet *ifp = &sc->arpcom.ac_if;
544 struct mbuf *m;
545 rtems_event_set events;
546
547 for (;;)
548 {
549     /* turn on TX interrupt, then wait for one */
550     EMAC_REG(EMAC_IER) = EMAC_INT_TCOM;     /* Transmit complete */
551     
552     rtems_bsdnet_event_receive(
553         START_TRANSMIT_EVENT,
554         RTEMS_EVENT_ANY | RTEMS_WAIT,
555         RTEMS_NO_TIMEOUT,
556         &events);
557/*printk("txDaemon event\n");*/
558     
559     /* Send packets till queue is empty */
560     for (;;)
561     {
562         /* Get the next mbuf chain to transmit. */
563         IF_DEQUEUE(&ifp->if_snd, m);
564         if (!m)
565             break;
566         at91rm9200_emac_sendpacket (ifp, m);
567     }
568     ifp->if_flags &= ~IFF_OACTIVE;
569 }
570}
571
572/* Send packet */
573void at91rm9200_emac_sendpacket (struct ifnet *ifp, struct mbuf *m)
574{
575 struct mbuf *l = NULL;
576 unsigned int pkt_offset = 0;
577 delay_cnt = 0;
578 unsigned int i;
579 printf("at91rm9200_emac_sendpacket %p\n", m); 
580 
581 /* Wait for EMAC Transmit Queue to become available. */
582 while (((EMAC_REG(EMAC_TSR) & EMAC_TSR_COMP) == 0) &&
583        ((EMAC_REG(EMAC_TSR) & EMAC_TSR_TXIDLE) == 0))
584 {
585     delay_cnt++;
586/*        sleep(0);       make sure we don't hog the cpu */
587     continue;
588 }
589 
590 /* copy the mbuf chain into the transmit buffer */
591 l = m;     
592 while (l != NULL) {
593     memcpy(((char *)txbuf + pkt_offset),  /* offset into pkt for mbuf */ 
594            (char *)mtod(l, void *),       /* cast to void */ 
595            l->m_len);                     /* length of this mbuf */
596     
597     pkt_offset += l->m_len;               /* update offset */
598     l = l->m_next;                        /* get next mbuf, if any */     
599 }
600 
601 /* free the mbuf chain we just copied */
602 m_freem(m);
603#if 0   
604 /* clear any pending status */
605 EMAC_REG(EMAC_TSR) = (EMAC_TSR_OVR | EMAC_TSR_COL | EMAC_TSR_RLE
606                       | EMAC_TSR_COMP | EMAC_TSR_UND);
607#endif
608#if 0
609 for(i = 0; i < pkt_offset*4; i ++){
610        printf("%02x ", (unsigned char *)txbuf[i]);
611        if(i%30 == 0) printf("\n");
612 }
613#endif
614 /* tell the EMAC about our buffer */
615 EMAC_REG(EMAC_TAR) = (unsigned long)txbuf;
616 EMAC_REG(EMAC_TCR) = (unsigned long)pkt_offset;
617 
618 while(EMAC_REG(EMAC_TCR)&0x7FF);
619 EMAC_REG(EMAC_TSR) |= EMAC_TSR_COMP;
620 
621} /* at91rm9200_emac_sendpacket () */
622
623
624/* SONIC reader task */
625void at91rm9200_emac_rxDaemon(void *arg)
626{
627 at91rm9200_emac_softc_t *sc = (at91rm9200_emac_softc_t *)arg;
628 struct ifnet *ifp = &sc->arpcom.ac_if;
629 struct mbuf *m;
630 struct ether_header *eh;
631 rtems_event_set events;
632 int pktlen;
633
634 /* Input packet handling loop */
635 for (;;) {
636     /* turn on RX interrupts, then wait for one */
637     EMAC_REG(EMAC_IER) = (EMAC_INT_RCOM |   /* Receive complete */
638                           EMAC_INT_RBNA |   /* Receive buf not available */
639                           EMAC_INT_ROVR);   /* Receive overrun */
640
641     rtems_bsdnet_event_receive(
642         START_RECEIVE_EVENT,
643         RTEMS_EVENT_ANY | RTEMS_WAIT,
644         RTEMS_NO_TIMEOUT,
645         &events);
646/*printf("rxDaemon event:EMAC_REG(EMAC_RSR)=0x%x\n", EMAC_REG(EMAC_RSR));*/
647     if (EMAC_REG(EMAC_RSR) & EMAC_RSR_BNA) {
648         printf("1: EMAC_BNA\n");
649     }
650
651     if (EMAC_REG(EMAC_RSR) & EMAC_RSR_OVR) {
652         printf("1: EMAC_OVR\n");
653     }
654
655     /* clear the receive status as we do not use it anyway */
656     EMAC_REG(EMAC_RSR) = (EMAC_RSR_REC | EMAC_RSR_OVR | EMAC_RSR_BNA);
657     
658     /* scan the buffer descriptors looking for any with data in them */
659     while (rxbuf_hdrs[sc->rx_buf_idx].address & RXBUF_ADD_OWNED) {
660         pktlen = rxbuf_hdrs[sc->rx_buf_idx].status & RXBUF_STAT_LEN_MASK;
661
662         /* get an mbuf this packet */
663         MGETHDR(m, M_WAIT, MT_DATA);
664
665         /* now get a cluster pointed to by the mbuf */
666         /* since an mbuf by itself is too small */
667         MCLGET(m, M_WAIT);
668
669         /* set the type of mbuf to ifp (ethernet I/F) */
670         m->m_pkthdr.rcvif = ifp;
671         m->m_nextpkt = 0;
672
673         /* copy the packet into the cluster pointed to by the mbuf */   
674         memcpy((char *)m->m_ext.ext_buf,
675                (char *)(rxbuf_hdrs[sc->rx_buf_idx].address & 0xfffffffc),
676                pktlen);
677
678         /* Release the buffer ASAP back to the EMAC */
679         rxbuf_hdrs[sc->rx_buf_idx].address &= ~RXBUF_ADD_OWNED;
680
681         /* set the length of the mbuf */
682         m->m_len = pktlen - (sizeof(struct ether_header) + 4);
683         m->m_pkthdr.len = m->m_len;
684         
685         /* strip off the ethernet header from the mbuf */
686         /* but save the pointer to it */
687         eh = mtod (m, struct ether_header *);
688         m->m_data += sizeof(struct ether_header);
689
690         /* increment the buffer index */
691         sc->rx_buf_idx++;
692         if (sc->rx_buf_idx >= NUM_RXBDS) {
693             sc->rx_buf_idx = 0;
694         }
695       
696         if(eh->ether_shost[0] != 0xff){
697           printf("eh:%02x:%02x:%02x:%02x:%02x:%02x\n",eh->ether_shost[0],eh->ether_shost[1], \
698                eh->ether_shost[2],eh->ether_shost[3],eh->ether_shost[4],eh->ether_shost[5]);
699            }
700         /* give all this stuff to the stack */
701         ether_input(ifp, eh, m);
702         
703     } /* while ADD_OWNED = 0 */
704
705     if (EMAC_REG(EMAC_RSR) & EMAC_RSR_BNA) {
706         printf("2:EMAC_BNA\n");
707     }
708     if (EMAC_REG(EMAC_RSR) & EMAC_RSR_OVR) {
709         printf("2:EMAC_OVR\n");
710     }
711
712
713 } /* for (;;) */
714} /* at91rm9200_emac_rxDaemon() */ 
715
716
717/* Show interface statistics */
718void at91rm9200_emac_stats (at91rm9200_emac_softc_t *sc)
719{
720 printf (" Total Interrupts:%-8lu",          sc->Interrupts);
721 printf ("    Rx Interrupts:%-8lu",          sc->rxInterrupts);
722 printf ("            Giant:%-8lu",          sc->rxGiant);
723 printf ("        Non-octet:%-8lu\n",                sc->rxNonOctet);
724 printf ("          Bad CRC:%-8lu",          sc->rxBadCRC);
725 printf ("        Collision:%-8lu",          sc->rxCollision);
726 printf ("           Missed:%-8lu\n",                sc->rxMissed);
727 
728 printf (    "    Tx Interrupts:%-8lu",      sc->txInterrupts);
729 printf (  "           Deferred:%-8lu",      sc->txDeferred);
730 printf ("        Lost Carrier:%-8lu\n",     sc->txLostCarrier);
731 printf (   "Single Collisions:%-8lu",       sc->txSingleCollision);
732 printf ( "Multiple Collisions:%-8lu",       sc->txMultipleCollision);
733 printf ("Excessive Collisions:%-8lu\n",     sc->txExcessiveCollision);
734 printf (   " Total Collisions:%-8lu",       sc->txCollision);
735 printf ( "     Late Collision:%-8lu",       sc->txLateCollision);
736 printf ("            Underrun:%-8lu\n",     sc->txUnderrun);
737 printf (   "  Raw output wait:%-8lu\n",     sc->txRawWait);
738}
739
740
741/* Enables at91rm9200_emac interrupts. */
742static void at91rm9200_emac_isr_on(const rtems_irq_connect_data *unused)
743{
744 /* Enable various TX/RX interrupts */
745 EMAC_REG(EMAC_IER) = (EMAC_INT_RCOM | /* Receive complete */
746                       EMAC_INT_RBNA | /* Receive buffer not available */
747                       EMAC_INT_TCOM | /* Transmit complete */
748                       EMAC_INT_ROVR | /* Receive overrun */
749                       EMAC_INT_ABT);  /* Abort on DMA transfer */
750 
751 return;
752}
753
754/* Disables at91rm9200_emac interrupts */
755static void at91rm9200_emac_isr_off(const rtems_irq_connect_data *unused)
756{
757 /* disable all various TX/RX interrupts */
758 EMAC_REG(EMAC_IDR) = 0xffffffff;
759 return;
760}
761
762/* Tests to see if at91rm9200_emac interrupts are enabled, and
763* returns non-0 if so.
764* If interrupt is not enabled, returns 0.
765*/
766static int at91rm9200_emac_isr_is_on(const rtems_irq_connect_data *irq)
767{
768 return EMAC_REG(EMAC_IMR); /* any interrupts enabled? */
769}
770
771/*  Driver ioctl handler */
772static int
773at91rm9200_emac_ioctl (struct ifnet *ifp, int command, caddr_t data)
774{
775 at91rm9200_emac_softc_t *sc = ifp->if_softc;
776 int error = 0;
777 
778 switch (command) {
779 case SIOCGIFADDR:
780 case SIOCSIFADDR:
781     ether_ioctl (ifp, command, data);
782     break;
783     
784 case SIOCSIFFLAGS:
785     switch (ifp->if_flags & (IFF_UP | IFF_RUNNING))
786     {
787     case IFF_RUNNING:
788         at91rm9200_emac_stop (sc);
789         break;
790         
791     case IFF_UP:
792         at91rm9200_emac_init (sc);
793         break;
794         
795     case IFF_UP | IFF_RUNNING:
796         at91rm9200_emac_stop (sc);
797         at91rm9200_emac_init (sc);
798         break;
799         
800     default:
801         break;
802     } /* switch (if_flags) */
803     break;
804     
805 case SIO_RTEMS_SHOW_STATS:
806     at91rm9200_emac_stats (sc);
807     break;
808     
809     /*
810      * FIXME: All sorts of multicast commands need to be added here!
811      */
812 default:
813     error = EINVAL;
814     break;
815 } /* switch (command) */
816 return error;
817}
818
819/* interrupt handler */
820rtems_isr at91rm9200_emac_isr (rtems_vector_number v)
821{
822 unsigned long status32;
823
824 /* get the ISR status and determine RX or TX */
825 status32 = EMAC_REG(EMAC_ISR);
826 
827 if (status32 & EMAC_INT_ABT) {
828     EMAC_REG(EMAC_IDR) = EMAC_INT_ABT; /* disable it */
829     rtems_panic("AT91RM9200 Ethernet MAC has received an Abort.\n");
830 }
831 
832 if (status32 & (EMAC_INT_RCOM |    /* Receive complete */
833                 EMAC_INT_RBNA |    /* Receive buffer not available */
834                 EMAC_INT_ROVR)) {  /* Receive overrun */
835
836     /* disable the RX interrupts */
837     EMAC_REG(EMAC_IDR) = (EMAC_INT_RCOM |  /* Receive complete */
838                           EMAC_INT_RBNA |  /* Receive buf not available */
839                           EMAC_INT_ROVR);  /* Receive overrun */
840     rtems_event_send (softc.rxDaemonTid, START_RECEIVE_EVENT);
841 }   
842
843 if (status32 & EMAC_INT_TCOM) {      /* Transmit buffer register empty */
844     
845     /* disable the TX interrupts */
846     EMAC_REG(EMAC_IDR) = EMAC_INT_TCOM;
847
848     rtems_event_send (softc.txDaemonTid, START_TRANSMIT_EVENT);
849 }   
850}
851
852/*********************************************************************/
853
854int  miiphy_read(unsigned char addr, unsigned char reg, unsigned short * value)
855{
856        at91rm9200_EmacEnableMDIO();
857        at91rm9200_EmacReadPhy(reg, value);
858        at91rm9200_EmacDisableMDIO();
859        return 0;
860}
861
862int  miiphy_write(unsigned char addr, unsigned char reg, unsigned short value)
863{
864        at91rm9200_EmacEnableMDIO();
865        at91rm9200_EmacWritePhy(reg, &value);
866        at91rm9200_EmacDisableMDIO();
867        return 0;
868}
869
870static void at91rm9200_EmacEnableMDIO()
871{
872        /* Mac CTRL reg set for MDIO enable */
873        EMAC_REG(EMAC_CTL) |= EMAC_CTL_MPE;
874}
875
876static void at91rm9200_EmacDisableMDIO()
877{
878        /* Mac CTRL reg set for MDIO disable */
879        EMAC_REG(EMAC_CTL) &= (~EMAC_CTL_MPE);
880}
881
882static UCHAR at91rm9200_EmacReadPhy (unsigned char RegisterAddress,
883                                     unsigned short *pInput)
884{
885        EMAC_REG(EMAC_MAN) = (AT91C_EMAC_HIGH & ~AT91C_EMAC_LOW) |
886                          (AT91C_EMAC_RW_R) |
887                          (RegisterAddress << 18) |
888                          (AT91C_EMAC_CODE_802_3);
889
890        rtems_task_wake_after( PHY_WAIT );
891
892        *pInput = (unsigned short) EMAC_REG(EMAC_MAN);
893
894        return 1;
895}
896
897static UCHAR at91rm9200_EmacWritePhy(unsigned char RegisterAddress,
898                                      unsigned short *pOutput)
899{
900
901        EMAC_REG(EMAC_MAN) = (AT91C_EMAC_HIGH & ~AT91C_EMAC_LOW) |
902                        AT91C_EMAC_CODE_802_3 | AT91C_EMAC_RW_W |
903                        (RegisterAddress << 18) | *pOutput;
904
905        rtems_task_wake_after( PHY_WAIT );
906
907        return 1;
908}
909
910static unsigned int dm9161_IsPhyConnected()
911{
912        unsigned short Id1, Id2;
913
914        at91rm9200_EmacEnableMDIO();
915        at91rm9200_EmacReadPhy (DM9161_PHYID1, &Id1);
916        at91rm9200_EmacReadPhy (DM9161_PHYID2, &Id2);
917        at91rm9200_EmacDisableMDIO();
918
919        if ((Id1 == (DM9161_PHYID1_OUI >> 6)) &&
920                ((Id2 >> 10) == (DM9161_PHYID1_OUI & DM9161_LSB_MASK)))
921                return 1;
922
923        return 0;
924}
925
926static UCHAR dm9161_GetLinkSpeed()
927{
928        unsigned short stat1, stat2;
929
930        if (!at91rm9200_EmacReadPhy (DM9161_BMSR, &stat1))
931                return 0;
932
933        if (!(stat1 & DM9161_LINK_STATUS))      /* link status up? */
934                return 0;
935
936        if (!at91rm9200_EmacReadPhy (DM9161_DSCSR, &stat2))
937                return 0;
938
939        if ((stat1 & DM9161_100BASE_TX_FD) && (stat2 & DM9161_100FDX)) {
940                /*set Emac for 100BaseTX and Full Duplex  */
941                printf("100 Base TX Full Duplex.\n");
942                EMAC_REG(EMAC_CFG) = AT91C_EMAC_SPD | AT91C_EMAC_FD;
943                return 1;
944        }
945
946        if ((stat1 & DM9161_10BASE_T_FD) && (stat2 & DM9161_10FDX)) {
947                printf("10 Base TX Full Duplex.\n");
948                /*set MII for 10BaseT and Full Duplex  */
949                EMAC_REG(EMAC_CFG) = (EMAC_REG(EMAC_CFG) &
950                                ~(AT91C_EMAC_SPD | AT91C_EMAC_FD))
951                                | AT91C_EMAC_FD;
952                return 1;
953        }
954
955        if ((stat1 & DM9161_100BASE_T4_HD) && (stat2 & DM9161_100HDX)) {
956                printf("100 Base TX Half Duplex.\n");
957                /*set MII for 100BaseTX and Half Duplex  */
958                EMAC_REG(EMAC_CFG) = (EMAC_REG(EMAC_CFG) &
959                                ~(AT91C_EMAC_SPD | AT91C_EMAC_FD))
960                                | AT91C_EMAC_SPD;
961                return 1;
962        }
963
964        if ((stat1 & DM9161_10BASE_T_HD) && (stat2 & DM9161_10HDX)) {
965                printf("10 Base TX Half Duplex.\n");
966                /*set MII for 10BaseT and Half Duplex  */
967                EMAC_REG(EMAC_CFG) &= ~(AT91C_EMAC_SPD | AT91C_EMAC_FD);
968                return 1;
969        }
970        return 0;
971}
972
973
974static UCHAR dm9161_InitPhy()
975{
976        UCHAR ret = 1;
977        unsigned short IntValue;
978
979        at91rm9200_EmacEnableMDIO();
980
981        if (!dm9161_GetLinkSpeed ()) {
982                /* Try another time */
983                ret = dm9161_GetLinkSpeed ();
984        }
985
986        /* Disable PHY Interrupts */
987        at91rm9200_EmacReadPhy(DM9161_MDINTR, &IntValue);
988        /* clear FDX, SPD, Link, INTR masks */
989        IntValue &= ~(DM9161_FDX_MASK | DM9161_SPD_MASK |
990                      DM9161_LINK_MASK | DM9161_INTR_MASK);
991        at91rm9200_EmacWritePhy (DM9161_MDINTR, &IntValue);
992        at91rm9200_EmacDisableMDIO();
993
994        return (ret);
995}
996
997static UCHAR dm9161_AutoNegotiate (int *status)
998{
999        unsigned short value;
1000        unsigned short PhyAnar;
1001        unsigned short PhyAnalpar;
1002
1003        /* Set dm9161 control register */
1004        if (!at91rm9200_EmacReadPhy (DM9161_BMCR, &value))
1005                return 0;
1006        value &= ~DM9161_AUTONEG;       /* remove autonegotiation enable */
1007        value |= DM9161_ISOLATE;        /* Electrically isolate PHY */
1008        if (!at91rm9200_EmacWritePhy(DM9161_BMCR, &value))
1009                return 0;
1010
1011        /* Set the Auto_negotiation Advertisement Register */
1012        /* MII advertising for Next page, 100BaseTxFD and HD, 10BaseTFD and HD, IEEE 802.3 */
1013        PhyAnar = DM9161_NP | DM9161_TX_FDX | DM9161_TX_HDX |
1014                  DM9161_10_FDX | DM9161_10_HDX | DM9161_AN_IEEE_802_3;
1015        if (!at91rm9200_EmacWritePhy(DM9161_ANAR, &PhyAnar))
1016                return 0;
1017
1018        /* Read the Control Register     */
1019        if (!at91rm9200_EmacReadPhy(DM9161_BMCR, &value))
1020                return 0;
1021
1022        value |= DM9161_SPEED_SELECT | DM9161_AUTONEG | DM9161_DUPLEX_MODE;
1023        if (!at91rm9200_EmacWritePhy(DM9161_BMCR, &value))
1024                return 0;
1025        /* Restart Auto_negotiation  */
1026        value |= DM9161_RESTART_AUTONEG;
1027        if (!at91rm9200_EmacWritePhy(DM9161_BMCR, &value))
1028                return 0;
1029
1030        /*check AutoNegotiate complete */
1031        rtems_task_wake_after( PHY_WAIT );
1032       
1033        at91rm9200_EmacReadPhy(DM9161_BMSR, &value);
1034        if (!(value & DM9161_AUTONEG_COMP))
1035                return 0;
1036
1037        /* Get the AutoNeg Link partner base page */
1038        if (!at91rm9200_EmacReadPhy(DM9161_ANLPAR, &PhyAnalpar))
1039                return 0;
1040
1041        if ((PhyAnar & DM9161_TX_FDX) && (PhyAnalpar & DM9161_TX_FDX)) {
1042                /*set MII for 100BaseTX and Full Duplex  */
1043                EMAC_REG(EMAC_CFG) |= AT91C_EMAC_SPD | AT91C_EMAC_FD;
1044                printf("100 Base TX Full Duplex\n");
1045                return 1;
1046        }
1047
1048        if ((PhyAnar & DM9161_10_FDX) && (PhyAnalpar & DM9161_10_FDX)) {
1049                /*set MII for 10BaseT and Full Duplex  */
1050                printf("10 Base TX Full Duplex\n");
1051                EMAC_REG(EMAC_CFG) = (EMAC_REG(EMAC_CFG) &
1052                                ~(AT91C_EMAC_SPD | AT91C_EMAC_FD))
1053                                | AT91C_EMAC_FD;
1054                return 1;
1055        }
1056        return 0;
1057}
1058
1059