source: mainline/uspace/lib/net/netif/netif_local.c@ d52fbaf

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since d52fbaf was c7a8442, checked in by Jakub Jermar <jakub@…>, 15 years ago

Move net_modules.[ch] to the standard library. Note that this functionality is
not directly related to networking so the next step regarding these two files
would be to somehow merge its functionality with what we already have in lib c.

  • Property mode set to 100644
File size: 13.1 KB
Line 
1/*
2 * Copyright (c) 2009 Lukas Mejdrech
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup netif
30 * @{
31 */
32
33/** @file
34 * Network interface module skeleton implementation.
35 * @see netif.h
36 */
37
38#include <async.h>
39#include <mem.h>
40#include <fibril_synch.h>
41#include <stdio.h>
42#include <ipc/ipc.h>
43#include <ipc/services.h>
44#include <err.h>
45
46#include <net_messages.h>
47#include <net/modules.h>
48#include <packet/packet.h>
49#include <packet/packet_client.h>
50#include <packet/packet_server.h>
51#include <packet_remote.h>
52#include <adt/measured_strings.h>
53#include <net_device.h>
54#include <nil_interface.h>
55#include <netif_local.h>
56#include <netif_messages.h>
57#include <netif_interface.h>
58
59DEVICE_MAP_IMPLEMENT(netif_device_map, netif_device_t);
60
61/** Network interface global data.
62 */
63netif_globals_t netif_globals;
64
65/** Probe the existence of the device.
66 *
67 * @param[in] netif_phone The network interface phone.
68 * @param[in] device_id The device identifier.
69 * @param[in] irq The device interrupt number.
70 * @param[in] io The device input/output address.
71 *
72 * @return EOK on success.
73 * @return Other errro codes as defined for the netif_probe_message().
74 *
75 */
76int netif_probe_req_local(int netif_phone, device_id_t device_id, int irq, int io)
77{
78 fibril_rwlock_write_lock(&netif_globals.lock);
79 int result = netif_probe_message(device_id, irq, io);
80 fibril_rwlock_write_unlock(&netif_globals.lock);
81
82 return result;
83}
84
85/** Send the packet queue.
86 *
87 * @param[in] netif_phone The network interface phone.
88 * @param[in] device_id The device identifier.
89 * @param[in] packet The packet queue.
90 * @param[in] sender The sending module service.
91 *
92 * @return EOK on success.
93 * @return Other error codes as defined for the generic_send_msg() function.
94 *
95 */
96int netif_send_msg_local(int netif_phone, device_id_t device_id,
97 packet_t packet, services_t sender)
98{
99 fibril_rwlock_write_lock(&netif_globals.lock);
100 int result = netif_send_message(device_id, packet, sender);
101 fibril_rwlock_write_unlock(&netif_globals.lock);
102
103 return result;
104}
105
106/** Start the device.
107 *
108 * @param[in] netif_phone The network interface phone.
109 * @param[in] device_id The device identifier.
110 *
111 * @return EOK on success.
112 * @return Other error codes as defined for the find_device() function.
113 * @return Other error codes as defined for the netif_start_message() function.
114 *
115 */
116int netif_start_req_local(int netif_phone, device_id_t device_id)
117{
118 ERROR_DECLARE;
119
120 fibril_rwlock_write_lock(&netif_globals.lock);
121
122 netif_device_t *device;
123 if (ERROR_OCCURRED(find_device(device_id, &device))) {
124 fibril_rwlock_write_unlock(&netif_globals.lock);
125 return ERROR_CODE;
126 }
127
128 int result = netif_start_message(device);
129 if (result > NETIF_NULL) {
130 int phone = device->nil_phone;
131 fibril_rwlock_write_unlock(&netif_globals.lock);
132 nil_device_state_msg(phone, device_id, result);
133 return EOK;
134 }
135
136 fibril_rwlock_write_unlock(&netif_globals.lock);
137
138 return result;
139}
140
141/** Stop the device.
142 *
143 * @param[in] netif_phone The network interface phone.
144 * @param[in] device_id The device identifier.
145 *
146 * @return EOK on success.
147 * @return Other error codes as defined for the find_device() function.
148 * @return Other error codes as defined for the netif_stop_message() function.
149 *
150 */
151int netif_stop_req_local(int netif_phone, device_id_t device_id)
152{
153 ERROR_DECLARE;
154
155 fibril_rwlock_write_lock(&netif_globals.lock);
156
157 netif_device_t *device;
158 if (ERROR_OCCURRED(find_device(device_id, &device))) {
159 fibril_rwlock_write_unlock(&netif_globals.lock);
160 return ERROR_CODE;
161 }
162
163 int result = netif_stop_message(device);
164 if (result > NETIF_NULL) {
165 int phone = device->nil_phone;
166 fibril_rwlock_write_unlock(&netif_globals.lock);
167 nil_device_state_msg(phone, device_id, result);
168 return EOK;
169 }
170
171 fibril_rwlock_write_unlock(&netif_globals.lock);
172
173 return result;
174}
175
176/** Return the device usage statistics.
177 *
178 * @param[in] netif_phone The network interface phone.
179 * @param[in] device_id The device identifier.
180 * @param[out] stats The device usage statistics.
181 *
182 * @return EOK on success.
183 *
184 */
185int netif_stats_req_local(int netif_phone, device_id_t device_id,
186 device_stats_ref stats)
187{
188 fibril_rwlock_read_lock(&netif_globals.lock);
189 int res = netif_get_device_stats(device_id, stats);
190 fibril_rwlock_read_unlock(&netif_globals.lock);
191
192 return res;
193}
194
195/** Return the device local hardware address.
196 *
197 * @param[in] netif_phone The network interface phone.
198 * @param[in] device_id The device identifier.
199 * @param[out] address The device local hardware address.
200 * @param[out] data The address data.
201 *
202 * @return EOK on success.
203 * @return EBADMEM if the address parameter is NULL.
204 * @return ENOENT if there no such device.
205 * @return Other error codes as defined for the netif_get_addr_message()
206 * function.
207 *
208 */
209int netif_get_addr_req_local(int netif_phone, device_id_t device_id,
210 measured_string_ref *address, char **data)
211{
212 ERROR_DECLARE;
213
214 if ((!address) || (!data))
215 return EBADMEM;
216
217 fibril_rwlock_read_lock(&netif_globals.lock);
218
219 measured_string_t translation;
220 if (!ERROR_OCCURRED(netif_get_addr_message(device_id, &translation))) {
221 *address = measured_string_copy(&translation);
222 ERROR_CODE = (*address) ? EOK : ENOMEM;
223 }
224
225 fibril_rwlock_read_unlock(&netif_globals.lock);
226
227 *data = (**address).value;
228
229 return ERROR_CODE;
230}
231
232/** Create bidirectional connection with the network interface module and registers the message receiver.
233 *
234 * @param[in] service The network interface module service.
235 * @param[in] device_id The device identifier.
236 * @param[in] me The requesting module service.
237 * @param[in] receiver The message receiver.
238 *
239 * @return The phone of the needed service.
240 * @return EOK on success.
241 * @return Other error codes as defined for the bind_service() function.
242 *
243 */
244int netif_bind_service_local(services_t service, device_id_t device_id,
245 services_t me, async_client_conn_t receiver)
246{
247 return EOK;
248}
249
250/** Find the device specific data.
251 *
252 * @param[in] device_id The device identifier.
253 * @param[out] device The device specific data.
254 *
255 * @return EOK on success.
256 * @return ENOENT if device is not found.
257 * @return EPERM if the device is not initialized.
258 *
259 */
260int find_device(device_id_t device_id, netif_device_t **device)
261{
262 if (!device)
263 return EBADMEM;
264
265 *device = netif_device_map_find(&netif_globals.device_map, device_id);
266 if (*device == NULL)
267 return ENOENT;
268
269 if ((*device)->state == NETIF_NULL)
270 return EPERM;
271
272 return EOK;
273}
274
275/** Clear the usage statistics.
276 *
277 * @param[in] stats The usage statistics.
278 *
279 */
280void null_device_stats(device_stats_ref stats)
281{
282 bzero(stats, sizeof(device_stats_t));
283}
284
285/** Initialize the netif module.
286 *
287 * @param[in] client_connection The client connection functio to be
288 * registered.
289 *
290 * @return EOK on success.
291 * @return Other error codes as defined for each specific module
292 * message function.
293 *
294 */
295int netif_init_module(async_client_conn_t client_connection)
296{
297 ERROR_DECLARE;
298
299 async_set_client_connection(client_connection);
300
301 netif_globals.net_phone = connect_to_service(SERVICE_NETWORKING);
302 netif_device_map_initialize(&netif_globals.device_map);
303
304 ERROR_PROPAGATE(pm_init());
305
306 fibril_rwlock_initialize(&netif_globals.lock);
307 if (ERROR_OCCURRED(netif_initialize())) {
308 pm_destroy();
309 return ERROR_CODE;
310 }
311
312 return EOK;
313}
314
315/** Release the given packet.
316 *
317 * Prepared for future optimization.
318 *
319 * @param[in] packet_id The packet identifier.
320 *
321 */
322void netif_pq_release(packet_id_t packet_id)
323{
324 pq_release_remote(netif_globals.net_phone, packet_id);
325}
326
327/** Allocate new packet to handle the given content size.
328 *
329 * @param[in] content The minimum content size.
330 *
331 * @return The allocated packet.
332 * @return NULL if there is an error.
333 *
334 */
335packet_t netif_packet_get_1(size_t content)
336{
337 return packet_get_1_remote(netif_globals.net_phone, content);
338}
339
340/** Register the device notification receiver, the network interface layer module.
341 *
342 * @param[in] name Module name.
343 * @param[in] device_id The device identifier.
344 * @param[in] phone The network interface layer module phone.
345 *
346 * @return EOK on success.
347 * @return ENOENT if there is no such device.
348 * @return ELIMIT if there is another module registered.
349 *
350 */
351static int register_message(const char *name, device_id_t device_id, int phone)
352{
353 ERROR_DECLARE;
354
355 netif_device_t *device;
356 ERROR_PROPAGATE(find_device(device_id, &device));
357 if(device->nil_phone > 0)
358 return ELIMIT;
359
360 device->nil_phone = phone;
361 printf("%s: Receiver of device %d registered (phone: %d)\n",
362 name, device->device_id, device->nil_phone);
363 return EOK;
364}
365
366/** Process the netif module messages.
367 *
368 * @param[in] name Module name.
369 * @param[in] callid The message identifier.
370 * @param[in] call The message parameters.
371 * @param[out] answer The message answer parameters.
372 * @param[out] answer_count The last parameter for the actual answer
373 * in the answer parameter.
374 *
375 * @return EOK on success.
376 * @return ENOTSUP if the message is not known.
377 * @return Other error codes as defined for each specific module message function.
378 *
379 * @see IS_NET_NETIF_MESSAGE()
380 *
381 */
382int netif_module_message_standalone(const char *name, ipc_callid_t callid,
383 ipc_call_t *call, ipc_call_t *answer, int *answer_count)
384{
385 ERROR_DECLARE;
386
387 size_t length;
388 device_stats_t stats;
389 packet_t packet;
390 measured_string_t address;
391
392 *answer_count = 0;
393 switch (IPC_GET_METHOD(*call)) {
394 case IPC_M_PHONE_HUNGUP:
395 return EOK;
396 case NET_NETIF_PROBE:
397 return netif_probe_req_local(0, IPC_GET_DEVICE(call),
398 NETIF_GET_IRQ(call), NETIF_GET_IO(call));
399 case IPC_M_CONNECT_TO_ME:
400 fibril_rwlock_write_lock(&netif_globals.lock);
401 ERROR_CODE = register_message(name, IPC_GET_DEVICE(call),
402 IPC_GET_PHONE(call));
403 fibril_rwlock_write_unlock(&netif_globals.lock);
404 return ERROR_CODE;
405 case NET_NETIF_SEND:
406 ERROR_PROPAGATE(packet_translate_remote(netif_globals.net_phone,
407 &packet, IPC_GET_PACKET(call)));
408 return netif_send_msg_local(0, IPC_GET_DEVICE(call), packet,
409 IPC_GET_SENDER(call));
410 case NET_NETIF_START:
411 return netif_start_req_local(0, IPC_GET_DEVICE(call));
412 case NET_NETIF_STATS:
413 fibril_rwlock_read_lock(&netif_globals.lock);
414 if (!ERROR_OCCURRED(async_data_read_receive(&callid, &length))) {
415 if (length < sizeof(device_stats_t))
416 ERROR_CODE = EOVERFLOW;
417 else {
418 if (!ERROR_OCCURRED(netif_get_device_stats(
419 IPC_GET_DEVICE(call), &stats)))
420 ERROR_CODE = async_data_read_finalize(callid, &stats,
421 sizeof(device_stats_t));
422 }
423 }
424 fibril_rwlock_read_unlock(&netif_globals.lock);
425 return ERROR_CODE;
426 case NET_NETIF_STOP:
427 return netif_stop_req_local(0, IPC_GET_DEVICE(call));
428 case NET_NETIF_GET_ADDR:
429 fibril_rwlock_read_lock(&netif_globals.lock);
430 if (!ERROR_OCCURRED(netif_get_addr_message(IPC_GET_DEVICE(call),
431 &address)))
432 ERROR_CODE = measured_strings_reply(&address, 1);
433 fibril_rwlock_read_unlock(&netif_globals.lock);
434 return ERROR_CODE;
435 }
436
437 return netif_specific_message(callid, call, answer, answer_count);
438}
439
440/** Start the network interface module.
441 *
442 * Initialize the client connection serving function, initialize
443 * the module, registers the module service and start the async
444 * manager, processing IPC messages in an infinite loop.
445 *
446 * @param[in] client_connection The client connection processing
447 * function. The module skeleton propagates
448 * its own one.
449 *
450 * @return EOK on success.
451 * @return Other error codes as defined for each specific module message
452 * function.
453 *
454 */
455int netif_module_start_standalone(async_client_conn_t client_connection)
456{
457 ERROR_DECLARE;
458
459 ERROR_PROPAGATE(netif_init_module(client_connection));
460
461 async_manager();
462
463 pm_destroy();
464 return EOK;
465}
466
467/** @}
468 */
Note: See TracBrowser for help on using the repository browser.