00001 /*############################################################################## 00002 00003 nIP - nano IP stack 00004 00005 File : ethernet.c 00006 00007 Description : Functions to serve ethernet interfaces 00008 00009 Copyright notice: 00010 00011 Copyright (C) 2005 - 00012 Andreas Dittrich, dittrich@informatik.hu-berlin.de 00013 Jon Kowal, kowal@informatik.hu-berlin.de 00014 00015 This program is free software; you can redistribute it and/or 00016 modify it under the terms of the GNU General Public License 00017 as published by the Free Software Foundation; either version 2 00018 of the License, or (at your option) any later version. 00019 00020 This program is distributed in the hope that it will be useful, 00021 but WITHOUT ANY WARRANTY; without even the implied warranty of 00022 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00023 GNU General Public License for more details. 00024 00025 You should have received a copy of the GNU General Public License 00026 along with this program; if not, write to the Free Software 00027 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00028 00029 ##############################################################################*/ 00030 00031 #include "dispatcher.h" 00032 #include "net/ethernet.h" 00033 #include "net/arp.h" 00034 #include "net/ip.h" 00035 00036 #if (NIP_ETH_ENABLE == 1) 00037 00038 // string compare function only needed for mac address check 00039 #if !defined( ETH_NIC_CHECK_MAC ) 00040 # include <string.h> 00041 #endif 00042 00043 #include "nip_init.h" 00044 #include "net/net_if.h" 00045 00046 extern nip_net_if_t nip_net_if_list[]; 00047 extern nip_disp_state_t nip_disp; 00048 00049 00050 /** fill ethernet interface configuration with default values 00051 * 00052 * @param id id of network interface to configure 00053 **/ 00054 void nip_eth_configure_if_defaults( nip_net_if_id_t id ) 00055 { 00056 nip_net_if_list[id].phy_conf.flags = NIP_PHY_IFF_BROADCAST; 00057 nip_net_if_list[id].phy_conf.hw_addr_size = 6; 00058 nip_net_if_list[id].phy_conf.open = NULL; /* driver will fill in */ 00059 nip_net_if_list[id].phy_conf.close = NULL; /* driver will fill in */ 00060 nip_net_if_list[id].phy_conf.hard_disp_recv = &nip_eth_disp_receive; 00061 nip_net_if_list[id].phy_conf.hard_send_init = NULL; /* driver will fill in */ 00062 nip_net_if_list[id].phy_conf.hard_send = NULL; /* driver will fill in */ 00063 nip_net_if_list[id].phy_conf.hard_read_init = NULL; /* driver will fill in */ 00064 nip_net_if_list[id].phy_conf.hard_read = NULL; /* driver will fill in */ 00065 } 00066 00067 00068 /** Function to be called upon packet reception from Network Interface. 00069 * 00070 * The function will read the first packet from buffer and hand it to the 00071 * appropriate protocol handler. No decision on discarding the packet will be 00072 * made here, unless the ethernet address check fails. Discarding due to lack 00073 * of ressources is up to the protocol handler which may decide to have no 00074 * buffer space for the data. Also it's up to the protocol handler to decide 00075 * which transmission the packet will be assigned to (e.g. only IP can know if 00076 * the received data belongs to a fragmented packet waiting to be completed). 00077 */ 00078 void nip_eth_disp_receive( void ) 00079 { 00080 uint8_t tmp[6]; 00081 uint8_t type[2]; 00082 nip_net_if_id_t tmp_if_id = NIP_CURR_IF; 00083 #if !defined( ETH_NIC_CHECK_MAC ) 00084 uint8_t tmp1; 00085 #endif 00086 // Packet reception should be completed at this point. There may be packets 00087 // waiting in the interface's buffer, but the previous packet should've been 00088 // received completely. To avoid errors and deadlocks this routine double 00089 // checks on that and empties the receive-buffer if necessary. 00090 if ( nip_net_if_list[ tmp_if_id ].phy_conf.rx_bytes > 0 ) 00091 { 00092 nip_net_if_list[ tmp_if_id ].phy_conf.hard_read( 00093 NIP_CURR_IF, 00094 NULL, 00095 nip_net_if_list[ tmp_if_id ].phy_conf.rx_bytes 00096 ); 00097 } 00098 00099 00100 // initialize packet reading 00101 if ( nip_net_if_list[tmp_if_id].phy_conf.hard_read_init( tmp_if_id ) != NIP_E_OK ) 00102 return; 00103 00104 // make sure we come back and check for another packet (we don't know how 00105 // many packets have been received) 00106 nip_disp_notify_if( tmp_if_id, NIP_DISP_IF_ETH_R ); 00107 00108 // read destination address 00109 nip_net_if_list[tmp_if_id].phy_conf.hard_read( tmp_if_id, tmp, 6 ); 00110 00111 // if the NIC is not doing the physical address check, we'll have to do that 00112 #if !defined( ETH_NIC_CHECK_MAC ) 00113 // Check if destination address is broadcast address 00114 tmp1 = 0; 00115 do 00116 { 00117 if ( tmp[tmp1] != 255 ) break; 00118 } 00119 while ( ++tmp1 < 6 ); 00120 00121 // If all 6 Bytes equalled 255, the given message is a ethernet broadcast 00122 if ( tmp1 == 6 ) 00123 { 00124 } 00125 else 00126 #endif 00127 // If the least significant bit of the first address byte equals 1, 00128 // the given ethernet address is a (multicast) group address. 00129 if ( (tmp[0]& 0x01) > 0 ) 00130 { 00131 // TODO check multicast destination. Is this message for us? Treat 00132 // broadcast as special kind of multicast. Remove above broadcast check 00133 // when done. 00134 // if check failed goto terminate_read 00135 } 00136 00137 // if the NIC is not doing the physical address check, we'll have to do that 00138 #if !defined( ETH_NIC_CHECK_MAC ) 00139 else 00140 // check unicast destination 00141 if ( nip_memcmp( tmp, nip_net_if_list[tmp_if_id].phy_conf.hw_addr, 6 ) == 0 ) 00142 { 00143 } 00144 else 00145 { 00146 // Ethernet address check failed 00147 // TODO discard packet 00148 00149 // we use 'goto' here because it's the only way to skip the following 00150 // lines without having to use additional status variables and conditions. 00151 // (That saves about 32 Bytes of lovely program memory over the next 00152 // favorable solution of using tmp1 as status variable indicating wether 00153 // we're the the correct receiver of the packet) 00154 goto terminate_read; 00155 } 00156 #endif 00157 00158 // read source address 00159 nip_net_if_list[tmp_if_id].phy_conf.hard_read( tmp_if_id, nip_disp.next.common.remote_hw_addr, 6 ); 00160 00161 // read type 00162 nip_net_if_list[tmp_if_id].phy_conf.hard_read( tmp_if_id, type, 2 ); 00163 00164 // eval type 00165 #if (NIP_ARP_ENABLE == 1) 00166 if ( type[0] == 0x08 && type[1] == 0x06 ) 00167 { 00168 // received ARP packet 00169 NIP_CURR_CMD = &nip_disp_arp_receive;; 00170 return; 00171 } 00172 #endif 00173 #if (NIP_IP_ENABLE == 1) 00174 if ( type[0] == 0x08 && type[1] == 0x00 ) 00175 { 00176 // received IP packet 00177 NIP_CURR_CMD = &nip_ip_disp_receive;; 00178 return; 00179 } 00180 #endif 00181 00182 #if !defined( ETH_NIC_CHECK_MAC ) 00183 terminate_read: 00184 // read remaining packet bytes from NIC 00185 nip_net_if_list[tmp_if_id].phy_conf.hard_read( 00186 tmp_if_id, 00187 NULL, 00188 nip_net_if_list[tmp_if_id].phy_conf.rx_bytes 00189 ); 00190 #endif 00191 00192 return; 00193 } 00194 00195 #endif /* NIP_ETH_ENABLE == 1 */