ZG2100 Network interface source

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers zg_net.c Source File

zg_net.c

00001 
00002 /*
00003 Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
00004  
00005 Permission is hereby granted, free of charge, to any person obtaining a copy
00006 of this software and associated documentation files (the "Software"), to deal
00007 in the Software without restriction, including without limitation the rights
00008 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00009 copies of the Software, and to permit persons to whom the Software is
00010 furnished to do so, subject to the following conditions:
00011  
00012 The above copyright notice and this permission notice shall be included in
00013 all copies or substantial portions of the Software.
00014  
00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00016 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00017 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00018 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00019 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00020 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00021 THE SOFTWARE.
00022 */
00023 
00024 #include "netCfg.h"
00025 #if NET_ZG2100
00026 
00027 #include "zg_defs.h"
00028 #include "zg_net.h"
00029 #include "zg_drv.h"
00030 
00031 #include "lwip/opt.h"
00032 
00033 #include "lwip/def.h"
00034 #include "lwip/pbuf.h"
00035 #include "lwip/sys.h"
00036 #include "lwip/stats.h"
00037 #include "netif/etharp.h"
00038 
00039 #include "string.h"
00040 
00041 #ifdef __LWIP_DEBUG
00042 #undef __LWIP_DEBUG
00043 #endif
00044 //#define __DEBUG
00045 #include "dbg/dbg.h"
00046 
00047 #define IFNAME0 'w'
00048 #define IFNAME1 'l'
00049 
00050 //void hexdump(byte* buffer, int size);
00051 #define hexdump(x,y)
00052 
00053 const char snap[ZG_SNAP_LEN] = { 0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00 }; //Snap word, see IEEE 802-2001 10.3 Subnetwork Access Protocol (p. 23 ~ 29)
00054 struct netif* zg_netif;
00055 
00056 //To be called by Lwip
00057 static err_t zg_output(struct netif *netif, struct pbuf *p) //Transfer an ethernet frame : convert into ZG frame & TX it
00058 {
00059   DBG("\r\nOut packet\r\n");
00060   
00061   while( zg_send_is_busy() )
00062   {
00063     zg_process(); //Ugly but prevents lwip from feeding other packets
00064   }
00065   #if ETH_PAD_SIZE
00066     pbuf_header(p, -ETH_PAD_SIZE); //Drop padding word
00067   #endif
00068   
00069   ZG_ETH_HDR* eth_hdr = (ZG_ETH_HDR*) p->payload;
00070   
00071   ZG_TX_HDR* tx_hdr = (ZG_TX_HDR*)fifo_buf;
00072   memset((void*)tx_hdr, 0, sizeof(ZG_TX_HDR));
00073   
00074   //Convert headers properly
00075   tx_hdr->zero = HTODS( 0 );
00076   memcpy( tx_hdr->dest, eth_hdr->dest, ZG_MACADDR_LEN );
00077   memcpy( tx_hdr->snap, snap, ZG_SNAP_LEN );
00078   tx_hdr->type = eth_hdr->type; //Lwip has already put the type in BE
00079   
00080   DBG("\r\nEth header\r\n");
00081   hexdump((byte*)eth_hdr, sizeof(ZG_ETH_HDR));
00082   
00083   DBG("\r\nZg header\r\n");
00084   hexdump((byte*)tx_hdr, sizeof(ZG_TX_HDR));
00085   
00086   //Open TX fifo & send header
00087   zg_send_start();
00088   zg_send( (byte*)tx_hdr, sizeof(ZG_TX_HDR) );
00089   
00090   //Send remaining payload of this buf
00091   zg_send( (byte*)(((byte*)p->payload) + sizeof(ZG_ETH_HDR)), (p->len - sizeof(ZG_ETH_HDR)) );
00092   
00093   while(p->next != NULL)
00094   {
00095     p = p->next;
00096     zg_send((byte*)p->payload, p->len);
00097     //FIX: Watchout, p content MUST be preserved for proper TCP functionality!!!  
00098   }
00099 
00100   zg_send_end();
00101 
00102   #if ETH_PAD_SIZE
00103     pbuf_header(p, ETH_PAD_SIZE); //Reclaim padding word
00104   #endif
00105   
00106   LINK_STATS_INC(link.xmit);
00107   return ERR_OK;  
00108 }
00109 
00110 //Callback from zg_drv
00111 void zg_on_input(byte* buf, int len) //On reception of a ZG frame : convert into Eth frame & feed lwip
00112 {
00113   struct pbuf *frame, *p; //Lwip buffers
00114   byte* eth_buf; //Position of the Ethernet packet buffer
00115   int eth_len; //Length of this buffer
00116   ZG_ETH_HDR eth_hdr_data; //Temporary buffer
00117   ZG_ETH_HDR* eth_hdr = &eth_hdr_data; //just to remain consistent in notations
00118   memset((void*)eth_hdr, 0, sizeof(ZG_ETH_HDR));
00119   
00120   DBG("\r\nIncoming packet\r\n");
00121   hexdump(buf, len);
00122   
00123   ZG_RX_HDR* rx_hdr = (ZG_RX_HDR*)buf;
00124   
00125   memcpy( eth_hdr->dest, rx_hdr->dest, ZG_MACADDR_LEN );
00126   memcpy( eth_hdr->src, rx_hdr->src, ZG_MACADDR_LEN );
00127   eth_hdr->type = rx_hdr->type; //Lwip will convert the type in LE
00128   
00129   DBG("\r\nZg header\r\n");
00130   hexdump((byte*)rx_hdr, sizeof(ZG_RX_HDR));
00131   
00132   DBG("\r\nEth header\r\n");
00133   hexdump((byte*)eth_hdr, sizeof(ZG_ETH_HDR));
00134   
00135   //Since the ZG_ETH_HDR header is smaller than the ZG_RX_HDR one, we can copy the new header before the payload to get a full ethernet packet
00136   eth_buf = buf + sizeof(ZG_RX_HDR) - sizeof(ZG_ETH_HDR);
00137   eth_len = len - sizeof(ZG_RX_HDR) + sizeof(ZG_ETH_HDR);
00138   memcpy( eth_buf, (void*)eth_hdr, sizeof(ZG_ETH_HDR) );
00139   
00140   //Filter on packet type
00141   
00142   switch (htons(eth_hdr->type)) {
00143   //IP or ARP packet
00144   case ETHTYPE_IP:
00145   case ETHTYPE_ARP:
00146     break; //OK
00147   default:
00148     return; //We do not know how to handle this
00149   }
00150   
00151   #if ETH_PAD_SIZE
00152   eth_len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
00153   #endif
00154   
00155   //Now we can pass this nice ethernet packet to lwip 
00156   //Allocate a buffer
00157   frame = pbuf_alloc(PBUF_RAW, eth_len, PBUF_POOL);
00158   if(frame == NULL)
00159   {
00160     //Out of memory
00161     return;
00162   }
00163   p = frame;
00164   
00165   #if ETH_PAD_SIZE
00166     pbuf_header(frame, -ETH_PAD_SIZE); /* drop the padding word */
00167   #endif
00168   
00169   //Copy buffer into lwip memory pool
00170   while( eth_len > 0 )
00171   {
00172     memcpy(p->payload, eth_buf, p->len);
00173     eth_buf += p->len;
00174     eth_len -= p->len;
00175     p = p->next;
00176     if( p == NULL )
00177     {
00178       //Should not happen
00179       break;
00180     }
00181   }
00182 
00183   if ( ethernet_input(frame, zg_netif) != ERR_OK ) //Pass the frame to lwip
00184   { 
00185     LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
00186     pbuf_free(frame);
00187     frame = NULL;
00188   }
00189 }
00190 
00191 
00192 err_t zg_net_init(struct netif *netif) {
00193   LWIP_ASSERT("netif != NULL", (netif != NULL));
00194   
00195   memset(netif, 0, sizeof(struct netif));
00196   
00197   NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 1500/*ZG_FIFO_BUF_SIZE*10*/);
00198   
00199   /* maximum transfer unit */
00200   netif->mtu = 1500;//ZG_FIFO_BUF_SIZE;
00201   
00202   /* set MAC hardware address length */
00203   netif->hwaddr_len = ETHARP_HWADDR_LEN;
00204 
00205   /* set MAC hardware address */
00206   if( !zg_data_mask.mac_addr ) //Get MAC addr from chip if not known yet
00207   {
00208     zg_mgmt_get_param(ZG_FIFO_MGMT_PARM_MACAD);
00209   }
00210   
00211   memcpy(netif->hwaddr, zg_data.mac_addr, ETHARP_HWADDR_LEN);
00212   
00213   /* device capabilities */
00214   /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
00215   netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_IGMP;
00216 
00217   netif->state = NULL;
00218 
00219   netif->name[0] = IFNAME0;
00220   netif->name[1] = IFNAME1;
00221 
00222   /* We directly use etharp_output() here to save a function call.
00223    * You can instead declare your own function an call etharp_output()
00224    * from it if you have to do some checks before sending (e.g. if link
00225    * is available...) */
00226   netif->output          = etharp_output;
00227   netif->linkoutput      = zg_output;
00228   
00229   zg_netif = netif;
00230 
00231   return ERR_OK;
00232 }
00233 
00234 #endif