Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 4191 → Rev 4192

/branches/network/uspace/srv/net/nil/eth/eth.c
37,8 → 37,8
 
#include <async.h>
#include <malloc.h>
#include <mem.h>
#include <stdio.h>
#include <string.h>
 
#include <ipc/ipc.h>
#include <ipc/services.h>
76,9 → 76,11
*/
#define IPC_GET_PACKET( call ) ( packet_id_t ) IPC_GET_ARG2( * call )
 
#define IPC_GET_STATE( call ) ( device_state_t ) IPC_GET_ARG2( * call )
 
/** Returns the protocol service message parameter.
*/
#define IPC_GET_PROTO( call ) ( services_t ) IPC_GET_ARG1( * call )
#define IPC_GET_PROTO( call ) ( services_t ) IPC_GET_ARG2( * call )
 
/** Returns the device driver service message parameter.
*/
123,7 → 125,7
int eth_send_message( device_id_t device_id, packet_t packet, services_t sender );
int eth_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count );
void eth_receiver( ipc_callid_t iid, ipc_call_t * icall );
eth_proto_ref eth_proccess_packet( int dummy, packet_t packet );
eth_proto_ref eth_process_packet( int dummy, packet_t packet );
int eth_prepare_packet( int dummy, packet_t packet, uint8_t * src_addr, int ethertype );
 
int eth_initialize( void ){
151,7 → 153,8
aid_t message;
ipc_call_t answer;
eth_device_ref device;
int result;
ipcarg_t result;
int index;
 
rwlock_write_lock( & eth_globals.devices_lock );
// an existing device?
190,7 → 193,7
async_wait_for( message, NULL );
return ERROR_CODE;
}
async_wait_for( message, ( ipcarg_t * ) & result );
async_wait_for( message, & result );
if( ERROR_OCCURRED( result )){
rwlock_write_unlock( & eth_globals.devices_lock );
free( device->addr );
199,12 → 202,13
return ERROR_CODE;
}
// add to the cache
if( ERROR_OCCURRED( eth_devices_add( & eth_globals.devices, device->device_id, device ))){
index = eth_devices_add( & eth_globals.devices, device->device_id, device );
if( index < 0 ){
rwlock_write_unlock( & eth_globals.devices_lock );
free( device->addr );
free( device->addr_data );
free( device );
return ERROR_CODE;
return index;
}
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 ] );
}
212,7 → 216,7
return EOK;
}
 
eth_proto_ref eth_proccess_packet( int dummy, packet_t packet ){
eth_proto_ref eth_process_packet( int dummy, packet_t packet ){
ERROR_DECLARE;
 
eth_header_ex_ref header;
286,12 → 290,12
rwlock_read_lock( & eth_globals.protos_lock );
do{
next = pq_detach( packet );
proto = eth_proccess_packet( dummy, packet );
proto = eth_process_packet( dummy, packet );
if( proto ){
async_msg_2( proto->phone, NET_IL_RECEIVED, device_id, packet_get_id( packet ));
}else{
// drop invalid/unknown
packet_release( eth_globals.networking_phone, packet_get_id( packet ));
pq_release( eth_globals.networking_phone, packet_get_id( packet ));
}
packet = next;
}while( packet );
303,14 → 307,14
eth_device_ref device;
 
if( !( addr_len && prefix && content && suffix )) return EINVAL;
rwlock_write_lock( & eth_globals.devices_lock );
rwlock_read_lock( & eth_globals.devices_lock );
device = eth_devices_find( & eth_globals.devices, device_id );
if( ! device ){
rwlock_write_unlock( & eth_globals.devices_lock );
rwlock_read_unlock( & eth_globals.devices_lock );
return ENOENT;
}
* content = ( ETH_MAX_CONTENT > device->mtu ) ? device->mtu : ETH_MAX_CONTENT;
rwlock_write_unlock( & eth_globals.devices_lock );
rwlock_read_unlock( & eth_globals.devices_lock );
* addr_len = ETH_ADDR;
* prefix = ETH_PREFIX;
* suffix = ETH_MIN_CONTENT + ETH_SUFFIX;
324,23 → 328,22
if( type == ETH_BROADCAST_ADDR ){
* address = eth_globals.broadcast_addr;
}else{
rwlock_write_lock( & eth_globals.devices_lock );
rwlock_read_lock( & eth_globals.devices_lock );
device = eth_devices_find( & eth_globals.devices, device_id );
if( ! device ){
rwlock_write_unlock( & eth_globals.devices_lock );
rwlock_read_unlock( & eth_globals.devices_lock );
return ENOENT;
}
* address = device->addr;
rwlock_write_unlock( & eth_globals.devices_lock );
rwlock_read_unlock( & eth_globals.devices_lock );
}
return ( * address ) ? EOK : ENOENT;
}
 
int eth_register_message( services_t service, int phone ){
ERROR_DECLARE;
 
eth_proto_ref proto;
int protocol;
int index;
 
protocol = protocol_map( SERVICE_ETHERNET, service );
if( ! protocol ) return ENOENT;
359,13 → 362,14
proto->service = service;
proto->protocol = protocol;
proto->phone = phone;
if( ERROR_OCCURRED( eth_protos_add( & eth_globals.protos, protocol, proto ))){
index = eth_protos_add( & eth_globals.protos, protocol, proto );
if( index < 0 ){
rwlock_write_unlock( & eth_globals.protos_lock );
free( proto );
return ERROR_CODE;
return index;
}
}
printf( "\nNew protocol registered:\n\tprotocol\t= %d\n\tservice\t= %d\n\tphone\t= %d", proto->protocol, proto->service, proto->phone );
printf( "\nNew protocol registered:\n\tprotocol\t= 0x%x\n\tservice\t= %d\n\tphone\t= %d", proto->protocol, proto->service, proto->phone );
rwlock_write_unlock( & eth_globals.protos_lock );
return EOK;
}
398,7 → 402,7
if( length < ETH_MIN_CONTENT ){
padding = packet_suffix( packet, ETH_MIN_CONTENT - length );
if( ! padding ) return ENOMEM;
memset( padding, 0, ETH_MIN_CONTENT - length );
bzero( padding, ETH_MIN_CONTENT - length );
}
header->header.ethertype = htons( length );
header->lsap.dsap = 0xAA;
424,7 → 428,7
 
ethertype = htons( protocol_map( SERVICE_ETHERNET, sender ));
if( ! ethertype ){
packet_release( eth_globals.networking_phone, packet_get_id( packet ));
pq_release( eth_globals.networking_phone, packet_get_id( packet ));
return EINVAL;
}
rwlock_read_lock( & eth_globals.devices_lock );
433,13 → 437,13
rwlock_read_unlock( & eth_globals.devices_lock );
return ENOENT;
}
// proccess packet queue
// process packet queue
next = packet;
do{
if( ERROR_OCCURRED( eth_prepare_packet( device->dummy, next, ( uint8_t * ) device->addr->value, ethertype ))){
// release invalid packet
tmp = pq_detach( next );
packet_release( eth_globals.networking_phone, packet_get_id( next ));
pq_release( eth_globals.networking_phone, packet_get_id( next ));
next = tmp;
}else{
next = pq_next( next );
471,18 → 475,11
* answer_count = 3;
return EOK;
case NET_NIL_ADDR:
rwlock_read_lock( & eth_globals.devices_lock );
if( ! ERROR_OCCURRED( eth_addr_message( IPC_GET_DEVICE( call ), ETH_LOCAL_ADDR, & address ))){
ERROR_CODE = measured_strings_reply( address, 1 );
}
rwlock_read_unlock( & eth_globals.devices_lock );
return ERROR_CODE;
ERROR_PROPAGATE( eth_addr_message( IPC_GET_DEVICE( call ), ETH_LOCAL_ADDR, & address ));
return measured_strings_reply( address, 1 );
case NET_NIL_BROADCAST_ADDR:
rwlock_read_lock( & eth_globals.devices_lock );
if( ! ERROR_OCCURRED( eth_addr_message( IPC_GET_DEVICE( call ), ETH_BROADCAST_ADDR, & address ))){
ERROR_CODE = measured_strings_reply( address, 1 );
}
rwlock_read_unlock( & eth_globals.devices_lock );
ERROR_PROPAGATE( eth_addr_message( IPC_GET_DEVICE( call ), ETH_BROADCAST_ADDR, & address ));
return measured_strings_reply( address, 1 );
return ERROR_CODE;
case IPC_M_CONNECT_TO_ME:
return eth_register_message( IPC_GET_PROTO( call ), IPC_GET_PHONE( call ));
494,11 → 491,20
ERROR_DECLARE;
 
packet_t packet;
int index;
eth_proto_ref proto;
 
while( true ){
switch( IPC_GET_METHOD( * icall )){
case NET_NIL_DEVICE_STATE:
//TODO clear device if off?
rwlock_read_lock( & eth_globals.protos_lock );
for( index = eth_protos_count( & eth_globals.protos ) - 1; index >= 0; -- index ){
proto = eth_protos_get_index( & eth_globals.protos, index );
if( proto && proto->phone ) async_msg_2( proto->phone, NET_IL_DEVICE_STATE, IPC_GET_DEVICE( icall ), IPC_GET_STATE( icall ));
}
rwlock_read_unlock( & eth_globals.protos_lock );
ipc_answer_0( iid, EOK );
break;
case NET_NIL_RECEIVED:
if( ! ERROR_OCCURRED( packet_translate( eth_globals.networking_phone, & packet, IPC_GET_PACKET( icall )))){