netif_skel.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2009 Lukas Mejdrech
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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          * Accept the connection by answering
00368          * the initial IPC_M_CONNECT_ME_TO call.
00369          */
00370         async_answer_0(iid, EOK);
00371         
00372         while (true) {
00373                 ipc_call_t answer;
00374                 size_t count;
00375                 
00376                 /* Clear the answer structure */
00377                 refresh_answer(&answer, &count);
00378                 
00379                 /* Fetch the next message */
00380                 ipc_call_t call;
00381                 ipc_callid_t callid = async_get_call(&call);
00382                 
00383                 /* Process the message */
00384                 int res = netif_module_message(callid, &call, &answer, &count);
00385                 
00386                 /* End if said to either by the message or the processing result */
00387                 if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) ||
00388                     (res == EHANGUP))
00389                         return;
00390                 
00391                 /* Answer the message */
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 

Generated on Thu Jun 2 07:45:48 2011 for HelenOS/USB by  doxygen 1.4.7