Rev 4163 | Rev 4243 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4163 | Rev 4192 | ||
---|---|---|---|
Line 35... | Line 35... | ||
35 | * @see eth.h |
35 | * @see eth.h |
36 | */ |
36 | */ |
37 | 37 | ||
38 | #include <async.h> |
38 | #include <async.h> |
39 | #include <malloc.h> |
39 | #include <malloc.h> |
- | 40 | #include <mem.h> |
|
40 | #include <stdio.h> |
41 | #include <stdio.h> |
41 | #include <string.h> |
- | |
42 | 42 | ||
43 | #include <ipc/ipc.h> |
43 | #include <ipc/ipc.h> |
44 | #include <ipc/services.h> |
44 | #include <ipc/services.h> |
45 | 45 | ||
46 | #include "../../err.h" |
46 | #include "../../err.h" |
Line 74... | Line 74... | ||
74 | 74 | ||
75 | /** Returns the packet identifier message parameter. |
75 | /** Returns the packet identifier message parameter. |
76 | */ |
76 | */ |
77 | #define IPC_GET_PACKET( call ) ( packet_id_t ) IPC_GET_ARG2( * call ) |
77 | #define IPC_GET_PACKET( call ) ( packet_id_t ) IPC_GET_ARG2( * call ) |
78 | 78 | ||
- | 79 | #define IPC_GET_STATE( call ) ( device_state_t ) IPC_GET_ARG2( * call ) |
|
- | 80 | ||
79 | /** Returns the protocol service message parameter. |
81 | /** Returns the protocol service message parameter. |
80 | */ |
82 | */ |
81 | #define IPC_GET_PROTO( call ) ( services_t ) IPC_GET_ARG1( * call ) |
83 | #define IPC_GET_PROTO( call ) ( services_t ) IPC_GET_ARG2( * call ) |
82 | 84 | ||
83 | /** Returns the device driver service message parameter. |
85 | /** Returns the device driver service message parameter. |
84 | */ |
86 | */ |
85 | #define IPC_GET_SERVICE( call ) ( services_t ) IPC_GET_ARG2( * call ) |
87 | #define IPC_GET_SERVICE( call ) ( services_t ) IPC_GET_ARG2( * call ) |
86 | 88 | ||
Line 121... | Line 123... | ||
121 | int eth_addr_message( device_id_t device_id, eth_addr_type_t type, measured_string_ref * address ); |
123 | int eth_addr_message( device_id_t device_id, eth_addr_type_t type, measured_string_ref * address ); |
122 | int eth_register_message( services_t service, int phone ); |
124 | int eth_register_message( services_t service, int phone ); |
123 | int eth_send_message( device_id_t device_id, packet_t packet, services_t sender ); |
125 | int eth_send_message( device_id_t device_id, packet_t packet, services_t sender ); |
124 | int eth_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ); |
126 | int eth_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ); |
125 | void eth_receiver( ipc_callid_t iid, ipc_call_t * icall ); |
127 | void eth_receiver( ipc_callid_t iid, ipc_call_t * icall ); |
126 | eth_proto_ref eth_proccess_packet( int dummy, packet_t packet ); |
128 | eth_proto_ref eth_process_packet( int dummy, packet_t packet ); |
127 | int eth_prepare_packet( int dummy, packet_t packet, uint8_t * src_addr, int ethertype ); |
129 | int eth_prepare_packet( int dummy, packet_t packet, uint8_t * src_addr, int ethertype ); |
128 | 130 | ||
129 | int eth_initialize( void ){ |
131 | int eth_initialize( void ){ |
130 | ERROR_DECLARE; |
132 | ERROR_DECLARE; |
131 | 133 | ||
Line 149... | Line 151... | ||
149 | ERROR_DECLARE; |
151 | ERROR_DECLARE; |
150 | 152 | ||
151 | aid_t message; |
153 | aid_t message; |
152 | ipc_call_t answer; |
154 | ipc_call_t answer; |
153 | eth_device_ref device; |
155 | eth_device_ref device; |
- | 156 | ipcarg_t result; |
|
154 | int result; |
157 | int index; |
155 | 158 | ||
156 | rwlock_write_lock( & eth_globals.devices_lock ); |
159 | rwlock_write_lock( & eth_globals.devices_lock ); |
157 | // an existing device? |
160 | // an existing device? |
158 | device = eth_devices_find( & eth_globals.devices, device_id ); |
161 | device = eth_devices_find( & eth_globals.devices, device_id ); |
159 | if( device ){ |
162 | if( device ){ |
Line 188... | Line 191... | ||
188 | rwlock_write_unlock( & eth_globals.devices_lock ); |
191 | rwlock_write_unlock( & eth_globals.devices_lock ); |
189 | free( device ); |
192 | free( device ); |
190 | async_wait_for( message, NULL ); |
193 | async_wait_for( message, NULL ); |
191 | return ERROR_CODE; |
194 | return ERROR_CODE; |
192 | } |
195 | } |
193 | async_wait_for( message, ( ipcarg_t * ) & result ); |
196 | async_wait_for( message, & result ); |
194 | if( ERROR_OCCURRED( result )){ |
197 | if( ERROR_OCCURRED( result )){ |
195 | rwlock_write_unlock( & eth_globals.devices_lock ); |
198 | rwlock_write_unlock( & eth_globals.devices_lock ); |
196 | free( device->addr ); |
199 | free( device->addr ); |
197 | free( device->addr_data ); |
200 | free( device->addr_data ); |
198 | free( device ); |
201 | free( device ); |
199 | return ERROR_CODE; |
202 | return ERROR_CODE; |
200 | } |
203 | } |
201 | // add to the cache |
204 | // add to the cache |
202 | if( ERROR_OCCURRED( eth_devices_add( & eth_globals.devices, device->device_id, device ))){ |
205 | index = eth_devices_add( & eth_globals.devices, device->device_id, device ); |
- | 206 | if( index < 0 ){ |
|
203 | rwlock_write_unlock( & eth_globals.devices_lock ); |
207 | rwlock_write_unlock( & eth_globals.devices_lock ); |
204 | free( device->addr ); |
208 | free( device->addr ); |
205 | free( device->addr_data ); |
209 | free( device->addr_data ); |
206 | free( device ); |
210 | free( device ); |
207 | return ERROR_CODE; |
211 | return index; |
208 | } |
212 | } |
209 | printf( "\nNew device registered:\n\tid\t= %d\n\tservice\t= %d\n\tMTU\t= %d\n\taddress\t= %X:%X:%X:%X:%X:%X", device->device_id, device->service, device->mtu, device->addr_data[ 0 ], device->addr_data[ 1 ], device->addr_data[ 2 ], device->addr_data[ 3 ], device->addr_data[ 4 ], device->addr_data[ 5 ] ); |
213 | printf( "\nNew device registered:\n\tid\t= %d\n\tservice\t= %d\n\tMTU\t= %d\n\taddress\t= %X:%X:%X:%X:%X:%X", device->device_id, device->service, device->mtu, device->addr_data[ 0 ], device->addr_data[ 1 ], device->addr_data[ 2 ], device->addr_data[ 3 ], device->addr_data[ 4 ], device->addr_data[ 5 ] ); |
210 | } |
214 | } |
211 | rwlock_write_unlock( & eth_globals.devices_lock ); |
215 | rwlock_write_unlock( & eth_globals.devices_lock ); |
212 | return EOK; |
216 | return EOK; |
213 | } |
217 | } |
214 | 218 | ||
215 | eth_proto_ref eth_proccess_packet( int dummy, packet_t packet ){ |
219 | eth_proto_ref eth_process_packet( int dummy, packet_t packet ){ |
216 | ERROR_DECLARE; |
220 | ERROR_DECLARE; |
217 | 221 | ||
218 | eth_header_ex_ref header; |
222 | eth_header_ex_ref header; |
219 | size_t length; |
223 | size_t length; |
220 | int type; |
224 | int type; |
Line 284... | Line 288... | ||
284 | dummy = device->dummy; |
288 | dummy = device->dummy; |
285 | rwlock_read_unlock( & eth_globals.devices_lock ); |
289 | rwlock_read_unlock( & eth_globals.devices_lock ); |
286 | rwlock_read_lock( & eth_globals.protos_lock ); |
290 | rwlock_read_lock( & eth_globals.protos_lock ); |
287 | do{ |
291 | do{ |
288 | next = pq_detach( packet ); |
292 | next = pq_detach( packet ); |
289 | proto = eth_proccess_packet( dummy, packet ); |
293 | proto = eth_process_packet( dummy, packet ); |
290 | if( proto ){ |
294 | if( proto ){ |
291 | async_msg_2( proto->phone, NET_IL_RECEIVED, device_id, packet_get_id( packet )); |
295 | async_msg_2( proto->phone, NET_IL_RECEIVED, device_id, packet_get_id( packet )); |
292 | }else{ |
296 | }else{ |
293 | // drop invalid/unknown |
297 | // drop invalid/unknown |
294 | packet_release( eth_globals.networking_phone, packet_get_id( packet )); |
298 | pq_release( eth_globals.networking_phone, packet_get_id( packet )); |
295 | } |
299 | } |
296 | packet = next; |
300 | packet = next; |
297 | }while( packet ); |
301 | }while( packet ); |
298 | rwlock_read_unlock( & eth_globals.protos_lock ); |
302 | rwlock_read_unlock( & eth_globals.protos_lock ); |
299 | return EOK; |
303 | return EOK; |
Line 301... | Line 305... | ||
301 | 305 | ||
302 | int eth_packet_space_message( device_id_t device_id, size_t * addr_len, size_t * prefix, size_t * content, size_t * suffix ){ |
306 | int eth_packet_space_message( device_id_t device_id, size_t * addr_len, size_t * prefix, size_t * content, size_t * suffix ){ |
303 | eth_device_ref device; |
307 | eth_device_ref device; |
304 | 308 | ||
305 | if( !( addr_len && prefix && content && suffix )) return EINVAL; |
309 | if( !( addr_len && prefix && content && suffix )) return EINVAL; |
306 | rwlock_write_lock( & eth_globals.devices_lock ); |
310 | rwlock_read_lock( & eth_globals.devices_lock ); |
307 | device = eth_devices_find( & eth_globals.devices, device_id ); |
311 | device = eth_devices_find( & eth_globals.devices, device_id ); |
308 | if( ! device ){ |
312 | if( ! device ){ |
309 | rwlock_write_unlock( & eth_globals.devices_lock ); |
313 | rwlock_read_unlock( & eth_globals.devices_lock ); |
310 | return ENOENT; |
314 | return ENOENT; |
311 | } |
315 | } |
312 | * content = ( ETH_MAX_CONTENT > device->mtu ) ? device->mtu : ETH_MAX_CONTENT; |
316 | * content = ( ETH_MAX_CONTENT > device->mtu ) ? device->mtu : ETH_MAX_CONTENT; |
313 | rwlock_write_unlock( & eth_globals.devices_lock ); |
317 | rwlock_read_unlock( & eth_globals.devices_lock ); |
314 | * addr_len = ETH_ADDR; |
318 | * addr_len = ETH_ADDR; |
315 | * prefix = ETH_PREFIX; |
319 | * prefix = ETH_PREFIX; |
316 | * suffix = ETH_MIN_CONTENT + ETH_SUFFIX; |
320 | * suffix = ETH_MIN_CONTENT + ETH_SUFFIX; |
317 | return EOK; |
321 | return EOK; |
318 | } |
322 | } |
Line 322... | Line 326... | ||
322 | 326 | ||
323 | if( ! address ) return EINVAL; |
327 | if( ! address ) return EINVAL; |
324 | if( type == ETH_BROADCAST_ADDR ){ |
328 | if( type == ETH_BROADCAST_ADDR ){ |
325 | * address = eth_globals.broadcast_addr; |
329 | * address = eth_globals.broadcast_addr; |
326 | }else{ |
330 | }else{ |
327 | rwlock_write_lock( & eth_globals.devices_lock ); |
331 | rwlock_read_lock( & eth_globals.devices_lock ); |
328 | device = eth_devices_find( & eth_globals.devices, device_id ); |
332 | device = eth_devices_find( & eth_globals.devices, device_id ); |
329 | if( ! device ){ |
333 | if( ! device ){ |
330 | rwlock_write_unlock( & eth_globals.devices_lock ); |
334 | rwlock_read_unlock( & eth_globals.devices_lock ); |
331 | return ENOENT; |
335 | return ENOENT; |
332 | } |
336 | } |
333 | * address = device->addr; |
337 | * address = device->addr; |
334 | rwlock_write_unlock( & eth_globals.devices_lock ); |
338 | rwlock_read_unlock( & eth_globals.devices_lock ); |
335 | } |
339 | } |
336 | return ( * address ) ? EOK : ENOENT; |
340 | return ( * address ) ? EOK : ENOENT; |
337 | } |
341 | } |
338 | 342 | ||
339 | int eth_register_message( services_t service, int phone ){ |
343 | int eth_register_message( services_t service, int phone ){ |
340 | ERROR_DECLARE; |
- | |
341 | - | ||
342 | eth_proto_ref proto; |
344 | eth_proto_ref proto; |
343 | int protocol; |
345 | int protocol; |
- | 346 | int index; |
|
344 | 347 | ||
345 | protocol = protocol_map( SERVICE_ETHERNET, service ); |
348 | protocol = protocol_map( SERVICE_ETHERNET, service ); |
346 | if( ! protocol ) return ENOENT; |
349 | if( ! protocol ) return ENOENT; |
347 | rwlock_write_lock( & eth_globals.protos_lock ); |
350 | rwlock_write_lock( & eth_globals.protos_lock ); |
348 | proto = eth_protos_find( & eth_globals.protos, protocol ); |
351 | proto = eth_protos_find( & eth_globals.protos, protocol ); |
Line 357... | Line 360... | ||
357 | return ENOMEM; |
360 | return ENOMEM; |
358 | } |
361 | } |
359 | proto->service = service; |
362 | proto->service = service; |
360 | proto->protocol = protocol; |
363 | proto->protocol = protocol; |
361 | proto->phone = phone; |
364 | proto->phone = phone; |
362 | if( ERROR_OCCURRED( eth_protos_add( & eth_globals.protos, protocol, proto ))){ |
365 | index = eth_protos_add( & eth_globals.protos, protocol, proto ); |
- | 366 | if( index < 0 ){ |
|
363 | rwlock_write_unlock( & eth_globals.protos_lock ); |
367 | rwlock_write_unlock( & eth_globals.protos_lock ); |
364 | free( proto ); |
368 | free( proto ); |
365 | return ERROR_CODE; |
369 | return index; |
366 | } |
370 | } |
367 | } |
371 | } |
368 | printf( "\nNew protocol registered:\n\tprotocol\t= %d\n\tservice\t= %d\n\tphone\t= %d", proto->protocol, proto->service, proto->phone ); |
372 | printf( "\nNew protocol registered:\n\tprotocol\t= 0x%x\n\tservice\t= %d\n\tphone\t= %d", proto->protocol, proto->service, proto->phone ); |
369 | rwlock_write_unlock( & eth_globals.protos_lock ); |
373 | rwlock_write_unlock( & eth_globals.protos_lock ); |
370 | return EOK; |
374 | return EOK; |
371 | } |
375 | } |
372 | 376 | ||
373 | int eth_prepare_packet( int dummy, packet_t packet, uint8_t * src_addr, int ethertype ){ |
377 | int eth_prepare_packet( int dummy, packet_t packet, uint8_t * src_addr, int ethertype ){ |
Line 396... | Line 400... | ||
396 | length = packet_get_data_length( packet ); |
400 | length = packet_get_data_length( packet ); |
397 | if( length > ETH_MAX_CONTENT ) return EINVAL; |
401 | if( length > ETH_MAX_CONTENT ) return EINVAL; |
398 | if( length < ETH_MIN_CONTENT ){ |
402 | if( length < ETH_MIN_CONTENT ){ |
399 | padding = packet_suffix( packet, ETH_MIN_CONTENT - length ); |
403 | padding = packet_suffix( packet, ETH_MIN_CONTENT - length ); |
400 | if( ! padding ) return ENOMEM; |
404 | if( ! padding ) return ENOMEM; |
401 | memset( padding, 0, ETH_MIN_CONTENT - length ); |
405 | bzero( padding, ETH_MIN_CONTENT - length ); |
402 | } |
406 | } |
403 | header->header.ethertype = htons( length ); |
407 | header->header.ethertype = htons( length ); |
404 | header->lsap.dsap = 0xAA; |
408 | header->lsap.dsap = 0xAA; |
405 | header->lsap.ssap = header->lsap.dsap; |
409 | header->lsap.ssap = header->lsap.dsap; |
406 | header->lsap.ctrl = 0; |
410 | header->lsap.ctrl = 0; |
Line 422... | Line 426... | ||
422 | packet_t tmp; |
426 | packet_t tmp; |
423 | int ethertype; |
427 | int ethertype; |
424 | 428 | ||
425 | ethertype = htons( protocol_map( SERVICE_ETHERNET, sender )); |
429 | ethertype = htons( protocol_map( SERVICE_ETHERNET, sender )); |
426 | if( ! ethertype ){ |
430 | if( ! ethertype ){ |
427 | packet_release( eth_globals.networking_phone, packet_get_id( packet )); |
431 | pq_release( eth_globals.networking_phone, packet_get_id( packet )); |
428 | return EINVAL; |
432 | return EINVAL; |
429 | } |
433 | } |
430 | rwlock_read_lock( & eth_globals.devices_lock ); |
434 | rwlock_read_lock( & eth_globals.devices_lock ); |
431 | device = eth_devices_find( & eth_globals.devices, device_id ); |
435 | device = eth_devices_find( & eth_globals.devices, device_id ); |
432 | if( ! device ){ |
436 | if( ! device ){ |
433 | rwlock_read_unlock( & eth_globals.devices_lock ); |
437 | rwlock_read_unlock( & eth_globals.devices_lock ); |
434 | return ENOENT; |
438 | return ENOENT; |
435 | } |
439 | } |
436 | // proccess packet queue |
440 | // process packet queue |
437 | next = packet; |
441 | next = packet; |
438 | do{ |
442 | do{ |
439 | if( ERROR_OCCURRED( eth_prepare_packet( device->dummy, next, ( uint8_t * ) device->addr->value, ethertype ))){ |
443 | if( ERROR_OCCURRED( eth_prepare_packet( device->dummy, next, ( uint8_t * ) device->addr->value, ethertype ))){ |
440 | // release invalid packet |
444 | // release invalid packet |
441 | tmp = pq_detach( next ); |
445 | tmp = pq_detach( next ); |
442 | packet_release( eth_globals.networking_phone, packet_get_id( next )); |
446 | pq_release( eth_globals.networking_phone, packet_get_id( next )); |
443 | next = tmp; |
447 | next = tmp; |
444 | }else{ |
448 | }else{ |
445 | next = pq_next( next ); |
449 | next = pq_next( next ); |
446 | } |
450 | } |
447 | }while( next ); |
451 | }while( next ); |
Line 469... | Line 473... | ||
469 | case NET_NIL_PACKET_SPACE: |
473 | case NET_NIL_PACKET_SPACE: |
470 | ERROR_PROPAGATE( eth_packet_space_message( IPC_GET_DEVICE( call ), IPC_SET_ADDR( answer ), IPC_SET_PREFIX( answer ), IPC_SET_CONTENT( answer ), IPC_SET_SUFFIX( answer ))); |
474 | ERROR_PROPAGATE( eth_packet_space_message( IPC_GET_DEVICE( call ), IPC_SET_ADDR( answer ), IPC_SET_PREFIX( answer ), IPC_SET_CONTENT( answer ), IPC_SET_SUFFIX( answer ))); |
471 | * answer_count = 3; |
475 | * answer_count = 3; |
472 | return EOK; |
476 | return EOK; |
473 | case NET_NIL_ADDR: |
477 | case NET_NIL_ADDR: |
474 | rwlock_read_lock( & eth_globals.devices_lock ); |
- | |
475 | if( ! ERROR_OCCURRED( eth_addr_message( IPC_GET_DEVICE( call ), ETH_LOCAL_ADDR, & address ))){ |
478 | ERROR_PROPAGATE( eth_addr_message( IPC_GET_DEVICE( call ), ETH_LOCAL_ADDR, & address )); |
476 | ERROR_CODE = measured_strings_reply( address, 1 ); |
479 | return measured_strings_reply( address, 1 ); |
477 | } |
- | |
478 | rwlock_read_unlock( & eth_globals.devices_lock ); |
- | |
479 | return ERROR_CODE; |
- | |
480 | case NET_NIL_BROADCAST_ADDR: |
480 | case NET_NIL_BROADCAST_ADDR: |
481 | rwlock_read_lock( & eth_globals.devices_lock ); |
- | |
482 | if( ! ERROR_OCCURRED( eth_addr_message( IPC_GET_DEVICE( call ), ETH_BROADCAST_ADDR, & address ))){ |
481 | ERROR_PROPAGATE( eth_addr_message( IPC_GET_DEVICE( call ), ETH_BROADCAST_ADDR, & address )); |
483 | ERROR_CODE = measured_strings_reply( address, 1 ); |
482 | return measured_strings_reply( address, 1 ); |
484 | } |
- | |
485 | rwlock_read_unlock( & eth_globals.devices_lock ); |
- | |
486 | return ERROR_CODE; |
483 | return ERROR_CODE; |
487 | case IPC_M_CONNECT_TO_ME: |
484 | case IPC_M_CONNECT_TO_ME: |
488 | return eth_register_message( IPC_GET_PROTO( call ), IPC_GET_PHONE( call )); |
485 | return eth_register_message( IPC_GET_PROTO( call ), IPC_GET_PHONE( call )); |
489 | } |
486 | } |
490 | return ENOTSUP; |
487 | return ENOTSUP; |
Line 492... | Line 489... | ||
492 | 489 | ||
493 | void eth_receiver( ipc_callid_t iid, ipc_call_t * icall ){ |
490 | void eth_receiver( ipc_callid_t iid, ipc_call_t * icall ){ |
494 | ERROR_DECLARE; |
491 | ERROR_DECLARE; |
495 | 492 | ||
496 | packet_t packet; |
493 | packet_t packet; |
- | 494 | int index; |
|
- | 495 | eth_proto_ref proto; |
|
497 | 496 | ||
498 | while( true ){ |
497 | while( true ){ |
499 | switch( IPC_GET_METHOD( * icall )){ |
498 | switch( IPC_GET_METHOD( * icall )){ |
500 | case NET_NIL_DEVICE_STATE: |
499 | case NET_NIL_DEVICE_STATE: |
501 | //TODO clear device if off? |
500 | //TODO clear device if off? |
- | 501 | rwlock_read_lock( & eth_globals.protos_lock ); |
|
- | 502 | for( index = eth_protos_count( & eth_globals.protos ) - 1; index >= 0; -- index ){ |
|
- | 503 | proto = eth_protos_get_index( & eth_globals.protos, index ); |
|
- | 504 | if( proto && proto->phone ) async_msg_2( proto->phone, NET_IL_DEVICE_STATE, IPC_GET_DEVICE( icall ), IPC_GET_STATE( icall )); |
|
- | 505 | } |
|
- | 506 | rwlock_read_unlock( & eth_globals.protos_lock ); |
|
- | 507 | ipc_answer_0( iid, EOK ); |
|
502 | break; |
508 | break; |
503 | case NET_NIL_RECEIVED: |
509 | case NET_NIL_RECEIVED: |
504 | if( ! ERROR_OCCURRED( packet_translate( eth_globals.networking_phone, & packet, IPC_GET_PACKET( icall )))){ |
510 | if( ! ERROR_OCCURRED( packet_translate( eth_globals.networking_phone, & packet, IPC_GET_PACKET( icall )))){ |
505 | ERROR_CODE = eth_receive_message( IPC_GET_DEVICE( icall ), packet ); |
511 | ERROR_CODE = eth_receive_message( IPC_GET_DEVICE( icall ), packet ); |
506 | } |
512 | } |