SAMV71 Xplained Ultra Software Package 1.3

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_ALIGNED(8) static sGmacTxDescriptor gTxDs[TX_BUFFERS], gDummyTxDs[DUMMY_SIZE];
00087 
00088 
00089 /** TX callbacks list */
00090 COMPILER_ALIGNED(8) static fGmacdTransferCallback gTxCbs[TX_BUFFERS], gDummyTxCbs[DUMMY_SIZE];
00091 
00092 /** RX descriptors list */
00093 COMPILER_ALIGNED(8) static sGmacRxDescriptor gRxDs[RX_BUFFERS], gDummyRxDs[DUMMY_SIZE];
00094 
00095 /** Send Buffer */
00096 /* Section 3.6 of AMBA 2.0 spec states that burst should not cross 1K Boundaries.
00097    Receive buffer manager writes are burst of 2 words => 3 lsb bits of the address
00098    shall be set to 0 */
00099 COMPILER_ALIGNED(4) static uint8_t pTxBuffer[TX_BUFFERS * BUFFER_SIZE], pTxDummyBuffer[DUMMY_SIZE * DUMMY_BUFF_SIZE];
00100 
00101 /** Receive Buffer */
00102 COMPILER_ALIGNED(4) static uint8_t pRxBuffer[RX_BUFFERS * BUFFER_SIZE], pRxDummyBuffer[DUMMY_SIZE * DUMMY_BUFF_SIZE];
00103 
00104 
00105 /*---------------------------------------------------------------------------
00106  *         Local functions
00107  *---------------------------------------------------------------------------*/
00108 
00109 
00110 /* Forward declarations. */
00111 static void  gmacif_input(struct netif *netif);
00112 static err_t gmacif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr);
00113 
00114 static void glow_level_init(struct netif *netif)
00115 {
00116     struct gmacif *gmacif = netif->state;
00117     sGmacd *pGmacd = &gGmacd;
00118     GMacb  *pGmacb = &gGmacb;
00119     sGmacInit Que0, Que;
00120 
00121     /* set MAC hardware address length */
00122     netif->hwaddr_len = ETHARP_HWADDR_LEN;
00123     /* set MAC hardware address */
00124     netif->hwaddr[0] = gmacif->ethaddr.addr[0];
00125     netif->hwaddr[1] = gmacif->ethaddr.addr[1];
00126     netif->hwaddr[2] = gmacif->ethaddr.addr[2];
00127     netif->hwaddr[3] = gmacif->ethaddr.addr[3];
00128     netif->hwaddr[4] = gmacif->ethaddr.addr[4];
00129     netif->hwaddr[5] = gmacif->ethaddr.addr[5];
00130     /* maximum transfer unit */
00131     netif->mtu = 1500;
00132    
00133     /* device capabilities */
00134     netif->flags = NETIF_FLAG_BROADCAST;
00135     _mem_barrier_
00136     /* Init GMAC driver structure */
00137     memset(&Que0, 0, sizeof(Que0));
00138     Que0.bIsGem = 1;
00139     Que0.bDmaBurstLength = 4;
00140     Que0.pRxBuffer =pRxBuffer;
00141     Que0.pRxD = gRxDs;
00142     Que0.wRxBufferSize = BUFFER_SIZE;
00143     Que0.wRxSize = RX_BUFFERS;
00144     Que0.pTxBuffer = pTxBuffer;
00145     Que0.pTxD = gTxDs;
00146     Que0.wTxBufferSize = BUFFER_SIZE;
00147     Que0.wTxSize = TX_BUFFERS;
00148     Que0.pTxCb = gTxCbs;
00149     
00150 
00151     
00152     memset(&Que, 0, sizeof(Que));
00153     Que.bIsGem = 1;
00154     Que.bDmaBurstLength = 4;
00155     Que.pRxBuffer =pRxDummyBuffer;
00156     Que.pRxD = gDummyRxDs;
00157     Que.wRxBufferSize = DUMMY_BUFF_SIZE;
00158     Que.wRxSize = DUMMY_SIZE;
00159     Que.pTxBuffer = pTxDummyBuffer;
00160     Que.pTxD = gDummyTxDs;
00161     Que.wTxBufferSize = DUMMY_BUFF_SIZE;
00162     Que.wTxSize = DUMMY_SIZE;
00163     Que.pTxCb = gDummyTxCbs;
00164     SCB_CleanInvalidateDCache();
00165     GMACD_Init(pGmacd, GMAC, ID_GMAC, GMAC_CAF_ENABLE, GMAC_NBC_DISABLE);
00166     GMACD_InitTransfer(pGmacd, &Que, GMAC_QUE_2);
00167     
00168     GMACD_InitTransfer(pGmacd, &Que, GMAC_QUE_1);
00169     
00170     GMACD_InitTransfer(pGmacd, &Que0, GMAC_QUE_0);
00171     
00172     GMAC_SetAddress(gGmacd.pHw, 0, Gmacif_config.ethaddr.addr);
00173     
00174      /* Setup interrupts */  
00175     NVIC_ClearPendingIRQ(GMAC_IRQn);
00176     NVIC_EnableIRQ(GMAC_IRQn);
00177     /* Init GMACB driver */
00178     GMACB_Init(pGmacb, pGmacd, BOARD_GMAC_PHY_ADDR);
00179     GMACB_ResetPhy(pGmacb);
00180     /* PHY initialize */
00181     if (!GMACB_InitPhy(pGmacb, BOARD_MCK,  0, 0,  gmacPins, PIO_LISTSIZE(gmacPins)))
00182     {
00183         printf("P: PHY Initialize ERROR!\n\r");
00184         return ;
00185     }
00186    
00187     /* Auto Negotiate, work in RMII mode */
00188     if (!GMACB_AutoNegotiate(pGmacb))
00189     {
00190         printf( "P: Auto Negotiate ERROR!\n\r" ) ;
00191         return;
00192     }
00193     printf( "P: Link detected \n\r" ) ;
00194 }
00195 
00196 /**
00197  * This function should do the actual transmission of the packet. The packet is
00198  * contained in the pbuf that is passed to the function. This pbuf
00199  * might be chained.
00200  *
00201  * @param netif the lwip network interface structure for this gmacif
00202  * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
00203  * @return ERR_OK if the packet could be sent
00204  *         an err_t value if the packet couldn't be sent
00205  */
00206 static err_t glow_level_output(struct netif *netif, struct pbuf *p)
00207 {
00208     struct pbuf *q;
00209     uint8_t buf[1514];
00210     uint8_t *bufptr = &buf[0];
00211     uint8_t rc;
00212 
00213 #if ETH_PAD_SIZE
00214     pbuf_header(p, -ETH_PAD_SIZE);    /* drop the padding word */
00215 #endif
00216 
00217     for(q = p; q != NULL; q = q->next) {
00218         /* Send the data from the pbuf to the interface, one pbuf at a
00219         time. The size of the data in each pbuf is kept in the ->len
00220         variable. */
00221 
00222         /* send data from(q->payload, q->len); */
00223         memcpy(bufptr, q->payload, q->len);
00224         bufptr += q->len;
00225         SCB_CleanInvalidateDCache();
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     SCB_CleanInvalidateDCache();
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     SCB_CleanInvalidateDCache();
00419     gmacif_input(netif);
00420 }
00421 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines