00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00038 #include <async.h>
00039 #include <mem.h>
00040 #include <fibril_synch.h>
00041 #include <stdio.h>
00042 #include <ipc/services.h>
00043 #include <ipc/netif.h>
00044 #include <errno.h>
00045
00046 #include <generic.h>
00047 #include <net/modules.h>
00048 #include <net/packet.h>
00049 #include <packet_client.h>
00050 #include <packet_remote.h>
00051 #include <adt/measured_strings.h>
00052 #include <net/device.h>
00053 #include <netif_skel.h>
00054 #include <nil_remote.h>
00055
00056 DEVICE_MAP_IMPLEMENT(netif_device_map, netif_device_t);
00057
00059 netif_globals_t netif_globals;
00060
00073 static int netif_probe_req_local(int netif_phone, device_id_t device_id,
00074 int irq, void *io)
00075 {
00076 fibril_rwlock_write_lock(&netif_globals.lock);
00077 int result = netif_probe_message(device_id, irq, io);
00078 fibril_rwlock_write_unlock(&netif_globals.lock);
00079
00080 return result;
00081 }
00082
00095 static int netif_send_msg_local(int netif_phone, device_id_t device_id,
00096 packet_t *packet, services_t sender)
00097 {
00098 fibril_rwlock_write_lock(&netif_globals.lock);
00099 int result = netif_send_message(device_id, packet, sender);
00100 fibril_rwlock_write_unlock(&netif_globals.lock);
00101
00102 return result;
00103 }
00104
00117 static int netif_start_req_local(int netif_phone, device_id_t device_id)
00118 {
00119 fibril_rwlock_write_lock(&netif_globals.lock);
00120
00121 netif_device_t *device;
00122 int rc = find_device(device_id, &device);
00123 if (rc != EOK) {
00124 fibril_rwlock_write_unlock(&netif_globals.lock);
00125 return rc;
00126 }
00127
00128 int result = netif_start_message(device);
00129 if (result > NETIF_NULL) {
00130 int phone = device->nil_phone;
00131 nil_device_state_msg(phone, device_id, result);
00132 fibril_rwlock_write_unlock(&netif_globals.lock);
00133 return EOK;
00134 }
00135
00136 fibril_rwlock_write_unlock(&netif_globals.lock);
00137
00138 return result;
00139 }
00140
00153 static int netif_stop_req_local(int netif_phone, device_id_t device_id)
00154 {
00155 fibril_rwlock_write_lock(&netif_globals.lock);
00156
00157 netif_device_t *device;
00158 int rc = find_device(device_id, &device);
00159 if (rc != EOK) {
00160 fibril_rwlock_write_unlock(&netif_globals.lock);
00161 return rc;
00162 }
00163
00164 int result = netif_stop_message(device);
00165 if (result > NETIF_NULL) {
00166 int phone = device->nil_phone;
00167 nil_device_state_msg(phone, device_id, result);
00168 fibril_rwlock_write_unlock(&netif_globals.lock);
00169 return EOK;
00170 }
00171
00172 fibril_rwlock_write_unlock(&netif_globals.lock);
00173
00174 return result;
00175 }
00176
00187 int find_device(device_id_t device_id, netif_device_t **device)
00188 {
00189 if (!device)
00190 return EBADMEM;
00191
00192 *device = netif_device_map_find(&netif_globals.device_map, device_id);
00193 if (*device == NULL)
00194 return ENOENT;
00195
00196 if ((*device)->state == NETIF_NULL)
00197 return EPERM;
00198
00199 return EOK;
00200 }
00201
00207 void null_device_stats(device_stats_t *stats)
00208 {
00209 bzero(stats, sizeof(device_stats_t));
00210 }
00211
00219 void netif_pq_release(packet_id_t packet_id)
00220 {
00221 pq_release_remote(netif_globals.net_phone, packet_id);
00222 }
00223
00232 packet_t *netif_packet_get_1(size_t content)
00233 {
00234 return packet_get_1_remote(netif_globals.net_phone, content);
00235 }
00236
00250 static int register_message(device_id_t device_id, int phone)
00251 {
00252 netif_device_t *device;
00253 int rc = find_device(device_id, &device);
00254 if (rc != EOK)
00255 return rc;
00256
00257 if (device->nil_phone >= 0)
00258 return ELIMIT;
00259
00260 device->nil_phone = phone;
00261 return EOK;
00262 }
00263
00279 static int netif_module_message(ipc_callid_t callid, ipc_call_t *call,
00280 ipc_call_t *answer, size_t *count)
00281 {
00282 size_t length;
00283 device_stats_t stats;
00284 packet_t *packet;
00285 measured_string_t address;
00286 int rc;
00287
00288 *count = 0;
00289
00290 switch (IPC_GET_IMETHOD(*call)) {
00291 case IPC_M_PHONE_HUNGUP:
00292 return EOK;
00293
00294 case NET_NETIF_PROBE:
00295 return netif_probe_req_local(0, IPC_GET_DEVICE(*call),
00296 NETIF_GET_IRQ(*call), NETIF_GET_IO(*call));
00297
00298 case IPC_M_CONNECT_TO_ME:
00299 fibril_rwlock_write_lock(&netif_globals.lock);
00300
00301 rc = register_message(IPC_GET_DEVICE(*call), IPC_GET_PHONE(*call));
00302
00303 fibril_rwlock_write_unlock(&netif_globals.lock);
00304 return rc;
00305
00306 case NET_NETIF_SEND:
00307 rc = packet_translate_remote(netif_globals.net_phone, &packet,
00308 IPC_GET_PACKET(*call));
00309 if (rc != EOK)
00310 return rc;
00311
00312 return netif_send_msg_local(0, IPC_GET_DEVICE(*call), packet,
00313 IPC_GET_SENDER(*call));
00314
00315 case NET_NETIF_START:
00316 return netif_start_req_local(0, IPC_GET_DEVICE(*call));
00317
00318 case NET_NETIF_STATS:
00319 fibril_rwlock_read_lock(&netif_globals.lock);
00320
00321 rc = async_data_read_receive(&callid, &length);
00322 if (rc != EOK) {
00323 fibril_rwlock_read_unlock(&netif_globals.lock);
00324 return rc;
00325 }
00326
00327 if (length < sizeof(device_stats_t)) {
00328 fibril_rwlock_read_unlock(&netif_globals.lock);
00329 return EOVERFLOW;
00330 }
00331
00332 rc = netif_get_device_stats(IPC_GET_DEVICE(*call), &stats);
00333 if (rc == EOK) {
00334 rc = async_data_read_finalize(callid, &stats,
00335 sizeof(device_stats_t));
00336 }
00337
00338 fibril_rwlock_read_unlock(&netif_globals.lock);
00339 return rc;
00340
00341 case NET_NETIF_STOP:
00342 return netif_stop_req_local(0, IPC_GET_DEVICE(*call));
00343
00344 case NET_NETIF_GET_ADDR:
00345 fibril_rwlock_read_lock(&netif_globals.lock);
00346
00347 rc = netif_get_addr_message(IPC_GET_DEVICE(*call), &address);
00348 if (rc == EOK)
00349 rc = measured_strings_reply(&address, 1);
00350
00351 fibril_rwlock_read_unlock(&netif_globals.lock);
00352 return rc;
00353 }
00354
00355 return netif_specific_message(callid, call, answer, count);
00356 }
00357
00364 static void netif_client_connection(ipc_callid_t iid, ipc_call_t *icall)
00365 {
00366
00367
00368
00369
00370 async_answer_0(iid, EOK);
00371
00372 while (true) {
00373 ipc_call_t answer;
00374 size_t count;
00375
00376
00377 refresh_answer(&answer, &count);
00378
00379
00380 ipc_call_t call;
00381 ipc_callid_t callid = async_get_call(&call);
00382
00383
00384 int res = netif_module_message(callid, &call, &answer, &count);
00385
00386
00387 if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) ||
00388 (res == EHANGUP))
00389 return;
00390
00391
00392 answer_call(callid, res, &answer, count);
00393 }
00394 }
00395
00407 int netif_module_start(void)
00408 {
00409 async_set_client_connection(netif_client_connection);
00410
00411 netif_globals.net_phone = connect_to_service(SERVICE_NETWORKING);
00412 netif_device_map_initialize(&netif_globals.device_map);
00413
00414 int rc = pm_init();
00415 if (rc != EOK)
00416 return rc;
00417
00418 fibril_rwlock_initialize(&netif_globals.lock);
00419
00420 rc = netif_initialize();
00421 if (rc != EOK) {
00422 pm_destroy();
00423 return rc;
00424 }
00425
00426 async_manager();
00427
00428 pm_destroy();
00429 return EOK;
00430 }
00431