at91_emac.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2006-2007 by egnite Software GmbH. All rights reserved.
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions
00006  * are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the copyright holders nor the names of
00014  *    contributors may be used to endorse or promote products derived
00015  *    from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS
00018  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00019  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00020  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
00021  * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00022  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00023  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00024  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00025  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00026  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00027  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00028  * SUCH DAMAGE.
00029  *
00030  * For additional information see http://www.ethernut.de/
00031  *
00032  */
00033 
00034 /*
00035  * $Log: at91_emac.c,v $
00036  * Revision 1.11  2007/09/06 20:07:24  olereinhardt
00037  * Changed phy detection and added support for micel phy (SAM7-EX256 Board)
00038  *
00039  * Revision 1.10  2007/08/29 07:43:52  haraldkipp
00040  * Documentation updated and corrected.
00041  *
00042  * Revision 1.9  2007/05/02 11:20:26  haraldkipp
00043  * Pull-up enable/disable simplified.
00044  * Added multicast table entry.
00045  *
00046  * Revision 1.8  2007/04/20 13:06:08  haraldkipp
00047  * Previous change failed on SAM7X-EK. We are now using PHY address 0 by
00048  * default and disable all pull-ups during PHY reset.
00049  *
00050  * Revision 1.7  2007/04/12 09:13:10  haraldkipp
00051  * Bugfix: PHY initialization may fail with pull-ups enabled.
00052  *
00053  * Revision 1.6  2007/02/15 16:00:45  haraldkipp
00054  * Configurable buffer usage and link timeout.
00055  *
00056  * Revision 1.5  2006/10/17 11:06:12  haraldkipp
00057  * Number of loops waiting for links increased to 10000 and NIC resets
00058  * reduced. This will help to link to auto MDIX via direct cable.
00059  *
00060  * Revision 1.4  2006/10/08 16:41:34  haraldkipp
00061  * PHY address and power down bit are now configurable.
00062  *
00063  * Revision 1.3  2006/10/05 17:10:37  haraldkipp
00064  * Link detection was unreliable. This also caused bug #1567785.
00065  * Now NutRegisterDevice will return an error, if there is no
00066  * link available. Applications may then call NutRegisterDevice again.
00067  *
00068  * Revision 1.2  2006/09/29 12:29:16  haraldkipp
00069  * Several fixes to make it running reliably on the AT91SAM9260.
00070  *
00071  * Revision 1.1  2006/08/31 18:58:47  haraldkipp
00072  * More general AT91 MAC driver replaces the SAM7X specific version.
00073  * This had been tested on the SAM9260, but loses Ethernet packets
00074  * for a yet unknown reason.
00075  *
00076  */
00077 
00078 #include <cfg/os.h>
00079 #include <cfg/dev.h>
00080 #include <arch/arm.h>
00081 #include <cfg/arch/gpio.h>
00082 
00083 #include <string.h>
00084 
00085 #include <sys/atom.h>
00086 #include <sys/heap.h>
00087 #include <sys/thread.h>
00088 #include <sys/event.h>
00089 #include <sys/timer.h>
00090 #include <sys/confnet.h>
00091 
00092 #include <netinet/if_ether.h>
00093 #include <net/ether.h>
00094 #include <net/if_var.h>
00095 
00096 #include <dev/irqreg.h>
00097 #include <dev/at91_emac.h>
00098 
00099 #ifdef NUTDEBUG
00100 #include <stdio.h>
00101 #endif
00102 
00103 #ifndef NUT_THREAD_NICRXSTACK
00104 #define NUT_THREAD_NICRXSTACK   768
00105 #endif
00106 
00107 #ifndef EMAC_RX_BUFFERS
00108 #define EMAC_RX_BUFFERS         32
00109 #endif
00110 #define EMAC_RX_BUFSIZ          128
00111 
00112 #define EMAC_TX_BUFFERS         2
00113 #ifndef EMAC_TX_BUFSIZ
00114 #define EMAC_TX_BUFSIZ          1536
00115 #endif
00116 
00117 #ifndef EMAC_LINK_LOOPS
00118 #define EMAC_LINK_LOOPS         1000000
00119 #endif
00120 
00125 #define NIC_PHY_BMCR            0x00    
00126 #define NIC_PHY_BMCR_COLTEST    0x0080  
00127 #define NIC_PHY_BMCR_FDUPLEX    0x0100  
00128 #define NIC_PHY_BMCR_ANEGSTART  0x0200  
00129 #define NIC_PHY_BMCR_ISOLATE    0x0400  
00130 #define NIC_PHY_BMCR_PWRDN      0x0800  
00131 #define NIC_PHY_BMCR_ANEGENA    0x1000  
00132 #define NIC_PHY_BMCR_100MBPS    0x2000  
00133 #define NIC_PHY_BMCR_LOOPBACK   0x4000  
00134 #define NIC_PHY_BMCR_RESET      0x8000  
00136 #define NIC_PHY_BMSR            0x01    
00137 #define NIC_PHY_BMSR_ANCOMPL    0x0020  
00138 #define NIC_PHY_BMSR_LINKSTAT   0x0004  
00140 #define NIC_PHY_ID1             0x02    
00141 #define NIC_PHY_ID2             0x03    
00142 #define NIC_PHY_ANAR            0x04    
00143 #define NIC_PHY_ANLPAR          0x05    
00144 #define NIC_PHY_ANEG_NP         0x8000  
00145 #define NIC_PHY_ANEG_ACK        0x4000  
00146 #define NIC_PHY_ANEG_RF         0x2000  
00147 #define NIC_PHY_ANEG_FCS        0x0400  
00148 #define NIC_PHY_ANEG_T4         0x0200  
00149 #define NIC_PHY_ANEG_TX_FDX     0x0100  
00150 #define NIC_PHY_ANEG_TX_HDX     0x0080  
00151 #define NIC_PHY_ANEG_10_FDX     0x0040  
00152 #define NIC_PHY_ANEG_10_HDX     0x0020  
00153 #define NIC_PHY_ANEG_BINSEL     0x001F  
00155 #define NIC_PHY_ANER            0x06    
00158 
00159 
00165 #ifndef NIC_PHY_ADDR
00166 #define NIC_PHY_ADDR            0
00167 #endif
00168 
00169 
00170 #if defined (MCU_AT91SAM9260)
00171 
00177 #define PHY_MODE_RMII
00178 
00179 //#define EMAC_PIO_PER            PIOA_PER
00180 //#define EMAC_PIO_OER            PIOA_OER
00181 //#define EMAC_PIO_CODR           PIOA_CODR
00182 #define EMAC_PIO_PUER           PIOA_PUER
00183 #define EMAC_PIO_PUDR           PIOA_PUDR
00184 #define EMAC_PIO_ASR            PIOA_ASR
00185 #define EMAC_PIO_BSR            PIOA_BSR
00186 #define EMAC_PIO_PDR            PIOA_PDR
00187 
00188 #define PHY_TXD0_BIT            PA12_ETX0_A     
00189 #define PHY_TXD1_BIT            PA13_ETX1_A     
00190 #define PHY_RXD0_AD0_BIT        PA14_ERX0_A     
00191 #define PHY_RXD1_AD1_BIT        PA15_ERX1_A     
00192 #define PHY_TXEN_BIT            PA16_ETXEN_A    
00193 #define PHY_RXDV_TESTMODE_BIT   PA17_ERXDV_A    
00194 #define PHY_RXER_RXD4_RPTR_BIT  PA18_ERXER_A    
00195 #define PHY_TXCLK_ISOLATE_BIT   PA19_ETXCK_A    
00196 #define PHY_MDC_BIT             PA20_EMDC_A     
00197 #define PHY_MDIO_BIT            PA21_EMDIO_A    
00199 #ifndef PHY_MODE_RMII
00200 #define PHY_TXD2_BIT            PA10_ETX2_B     
00201 #define PHY_TXD3_BIT            PA11_ETX3_B     
00202 #define PHY_TXER_TXD4_BIT       PA22_ETXER_B    
00203 #define PHY_RXCLK_10BTSER_BIT   PA27_ERXCK_B    
00204 #define PHY_COL_RMII_BIT        PA29_ECOL_B     
00205 #endif
00206 
00207 #define PHY_RXD2_AD2_BIT        PA25_ERX2_B     
00208 #define PHY_RXD3_AD3_BIT        PA26_ERX3_B     
00209 #define PHY_CRS_AD4_BIT         PA28_ECRS_B     
00211 #define PHY_MII_PINS_A 0 \
00212     | _BV(PHY_TXD0_BIT) \
00213     | _BV(PHY_TXD1_BIT) \
00214     | _BV(PHY_RXD0_AD0_BIT) \
00215     | _BV(PHY_RXD1_AD1_BIT) \
00216     | _BV(PHY_TXEN_BIT) \
00217     | _BV(PHY_RXDV_TESTMODE_BIT) \
00218     | _BV(PHY_RXER_RXD4_RPTR_BIT) \
00219     | _BV(PHY_TXCLK_ISOLATE_BIT) \
00220     | _BV(PHY_MDC_BIT) \
00221     | _BV(PHY_MDIO_BIT)
00222 
00223 #ifdef PHY_MODE_RMII
00224 #define PHY_MII_PINS_B 0
00225 #else
00226 #define PHY_MII_PINS_B 0 \
00227     | _BV(PHY_TXD2_BIT) \
00228     | _BV(PHY_TXD3_BIT) \
00229     | _BV(PHY_TXER_TXD4_BIT) \
00230     | _BV(PHY_RXD2_AD2_BIT) \
00231     | _BV(PHY_RXD3_AD3_BIT) \
00232     | _BV(PHY_RXCLK_10BTSER_BIT) \
00233     | _BV(PHY_CRS_AD4_BIT) \
00234     | _BV(PHY_COL_RMII_BIT)
00235 #endif
00236 
00237 #elif defined (MCU_AT91SAM7X256)
00238 
00239 #define EMAC_PIO_PER            PIOB_PER
00240 #define EMAC_PIO_OER            PIOB_OER
00241 #define EMAC_PIO_CODR           PIOB_CODR
00242 #define EMAC_PIO_SODR           PIOB_SODR
00243 #define EMAC_PIO_PUER           PIOB_PUER
00244 #define EMAC_PIO_PUDR           PIOB_PUDR
00245 #define EMAC_PIO_ASR            PIOB_ASR
00246 #define EMAC_PIO_BSR            PIOB_BSR
00247 #define EMAC_PIO_PDR            PIOB_PDR
00248 
00249 #define PHY_TXCLK_ISOLATE_BIT   0
00250 #define PHY_REFCLK_XT2_BIT      0
00251 #define PHY_TXEN_BIT            1
00252 #define PHY_TXD0_BIT            2
00253 #define PHY_TXD1_BIT            3
00254 #define PHY_CRS_AD4_BIT         4
00255 #define PHY_RXD0_AD0_BIT        5
00256 #define PHY_RXD1_AD1_BIT        6
00257 #define PHY_RXER_RXD4_RPTR_BIT  7
00258 #define PHY_MDC_BIT             8
00259 #define PHY_MDIO_BIT            9
00260 #define PHY_TXD2_BIT            10
00261 #define PHY_TXD3_BIT            11
00262 #define PHY_TXER_TXD4_BIT       12
00263 #define PHY_RXD2_AD2_BIT        13
00264 #define PHY_RXD3_AD3_BIT        14
00265 #define PHY_RXDV_TESTMODE_BIT   15
00266 #define PHY_COL_RMII_BIT        16
00267 #define PHY_RXCLK_10BTSER_BIT   17
00268 #ifndef PHY_PWRDN_BIT
00269 #define PHY_PWRDN_BIT           18
00270 #endif
00271 #define PHY_MDINTR_BIT          26
00272 
00273 #define PHY_MII_PINS_A 0 \
00274     | _BV(PHY_REFCLK_XT2_BIT) \
00275     | _BV(PHY_TXEN_BIT) \
00276     | _BV(PHY_TXD0_BIT) \
00277     | _BV(PHY_TXD1_BIT) \
00278     | _BV(PHY_CRS_AD4_BIT) \
00279     | _BV(PHY_RXD0_AD0_BIT) \
00280     | _BV(PHY_RXD1_AD1_BIT) \
00281     | _BV(PHY_RXER_RXD4_RPTR_BIT) \
00282     | _BV(PHY_MDC_BIT) \
00283     | _BV(PHY_MDIO_BIT) \
00284     | _BV(PHY_TXD2_BIT) \
00285     | _BV(PHY_TXD3_BIT) \
00286     | _BV(PHY_TXER_TXD4_BIT) \
00287     | _BV(PHY_RXD2_AD2_BIT) \
00288     | _BV(PHY_RXD3_AD3_BIT) \
00289     | _BV(PHY_RXDV_TESTMODE_BIT) \
00290     | _BV(PHY_COL_RMII_BIT) \
00291     | _BV(PHY_RXCLK_10BTSER_BIT)
00292 
00293 #define PHY_MII_PINS_B 0
00294 
00295 #endif
00296 
00300 struct _EMACINFO {
00301 #ifdef NUT_PERFMON
00302     u_long ni_rx_packets;       
00303     u_long ni_tx_packets;       
00304     u_long ni_overruns;         
00305     u_long ni_rx_frame_errors;  
00306     u_long ni_rx_crc_errors;    
00307     u_long ni_rx_missed_errors; 
00308 #endif
00309     HANDLE volatile ni_rx_rdy;  
00310     HANDLE volatile ni_tx_rdy;  
00311     HANDLE ni_mutex;            
00312     volatile int ni_tx_queued;  
00313     volatile int ni_tx_quelen;  
00314     volatile int ni_insane;     
00315     int ni_iomode;              
00316 };
00317 
00321 typedef struct _EMACINFO EMACINFO;
00322 
00323 /*
00324  * TODO: Buffers and their descriptors should be part of the EMACINFO
00325  * structure. Actually there will be no dual Ethernet chip (sure?),
00326  * but just to keep the code clean.
00327  */
00328 typedef struct _BufDescriptor {
00329     u_int addr;
00330     u_int stat;
00331 } BufDescriptor;
00332 
00333 static volatile BufDescriptor txBufTab[EMAC_TX_BUFFERS];
00334 static volatile u_char txBuf[EMAC_TX_BUFFERS * EMAC_TX_BUFSIZ] __attribute__ ((aligned(8)));
00335 static u_int txBufIdx;
00336 
00337 static volatile BufDescriptor rxBufTab[EMAC_RX_BUFFERS];
00338 static volatile u_char rxBuf[EMAC_RX_BUFFERS * EMAC_RX_BUFSIZ] __attribute__ ((aligned(8)));
00339 static u_int rxBufIdx;
00340 
00341 #define RXBUF_OWNERSHIP     0x00000001
00342 #define RXBUF_WRAP          0x00000002
00343 #define RXBUF_ADDRMASK      0xFFFFFFFC
00344 
00345 #define RXS_BROADCAST_ADDR  0x80000000  
00346 #define RXS_MULTICAST_HASH  0x40000000  
00347 #define RXS_UNICAST_HASH    0x20000000  
00348 #define RXS_EXTERNAL_ADDR   0x10000000  
00349 #define RXS_SA1_ADDR        0x04000000  
00350 #define RXS_SA2_ADDR        0x02000000  
00351 #define RXS_SA3_ADDR        0x01000000  
00352 #define RXS_SA4_ADDR        0x00800000  
00353 #define RXS_TYPE_ID         0x00400000  
00354 #define RXS_VLAN_TAG        0x00200000  
00355 #define RXS_PRIORITY_TAG    0x00100000  
00356 #define RXS_VLAN_PRIORITY   0x000E0000  
00357 #define RXS_CFI_IND         0x00010000  
00358 #define RXS_EOF             0x00008000  
00359 #define RXS_SOF             0x00004000  
00360 #define RXS_RBF_OFFSET      0x00003000  
00361 #define RXS_LENGTH_FRAME    0x000007FF  
00363 #define TXS_USED            0x80000000  
00364 #define TXS_WRAP            0x40000000  
00365 #define TXS_ERROR           0x20000000  
00366 #define TXS_UNDERRUN        0x10000000  
00367 #define TXS_NO_BUFFER       0x08000000  
00368 #define TXS_NO_CRC          0x00010000  
00369 #define TXS_LAST_BUFF       0x00008000  
00376 
00377 
00384 static u_short phy_inw(u_char reg)
00385 {
00386     /* PHY read command. */
00387     outr(EMAC_MAN, EMAC_SOF | EMAC_RW_READ | EMAC_CODE | 
00388         (NIC_PHY_ADDR << EMAC_PHYA_LSB) | (reg << EMAC_REGA_LSB));
00389 
00390     /* Wait until PHY logic completed. */
00391     while ((inr(EMAC_NSR) & EMAC_IDLE) == 0);
00392 
00393     /* Get data from PHY maintenance register. */
00394     return (u_short) (inr(EMAC_MAN) >> EMAC_DATA_LSB);
00395 }
00396 
00397 #ifndef PHY_MODE_RMII
00398 
00404 static void phy_outw(u_char reg, u_short val)
00405 {
00406     /* PHY write command. */
00407     outr(EMAC_MAN, EMAC_SOF | EMAC_RW_WRITE | EMAC_CODE | 
00408         (NIC_PHY_ADDR << EMAC_PHYA_LSB) | (reg << EMAC_REGA_LSB) | val);
00409 
00410     /* Wait until PHY logic completed. */
00411     while ((inr(EMAC_NSR) & EMAC_IDLE) == 0);
00412 }
00413 #endif
00414 
00420 static int EmacReset(u_long tmo)
00421 {
00422     u_short phyval;
00423 
00424     outr(PMC_PCER, _BV(PIOA_ID));
00425     outr(PMC_PCER, _BV(PIOB_ID));
00426     outr(PMC_PCER, _BV(EMAC_ID));
00427 
00428     /* Disable TESTMODE and set PHY address 0 and by disabling pull-ups. */
00429     outr(EMAC_PIO_PUDR,
00430 #if !defined(PHY_MODE_RMII)
00431         /* Additionally disable RMII, if not configured. */
00432         _BV(PHY_COL_RMII_BIT) | 
00433 #endif
00434         _BV(PHY_RXDV_TESTMODE_BIT) | 
00435         _BV(PHY_RXD0_AD0_BIT) | _BV(PHY_RXD1_AD1_BIT) |
00436         _BV(PHY_RXD2_AD2_BIT) | _BV(PHY_RXD3_AD3_BIT) | _BV(PHY_CRS_AD4_BIT));
00437 
00438 #ifdef PHY_PWRDN_BIT
00439     /* Disable PHY power down. */
00440     outr(EMAC_PIO_PER, _BV(PHY_PWRDN_BIT));
00441     outr(EMAC_PIO_OER, _BV(PHY_PWRDN_BIT));
00442 #ifdef PHY_PWRDN_NEGPOL
00443     outr(EMAC_PIO_SODR, _BV(PHY_PWRDN_BIT));
00444 #else
00445     outr(EMAC_PIO_CODR, _BV(PHY_PWRDN_BIT));
00446 #endif
00447 #endif
00448 
00449     /* Toggle external hardware reset pin. */
00450     outr(RSTC_MR, RSTC_KEY | (2 << RSTC_ERSTL_LSB) | RSTC_URSTEN);
00451     outr(RSTC_CR, RSTC_KEY | RSTC_EXTRST);
00452     while ((inr(RSTC_SR) & RSTC_NRSTL) == 0);
00453 
00454     /* Re-enable pull-ups. */
00455     outr(EMAC_PIO_PUER, _BV(PHY_RXDV_TESTMODE_BIT) | 
00456         _BV(PHY_RXD0_AD0_BIT) | _BV(PHY_RXD1_AD1_BIT) |
00457         _BV(PHY_RXD2_AD2_BIT) | _BV(PHY_RXD3_AD3_BIT) | _BV(PHY_CRS_AD4_BIT));
00458 
00459     /* Configure MII port. */
00460     outr(EMAC_PIO_ASR, PHY_MII_PINS_A);
00461     outr(EMAC_PIO_BSR, PHY_MII_PINS_B);
00462     outr(EMAC_PIO_PDR, PHY_MII_PINS_A | PHY_MII_PINS_B);
00463 
00464     /* Enable management port. */
00465     outr(EMAC_NCR, inr(EMAC_NCR) | EMAC_MPE);
00466     outr(EMAC_NCFGR, inr(EMAC_NCFGR) | EMAC_CLK_HCLK_64);
00467 
00468     /* Wait for PHY ready. */
00469     NutDelay(255);
00470 
00471 #ifndef PHY_MODE_RMII
00472     /* Clear MII isolate. */
00473     phy_inw(NIC_PHY_BMCR);
00474     phy_outw(NIC_PHY_BMCR, phy_inw(NIC_PHY_BMCR) & ~NIC_PHY_BMCR_ISOLATE);
00475 #endif
00476 
00477 //    /* For some unknown reason it seems to be required to read the ID registers first. */
00478 //    if (phy_inw(NIC_PHY_ID1) != 0x0181 || (phy_inw(NIC_PHY_ID2) & 0xFFF0) != 0xB8A0) {
00479 //        outr(EMAC_NCR, inr(EMAC_NCR) & ~EMAC_MPE);
00480 //        return -1;
00481 //    }
00482 
00483 // TODO: Make phy id configurable
00484 /* PHY ID */
00485 #define MII_DM9161_ID_H     0x0181
00486 #define MII_DM9161_ID_L     0xb8a0
00487 
00488 #define MII_AM79C875_ID_H   0x0022
00489 #define MII_AM79C875_ID_L   0x5540      
00490 
00491 #define MII_MICREL_ID_H     0x0022
00492 #define MII_MICREL_ID_L     0x1610
00493 
00494      /* For some unknown reason it seems to be required to read the ID 
00495 registers first. */
00496 
00497      // Check for DM PHY (as used on the ATMEL EK)
00498      if (phy_inw(NIC_PHY_ID1) != MII_DM9161_ID_H ||
00499         (phy_inw(NIC_PHY_ID2) & 0xFFF0) != MII_DM9161_ID_L) {
00500      // Check for MICREL PHY (as used on the Olimex SAM7-EX256)         
00501          if (phy_inw(NIC_PHY_ID1) != MII_MICREL_ID_H ||
00502            (phy_inw(NIC_PHY_ID2) & 0xFFF0) != MII_MICREL_ID_L) {
00503             outr(EMAC_NCR, inr(EMAC_NCR) & ~EMAC_MPE);
00504             return -1;
00505          }
00506      }
00507 
00508 
00509 // TODO: END
00510 
00511     /* Handle auto negotiation if configured. */
00512     phyval = phy_inw(NIC_PHY_BMCR);
00513     if (phyval & NIC_PHY_BMCR_ANEGENA) {
00514         /* Wait for auto negotiation completed. */
00515         phy_inw(NIC_PHY_BMSR);  /* Discard previously latched status. */
00516         while (--tmo) {
00517             if (phy_inw(NIC_PHY_BMSR) & NIC_PHY_BMSR_ANCOMPL) {
00518                 break;
00519             }
00520         }
00521         /* Return error on link timeout. */
00522         if (tmo == 0) {
00523             outr(EMAC_NCR, inr(EMAC_NCR) & ~EMAC_MPE);
00524             return -1;
00525         }
00526 
00527         /*
00528          * Read link partner abilities and configure EMAC.
00529          */
00530         phyval = phy_inw(NIC_PHY_ANLPAR);
00531         if (phyval & NIC_PHY_ANEG_TX_FDX) {
00532             /* 100Mb full duplex. */
00533             outr(EMAC_NCFGR, inr(EMAC_NCFGR) | EMAC_SPD | EMAC_FD);
00534         }
00535         else if (phyval & NIC_PHY_ANEG_TX_HDX) {
00536             /* 100Mb half duplex. */
00537             outr(EMAC_NCFGR, (inr(EMAC_NCFGR) & ~EMAC_FD) | EMAC_SPD);
00538         }
00539         else if (phyval & NIC_PHY_ANEG_10_FDX) {
00540             /* 10Mb full duplex. */
00541             outr(EMAC_NCFGR, (inr(EMAC_NCFGR) & ~EMAC_SPD) | EMAC_FD);
00542         }
00543         else {
00544             /* 10Mb half duplex. */
00545             outr(EMAC_NCFGR, inr(EMAC_NCFGR) & ~(EMAC_SPD | EMAC_FD));
00546         }
00547     }
00548 
00549     /* Disable management port. */
00550     outr(EMAC_NCR, inr(EMAC_NCR) & ~EMAC_MPE);
00551 
00552     /* Enable receive and transmit clocks and set MII mode. */
00553 #ifdef PHY_MODE_RMII
00554     outr(EMAC_USRIO, EMAC_RMII | EMAC_CLKEN);
00555 #else
00556     outr(EMAC_USRIO, EMAC_CLKEN);
00557 #endif
00558 
00559     return 0;
00560 }
00561 
00562 /*
00563  * NIC interrupt entry.
00564  */
00565 static void EmacInterrupt(void *arg)
00566 {
00567     u_int isr;
00568     EMACINFO *ni = (EMACINFO *) ((NUTDEVICE *) arg)->dev_dcb;
00569 
00570     /* Read interrupt status and disable interrupts. */
00571     isr = inr(EMAC_ISR);
00572 
00573     /* Receiver interrupt. */
00574     //if ((isr & EMAC_RCOMP) != 0 || (isr & EMAC_ROVR) != 0 || (inr(EMAC_RSR) & EMAC_REC) != 0) {
00575     if ((isr & (EMAC_RCOMP | EMAC_ROVR | EMAC_RXUBR)) != 0) {
00576         //outr(EMAC_RSR, EMAC_REC);
00577         outr(EMAC_IDR, EMAC_RCOMP | EMAC_ROVR | EMAC_RXUBR);
00578         NutEventPostFromIrq(&ni->ni_rx_rdy);
00579     }
00580 
00581     /* Transmitter interrupt. */
00582     if ((isr & EMAC_TCOMP) != 0 || (inr(EMAC_TSR) & EMAC_COMP) != 0) {
00583         //outr(EMAC_TSR, EMAC_COMP);
00584         NutEventPostFromIrq(&ni->ni_tx_rdy);
00585     }
00586 }
00587 
00593 static int EmacGetPacket(EMACINFO * ni, NETBUF ** nbp)
00594 {
00595     int rc = -1;
00596     u_int fbc = 0;
00597     u_int i;
00598     *nbp = NULL;
00599 
00600     /*
00601      * Search the next frame start. Release any fragment.
00602      */
00603     while ((rxBufTab[rxBufIdx].addr & RXBUF_OWNERSHIP) != 0 && (rxBufTab[rxBufIdx].stat & RXS_SOF) == 0) {
00604         rxBufTab[rxBufIdx].addr &= ~(RXBUF_OWNERSHIP);
00605         rxBufIdx++;
00606         if (rxBufIdx >= EMAC_RX_BUFFERS) {
00607             rxBufIdx = 0;
00608         }
00609     }
00610 
00611     /*
00612      * Determine the size of the next frame.
00613      */
00614     i = rxBufIdx;
00615     while (rxBufTab[i].addr & RXBUF_OWNERSHIP) {
00616         if (i != rxBufIdx && (rxBufTab[i].stat & RXS_SOF) != 0) {
00617             do {
00618                 rxBufTab[rxBufIdx].addr &= ~(RXBUF_OWNERSHIP);
00619                 rxBufIdx++;
00620                 if (rxBufIdx >= EMAC_RX_BUFFERS) {
00621                     rxBufIdx = 0;
00622                 }
00623             } while ((rxBufTab[rxBufIdx].addr & RXBUF_OWNERSHIP) != 0 && (rxBufTab[rxBufIdx].stat & RXS_SOF) == 0);
00624             break;
00625         }
00626         if ((fbc = rxBufTab[i].stat & RXS_LENGTH_FRAME) != 0) {
00627             break;
00628         }
00629         i++;
00630         if (i >= EMAC_RX_BUFFERS) {
00631             i = 0;
00632         }
00633     }
00634 
00635     if (fbc) {
00636         /*
00637          * Receiving long packets is unexpected. Let's declare the 
00638          * chip insane. Short packets will be handled by the caller.
00639          */
00640         if (fbc > 1536) {
00641             ni->ni_insane = 1;
00642         } else {
00643             *nbp = NutNetBufAlloc(0, NBAF_DATALINK, (u_short)fbc);
00644             if (*nbp != NULL) {
00645                 u_char *bp = (u_char *) (* nbp)->nb_dl.vp;
00646                 u_int len;
00647 
00648                 while (fbc) {
00649                     if (fbc > EMAC_RX_BUFSIZ) {
00650                         len = EMAC_RX_BUFSIZ;
00651                     } else {
00652                         len = fbc;
00653                     }
00654                     memcpy(bp, (void *) (rxBufTab[rxBufIdx].addr & RXBUF_ADDRMASK), len);
00655                     rxBufTab[rxBufIdx].addr &= ~RXBUF_OWNERSHIP;
00656                     rxBufIdx++;
00657                     if (rxBufIdx >= EMAC_RX_BUFFERS) {
00658                         rxBufIdx = 0;
00659                     }
00660                     fbc -= len;
00661                     bp += len;
00662                 }
00663                 rc = 0;
00664             }
00665         }
00666     }
00667     return rc;
00668 }
00669 
00684 static int EmacPutPacket(int bufnum, EMACINFO * ni, NETBUF * nb)
00685 {
00686     int rc = -1;
00687     u_int sz;
00688     u_char *buf;
00689 
00690     /*
00691      * Calculate the number of bytes to be send. Do not send packets 
00692      * larger than the Ethernet maximum transfer unit. The MTU
00693      * consist of 1500 data bytes plus the 14 byte Ethernet header
00694      * plus 4 bytes CRC. We check the data bytes only.
00695      */
00696     if ((sz = nb->nb_nw.sz + nb->nb_tp.sz + nb->nb_ap.sz) > ETHERMTU) {
00697         return -1;
00698     }
00699     sz += nb->nb_dl.sz;
00700     if (sz & 1) {
00701         sz++;
00702     }
00703 
00704     /* Disable EMAC interrupts. */
00705     NutIrqDisable(&sig_EMAC);
00706 
00707     /* TODO: Check for link. */
00708     if (ni->ni_insane == 0) {
00709         buf = (u_char *) txBufTab[bufnum].addr;
00710         memcpy(buf, nb->nb_dl.vp, nb->nb_dl.sz);
00711         buf += nb->nb_dl.sz;
00712         memcpy(buf, nb->nb_nw.vp, nb->nb_nw.sz);
00713         buf += nb->nb_nw.sz;
00714         memcpy(buf, nb->nb_tp.vp, nb->nb_tp.sz);
00715         buf += nb->nb_tp.sz;
00716         memcpy(buf, nb->nb_ap.vp, nb->nb_ap.sz);
00717         sz |= TXS_LAST_BUFF;
00718         if (bufnum) {
00719             sz |= TXS_WRAP;
00720         }
00721         txBufTab[bufnum].stat = sz;
00722         outr(EMAC_NCR, inr(EMAC_NCR) | EMAC_TSTART);
00723         rc = 0;
00724 #ifdef NUT_PERFMON
00725         ni->ni_tx_packets++;
00726 #endif
00727     }
00728 
00729     /* Enable EMAC interrupts. */
00730     NutIrqEnable(&sig_EMAC);
00731 
00732     return rc;
00733 }
00734 
00735 
00743 static int EmacStart(CONST u_char * mac)
00744 {
00745     u_int i;
00746 
00747     /* Set local MAC address. */
00748     outr(EMAC_SA1L, (mac[3] << 24) | (mac[2] << 16) | (mac[1] << 8) | mac[0]);
00749     outr(EMAC_SA1H, (mac[5] << 8) | mac[4]);
00750 
00751     /* Initialize receive buffer descriptors. */
00752     for (i = 0; i < EMAC_RX_BUFFERS - 1; i++) {
00753         rxBufTab[i].addr = (u_int) (&rxBuf[i * EMAC_RX_BUFSIZ]) & RXBUF_ADDRMASK;
00754     }
00755     rxBufTab[i].addr = ((u_int) (&rxBuf[i * EMAC_RX_BUFSIZ]) & RXBUF_ADDRMASK) | RXBUF_WRAP;
00756     outr(EMAC_RBQP, (u_int) rxBufTab);
00757 
00758     /* Initialize transmit buffer descriptors. */
00759     txBufTab[0].addr = (u_int) (&txBuf[0]);
00760     txBufTab[0].stat = TXS_USED;
00761     txBufTab[1].addr = (u_int) (&txBuf[EMAC_TX_BUFSIZ]);
00762     txBufTab[1].stat = TXS_USED | TXS_WRAP;
00763     outr(EMAC_TBQP, (u_int) txBufTab);
00764 
00765     /* Clear receiver status. */
00766     outr(EMAC_RSR, EMAC_OVR | EMAC_REC | EMAC_BNA);
00767 
00768     /* Copy all frames and discard FCS. */
00769     outr(EMAC_NCFGR, inr(EMAC_NCFGR) | EMAC_CAF | EMAC_DRFCS);
00770 
00771     /* Enable receiver, transmitter and statistics. */
00772     outr(EMAC_NCR, inr(EMAC_NCR) | EMAC_TE | EMAC_RE | EMAC_WESTAT);
00773 
00774     return 0;
00775 }
00776 
00781 THREAD(EmacRxThread, arg)
00782 {
00783     NUTDEVICE *dev;
00784     IFNET *ifn;
00785     EMACINFO *ni;
00786     NETBUF *nb;
00787 
00788     dev = arg;
00789     ifn = (IFNET *) dev->dev_icb;
00790     ni = (EMACINFO *) dev->dev_dcb;
00791 
00792     /*
00793      * This is a temporary hack. Due to a change in initialization,
00794      * we may not have got a MAC address yet. Wait until one has been
00795      * set.
00796      */
00797     for (;;) {
00798         int i;
00799 
00800         for (i = 0; i < sizeof(ifn->if_mac); i++) {
00801             if (ifn->if_mac[i] && ifn->if_mac[i] != 0xFF) {
00802                 break;
00803             }
00804         }
00805         if (i < sizeof(ifn->if_mac)) {
00806             break;
00807         }
00808         NutSleep(63);
00809     }
00810 
00811     /*
00812      * Do not continue unless we managed to start the NIC. We are
00813      * trapped here if the Ethernet link cannot be established.
00814      * This happens, for example, if no Ethernet cable is plugged
00815      * in.
00816      */
00817     while (EmacStart(ifn->if_mac)) {
00818         EmacReset(EMAC_LINK_LOOPS);
00819         NutSleep(1000);
00820     }
00821 
00822     /* Initialize the access mutex. */
00823     NutEventPost(&ni->ni_mutex);
00824 
00825     /* Run at high priority. */
00826     NutThreadSetPriority(9);
00827 
00828     /* Enable receive and transmit interrupts. */
00829     outr(EMAC_IER, EMAC_ROVR | EMAC_TCOMP | EMAC_TUND | EMAC_RXUBR | EMAC_RCOMP);
00830     NutIrqEnable(&sig_EMAC);
00831 
00832     for (;;) {
00833         /*
00834          * Wait for the arrival of new packets or poll the receiver every 
00835          * 200 milliseconds. This short timeout helps a bit to deal with
00836          * the SAM9260 Ethernet problem.
00837          */
00838         NutEventWait(&ni->ni_rx_rdy, 200);
00839 
00840         /*
00841          * Fetch all packets from the NIC's internal buffer and pass 
00842          * them to the registered handler.
00843          */
00844         while (EmacGetPacket(ni, &nb) == 0) {
00845             /* Discard short packets. */
00846             if (nb->nb_dl.sz < 60) {
00847                 NutNetBufFree(nb);
00848             } else {
00849                 (*ifn->if_recv) (dev, nb);
00850             }
00851         }
00852         outr(EMAC_IER, EMAC_ROVR | EMAC_RXUBR | EMAC_RCOMP);
00853 
00854         /* We got a weird chip, try to restart it. */
00855         while (ni->ni_insane) {
00856             EmacReset(EMAC_LINK_LOOPS);
00857             if (EmacStart(ifn->if_mac) == 0) {
00858                 ni->ni_insane = 0;
00859                 ni->ni_tx_queued = 0;
00860                 ni->ni_tx_quelen = 0;
00861                 NutIrqEnable(&sig_EMAC);
00862             } else {
00863                 NutSleep(1000);
00864             }
00865         }
00866     }
00867 }
00868 
00879 int EmacOutput(NUTDEVICE * dev, NETBUF * nb)
00880 {
00881     static u_long mx_wait = 5000;
00882     int rc = -1;
00883     EMACINFO *ni = (EMACINFO *) dev->dev_dcb;
00884 
00885     /*
00886      * After initialization we are waiting for a long time to give
00887      * the PHY a chance to establish an Ethernet link.
00888      */
00889     while (rc) {
00890         if (ni->ni_insane) {
00891             break;
00892         }
00893         if (NutEventWait(&ni->ni_mutex, mx_wait)) {
00894             break;
00895         }
00896 
00897         /* Check for packet queue space. */
00898         if ((txBufTab[txBufIdx].stat & TXS_USED) == 0) {
00899             if (NutEventWait(&ni->ni_tx_rdy, 500) && (txBufTab[txBufIdx].stat & TXS_USED) == 0) {
00900                 /* No queue space. Release the lock and give up. */
00901                 txBufTab[txBufIdx].stat |= TXS_USED;
00902                 txBufIdx++;
00903                 txBufIdx &= 1;
00904                 NutEventPost(&ni->ni_mutex);
00905                 break;
00906             }
00907         } else {
00908             if (inr(EMAC_TSR) & EMAC_UND) {
00909                 txBufIdx = 0;
00910                 outr(EMAC_TSR, EMAC_UND);
00911             }
00912             if (inr(EMAC_TSR) & EMAC_COMP) {
00913                 outr(EMAC_TSR, EMAC_COMP);
00914             }
00915 
00916             if ((rc = EmacPutPacket(txBufIdx, ni, nb)) == 0) {
00917                 txBufIdx++;
00918                 txBufIdx &= 1;
00919             }
00920         }
00921         NutEventPost(&ni->ni_mutex);
00922     }
00923 
00924     /*
00925      * Probably no Ethernet link. Significantly reduce the waiting
00926      * time, so following transmission will soon return an error.
00927      */
00928     if (rc) {
00929         mx_wait = 500;
00930     } else {
00931         /* Ethernet works. Set a long waiting time in case we
00932            temporarly lose the link next time. */
00933         mx_wait = 5000;
00934     }
00935     return rc;
00936 }
00937 
00947 int EmacInit(NUTDEVICE * dev)
00948 {
00949     EMACINFO *ni = (EMACINFO *) dev->dev_dcb;
00950 
00951     /* Reset the controller. */
00952     if (EmacReset(EMAC_LINK_LOOPS)) {
00953         if (EmacReset(EMAC_LINK_LOOPS)) {
00954             return -1;
00955         }
00956     }
00957 
00958     /* Clear EMACINFO structure. */
00959     memset(ni, 0, sizeof(EMACINFO));
00960 
00961     /* Register interrupt handler. */
00962     if (NutRegisterIrqHandler(&sig_EMAC, EmacInterrupt, dev)) {
00963         return -1;
00964     }
00965 
00966     /* Start the receiver thread. */
00967     if (NutThreadCreate("emacrx", EmacRxThread, dev, NUT_THREAD_NICRXSTACK) == NULL) {
00968         return -1;
00969     }
00970     return 0;
00971 }
00972 
00973 static EMACINFO dcb_eth0;
00974 
00980 static IFNET ifn_eth0 = {
00981     IFT_ETHER,                  
00982     {0, 0, 0, 0, 0, 0},         
00983     0,                          
00984     0,                          
00985     0,                          
00986     ETHERMTU,                   
00987     0,                          
00988     0,                          
00989     0,                          
00990     NutEtherInput,              
00991     EmacOutput,                 
00992     NutEtherOutput              
00993 };
00994 
01004 NUTDEVICE devAt91Emac = {
01005     0,                          
01006     {'e', 't', 'h', '0', 0, 0, 0, 0, 0},        
01007     IFTYP_NET,                  
01008     0,                          
01009     0,                          
01010     &ifn_eth0,                  
01011     &dcb_eth0,                  
01012     EmacInit,                   
01013     0,                          
01014     0,                          
01015     0,                          
01016 #ifdef __HARVARD_ARCH__
01017     0,                          
01018 #endif
01019     0,                          
01020     0,                          
01021     0                           
01022 };
01023 

© 2000-2007 by egnite Software GmbH - visit http://www.ethernut.de/