SAMV71 Xplained Ultra Software Package 1.4

gmacif.c

00001 /* ----------------------------------------------------------------------------
00002  *         SAM Software Package License 
00003  * ----------------------------------------------------------------------------
00004  * Copyright (c) 2013, Atmel Corporation
00005  *
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *
00011  * - Redistributions of source code must retain the above copyright notice,
00012  * this list of conditions and the disclaimer below.
00013  *
00014  * Atmel's name may not be used to endorse or promote products derived from
00015  * this software without specific prior written permission.
00016  *
00017  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00019  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
00020  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00022  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
00023  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00024  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00025  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
00026  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  * ----------------------------------------------------------------------------
00028  */
00029 
00030 /*
00031  * This file is a skeleton for developing Ethernet network interface
00032  * drivers for lwIP. Add code to the low_level functions and do a
00033  * search-and-replace for the word "gmacif" to replace it with
00034  * something that better describes your network interface.
00035  */
00036 
00037 /*----------------------------------------------------------------------------
00038  *        Headers
00039  *----------------------------------------------------------------------------*/
00040 
00041 #include <board.h>
00042 
00043 #include "lwip/opt.h"
00044 #include "gmacif.h"
00045 
00046 #include "lwip/def.h"
00047 #include "lwip/mem.h"
00048 #include "lwip/pbuf.h"
00049 #include "lwip/sys.h"
00050 #include "lwip/stats.h"
00051 #include "netif/etharp.h"
00052 #include "string.h"
00053 /*----------------------------------------------------------------------------
00054  *        Definitions
00055  *----------------------------------------------------------------------------*/
00056 
00057 #define _mem_barrier_   __DSB();
00058 
00059 /* Define those to better describe your network interface. */
00060 #define IFNAME0 'e'
00061 #define IFNAME1 'n'
00062 
00063 #define TX_BUFFERS        32     /** Must be a power of 2 */
00064 #define RX_BUFFERS        32     /** Must be a power of 2 */
00065 #define BUFFER_SIZE        512
00066 #define DUMMY_SIZE              2
00067 #define DUMMY_BUFF_SIZE         512
00068 
00069 #define GMAC_CAF_DISABLE  0
00070 #define GMAC_CAF_ENABLE   1
00071 #define GMAC_NBC_DISABLE  0
00072 #define GMAC_NBC_ENABLE   1
00073 
00074 /* The GMAC driver instance */
00075 sGmacd gGmacd;
00076 
00077 /* The GMACB driver instance */
00078 GMacb gGmacb;
00079 
00080 static struct gmacif Gmacif_config;
00081 
00082 /** The PINs for GMAC */
00083 const Pin gmacPins[] = {BOARD_GMAC_RUN_PINS};
00084 
00085 /** TX descriptors list */
00086 COMPILER_SECTION(".ram_nocache")
00087 COMPILER_ALIGNED(8) static sGmacTxDescriptor gTxDs[TX_BUFFERS], gDummyTxDs[DUMMY_SIZE];
00088 
00089 
00090 /** TX callbacks list */
00091 COMPILER_ALIGNED(8) static fGmacdTransferCallback gTxCbs[TX_BUFFERS], gDummyTxCbs[DUMMY_SIZE];
00092 
00093 /** RX descriptors list */
00094 COMPILER_SECTION(".ram_nocache")
00095 COMPILER_ALIGNED(8) static sGmacRxDescriptor gRxDs[RX_BUFFERS], gDummyRxDs[DUMMY_SIZE];
00096 
00097 /** Send Buffer */
00098 /* Section 3.6 of AMBA 2.0 spec states that burst should not cross 1K Boundaries.
00099    Receive buffer manager writes are burst of 2 words => 3 lsb bits of the address
00100    shall be set to 0 */
00101 COMPILER_ALIGNED(4) static uint8_t pTxBuffer[TX_BUFFERS * BUFFER_SIZE], pTxDummyBuffer[DUMMY_SIZE * DUMMY_BUFF_SIZE];
00102 
00103 /** Receive Buffer */
00104 COMPILER_ALIGNED(4) static uint8_t pRxBuffer[RX_BUFFERS * BUFFER_SIZE], pRxDummyBuffer[DUMMY_SIZE * DUMMY_BUFF_SIZE];
00105 
00106 
00107 /*---------------------------------------------------------------------------
00108  *         Local functions
00109  *---------------------------------------------------------------------------*/
00110 
00111 
00112 /* Forward declarations. */
00113 static void  gmacif_input(struct netif *netif);
00114 static err_t gmacif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr);
00115 
00116 static void glow_level_init(struct netif *netif)
00117 {
00118     struct gmacif *gmacif = netif->state;
00119     sGmacd *pGmacd = &gGmacd;
00120     GMacb  *pGmacb = &gGmacb;
00121     sGmacInit Que0, Que;
00122 
00123     /* set MAC hardware address length */
00124     netif->hwaddr_len = ETHARP_HWADDR_LEN;
00125     /* set MAC hardware address */
00126     netif->hwaddr[0] = gmacif->ethaddr.addr[0];
00127     netif->hwaddr[1] = gmacif->ethaddr.addr[1];
00128     netif->hwaddr[2] = gmacif->ethaddr.addr[2];
00129     netif->hwaddr[3] = gmacif->ethaddr.addr[3];
00130     netif->hwaddr[4] = gmacif->ethaddr.addr[4];
00131     netif->hwaddr[5] = gmacif->ethaddr.addr[5];
00132     /* maximum transfer unit */
00133     netif->mtu = 1500;
00134    
00135     /* device capabilities */
00136     netif->flags = NETIF_FLAG_BROADCAST;
00137     _mem_barrier_
00138     /* Init GMAC driver structure */
00139     memset(&Que0, 0, sizeof(Que0));
00140     Que0.bIsGem = 1;
00141     Que0.bDmaBurstLength = 4;
00142     Que0.pRxBuffer =pRxBuffer;
00143     Que0.pRxD = gRxDs;
00144     Que0.wRxBufferSize = BUFFER_SIZE;
00145     Que0.wRxSize = RX_BUFFERS;
00146     Que0.pTxBuffer = pTxBuffer;
00147     Que0.pTxD = gTxDs;
00148     Que0.wTxBufferSize = BUFFER_SIZE;
00149     Que0.wTxSize = TX_BUFFERS;
00150     Que0.pTxCb = gTxCbs;
00151     
00152 
00153     
00154     memset(&Que, 0, sizeof(Que));
00155     Que.bIsGem = 1;
00156     Que.bDmaBurstLength = 4;
00157     Que.pRxBuffer =pRxDummyBuffer;
00158     Que.pRxD = gDummyRxDs;
00159     Que.wRxBufferSize = DUMMY_BUFF_SIZE;
00160     Que.wRxSize = DUMMY_SIZE;
00161     Que.pTxBuffer = pTxDummyBuffer;
00162     Que.pTxD = gDummyTxDs;
00163     Que.wTxBufferSize = DUMMY_BUFF_SIZE;
00164     Que.wTxSize = DUMMY_SIZE;
00165     Que.pTxCb = gDummyTxCbs;
00166     SCB_CleanInvalidateDCache();
00167     GMACD_Init(pGmacd, GMAC, ID_GMAC, GMAC_CAF_ENABLE, GMAC_NBC_DISABLE);
00168     GMACD_InitTransfer(pGmacd, &Que, GMAC_QUE_2);
00169     
00170     GMACD_InitTransfer(pGmacd, &Que, GMAC_QUE_1);
00171     
00172     GMACD_InitTransfer(pGmacd, &Que0, GMAC_QUE_0);
00173     
00174     GMAC_SetAddress(gGmacd.pHw, 0, Gmacif_config.ethaddr.addr);
00175     
00176      /* Setup interrupts */  
00177     NVIC_ClearPendingIRQ(GMAC_IRQn);
00178     NVIC_EnableIRQ(GMAC_IRQn);
00179     /* Init GMACB driver */
00180     GMACB_Init(pGmacb, pGmacd, BOARD_GMAC_PHY_ADDR);
00181     GMACB_ResetPhy(pGmacb);
00182     /* PHY initialize */
00183     if (!GMACB_InitPhy(pGmacb, BOARD_MCK,  0, 0,  gmacPins, PIO_LISTSIZE(gmacPins)))
00184     {
00185         printf("P: PHY Initialize ERROR!\n\r");
00186         return ;
00187     }
00188    
00189     /* Auto Negotiate, work in RMII mode */
00190     if (!GMACB_AutoNegotiate(pGmacb))
00191     {
00192         printf( "P: Auto Negotiate ERROR!\n\r" ) ;
00193         return;
00194     }
00195     printf( "P: Link detected \n\r" ) ;
00196 }
00197 
00198 /**
00199  * This function should do the actual transmission of the packet. The packet is
00200  * contained in the pbuf that is passed to the function. This pbuf
00201  * might be chained.
00202  *
00203  * @param netif the lwip network interface structure for this gmacif
00204  * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
00205  * @return ERR_OK if the packet could be sent
00206  *         an err_t value if the packet couldn't be sent
00207  */
00208 static err_t glow_level_output(struct netif *netif, struct pbuf *p)
00209 {
00210     struct pbuf *q;
00211     uint8_t buf[1514];
00212     uint8_t *bufptr = &buf[0];
00213     uint8_t rc;
00214 
00215 #if ETH_PAD_SIZE
00216     pbuf_header(p, -ETH_PAD_SIZE);    /* drop the padding word */
00217 #endif
00218 
00219     for(q = p; q != NULL; q = q->next) {
00220         /* Send the data from the pbuf to the interface, one pbuf at a
00221         time. The size of the data in each pbuf is kept in the ->len
00222         variable. */
00223 
00224         /* send data from(q->payload, q->len); */
00225         memcpy(bufptr, q->payload, q->len);
00226         bufptr += q->len;
00227     }
00228 
00229     /* signal that packet should be sent(); */
00230 //    rc = GMACD_Send(&gGmacd, buf, 0, NULL, GMAC_QUE_2);
00231 //    rc = GMACD_Send(&gGmacd, buf, 0, NULL, GMAC_QUE_1);
00232     rc = GMACD_Send(&gGmacd, buf, p->tot_len, NULL, GMAC_QUE_0);
00233     if (rc != GMACD_OK) {
00234         return ERR_BUF;
00235     }
00236 #if ETH_PAD_SIZE
00237     pbuf_header(p, ETH_PAD_SIZE);     /* reclaim the padding word */
00238 #endif
00239 
00240     LINK_STATS_INC(link.xmit);
00241     return ERR_OK;
00242 }
00243 
00244 /**
00245  * Should allocate a pbuf and transfer the bytes of the incoming
00246  * packet from the interface into the pbuf.
00247  *
00248  * @param netif the lwip network interface structure for this gmacif
00249  * @return a pbuf filled with the received packet (including MAC header)
00250  *         NULL on memory error
00251  */
00252 static struct pbuf *glow_level_input(struct netif *netif)
00253 {                    
00254     struct pbuf *p, *q;
00255     u16_t len;
00256     uint8_t buf[1514];
00257     uint8_t *bufptr = &buf[0];
00258     
00259     uint32_t frmlen;
00260     uint8_t rc;
00261     
00262     /* Obtain the size of the packet and put it into the "len"
00263        variable. */
00264     rc = GMACD_Poll(&gGmacd, buf, (uint32_t)sizeof(buf), (uint32_t*)&frmlen, GMAC_QUE_0);
00265     if (rc != GMACD_OK)
00266     { 
00267       return NULL;
00268     }
00269     len = frmlen;
00270     
00271 #if ETH_PAD_SIZE
00272     len += ETH_PAD_SIZE;      /* allow room for Ethernet padding */
00273 #endif
00274 
00275     /* We allocate a pbuf chain of pbufs from the pool. */
00276     p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
00277     
00278     if (p != NULL) {
00279 #if ETH_PAD_SIZE
00280         pbuf_header(p, -ETH_PAD_SIZE);          /* drop the padding word */
00281 #endif
00282         /* We iterate over the pbuf chain until we have read the entire
00283          * packet into the pbuf. */
00284         for(q = p; q != NULL; q = q->next) {
00285             /* Read enough bytes to fill this pbuf in the chain. The
00286              * available data in the pbuf is given by the q->len
00287              * variable. */
00288             /* read data into(q->payload, q->len); */
00289             memcpy(q->payload, bufptr, q->len);
00290             bufptr += q->len;
00291             memory_sync();
00292         }
00293         /* acknowledge that packet has been read(); */
00294 
00295 #if ETH_PAD_SIZE
00296         pbuf_header(p, ETH_PAD_SIZE);           /* reclaim the padding word */
00297 #endif
00298         LINK_STATS_INC(link.recv);
00299     } else {
00300         /* drop packet(); */
00301         LINK_STATS_INC(link.memerr);
00302         LINK_STATS_INC(link.drop);
00303     }
00304     return p;
00305 }
00306 
00307 /**
00308  * This function is called by the TCP/IP stack when an IP packet
00309  * should be sent. It calls the function called glow_level_output() to
00310  * do the actual transmission of the packet.
00311  *
00312  */
00313 static err_t gmacif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr)
00314 {
00315     /* resolve hardware address, then send (or queue) packet */
00316     return etharp_output(netif, p, ipaddr);
00317 }
00318 
00319 /**
00320  * This function should be called when a packet is ready to be read
00321  * from the interface. It uses the function low_level_input() that
00322  * should handle the actual reception of bytes from the network
00323  * interface. Then the type of the received packet is determined and
00324  * the appropriate input function is called.
00325  *
00326  * @param netif the lwip network interface structure for this gmacif
00327  */
00328 
00329 static void gmacif_input(struct netif *netif)
00330 {
00331     struct gmacif *gmacif;
00332     struct eth_hdr *ethhdr;
00333     struct pbuf *p;
00334     gmacif = netif->state;
00335     
00336     /* move received packet into a new pbuf */
00337     p = glow_level_input(netif);
00338     /* no packet could be read, silently ignore this */
00339     if (p == NULL) return;
00340     /* points to packet payload, which starts with an Ethernet header */
00341     ethhdr = p->payload;
00342     
00343     switch (htons(ethhdr->type)) {
00344         /* IP packet? */
00345         case ETHTYPE_IP:
00346             /* skip Ethernet header */
00347             pbuf_header(p, (s16_t)(-sizeof(struct eth_hdr)));
00348             /* pass to network layer */
00349             netif->input(p, netif);
00350             break;
00351         
00352         case ETHTYPE_ARP:
00353             /* pass p to ARP module  */
00354             etharp_arp_input(netif, &gmacif->ethaddr, p);
00355             break;
00356         default:
00357             pbuf_free(p);
00358             p = NULL;
00359             break;
00360         }
00361 }
00362 
00363 /*----------------------------------------------------------------------------
00364  *        Exported functions
00365  *----------------------------------------------------------------------------*/
00366 
00367 
00368 /**
00369  * Set the MAC address of the system.
00370  * Should only be called before gmacif_init is called.
00371  * The stack calls gmacif_init after the user calls netif_add
00372  *
00373  */
00374 
00375 void gmacif_setmac(u8_t *addr)
00376 {
00377     Gmacif_config.ethaddr.addr[0] = addr[0];
00378     Gmacif_config.ethaddr.addr[1] = addr[1];
00379     Gmacif_config.ethaddr.addr[2] = addr[2];
00380     Gmacif_config.ethaddr.addr[3] = addr[3];
00381     Gmacif_config.ethaddr.addr[4] = addr[4];
00382     Gmacif_config.ethaddr.addr[5] = addr[5];
00383 }
00384 
00385 /**
00386  * Should be called at the beginning of the program to set up the
00387  * network interface. It calls the function glow_level_init() to do the
00388  * actual setup of the hardware.
00389  *
00390  */
00391 err_t gmacif_init(struct netif *netif)
00392 {
00393     struct gmacif *gmacif;
00394     gmacif = &Gmacif_config;
00395     if (gmacif == NULL)
00396     {
00397         LWIP_DEBUGF(NETIF_DEBUG, ("gmacif_init: out of memory\n"));
00398         return ERR_MEM;
00399     }
00400     netif->state = gmacif;
00401     netif->name[0] = IFNAME0;
00402     netif->name[1] = IFNAME1;
00403     netif->output = gmacif_output;
00404     netif->linkoutput = glow_level_output;
00405     _mem_barrier_
00406     glow_level_init(netif);
00407     etharp_init();
00408     return ERR_OK;
00409 }
00410 
00411 /**
00412  * Polling task
00413  * Should be called periodically
00414  *
00415  */
00416 void gmacif_poll(struct netif *netif)
00417 {
00418     gmacif_input(netif);
00419 }
00420 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines