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$
00036  * Revision 1.16  2009/02/06 15:37:39  haraldkipp
00037  * Added stack space multiplier and addend. Adjusted stack space.
00038  *
00039  * Revision 1.15  2009/01/17 11:26:37  haraldkipp
00040  * Getting rid of two remaining BSD types in favor of stdint.
00041  * Replaced 'u_int' by 'unsinged int' and 'uptr_t' by 'uintptr_t'.
00042  *
00043  * Revision 1.14  2008/08/28 11:12:15  haraldkipp
00044  * Added interface flags, which will be required to implement Ethernet ioctl
00045  * functions.
00046  *
00047  * Revision 1.13  2008/08/11 06:59:04  haraldkipp
00048  * BSD types replaced by stdint types (feature request #1282721).
00049  *
00050  * Revision 1.12  2008/08/06 12:43:41  haraldkipp
00051  * First EMAC reset failed on power-up. Initialize EMAC clock and MII mode
00052  * earlier.
00053  * Added support for Ethernut 5 (AT91SAM9XE reference design).
00054  *
00055  * Revision 1.11  2007/09/06 20:07:24  olereinhardt
00056  * Changed phy detection and added support for micel phy (SAM7-EX256 Board)
00057  *
00058  * Revision 1.10  2007/08/29 07:43:52  haraldkipp
00059  * Documentation updated and corrected.
00060  *
00061  * Revision 1.9  2007/05/02 11:20:26  haraldkipp
00062  * Pull-up enable/disable simplified.
00063  * Added multicast table entry.
00064  *
00065  * Revision 1.8  2007/04/20 13:06:08  haraldkipp
00066  * Previous change failed on SAM7X-EK. We are now using PHY address 0 by
00067  * default and disable all pull-ups during PHY reset.
00068  *
00069  * Revision 1.7  2007/04/12 09:13:10  haraldkipp
00070  * Bugfix: PHY initialization may fail with pull-ups enabled.
00071  *
00072  * Revision 1.6  2007/02/15 16:00:45  haraldkipp
00073  * Configurable buffer usage and link timeout.
00074  *
00075  * Revision 1.5  2006/10/17 11:06:12  haraldkipp
00076  * Number of loops waiting for links increased to 10000 and NIC resets
00077  * reduced. This will help to link to auto MDIX via direct cable.
00078  *
00079  * Revision 1.4  2006/10/08 16:41:34  haraldkipp
00080  * PHY address and power down bit are now configurable.
00081  *
00082  * Revision 1.3  2006/10/05 17:10:37  haraldkipp
00083  * Link detection was unreliable. This also caused bug #1567785.
00084  * Now NutRegisterDevice will return an error, if there is no
00085  * link available. Applications may then call NutRegisterDevice again.
00086  *
00087  * Revision 1.2  2006/09/29 12:29:16  haraldkipp
00088  * Several fixes to make it running reliably on the AT91SAM9260.
00089  *
00090  * Revision 1.1  2006/08/31 18:58:47  haraldkipp
00091  * More general AT91 MAC driver replaces the SAM7X specific version.
00092  * This had been tested on the SAM9260, but loses Ethernet packets
00093  * for a yet unknown reason.
00094  *
00095  */
00096 
00097 #include <cfg/os.h>
00098 #include <cfg/dev.h>
00099 #include <arch/arm.h>
00100 #include <cfg/arch/gpio.h>
00101 
00102 #include <string.h>
00103 
00104 #include <sys/atom.h>
00105 #include <sys/heap.h>
00106 #include <sys/thread.h>
00107 #include <sys/event.h>
00108 #include <sys/timer.h>
00109 #include <sys/confnet.h>
00110 
00111 #include <netinet/if_ether.h>
00112 #include <net/ether.h>
00113 #include <net/if_var.h>
00114 
00115 #include <dev/irqreg.h>
00116 #include <dev/at91_emac.h>
00117 
00118 #ifdef NUTDEBUG
00119 #include <stdio.h>
00120 #endif
00121 
00122 #ifndef NUT_THREAD_NICRXSTACK
00123 /* arm-elf-gcc used 168 bytes with optimized, 412 bytes with debug code. */
00124 #define NUT_THREAD_NICRXSTACK   320
00125 #endif
00126 
00127 #ifndef EMAC_RX_BUFFERS
00128 #define EMAC_RX_BUFFERS         32
00129 #endif
00130 #define EMAC_RX_BUFSIZ          128
00131 
00132 #define EMAC_TX_BUFFERS         2
00133 #ifndef EMAC_TX_BUFSIZ
00134 #define EMAC_TX_BUFSIZ          1536
00135 #endif
00136 
00137 #ifndef EMAC_LINK_LOOPS
00138 #define EMAC_LINK_LOOPS         1000000
00139 #endif
00140 
00145 #define NIC_PHY_BMCR            0x00    
00146 #define NIC_PHY_BMCR_COLTEST    0x0080  
00147 #define NIC_PHY_BMCR_FDUPLEX    0x0100  
00148 #define NIC_PHY_BMCR_ANEGSTART  0x0200  
00149 #define NIC_PHY_BMCR_ISOLATE    0x0400  
00150 #define NIC_PHY_BMCR_PWRDN      0x0800  
00151 #define NIC_PHY_BMCR_ANEGENA    0x1000  
00152 #define NIC_PHY_BMCR_100MBPS    0x2000  
00153 #define NIC_PHY_BMCR_LOOPBACK   0x4000  
00154 #define NIC_PHY_BMCR_RESET      0x8000  
00156 #define NIC_PHY_BMSR            0x01    
00157 #define NIC_PHY_BMSR_ANCOMPL    0x0020  
00158 #define NIC_PHY_BMSR_LINKSTAT   0x0004  
00160 #define NIC_PHY_ID1             0x02    
00161 #define NIC_PHY_ID2             0x03    
00162 #define NIC_PHY_ANAR            0x04    
00163 #define NIC_PHY_ANLPAR          0x05    
00164 #define NIC_PHY_ANEG_NP         0x8000  
00165 #define NIC_PHY_ANEG_ACK        0x4000  
00166 #define NIC_PHY_ANEG_RF         0x2000  
00167 #define NIC_PHY_ANEG_FCS        0x0400  
00168 #define NIC_PHY_ANEG_T4         0x0200  
00169 #define NIC_PHY_ANEG_TX_FDX     0x0100  
00170 #define NIC_PHY_ANEG_TX_HDX     0x0080  
00171 #define NIC_PHY_ANEG_10_FDX     0x0040  
00172 #define NIC_PHY_ANEG_10_HDX     0x0020  
00173 #define NIC_PHY_ANEG_BINSEL     0x001F  
00175 #define NIC_PHY_ANER            0x06    
00178 
00179 
00185 #ifndef NIC_PHY_ADDR
00186 #define NIC_PHY_ADDR            0
00187 #endif
00188 
00194 #ifndef NIC_PHY_UID
00195 #define NIC_PHY_UID 0xffffffff
00196 #endif
00197 
00205 #define CHECK_ALL_KNOWN_PHY_IDS
00206 
00207 #if defined (MCU_AT91SAM9260) || defined(MCU_AT91SAM9XE512)
00208 
00214 #define PHY_MODE_RMII
00215 
00216 //#define EMAC_PIO_PER            PIOA_PER
00217 //#define EMAC_PIO_OER            PIOA_OER
00218 //#define EMAC_PIO_CODR           PIOA_CODR
00219 #define EMAC_PIO_ASR            PIOA_ASR
00220 #define EMAC_PIO_BSR            PIOA_BSR
00221 #define EMAC_PIO_PDR            PIOA_PDR
00222 
00223 #define PHY_TXD0_BIT            PA12_ETX0_A     
00224 #define PHY_TXD1_BIT            PA13_ETX1_A     
00225 #define PHY_RXD0_AD0_BIT        PA14_ERX0_A     
00226 #define PHY_RXD1_AD1_BIT        PA15_ERX1_A     
00227 #define PHY_TXEN_BIT            PA16_ETXEN_A    
00228 #define PHY_RXDV_TESTMODE_BIT   PA17_ERXDV_A    
00229 #define PHY_RXER_RXD4_RPTR_BIT  PA18_ERXER_A    
00230 #define PHY_TXCLK_ISOLATE_BIT   PA19_ETXCK_A    
00231 #define PHY_MDC_BIT             PA20_EMDC_A     
00232 #define PHY_MDIO_BIT            PA21_EMDIO_A    
00234 #ifndef PHY_MODE_RMII
00235 #define PHY_TXD2_BIT            PA10_ETX2_B     
00236 #define PHY_TXD3_BIT            PA11_ETX3_B     
00237 #define PHY_TXER_TXD4_BIT       PA22_ETXER_B    
00238 #define PHY_RXCLK_10BTSER_BIT   PA27_ERXCK_B    
00239 #define PHY_COL_RMII_BIT        PA29_ECOL_B     
00240 #endif
00241 
00242 #define PHY_RXD2_AD2_BIT        PA25_ERX2_B     
00243 #define PHY_RXD3_AD3_BIT        PA26_ERX3_B     
00244 #define PHY_CRS_AD4_BIT         PA28_ECRS_B     
00246 #define PHY_MII_PINS_A 0 \
00247     | _BV(PHY_TXD0_BIT) \
00248     | _BV(PHY_TXD1_BIT) \
00249     | _BV(PHY_RXD0_AD0_BIT) \
00250     | _BV(PHY_RXD1_AD1_BIT) \
00251     | _BV(PHY_TXEN_BIT) \
00252     | _BV(PHY_RXDV_TESTMODE_BIT) \
00253     | _BV(PHY_RXER_RXD4_RPTR_BIT) \
00254     | _BV(PHY_TXCLK_ISOLATE_BIT) \
00255     | _BV(PHY_MDC_BIT) \
00256     | _BV(PHY_MDIO_BIT)
00257 
00258 #ifdef PHY_MODE_RMII
00259 #define PHY_MII_PINS_B 0
00260 #else
00261 #define PHY_MII_PINS_B 0 \
00262     | _BV(PHY_TXD2_BIT) \
00263     | _BV(PHY_TXD3_BIT) \
00264     | _BV(PHY_TXER_TXD4_BIT) \
00265     | _BV(PHY_RXD2_AD2_BIT) \
00266     | _BV(PHY_RXD3_AD3_BIT) \
00267     | _BV(PHY_RXCLK_10BTSER_BIT) \
00268     | _BV(PHY_CRS_AD4_BIT) \
00269     | _BV(PHY_COL_RMII_BIT)
00270 #endif
00271 
00272 #elif defined (MCU_AT91SAM7X)
00273 
00274 #define EMAC_PIO_PER            PIOB_PER
00275 #define EMAC_PIO_OER            PIOB_OER
00276 #define EMAC_PIO_CODR           PIOB_CODR
00277 #define EMAC_PIO_SODR           PIOB_SODR
00278 #define EMAC_PIO_PUER           PIOB_PUER
00279 #define EMAC_PIO_PUDR           PIOB_PUDR
00280 #define EMAC_PIO_ASR            PIOB_ASR
00281 #define EMAC_PIO_BSR            PIOB_BSR
00282 #define EMAC_PIO_PDR            PIOB_PDR
00283 
00284 #define PHY_TXCLK_ISOLATE_BIT   0
00285 #define PHY_REFCLK_XT2_BIT      0
00286 #define PHY_TXEN_BIT            1
00287 #define PHY_TXD0_BIT            2
00288 #define PHY_TXD1_BIT            3
00289 #define PHY_CRS_AD4_BIT         4
00290 #define PHY_RXD0_AD0_BIT        5
00291 #define PHY_RXD1_AD1_BIT        6
00292 #define PHY_RXER_RXD4_RPTR_BIT  7
00293 #define PHY_MDC_BIT             8
00294 #define PHY_MDIO_BIT            9
00295 #define PHY_TXD2_BIT            10
00296 #define PHY_TXD3_BIT            11
00297 #define PHY_TXER_TXD4_BIT       12
00298 #define PHY_RXD2_AD2_BIT        13
00299 #define PHY_RXD3_AD3_BIT        14
00300 #define PHY_RXDV_TESTMODE_BIT   15
00301 #define PHY_COL_RMII_BIT        16
00302 #define PHY_RXCLK_10BTSER_BIT   17
00303 #ifndef PHY_PWRDN_BIT
00304 #define PHY_PWRDN_BIT           18
00305 #endif
00306 #define PHY_MDINTR_BIT          26
00307 
00308 #define PHY_MII_PINS_A 0 \
00309     | _BV(PHY_REFCLK_XT2_BIT) \
00310     | _BV(PHY_TXEN_BIT) \
00311     | _BV(PHY_TXD0_BIT) \
00312     | _BV(PHY_TXD1_BIT) \
00313     | _BV(PHY_CRS_AD4_BIT) \
00314     | _BV(PHY_RXD0_AD0_BIT) \
00315     | _BV(PHY_RXD1_AD1_BIT) \
00316     | _BV(PHY_RXER_RXD4_RPTR_BIT) \
00317     | _BV(PHY_MDC_BIT) \
00318     | _BV(PHY_MDIO_BIT) \
00319     | _BV(PHY_TXD2_BIT) \
00320     | _BV(PHY_TXD3_BIT) \
00321     | _BV(PHY_TXER_TXD4_BIT) \
00322     | _BV(PHY_RXD2_AD2_BIT) \
00323     | _BV(PHY_RXD3_AD3_BIT) \
00324     | _BV(PHY_RXDV_TESTMODE_BIT) \
00325     | _BV(PHY_COL_RMII_BIT) \
00326     | _BV(PHY_RXCLK_10BTSER_BIT)
00327 
00328 #define PHY_MII_PINS_B 0
00329 
00330 #endif
00331 
00335 struct _EMACINFO {
00336 #ifdef NUT_PERFMON
00337     uint32_t ni_rx_packets;       
00338     uint32_t ni_tx_packets;       
00339     uint32_t ni_overruns;         
00340     uint32_t ni_rx_frame_errors;  
00341     uint32_t ni_rx_crc_errors;    
00342     uint32_t ni_rx_missed_errors; 
00343 #endif
00344     HANDLE volatile ni_rx_rdy;  
00345     HANDLE volatile ni_tx_rdy;  
00346     HANDLE ni_mutex;            
00347     volatile int ni_tx_queued;  
00348     volatile int ni_tx_quelen;  
00349     volatile int ni_insane;     
00350     int ni_iomode;              
00351 };
00352 
00356 typedef struct _EMACINFO EMACINFO;
00357 
00358 /*
00359  * TODO: Buffers and their descriptors should be part of the EMACINFO
00360  * structure. Actually there will be no dual Ethernet chip (sure?),
00361  * but just to keep the code clean.
00362  */
00363 typedef struct _BufDescriptor {
00364     unsigned int addr;
00365     unsigned int stat;
00366 } BufDescriptor;
00367 
00368 static volatile BufDescriptor txBufTab[EMAC_TX_BUFFERS];
00369 static volatile uint8_t txBuf[EMAC_TX_BUFFERS * EMAC_TX_BUFSIZ] __attribute__ ((aligned(8)));
00370 static unsigned int txBufIdx;
00371 
00372 static volatile BufDescriptor rxBufTab[EMAC_RX_BUFFERS];
00373 static volatile uint8_t rxBuf[EMAC_RX_BUFFERS * EMAC_RX_BUFSIZ] __attribute__ ((aligned(8)));
00374 static unsigned int rxBufIdx;
00375 
00376 #define RXBUF_OWNERSHIP     0x00000001
00377 #define RXBUF_WRAP          0x00000002
00378 #define RXBUF_ADDRMASK      0xFFFFFFFC
00379 
00380 #define RXS_BROADCAST_ADDR  0x80000000  
00381 #define RXS_MULTICAST_HASH  0x40000000  
00382 #define RXS_UNICAST_HASH    0x20000000  
00383 #define RXS_EXTERNAL_ADDR   0x10000000  
00384 #define RXS_SA1_ADDR        0x04000000  
00385 #define RXS_SA2_ADDR        0x02000000  
00386 #define RXS_SA3_ADDR        0x01000000  
00387 #define RXS_SA4_ADDR        0x00800000  
00388 #define RXS_TYPE_ID         0x00400000  
00389 #define RXS_VLAN_TAG        0x00200000  
00390 #define RXS_PRIORITY_TAG    0x00100000  
00391 #define RXS_VLAN_PRIORITY   0x000E0000  
00392 #define RXS_CFI_IND         0x00010000  
00393 #define RXS_EOF             0x00008000  
00394 #define RXS_SOF             0x00004000  
00395 #define RXS_RBF_OFFSET      0x00003000  
00396 #define RXS_LENGTH_FRAME    0x000007FF  
00398 #define TXS_USED            0x80000000  
00399 #define TXS_WRAP            0x40000000  
00400 #define TXS_ERROR           0x20000000  
00401 #define TXS_UNDERRUN        0x10000000  
00402 #define TXS_NO_BUFFER       0x08000000  
00403 #define TXS_NO_CRC          0x00010000  
00404 #define TXS_LAST_BUFF       0x00008000  
00411 
00412 
00419 static uint16_t phy_inw(uint8_t reg)
00420 {
00421     /* PHY read command. */
00422     outr(EMAC_MAN, EMAC_SOF | EMAC_RW_READ | EMAC_CODE | 
00423         (NIC_PHY_ADDR << EMAC_PHYA_LSB) | (reg << EMAC_REGA_LSB));
00424 
00425     /* Wait until PHY logic completed. */
00426     while ((inr(EMAC_NSR) & EMAC_IDLE) == 0);
00427 
00428     /* Get data from PHY maintenance register. */
00429     return (uint16_t) (inr(EMAC_MAN) >> EMAC_DATA_LSB);
00430 }
00431 
00432 #if !defined(PHY_MODE_RMII) || (NIC_PHY_UID == 0x0007C0F0)
00433 
00439 static void phy_outw(uint8_t reg, uint16_t val)
00440 {
00441     /* PHY write command. */
00442     outr(EMAC_MAN, EMAC_SOF | EMAC_RW_WRITE | EMAC_CODE | 
00443         (NIC_PHY_ADDR << EMAC_PHYA_LSB) | (reg << EMAC_REGA_LSB) | val);
00444 
00445     /* Wait until PHY logic completed. */
00446     while ((inr(EMAC_NSR) & EMAC_IDLE) == 0);
00447 }
00448 #endif
00449 
00455 static int probePhy(uint32_t tmo)
00456 {
00457     uint32_t physID;
00458     uint16_t phyval;
00459 
00460     /* Read Phy ID. Ignore revision number. */
00461     physID = (phy_inw(NIC_PHY_ID2) & 0xFFF0) | ((phy_inw(NIC_PHY_ID1) << 16) & 0xFFFF0000);
00462 #if NIC_PHY_UID != 0xffffffff
00463     if ( physID != (NIC_PHY_UID & 0xFFFFFFF0) ) {
00464         outr(EMAC_NCR, inr(EMAC_NCR) & ~EMAC_MPE);
00465         return -1;
00466     }
00467 #elif defined(CHECK_ALL_KNOWN_PHY_IDS)
00468 #define MII_DM9161_ID     0x0181b8a0
00469 #define MII_AM79C875_ID   0x00225540
00470 #define MII_MICREL_ID     0x00221610
00471 #define MII_LAN8700_ID    0x0007c0c0
00472 
00473     if ( physID != MII_DM9161_ID && physID != MII_AM79C875_ID && physID != MII_MICREL_ID && physID != MII_LAN8700_ID ) {
00474         outr(EMAC_NCR, inr(EMAC_NCR) & ~EMAC_MPE);
00475         return -1;
00476     }
00477 #endif
00478 
00479     /* Handle auto negotiation if configured. */
00480     phyval = phy_inw(NIC_PHY_BMCR);
00481     if (phyval & NIC_PHY_BMCR_ANEGENA) {
00482         /* Wait for auto negotiation completed. */
00483         phy_inw(NIC_PHY_BMSR);  /* Discard previously latched status. */
00484         while (--tmo) {
00485             if (phy_inw(NIC_PHY_BMSR) & NIC_PHY_BMSR_ANCOMPL) {
00486                 break;
00487             }
00488         }
00489         /* Return error on link timeout. */
00490         if (tmo == 0) {
00491             outr(EMAC_NCR, inr(EMAC_NCR) & ~EMAC_MPE);
00492             return -1;
00493         }
00494 
00495         /*
00496         * Read link partner abilities and configure EMAC.
00497         */
00498         phyval = phy_inw(NIC_PHY_ANLPAR);
00499         if (phyval & NIC_PHY_ANEG_TX_FDX) {
00500             /* 100Mb full duplex. */
00501             outr(EMAC_NCFGR, inr(EMAC_NCFGR) | EMAC_SPD | EMAC_FD);
00502         }
00503         else if (phyval & NIC_PHY_ANEG_TX_HDX) {
00504             /* 100Mb half duplex. */
00505             outr(EMAC_NCFGR, (inr(EMAC_NCFGR) & ~EMAC_FD) | EMAC_SPD);
00506         }
00507         else if (phyval & NIC_PHY_ANEG_10_FDX) {
00508             /* 10Mb full duplex. */
00509             outr(EMAC_NCFGR, (inr(EMAC_NCFGR) & ~EMAC_SPD) | EMAC_FD);
00510         }
00511         else {
00512             /* 10Mb half duplex. */
00513             outr(EMAC_NCFGR, inr(EMAC_NCFGR) & ~(EMAC_SPD | EMAC_FD));
00514         }
00515     }
00516 
00517     /* Disable management port. */
00518     outr(EMAC_NCR, inr(EMAC_NCR) & ~EMAC_MPE);
00519 
00520     return 0;
00521 }
00522 
00528 static int EmacReset(uint32_t tmo)
00529 {
00530     outr(PMC_PCER, _BV(PIOA_ID));
00531     outr(PMC_PCER, _BV(PIOB_ID));
00532     outr(PMC_PCER, _BV(EMAC_ID));
00533 
00534 #if defined(MCU_AT91SAM7X) && (NIC_PHY_UID == 0x0181B8A0)
00535     {
00536     uint32_t rstcr_tmp;
00537 
00538         /* Disable TESTMODE and set PHY address 0 and by disabling pull-ups. */
00539         outr(EMAC_PIO_PUDR,
00540 #if !defined(PHY_MODE_RMII)
00541         /* Additionally disable RMII, if not configured. */
00542         _BV(PHY_COL_RMII_BIT) | 
00543 #endif
00544         _BV(PHY_RXDV_TESTMODE_BIT) | 
00545         _BV(PHY_RXD0_AD0_BIT) | _BV(PHY_RXD1_AD1_BIT) |
00546         _BV(PHY_RXD2_AD2_BIT) | _BV(PHY_RXD3_AD3_BIT) | _BV(PHY_CRS_AD4_BIT));
00547 
00548 #ifdef PHY_PWRDN_BIT
00549         /* Disable PHY power down. */
00550         outr(EMAC_PIO_PER, _BV(PHY_PWRDN_BIT));
00551         outr(EMAC_PIO_OER, _BV(PHY_PWRDN_BIT));
00552 #ifdef PHY_PWRDN_NEGPOL
00553         outr(EMAC_PIO_SODR, _BV(PHY_PWRDN_BIT));
00554 #else
00555         outr(EMAC_PIO_CODR, _BV(PHY_PWRDN_BIT));
00556 #endif
00557 #endif
00558 
00559         /* Toggle external hardware reset pin. */
00560         rstcr_tmp = inr(RSTC_MR) & 0x00FFFFFF;
00561         outr(RSTC_MR, RSTC_KEY | (2 << RSTC_ERSTL_LSB));
00562  
00563         outr(RSTC_CR, RSTC_KEY | RSTC_EXTRST);
00564         while ((inr(RSTC_SR) & RSTC_NRSTL) == 0);
00565         outr(RSTC_MR, RSTC_KEY | rstcr_tmp); 
00566 
00567         /* Re-enable pull-ups. */
00568         outr(EMAC_PIO_PUER, _BV(PHY_RXDV_TESTMODE_BIT) | 
00569             _BV(PHY_RXD0_AD0_BIT) | _BV(PHY_RXD1_AD1_BIT) |
00570             _BV(PHY_RXD2_AD2_BIT) | _BV(PHY_RXD3_AD3_BIT) | _BV(PHY_CRS_AD4_BIT));
00571     }
00572 #endif /* MCU_AT91SAM7X */
00573 
00574     /* Configure MII port. */
00575     outr(EMAC_PIO_ASR, PHY_MII_PINS_A);
00576     outr(EMAC_PIO_BSR, PHY_MII_PINS_B);
00577     outr(EMAC_PIO_PDR, PHY_MII_PINS_A | PHY_MII_PINS_B);
00578 
00579     /* Enable receive and transmit clocks and set MII mode. */
00580 #ifdef PHY_MODE_RMII
00581     outr(EMAC_USRIO, EMAC_RMII | EMAC_CLKEN);
00582 #else
00583     outr(EMAC_USRIO, EMAC_CLKEN);
00584 #endif
00585 
00586     /* Enable management port. */
00587     outr(EMAC_NCR, inr(EMAC_NCR) | EMAC_MPE);
00588     outr(EMAC_NCFGR, inr(EMAC_NCFGR) | EMAC_CLK_HCLK_64);
00589 
00590     /* Wait for PHY ready. */
00591     NutDelay(255);
00592 
00593 #if NIC_PHY_UID == 0x0007C0F0
00594     /* Set LAN8710 mode. */
00595     phy_outw(18, phy_inw(18) | 0x00E0);
00596     phy_outw(NIC_PHY_BMCR, NIC_PHY_BMCR_RESET);
00597     NutSleep(100);
00598 #endif
00599 
00600 #ifndef PHY_MODE_RMII
00601     /* Clear MII isolate. */
00602     phy_inw(NIC_PHY_BMCR);
00603     phy_outw(NIC_PHY_BMCR, phy_inw(NIC_PHY_BMCR) & ~NIC_PHY_BMCR_ISOLATE);
00604 #endif
00605 
00606     return probePhy(tmo);
00607 }
00608 
00609 /*
00610  * NIC interrupt entry.
00611  */
00612 static void EmacInterrupt(void *arg)
00613 {
00614     unsigned int isr;
00615     EMACINFO *ni = (EMACINFO *) ((NUTDEVICE *) arg)->dev_dcb;
00616 
00617     /* Read interrupt status and disable interrupts. */
00618     isr = inr(EMAC_ISR);
00619 
00620     /* Receiver interrupt. */
00621     //if ((isr & EMAC_RCOMP) != 0 || (isr & EMAC_ROVR) != 0 || (inr(EMAC_RSR) & EMAC_REC) != 0) {
00622     if ((isr & (EMAC_RCOMP | EMAC_ROVR | EMAC_RXUBR)) != 0) {
00623         //outr(EMAC_RSR, EMAC_REC);
00624         outr(EMAC_IDR, EMAC_RCOMP | EMAC_ROVR | EMAC_RXUBR);
00625         NutEventPostFromIrq(&ni->ni_rx_rdy);
00626     }
00627 
00628     /* Transmitter interrupt. */
00629     if ((isr & EMAC_TCOMP) != 0 || (inr(EMAC_TSR) & EMAC_COMP) != 0) {
00630         //outr(EMAC_TSR, EMAC_COMP);
00631         NutEventPostFromIrq(&ni->ni_tx_rdy);
00632     }
00633 }
00634 
00640 static int EmacGetPacket(EMACINFO * ni, NETBUF ** nbp)
00641 {
00642     int rc = -1;
00643     unsigned int fbc = 0;
00644     unsigned int i;
00645     *nbp = NULL;
00646 
00647     /*
00648      * Search the next frame start. Release any fragment.
00649      */
00650     while ((rxBufTab[rxBufIdx].addr & RXBUF_OWNERSHIP) != 0 && (rxBufTab[rxBufIdx].stat & RXS_SOF) == 0) {
00651         rxBufTab[rxBufIdx].addr &= ~(RXBUF_OWNERSHIP);
00652         rxBufIdx++;
00653         if (rxBufIdx >= EMAC_RX_BUFFERS) {
00654             rxBufIdx = 0;
00655         }
00656     }
00657 
00658     /*
00659      * Determine the size of the next frame.
00660      */
00661     i = rxBufIdx;
00662     while (rxBufTab[i].addr & RXBUF_OWNERSHIP) {
00663         if (i != rxBufIdx && (rxBufTab[i].stat & RXS_SOF) != 0) {
00664             do {
00665                 rxBufTab[rxBufIdx].addr &= ~(RXBUF_OWNERSHIP);
00666                 rxBufIdx++;
00667                 if (rxBufIdx >= EMAC_RX_BUFFERS) {
00668                     rxBufIdx = 0;
00669                 }
00670             } while ((rxBufTab[rxBufIdx].addr & RXBUF_OWNERSHIP) != 0 && (rxBufTab[rxBufIdx].stat & RXS_SOF) == 0);
00671             break;
00672         }
00673         if ((fbc = rxBufTab[i].stat & RXS_LENGTH_FRAME) != 0) {
00674             break;
00675         }
00676         i++;
00677         if (i >= EMAC_RX_BUFFERS) {
00678             i = 0;
00679         }
00680     }
00681 
00682     if (fbc) {
00683         /*
00684          * Receiving long packets is unexpected. Let's declare the 
00685          * chip insane. Short packets will be handled by the caller.
00686          */
00687         if (fbc > 1536) {
00688             ni->ni_insane = 1;
00689         } else {
00690             *nbp = NutNetBufAlloc(0, NBAF_DATALINK, (uint16_t)fbc);
00691             if (*nbp != NULL) {
00692                 uint8_t *bp = (uint8_t *) (* nbp)->nb_dl.vp;
00693                 unsigned int len;
00694 
00695                 while (fbc) {
00696                     if (fbc > EMAC_RX_BUFSIZ) {
00697                         len = EMAC_RX_BUFSIZ;
00698                     } else {
00699                         len = fbc;
00700                     }
00701                     memcpy(bp, (void *) (rxBufTab[rxBufIdx].addr & RXBUF_ADDRMASK), len);
00702                     rxBufTab[rxBufIdx].addr &= ~RXBUF_OWNERSHIP;
00703                     rxBufIdx++;
00704                     if (rxBufIdx >= EMAC_RX_BUFFERS) {
00705                         rxBufIdx = 0;
00706                     }
00707                     fbc -= len;
00708                     bp += len;
00709                 }
00710                 rc = 0;
00711             }
00712         }
00713     }
00714     return rc;
00715 }
00716 
00731 static int EmacPutPacket(int bufnum, EMACINFO * ni, NETBUF * nb)
00732 {
00733     int rc = -1;
00734     unsigned int sz;
00735     uint8_t *buf;
00736 
00737     /*
00738      * Calculate the number of bytes to be send. Do not send packets 
00739      * larger than the Ethernet maximum transfer unit. The MTU
00740      * consist of 1500 data bytes plus the 14 byte Ethernet header
00741      * plus 4 bytes CRC. We check the data bytes only.
00742      */
00743     if ((sz = nb->nb_nw.sz + nb->nb_tp.sz + nb->nb_ap.sz) > ETHERMTU) {
00744         return -1;
00745     }
00746     sz += nb->nb_dl.sz;
00747     if (sz & 1) {
00748         sz++;
00749     }
00750 
00751     /* Disable EMAC interrupts. */
00752     NutIrqDisable(&sig_EMAC);
00753 
00754     /* TODO: Check for link. */
00755     if (ni->ni_insane == 0) {
00756         buf = (uint8_t *) txBufTab[bufnum].addr;
00757         memcpy(buf, nb->nb_dl.vp, nb->nb_dl.sz);
00758         buf += nb->nb_dl.sz;
00759         memcpy(buf, nb->nb_nw.vp, nb->nb_nw.sz);
00760         buf += nb->nb_nw.sz;
00761         memcpy(buf, nb->nb_tp.vp, nb->nb_tp.sz);
00762         buf += nb->nb_tp.sz;
00763         memcpy(buf, nb->nb_ap.vp, nb->nb_ap.sz);
00764         sz |= TXS_LAST_BUFF;
00765         if (bufnum) {
00766             sz |= TXS_WRAP;
00767         }
00768         txBufTab[bufnum].stat = sz;
00769         outr(EMAC_NCR, inr(EMAC_NCR) | EMAC_TSTART);
00770         rc = 0;
00771 #ifdef NUT_PERFMON
00772         ni->ni_tx_packets++;
00773 #endif
00774     }
00775 
00776     /* Enable EMAC interrupts. */
00777     NutIrqEnable(&sig_EMAC);
00778 
00779     return rc;
00780 }
00781 
00782 
00790 static int EmacStart(CONST uint8_t * mac)
00791 {
00792     unsigned int i;
00793 
00794     /* Set local MAC address. */
00795     outr(EMAC_SA1L, (mac[3] << 24) | (mac[2] << 16) | (mac[1] << 8) | mac[0]);
00796     outr(EMAC_SA1H, (mac[5] << 8) | mac[4]);
00797 
00798     /* Initialize receive buffer descriptors. */
00799     for (i = 0; i < EMAC_RX_BUFFERS - 1; i++) {
00800         rxBufTab[i].addr = (unsigned int) (&rxBuf[i * EMAC_RX_BUFSIZ]) & RXBUF_ADDRMASK;
00801     }
00802     rxBufTab[i].addr = ((unsigned int) (&rxBuf[i * EMAC_RX_BUFSIZ]) & RXBUF_ADDRMASK) | RXBUF_WRAP;
00803     outr(EMAC_RBQP, (unsigned int) rxBufTab);
00804 
00805     /* Initialize transmit buffer descriptors. */
00806     txBufTab[0].addr = (unsigned int) (&txBuf[0]);
00807     txBufTab[0].stat = TXS_USED;
00808     txBufTab[1].addr = (unsigned int) (&txBuf[EMAC_TX_BUFSIZ]);
00809     txBufTab[1].stat = TXS_USED | TXS_WRAP;
00810     outr(EMAC_TBQP, (unsigned int) txBufTab);
00811 
00812     /* Clear receiver status. */
00813     outr(EMAC_RSR, EMAC_OVR | EMAC_REC | EMAC_BNA);
00814 
00815     /* Discard FCS. */
00816     outr(EMAC_NCFGR, inr(EMAC_NCFGR) | EMAC_DRFCS);
00817 
00818     /* Enable receiver, transmitter and statistics. */
00819     outr(EMAC_NCR, inr(EMAC_NCR) | EMAC_TE | EMAC_RE | EMAC_WESTAT);
00820 
00821     return 0;
00822 }
00823 
00828 THREAD(EmacRxThread, arg)
00829 {
00830     NUTDEVICE *dev;
00831     IFNET *ifn;
00832     EMACINFO *ni;
00833     NETBUF *nb;
00834 
00835     dev = arg;
00836     ifn = (IFNET *) dev->dev_icb;
00837     ni = (EMACINFO *) dev->dev_dcb;
00838 
00839     /*
00840      * This is a temporary hack. Due to a change in initialization,
00841      * we may not have got a MAC address yet. Wait until a valid one
00842      * has been set.
00843      */
00844     while (!ETHER_IS_UNICAST(ifn->if_mac)) {
00845         NutSleep(10);
00846     }
00847 
00848     /*
00849      * Do not continue unless we managed to start the NIC. We are
00850      * trapped here if the Ethernet link cannot be established.
00851      * This happens, for example, if no Ethernet cable is plugged
00852      * in.
00853      */
00854     while (EmacStart(ifn->if_mac)) {
00855         EmacReset(EMAC_LINK_LOOPS);
00856         NutSleep(1000);
00857     }
00858 
00859     /* Initialize the access mutex. */
00860     NutEventPost(&ni->ni_mutex);
00861 
00862     /* Run at high priority. */
00863     NutThreadSetPriority(9);
00864 
00865     /* Enable receive and transmit interrupts. */
00866     outr(EMAC_IER, EMAC_ROVR | EMAC_TCOMP | EMAC_TUND | EMAC_RXUBR | EMAC_RCOMP);
00867     NutIrqEnable(&sig_EMAC);
00868 
00869     for (;;) {
00870         /*
00871          * Wait for the arrival of new packets or poll the receiver every 
00872          * 200 milliseconds. This short timeout helps a bit to deal with
00873          * the SAM9260 Ethernet problem.
00874          */
00875         NutEventWait(&ni->ni_rx_rdy, 200);
00876 
00877         /*
00878          * Fetch all packets from the NIC's internal buffer and pass 
00879          * them to the registered handler.
00880          */
00881         while (EmacGetPacket(ni, &nb) == 0) {
00882             /* Discard short packets. */
00883             if (nb->nb_dl.sz < 60) {
00884                 NutNetBufFree(nb);
00885             } else {
00886                 (*ifn->if_recv) (dev, nb);
00887             }
00888         }
00889         outr(EMAC_IER, EMAC_ROVR | EMAC_RXUBR | EMAC_RCOMP);
00890 
00891         /* We got a weird chip, try to restart it. */
00892         while (ni->ni_insane) {
00893             EmacReset(EMAC_LINK_LOOPS);
00894             if (EmacStart(ifn->if_mac) == 0) {
00895                 ni->ni_insane = 0;
00896                 ni->ni_tx_queued = 0;
00897                 ni->ni_tx_quelen = 0;
00898                 NutIrqEnable(&sig_EMAC);
00899             } else {
00900                 NutSleep(1000);
00901             }
00902         }
00903     }
00904 }
00905 
00916 int EmacOutput(NUTDEVICE * dev, NETBUF * nb)
00917 {
00918     static uint32_t mx_wait = 5000;
00919     int rc = -1;
00920     EMACINFO *ni = (EMACINFO *) dev->dev_dcb;
00921 
00922     /*
00923      * After initialization we are waiting for a long time to give
00924      * the PHY a chance to establish an Ethernet link.
00925      */
00926     while (rc) {
00927         if (ni->ni_insane) {
00928             break;
00929         }
00930         if (NutEventWait(&ni->ni_mutex, mx_wait)) {
00931             break;
00932         }
00933 
00934         /* Check for packet queue space. */
00935         if ((txBufTab[txBufIdx].stat & TXS_USED) == 0) {
00936             if (NutEventWait(&ni->ni_tx_rdy, 500) && (txBufTab[txBufIdx].stat & TXS_USED) == 0) {
00937                 /* No queue space. Release the lock and give up. */
00938                 txBufTab[txBufIdx].stat |= TXS_USED;
00939                 txBufIdx++;
00940                 txBufIdx &= 1;
00941                 NutEventPost(&ni->ni_mutex);
00942                 break;
00943             }
00944         } else {
00945             if (inr(EMAC_TSR) & EMAC_UND) {
00946                 txBufIdx = 0;
00947                 outr(EMAC_TSR, EMAC_UND);
00948             }
00949             if (inr(EMAC_TSR) & EMAC_COMP) {
00950                 outr(EMAC_TSR, EMAC_COMP);
00951             }
00952 
00953             if ((rc = EmacPutPacket(txBufIdx, ni, nb)) == 0) {
00954                 txBufIdx++;
00955                 txBufIdx &= 1;
00956             }
00957         }
00958         NutEventPost(&ni->ni_mutex);
00959     }
00960 
00961     /*
00962      * Probably no Ethernet link. Significantly reduce the waiting
00963      * time, so following transmission will soon return an error.
00964      */
00965     if (rc) {
00966         mx_wait = 500;
00967     } else {
00968         /* Ethernet works. Set a long waiting time in case we
00969            temporarily lose the link next time. */
00970         mx_wait = 5000;
00971     }
00972     return rc;
00973 }
00974 
00984 int EmacInit(NUTDEVICE * dev)
00985 {
00986     EMACINFO *ni = (EMACINFO *) dev->dev_dcb;
00987 
00988     /* Reset the controller. */
00989     if (EmacReset(EMAC_LINK_LOOPS)) {
00990         if (EmacReset(EMAC_LINK_LOOPS)) {
00991             return -1;
00992         }
00993     }
00994 
00995     /* Clear EMACINFO structure. */
00996     memset(ni, 0, sizeof(EMACINFO));
00997 
00998     /* Register interrupt handler. */
00999     if (NutRegisterIrqHandler(&sig_EMAC, EmacInterrupt, dev)) {
01000         return -1;
01001     }
01002 
01003     /* Start the receiver thread. */
01004     if (NutThreadCreate("emacrx", EmacRxThread, dev, 
01005         (NUT_THREAD_NICRXSTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD) == NULL) {
01006         return -1;
01007     }
01008     return 0;
01009 }
01010 
01011 static EMACINFO dcb_eth0;
01012 
01018 static IFNET ifn_eth0 = {
01019     IFT_ETHER,                  
01020     0,                          
01021     {0, 0, 0, 0, 0, 0},         
01022     0,                          
01023     0,                          
01024     0,                          
01025     ETHERMTU,                   
01026     0,                          
01027     0,                          
01028     0,                          
01029     NutEtherInput,              
01030     EmacOutput,                 
01031     NutEtherOutput              
01032 };
01033 
01043 NUTDEVICE devAt91Emac = {
01044     0,                          
01045     {'e', 't', 'h', '0', 0, 0, 0, 0, 0},        
01046     IFTYP_NET,                  
01047     0,                          
01048     0,                          
01049     &ifn_eth0,                  
01050     &dcb_eth0,                  
01051     EmacInit,                   
01052     0,                          
01053     0,                          
01054     0,                          
01055 #ifdef __HARVARD_ARCH__
01056     0,                          
01057 #endif
01058     0,                          
01059     0,                          
01060     0                           
01061 };
01062 

© 2000-2010 by contributors - visit http://www.ethernut.de/