00001 /*############################################################################## 00002 00003 nIP - nano IP stack 00004 00005 File : dispatcher.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/net_if.h" 00033 #include "net/arp.h" 00034 #include "app/dhcp.h" 00035 #include "net/autoip.h" 00036 #include "app/mdns.h" 00037 00038 #if (NIP_DISP_ENABLE==1) 00039 00040 extern nip_net_if_t nip_net_if_list[]; 00041 nip_disp_state_t nip_disp; 00042 00043 /** Notify dispatcher about one or more events */ 00044 // void nip_disp_notify( uint8_t events ) 00045 // { 00046 // nip_disp.flags |= events; 00047 // } 00048 00049 /** Notify dispatcher to handle incoming ethernet data on given interface */ 00050 void nip_disp_notify_if( nip_net_if_id_t net_if_id, uint8_t event ) 00051 { 00052 nip_disp.if_flags[ net_if_id ] |= event; 00053 // nip_disp.flags |= NIP_DISP_CHECK_IF; 00054 nip_disp_notify( NIP_DISP_CHECK_IF ); 00055 } 00056 00057 /** Checks if dispatcher is running. 00058 * 00059 * @return NIP_E_OK if dispatcher is not running, or NIP_E_DISP_RUNNING else 00060 */ 00061 nip_error_t nip_disp_check() 00062 { 00063 if ( (nip_disp.flags & NIP_DISP_RUNNING) != 0 ) 00064 return NIP_E_DISP_RUNNING; 00065 else 00066 return NIP_E_OK; 00067 } 00068 00069 /** Call nIP stack dispatcher. The dispatcher will check for accumulated events 00070 * and act accordingly. That is, it will initiate packet reception, transmission 00071 * and retransmission. Events are used to put the dispatcher on track. 00072 * 00073 * Only one instance of the dispatcher can be running at a time. It will return 00074 * NIP_E_DISP_RUNNING if there is another instance active. That instance will 00075 * take care of all events so no event will be lost. 00076 * 00077 * For blocking operations that need to wait for the dispatcher to finish in 00078 * order to complete what they're doing, the nip_disp_check() function may be 00079 * used to check the dispatcher status. 00080 * 00081 * @note Interrupting the dispatcher may lead to deadlock in non-multitasking 00082 * environments, if you attempt to wait for the dispatcher to to finish within 00083 * the interrupt. E.g. Do NOT wait for the already running dispatcher to handle 00084 * your event/request/packet if you're not in a multicasting environment. 00085 */ 00086 nip_error_t nip_dispatcher() 00087 { 00088 void (*tmp_cmd)(void); 00089 00090 // only allow one instance of dispatcher to be active 00091 if (nip_disp_check() == NIP_E_DISP_RUNNING) return NIP_E_DISP_RUNNING; 00092 00093 // set dispatcher status 00094 nip_disp.flags |= NIP_DISP_RUNNING; 00095 00096 // Repeat processing until all pending events have been handled. This has to 00097 // be a loop since new events may be added as the dispatcher is running. 00098 while ( nip_disp.flags > NIP_DISP_RUNNING ) 00099 { 00100 NIP_CURR_CMD = NULL; 00101 00102 // Handle Network Interface Events 00103 if ( nip_disp.flags & NIP_DISP_CHECK_IF ) 00104 { 00105 // reset check_if flag 00106 nip_disp.flags &= ~NIP_DISP_CHECK_IF; 00107 00108 // check all interfaces for events 00109 SET_CURR_IF( 0 ); 00110 #if NIP_NET_IF_COUNT>1 00111 do 00112 { 00113 #endif 00114 // check for newly received (ethernet) packets 00115 if ( nip_disp.if_flags[ NIP_CURR_IF ] & NIP_DISP_IF_ETH_R ) 00116 { 00117 // NIP_CURR_CMD = NIP_DC_HARD_RECV; 00118 nip_disp.if_flags[ NIP_CURR_IF ] &= ~NIP_DISP_IF_ETH_R; 00119 NIP_CURR_CMD = nip_net_if_list[ NIP_CURR_IF ].phy_conf.hard_disp_recv; 00120 00121 // set check_if flag to make sure we didn't miss any event 00122 nip_disp_notify( NIP_DISP_CHECK_IF ); 00123 goto eval_cmd; 00124 } 00125 00126 if ( nip_disp.if_flags[ NIP_CURR_IF ] & NIP_DISP_IF_TIMER ) 00127 { 00128 nip_disp.if_flags[ NIP_CURR_IF ] &= ~NIP_DISP_IF_TIMER; 00129 nip_disp.if_flags[ NIP_CURR_IF ] = nip_disp.if_flags[NIP_CURR_IF] 00130 #if NIP_DHCP_ENABLE == 1 00131 | NIP_DISP_IF_DHCP 00132 #endif 00133 #if NIP_AUTOIP_ENABLE == 1 00134 | NIP_DISP_IF_AUTOIP 00135 #endif 00136 #if NIP_IGMP_ENABLE == 1 00137 | NIP_DISP_IF_GROUP 00138 #endif 00139 ; 00140 } 00141 00142 #if ( NIP_DHCP_ENABLE == 1 ) 00143 if ( nip_disp.if_flags[ NIP_CURR_IF ] & NIP_DISP_IF_DHCP ) 00144 { 00145 nip_disp.if_flags[ NIP_CURR_IF ] &= ~NIP_DISP_IF_DHCP; 00146 NIP_CURR_CMD = &nip_dhcp_disp_check; 00147 // set check_if flag to make sure we didn't miss any event 00148 nip_disp_notify( NIP_DISP_CHECK_IF ); 00149 goto eval_cmd; 00150 } 00151 #endif // ( NIP_DHCP_ENABLE == 1 ) 00152 00153 #if ( NIP_AUTOIP_ENABLE == 1 ) 00154 if ( nip_disp.if_flags[ NIP_CURR_IF ] & NIP_DISP_IF_AUTOIP ) 00155 { 00156 nip_disp.if_flags[ NIP_CURR_IF ] &= ~NIP_DISP_IF_AUTOIP; 00157 NIP_CURR_CMD = &nip_autoip_disp_check; 00158 // set check_if flag to make sure we didn't miss any event 00159 nip_disp_notify( NIP_DISP_CHECK_IF ); 00160 goto eval_cmd; 00161 } 00162 #endif 00163 00164 #if ( NIP_IGMP_ENABLE == 1 ) 00165 if ( nip_disp.if_flags[ NIP_CURR_IF ] & NIP_DISP_IF_GROUP ) 00166 { 00167 nip_disp.if_flags[ NIP_CURR_IF ] &= ~NIP_DISP_IF_GROUP; 00168 NIP_CURR_CMD = &nip_ip_disp_check_group; 00169 // set check_if flag to make sure we didn't miss any event 00170 nip_disp_notify( NIP_DISP_CHECK_IF ); 00171 goto eval_cmd; 00172 } 00173 #endif 00174 00175 #if NIP_NET_IF_COUNT>1 00176 } while ( ++NIP_CURR_IF < NIP_NET_IF_COUNT ); 00177 #endif 00178 } 00179 00180 if ( nip_disp.flags & NIP_DISP_TIMER ) 00181 { 00182 nip_disp.flags &= ~NIP_DISP_TIMER; 00183 nip_disp.flags |= 00184 NIP_DISP_CHECK_TRANS 00185 #if NIP_TCP_ENABLE == 1 00186 | NIP_DISP_CHECK_TCP 00187 #endif 00188 #if NIP_MDNS_ENABLE == 1 00189 | NIP_DISP_CHECK_MDNS 00190 #endif 00191 ; 00192 } 00193 00194 // Transmission events 00195 // check for IP address resolution flag 00196 if ( nip_disp.flags & NIP_DISP_CHECK_TRANS ) 00197 { 00198 00199 nip_disp.flags &= ~NIP_DISP_CHECK_TRANS; 00200 // find transmissions with status NIP_NET_IF_RESOLV_ADDR 00201 #if NIP_ARP_ENABLE == 1 00202 NIP_CURR_CMD = &nip_arp_disp_resolve_any; 00203 #endif 00204 goto eval_cmd; 00205 } 00206 00207 // mDNS events 00208 #if NIP_MDNS_ENABLE == 1 00209 if ( nip_disp.flags & NIP_DISP_CHECK_MDNS ) 00210 { 00211 00212 nip_disp.flags &= ~NIP_DISP_CHECK_MDNS; 00213 // find transmissions with status NIP_NET_IF_RESOLV_ADDR 00214 NIP_CURR_CMD = &nip_mdns_disp_check; 00215 goto eval_cmd; 00216 } 00217 #endif 00218 00219 #if NIP_TCP_ENABLE == 1 00220 // TCP events 00221 // check for IP address resolution flag 00222 if ( nip_disp.flags & NIP_DISP_CHECK_TCP ) 00223 { 00224 00225 nip_disp.flags &= ~NIP_DISP_CHECK_TCP; 00226 // find transmissions with status NIP_NET_IF_RESOLV_ADDR 00227 NIP_CURR_CMD = &nip_tcp_disp_check; 00228 goto eval_cmd; 00229 } 00230 #endif /* NIP_TCP_ENABLE */ 00231 00232 // Handle UDP Events if UDP has been enabled 00233 /// @todo Check if using an UDP state machine makes more sense than the 00234 /// current, direct approach of nip_udp_transmit(). Check nip_udp_disp_send() 00235 /// for further details. 00236 // #if ( NIP_UDP_ENABLE == 1 ) 00237 // if ( nip_disp.flags & NIP_DISP_CHECK_UDP ) 00238 // { 00239 // nip_disp.flags &= ~NIP_DISP_CHECK_UDP; 00240 // NIP_CURR_CMD = &nip_udp_disp_send; 00241 // goto eval_cmd; 00242 // } 00243 // #endif 00244 00245 // Execute Dispatcher Command Chain. A command is a pointer to a function 00246 // which may relocate that pointer during it's runtime. The dispatcher 00247 // will execute the new function after the previous function returned which 00248 // will possibly lead to chain of functions to be executed. In a non- 00249 // multitasking environment it is necessary that any chain of functions 00250 // implements defined exit points which will allow continuation of the 00251 // chain at a later, event-driven (e.g. timer) point of time. Any function 00252 // chain must ensure that no deadlock situation can arise from its 00253 // execution. 00254 eval_cmd: 00255 while ( NIP_CURR_CMD != NULL ) 00256 { 00257 tmp_cmd = NIP_CURR_CMD; 00258 NIP_CURR_CMD = NULL; 00259 tmp_cmd(); 00260 00261 } 00262 00263 00264 }; 00265 00266 ///\todo Take result value from nip_disp - Structure 00267 nip_disp.flags &= ~NIP_DISP_RUNNING; 00268 return NIP_E_OK; 00269 } 00270 #endif /*(NIP_DISP_ENABLE==1)*/