SAMV71 Xplained Ultra Software Package 1.5

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(32) static uint8_t pTxBuffer[TX_BUFFERS * BUFFER_SIZE], pTxDummyBuffer[DUMMY_SIZE * DUMMY_BUFF_SIZE];
00102 
00103 /** Receive Buffer */
00104 COMPILER_ALIGNED(32) 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     GMACD_Init(pGmacd, GMAC, ID_GMAC, GMAC_CAF_ENABLE, GMAC_NBC_DISABLE);
00167     GMACD_InitTransfer(pGmacd, &Que, GMAC_QUE_2);
00168     
00169     GMACD_InitTransfer(pGmacd, &Que, GMAC_QUE_1);
00170     
00171     GMACD_InitTransfer(pGmacd, &Que0, GMAC_QUE_0);
00172     
00173     GMAC_SetAddress(gGmacd.pHw, 0, Gmacif_config.ethaddr.addr);
00174     
00175      /* Setup interrupts */  
00176     NVIC_ClearPendingIRQ(GMAC_IRQn);
00177     NVIC_EnableIRQ(GMAC_IRQn);
00178     /* Init GMACB driver */
00179     GMACB_Init(pGmacb, pGmacd, BOARD_GMAC_PHY_ADDR);
00180     GMACB_ResetPhy(pGmacb);
00181     /* PHY initialize */
00182     if (!GMACB_InitPhy(pGmacb, BOARD_MCK,  0, 0,  gmacPins, PIO_LISTSIZE(gmacPins)))
00183     {
00184         printf("P: PHY Initialize ERROR!\n\r");
00185         return ;
00186     }
00187    
00188     /* Auto Negotiate, work in RMII mode */
00189     if (!GMACB_AutoNegotiate(pGmacb))
00190     {
00191         printf( "P: Auto Negotiate ERROR!\n\r" ) ;
00192         return;
00193     }
00194     printf( "P: Link detected \n\r" ) ;
00195 }
00196 
00197 /**
00198  * This function should do the actual transmission of the packet. The packet is
00199  * contained in the pbuf that is passed to the function. This pbuf
00200  * might be chained.
00201  *
00202  * @param netif the lwip network interface structure for this gmacif
00203  * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
00204  * @return ERR_OK if the packet could be sent
00205  *         an err_t value if the packet couldn't be sent
00206  */
00207 static err_t glow_level_output(struct netif *netif, struct pbuf *p)
00208 {
00209     struct pbuf *q;
00210     uint8_t buf[1514];
00211     uint8_t *bufptr = &buf[0];
00212     uint8_t rc;
00213 
00214 #if ETH_PAD_SIZE
00215     pbuf_header(p, -ETH_PAD_SIZE);    /* drop the padding word */
00216 #endif
00217 
00218     for(q = p; q != NULL; q = q->next) {
00219         /* Send the data from the pbuf to the interface, one pbuf at a
00220         time. The size of the data in each pbuf is kept in the ->len
00221         variable. */
00222 
00223         /* send data from(q->payload, q->len); */
00224         memcpy(bufptr, q->payload, q->len);
00225         bufptr += q->len;
00226     }
00227 
00228     /* signal that packet should be sent(); */
00229 //    rc = GMACD_Send(&gGmacd, buf, 0, NULL, GMAC_QUE_2);
00230 //    rc = GMACD_Send(&gGmacd, buf, 0, NULL, GMAC_QUE_1);
00231     rc = GMACD_Send(&gGmacd, buf, p->tot_len, NULL, GMAC_QUE_0);
00232     if (rc != GMACD_OK) {
00233         return ERR_BUF;
00234     }
00235 #if ETH_PAD_SIZE
00236     pbuf_header(p, ETH_PAD_SIZE);     /* reclaim the padding word */
00237 #endif
00238 
00239     LINK_STATS_INC(link.xmit);
00240     return ERR_OK;
00241 }
00242 
00243 /**
00244  * Should allocate a pbuf and transfer the bytes of the incoming
00245  * packet from the interface into the pbuf.
00246  *
00247  * @param netif the lwip network interface structure for this gmacif
00248  * @return a pbuf filled with the received packet (including MAC header)
00249  *         NULL on memory error
00250  */
00251 static struct pbuf *glow_level_input(struct netif *netif)
00252 {                    
00253     struct pbuf *p, *q;
00254     u16_t len;
00255     uint8_t buf[1514];
00256     uint8_t *bufptr = &buf[0];
00257     
00258     uint32_t frmlen;
00259     uint8_t rc;
00260     
00261     /* Obtain the size of the packet and put it into the "len"
00262        variable. */
00263     rc = GMACD_Poll(&gGmacd, buf, (uint32_t)sizeof(buf), (uint32_t*)&frmlen, GMAC_QUE_0);
00264     if (rc != GMACD_OK)
00265     { 
00266       return NULL;
00267     }
00268     len = frmlen;
00269     
00270 #if ETH_PAD_SIZE
00271     len += ETH_PAD_SIZE;      /* allow room for Ethernet padding */
00272 #endif
00273 
00274     /* We allocate a pbuf chain of pbufs from the pool. */
00275     p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
00276     
00277     if (p != NULL) {
00278 #if ETH_PAD_SIZE
00279         pbuf_header(p, -ETH_PAD_SIZE);          /* drop the padding word */
00280 #endif
00281         /* We iterate over the pbuf chain until we have read the entire
00282          * packet into the pbuf. */
00283         for(q = p; q != NULL; q = q->next) {
00284             /* Read enough bytes to fill this pbuf in the chain. The
00285              * available data in the pbuf is given by the q->len
00286              * variable. */
00287             /* read data into(q->payload, q->len); */
00288             memcpy(q->payload, bufptr, q->len);
00289             bufptr += q->len;
00290             memory_sync();
00291         }
00292         /* acknowledge that packet has been read(); */
00293 
00294 #if ETH_PAD_SIZE
00295         pbuf_header(p, ETH_PAD_SIZE);           /* reclaim the padding word */
00296 #endif
00297         LINK_STATS_INC(link.recv);
00298     } else {
00299         /* drop packet(); */
00300         LINK_STATS_INC(link.memerr);
00301         LINK_STATS_INC(link.drop);
00302     }
00303     return p;
00304 }
00305 
00306 /**
00307  * This function is called by the TCP/IP stack when an IP packet
00308  * should be sent. It calls the function called glow_level_output() to
00309  * do the actual transmission of the packet.
00310  *
00311  */
00312 static err_t gmacif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr)
00313 {
00314     /* resolve hardware address, then send (or queue) packet */
00315     return etharp_output(netif, p, ipaddr);
00316 }
00317 
00318 /**
00319  * This function should be called when a packet is ready to be read
00320  * from the interface. It uses the function low_level_input() that
00321  * should handle the actual reception of bytes from the network
00322  * interface. Then the type of the received packet is determined and
00323  * the appropriate input function is called.
00324  *
00325  * @param netif the lwip network interface structure for this gmacif
00326  */
00327 
00328 static void gmacif_input(struct netif *netif)
00329 {
00330     struct gmacif *gmacif;
00331     struct eth_hdr *ethhdr;
00332     struct pbuf *p;
00333     gmacif = netif->state;
00334     
00335     /* move received packet into a new pbuf */
00336     p = glow_level_input(netif);
00337     /* no packet could be read, silently ignore this */
00338     if (p == NULL) return;
00339     /* points to packet payload, which starts with an Ethernet header */
00340     ethhdr = p->payload;
00341     
00342     switch (htons(ethhdr->type)) {
00343         /* IP packet? */
00344         case ETHTYPE_IP:
00345             /* skip Ethernet header */
00346             pbuf_header(p, (s16_t)(-sizeof(struct eth_hdr)));
00347             /* pass to network layer */
00348             netif->input(p, netif);
00349             break;
00350         
00351         case ETHTYPE_ARP:
00352             /* pass p to ARP module  */
00353             etharp_arp_input(netif, &gmacif->ethaddr, p);
00354             break;
00355         default:
00356             pbuf_free(p);
00357             p = NULL;
00358             break;
00359         }
00360 }
00361 
00362 /*----------------------------------------------------------------------------
00363  *        Exported functions
00364  *----------------------------------------------------------------------------*/
00365 
00366 
00367 /**
00368  * Set the MAC address of the system.
00369  * Should only be called before gmacif_init is called.
00370  * The stack calls gmacif_init after the user calls netif_add
00371  *
00372  */
00373 
00374 void gmacif_setmac(u8_t *addr)
00375 {
00376     Gmacif_config.ethaddr.addr[0] = addr[0];
00377     Gmacif_config.ethaddr.addr[1] = addr[1];
00378     Gmacif_config.ethaddr.addr[2] = addr[2];
00379     Gmacif_config.ethaddr.addr[3] = addr[3];
00380     Gmacif_config.ethaddr.addr[4] = addr[4];
00381     Gmacif_config.ethaddr.addr[5] = addr[5];
00382 }
00383 
00384 /**
00385  * Should be called at the beginning of the program to set up the
00386  * network interface. It calls the function glow_level_init() to do the
00387  * actual setup of the hardware.
00388  *
00389  */
00390 err_t gmacif_init(struct netif *netif)
00391 {
00392     struct gmacif *gmacif;
00393     gmacif = &Gmacif_config;
00394     if (gmacif == NULL)
00395     {
00396         LWIP_DEBUGF(NETIF_DEBUG, ("gmacif_init: out of memory\n"));
00397         return ERR_MEM;
00398     }
00399     netif->state = gmacif;
00400     netif->name[0] = IFNAME0;
00401     netif->name[1] = IFNAME1;
00402     netif->output = gmacif_output;
00403     netif->linkoutput = glow_level_output;
00404     _mem_barrier_
00405     glow_level_init(netif);
00406     etharp_init();
00407     return ERR_OK;
00408 }
00409 
00410 /**
00411  * Polling task
00412  * Should be called periodically
00413  *
00414  */
00415 void gmacif_poll(struct netif *netif)
00416 {
00417     gmacif_input(netif);
00418 }
00419 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines