www.pudn.com > TCPmodbushy.rar > ethernetif.c


/* 
 * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 
 * All rights reserved.  
 *  
 * Redistribution and use in source and binary forms, with or without modification,  
 * are permitted provided that the following conditions are met: 
 * 
 * 1. Redistributions of source code must retain the above copyright notice, 
 *    this list of conditions and the following disclaimer. 
 * 2. Redistributions in binary form must reproduce the above copyright notice, 
 *    this list of conditions and the following disclaimer in the documentation 
 *    and/or other materials provided with the distribution. 
 * 3. The name of the author may not be used to endorse or promote products 
 *    derived from this software without specific prior written permission.  
 * 
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED  
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF  
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT  
 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING  
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY  
 * OF SUCH DAMAGE. 
 * 
 * This file is part of the lwIP TCP/IP stack. 
 *  
 * Author: Adam Dunkels  
 * 
 */ 
 
/* 
 * This file is a skeleton for developing Ethernet network interface 
 * drivers for lwIP. Add code to the low_level functions and do a 
 * search-and-replace for the word "ethernetif" to replace it with 
 * something that better describes your network interface. 
 */ 
 
#include "o:/lwip/opt.h" 
#include "o:/lwip/def.h" 
#include "o:/lwip/mem.h" 
#include "o:/lwip/pbuf.h" 
#include "o:/lwip/sys.h" 
#include "o:/netif/OP_FlashOfCP220.h" 
#include "o:/netif/CP220X_Core.h" 
#include "o:/netif/CP220X_Reg.h" 
#include "o:/lwip/stats.h"  
#include "o:/netif/ethernetif.h" 
 
 
#include "o:/netif/etharp.h" 
 
/* Define those to better describe your network interface. */ 
#define IFNAME0 'e' 
#define IFNAME1 'n' 
 
struct ethernetif { 
  struct eth_addr xdata *ethaddr; 
/****************************************************************************** 
* Addes( Begin ) 
******************************************************************************/ 
  /* Add whatever per-interface state that is needed here. */ 
  unsigned char Low_Level_Init_Result; 
/****************************************************************************** 
* Addes( End ) 
******************************************************************************/ 
}; 
 
//static code struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}}; 
 
/* Forward declarations. */ 
static err_t ethernetif_output(struct pbuf xdata *p, 
             struct ip_addr xdata *ipaddr); 
 
static void 
low_level_init() 
{ 
  struct ethernetif xdata *ethernetif = netif->state; 
   
/****************************************************************************** 
* Addes( Begin ) 
******************************************************************************/ 
INT0EN = 0xFF; 
 
if( INT0EN != 0xFF ) 
{ 
ethernetif->Low_Level_Init_Result = OSC_ERROR; 
return; 
} 
INT0EN = 0x00; 
if( INT0EN != 0x00 ) 
{ 
	ethernetif->Low_Level_Init_Result = OSC_ERROR; 
	return; 
} 
 
ReadBytesFromFlash( 0x1FFA, 6, netif->hwaddr ); 
 
if( (netif->hwaddr[0] != 0x00) 
	||(netif->hwaddr[1] != 0x0b) 
	||(netif->hwaddr[2] != 0x3c) ) 
{ 
	ethernetif->Low_Level_Init_Result = OSC_ERROR; 
	return; 
} 
/*  netif->hwaddr[0] = ReadByteFromFlash( 0x1FFA ); 
  netif->hwaddr[1] = ReadByteFromFlash( 0x1FFB ); 
  netif->hwaddr[2] = ReadByteFromFlash( 0x1FFC ); 
  netif->hwaddr[3] = ReadByteFromFlash( 0x1FFD ); 
  netif->hwaddr[4] = ReadByteFromFlash( 0x1FFE ); 
  netif->hwaddr[5] = ReadByteFromFlash( 0x1FFF );*/ 
/****************************************************************************** 
* Addes( End ) 
******************************************************************************/ 
 
  /* maximum transfer unit */ 
//  netif->mtu = 500; 
   
  /* broadcast capability */ 
  netif->flags = NETIF_FLAG_BROADCAST; 
 
/****************************************************************************** 
* Addes( Begin ) 
******************************************************************************/  
  /* Do whatever else is needed to initialize interface. */ 
  ethernetif->Low_Level_Init_Result = CP220x_HW_Reset(); 
  if( ethernetif->Low_Level_Init_Result & (OSC_ERROR | CAL_ERROR | MEM_ERROR) ) 
  { 
    return; 
  } 
 
  ethernetif->Low_Level_Init_Result = PHY_Init();      // Initialize the physical layer 
          
  if(ethernetif->Low_Level_Init_Result & LINK_ERROR)   // Check for the possible error codes 
  { 
  	return; 
  } 
  MAC_Init();                                         // Initialize the MAC 
 
  RXFILT = 0x0d;//ignor mulbroadcast 
 
  ethernetif->Low_Level_Init_Result = ERR_OK; 
/****************************************************************************** 
* Addes( End ) 
******************************************************************************/ 
} 
 
/* 
 * low_level_output(): 
 * 
 * Should do the actual transmission of the packet. The packet is 
 * contained in the pbuf that is passed to the function. This pbuf 
 * might be chained. 
 * 
 */ 
 
err_t 
low_level_output(struct pbuf xdata *p) 
{ 
  struct ethernetif xdata *ethernetif = netif->state; 
  unsigned int data ramaddr; 
  unsigned char xdata *temp; 
   
  // Step 1: Poll TXBUSY until it becomes 0x00 
  while(TXBUSY); 
 
#ifdef TESTDEBUG 
if( TXSTA3&0xf8 ) 
	test[8]++; 
#endif 
 
  // Step 2: Set the TXSTARTH:TXSTARTL address to 0x0000 
  TXSTARTH = 0x00; 
  TXSTARTL = 0x00; 
 
  // Step 3: Load data into transmit buffer 
  // When the random access method is used, we do not need to check for 
  // aborted packets. This method will be slightly slower than the Autowrite 
  // method, however, it reduces code space requirements. 
   
   ramaddr = 0x0000; 
 
  //send data from(q->payload, q->len); 
   temp = ( unsigned char xdata * )(p->payload); 
   while( ramaddr < p->len ) 
   { 
      TXAUTOWR = *temp; 
	  temp++; 
	  ramaddr++; 
   } 
   
   // Step 3e: Pad short packets 
  while(ramaddr < 64){ 
     TXAUTOWR = 0; 
     ramaddr++; 
  } 
       
  // Step 4: Set the TXSTARTH:TXSTARTL address back to 0x0000 
  TXSTARTH = 0x00; 
  TXSTARTL = 0x00; 
 
  // Step 5: Write '1' to TXGO to begin transmission 
  TXCN = 0x01; 
/****************************************************************************** 
* Addes( End ) 
******************************************************************************/ 
  return ERR_OK; 
} 
 
/* 
 * low_level_input(): 
 * 
 * Should allocate a pbuf and transfer the bytes of the incoming 
 * packet from the interface into the pbuf. 
 * 
 */ 
/* !!according to Low_level_input, when read the packet only leave the five packet, open receved!!!!!!!!!  */ 
static struct pbuf xdata * 
low_level_input(void) 
{ 
  struct ethernetif xdata *ethernetif = netif->state; 
  struct pbuf xdata *p; 
 
  u16_t data len; 
  bit rx_ok; 
 
  /* Obtain the size of the packet and put it into the "len" 
     variable. */ 
  // Step 1: Check the RXOK bit to see if packet was received correctly 
  if( TLBVALID ) 
  { 
    rx_ok = (CPINFOL & RXOK); 
    if( rx_ok ) 
    { 
       len = MAKE_WORD( CPLENH,CPLENL ); 
       p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); 
       if( p == NULL ) 
         return p; 
    } 
    else 
	{ 
	   p = NULL; 
#ifdef TESTDEBUG 
test[3]++; 
#endif 
	} 
    EA = OFF; 
    RcvedNum--; 
    if( RcvedNum <= 6 ) 
      RXCN = 0; 
    EA = ON; 
   
    if (p != NULL) { 
//read data into(q->payload, q->len); 
      unsigned char xdata *data TmpPayload = ( unsigned char xdata * )( p->payload ); 
	  while( len != 0 ) 
	  { 
	    len--; 
	    *TmpPayload = RXAUTORD; 
	    TmpPayload++; 
	  } 
	RXCN |= 0x04;                    // Clear the valid bit only 
//acknowledge that packet has been read(); 
    } else { 
      RXCN |= 0x02;                    // Skip the packet 
    } 
 
  }else{ 
    p = NULL; 
  } 
  return p; 
} 
 
/* 
 * ethernetif_output(): 
 * 
 * This function is called by the TCP/IP stack when an IP packet 
 * should be sent. It calls the function called low_level_output() to 
 * do the actual transmission of the packet. 
 * 
 */ 
 
err_t 
ethernetif_output(struct pbuf xdata *p, 
      struct ip_addr xdata *ipaddr) 
{ 
   
 /* resolve hardware address, then send (or queue) packet */ 
  return etharp_output(ipaddr, p); 
  
} 
 
/* 
 * ethernetif_input(): 
 * 
 * This function should be called when a packet is ready to be read 
 * from the interface. It uses the function low_level_input() that 
 * should handle the actual reception of bytes from the network 
 * interface. 
 * 
 */ 
void 
ethernetif_input(void) 
{ 
  struct ethernetif xdata *ethernetif; 
  struct eth_hdr xdata *ethhdr; 
  struct pbuf xdata *p; 
       
  ethernetif = netif->state; 
   
  /* move received packet into a new pbuf */ 
  p = low_level_input(); 
  /* no packet could be read, silently ignore this */ 
  if (p == NULL) 
  { 
    return; 
  } 
  /* points to packet payload, which starts with an Ethernet header */ 
  ethhdr = p->payload; 
   
  switch( htons(ethhdr->type) ){ 
  /* IP packet? */ 
  case ETHTYPE_IP: 
    /* update ARP table */ 
    etharp_ip_input( p ); 
    /* skip Ethernet header */ 
    pbuf_header(p, -sizeof(struct eth_hdr)); 
    /* pass to network layer */ 
//    netif->input(p, netif); 
      ip_input(p); 
    break; 
       
  case ETHTYPE_ARP: 
      /* pass p to ARP module  */ 
    etharp_arp_input(ethernetif->ethaddr, p); 
    break; 
  default: 
      pbuf_free(p); 
      p = NULL; 
      break; 
  } 
} 
 
/* 
 * ethernetif_init(): 
 * 
 * Should be called at the beginning of the program to set up the 
 * network interface. It calls the function low_level_init() to do the 
 * actual setup of the hardware. 
 * 
 */ 
 
err_t ethernetif_init(void) 
{ 
  struct ethernetif xdata *ethernetif; 
     
  ethernetif = mem_malloc(sizeof(struct ethernetif)); 
   
  if (ethernetif == NULL) 
  { 
  	return ERR_MEM; 
  } 
   
  netif->state = ethernetif; 
   
  ethernetif->ethaddr = (struct eth_addr xdata *)&(netif->hwaddr[0]); 
   
  low_level_init(); 
 
/****************************************************************************** 
* Addes( Begin ) 
******************************************************************************/ 
  if( ethernetif->Low_Level_Init_Result != ERR_OK ) 
  { 
    mem_free(ethernetif); 
	return( (err_t)ethernetif->Low_Level_Init_Result ); 
  } 
/****************************************************************************** 
* Addes( End ) 
******************************************************************************/ 
 
  etharp_init(); 
 
  return ERR_OK; 
}