source: mainline/uspace/lib/c/generic/devmap.c@ 47a7174f

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 47a7174f was 47a7174f, checked in by Vojtech Horky <vojtechhorky@…>, 15 years ago

Devmap drivers can customize forwarded connections

It is possible to set an extra parameter for forwarded connections through
devmap. The change shall ensure backward compatibility and allows to connect
to devman-style drivers through their devmap path.

  • Property mode set to 100644
File size: 10.6 KB
RevLine 
[1090b8c]1/*
2 * Copyright (c) 2007 Josef Cejka
3 * Copyright (c) 2009 Jiri Svoboda
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
[19f857a]30#include <str.h>
[1090b8c]31#include <ipc/ipc.h>
32#include <ipc/services.h>
33#include <ipc/devmap.h>
34#include <devmap.h>
35#include <async.h>
36#include <errno.h>
[1313ee9]37#include <malloc.h>
38#include <bool.h>
[1090b8c]39
[cb41a5e]40static int devmap_phone_driver = -1;
41static int devmap_phone_client = -1;
[1090b8c]42
43/** Get phone to device mapper task. */
[cb41a5e]44int devmap_get_phone(devmap_interface_t iface, unsigned int flags)
[1090b8c]45{
[cb41a5e]46 switch (iface) {
47 case DEVMAP_DRIVER:
48 if (devmap_phone_driver >= 0)
49 return devmap_phone_driver;
50
51 if (flags & IPC_FLAG_BLOCKING)
52 devmap_phone_driver = ipc_connect_me_to_blocking(PHONE_NS,
53 SERVICE_DEVMAP, DEVMAP_DRIVER, 0);
54 else
55 devmap_phone_driver = ipc_connect_me_to(PHONE_NS,
56 SERVICE_DEVMAP, DEVMAP_DRIVER, 0);
57
58 return devmap_phone_driver;
59 case DEVMAP_CLIENT:
60 if (devmap_phone_client >= 0)
61 return devmap_phone_client;
62
63 if (flags & IPC_FLAG_BLOCKING)
64 devmap_phone_client = ipc_connect_me_to_blocking(PHONE_NS,
65 SERVICE_DEVMAP, DEVMAP_CLIENT, 0);
66 else
67 devmap_phone_client = ipc_connect_me_to(PHONE_NS,
68 SERVICE_DEVMAP, DEVMAP_CLIENT, 0);
69
70 return devmap_phone_client;
71 default:
72 return -1;
[1090b8c]73 }
[cb41a5e]74}
[1090b8c]75
[cb41a5e]76void devmap_hangup_phone(devmap_interface_t iface)
77{
78 switch (iface) {
79 case DEVMAP_DRIVER:
80 if (devmap_phone_driver >= 0) {
81 ipc_hangup(devmap_phone_driver);
82 devmap_phone_driver = -1;
83 }
84 break;
85 case DEVMAP_CLIENT:
86 if (devmap_phone_client >= 0) {
87 ipc_hangup(devmap_phone_client);
88 devmap_phone_client = -1;
89 }
90 break;
91 default:
92 break;
93 }
[1090b8c]94}
95
96/** Register new driver with devmap. */
97int devmap_driver_register(const char *name, async_client_conn_t conn)
98{
[cb41a5e]99 int phone = devmap_get_phone(DEVMAP_DRIVER, IPC_FLAG_BLOCKING);
100
101 if (phone < 0)
[1090b8c]102 return phone;
103
[e77994dd]104 async_serialize_start();
105
[cb41a5e]106 ipc_call_t answer;
107 aid_t req = async_send_2(phone, DEVMAP_DRIVER_REGISTER, 0, 0, &answer);
108
[96b02eb9]109 sysarg_t retval = async_data_write_start(phone, name, str_size(name));
[1090b8c]110 if (retval != EOK) {
111 async_wait_for(req, NULL);
[e77994dd]112 async_serialize_end();
[1090b8c]113 return -1;
114 }
[cb41a5e]115
[1090b8c]116 async_set_client_connection(conn);
[cb41a5e]117
[96b02eb9]118 sysarg_t callback_phonehash;
[1090b8c]119 ipc_connect_to_me(phone, 0, 0, 0, &callback_phonehash);
120 async_wait_for(req, &retval);
[cb41a5e]121
[e77994dd]122 async_serialize_end();
123
[cb41a5e]124 return retval;
[1090b8c]125}
126
[cb41a5e]127/** Register new device.
128 *
[47a7174f]129 * The @p interface is used when forwarding connection to the driver.
130 * If not 0, the first argument is the interface and the second argument
131 * is the devmap handle of the device.
132 * When the interface is zero (default), the first argument is directly
133 * the handle (to ensure backward compatibility).
134 *
135 * @param fqdn Fully qualified device name.
136 * @param[out] handle Handle to the created instance of device.
137 * @param interface Interface when forwarding.
[cb41a5e]138 *
139 */
[47a7174f]140int devmap_device_register_with_iface(const char *fqdn,
141 devmap_handle_t *handle, sysarg_t interface)
[1090b8c]142{
[cb41a5e]143 int phone = devmap_get_phone(DEVMAP_DRIVER, IPC_FLAG_BLOCKING);
144
145 if (phone < 0)
146 return phone;
147
[e77994dd]148 async_serialize_start();
149
[1090b8c]150 ipc_call_t answer;
[47a7174f]151 aid_t req = async_send_2(phone, DEVMAP_DEVICE_REGISTER, interface, 0,
[cb41a5e]152 &answer);
153
[96b02eb9]154 sysarg_t retval = async_data_write_start(phone, fqdn, str_size(fqdn));
[cb41a5e]155 if (retval != EOK) {
156 async_wait_for(req, NULL);
[e77994dd]157 async_serialize_end();
[cb41a5e]158 return retval;
159 }
160
161 async_wait_for(req, &retval);
162
[e77994dd]163 async_serialize_end();
164
[cb41a5e]165 if (retval != EOK) {
166 if (handle != NULL)
167 *handle = -1;
168 return retval;
169 }
170
171 if (handle != NULL)
[991f645]172 *handle = (devmap_handle_t) IPC_GET_ARG1(answer);
[cb41a5e]173
174 return retval;
175}
[1090b8c]176
[47a7174f]177/** Register new device.
178 *
179 * @param fqdn Fully qualified device name.
180 * @param handle Output: Handle to the created instance of device.
181 *
182 */
183int devmap_device_register(const char *fqdn, devmap_handle_t *handle)
184{
185 return devmap_device_register_with_iface(fqdn, handle, 0);
186}
187
188
[991f645]189int devmap_device_get_handle(const char *fqdn, devmap_handle_t *handle, unsigned int flags)
[cb41a5e]190{
191 int phone = devmap_get_phone(DEVMAP_CLIENT, flags);
192
[1090b8c]193 if (phone < 0)
194 return phone;
[cb41a5e]195
[e77994dd]196 async_serialize_start();
197
[cb41a5e]198 ipc_call_t answer;
199 aid_t req = async_send_2(phone, DEVMAP_DEVICE_GET_HANDLE, flags, 0,
[1090b8c]200 &answer);
[cb41a5e]201
[96b02eb9]202 sysarg_t retval = async_data_write_start(phone, fqdn, str_size(fqdn));
[1313ee9]203 if (retval != EOK) {
204 async_wait_for(req, NULL);
205 async_serialize_end();
206 return retval;
207 }
208
209 async_wait_for(req, &retval);
210
211 async_serialize_end();
212
213 if (retval != EOK) {
214 if (handle != NULL)
[991f645]215 *handle = (devmap_handle_t) -1;
[1313ee9]216 return retval;
217 }
218
219 if (handle != NULL)
[991f645]220 *handle = (devmap_handle_t) IPC_GET_ARG1(answer);
[1313ee9]221
222 return retval;
223}
224
[991f645]225int devmap_namespace_get_handle(const char *name, devmap_handle_t *handle, unsigned int flags)
[1313ee9]226{
227 int phone = devmap_get_phone(DEVMAP_CLIENT, flags);
228
229 if (phone < 0)
230 return phone;
[cb41a5e]231
[1313ee9]232 async_serialize_start();
233
234 ipc_call_t answer;
235 aid_t req = async_send_2(phone, DEVMAP_NAMESPACE_GET_HANDLE, flags, 0,
236 &answer);
237
[96b02eb9]238 sysarg_t retval = async_data_write_start(phone, name, str_size(name));
[1090b8c]239 if (retval != EOK) {
240 async_wait_for(req, NULL);
[e77994dd]241 async_serialize_end();
[1090b8c]242 return retval;
243 }
[cb41a5e]244
[1090b8c]245 async_wait_for(req, &retval);
[cb41a5e]246
[e77994dd]247 async_serialize_end();
248
[1090b8c]249 if (retval != EOK) {
250 if (handle != NULL)
[991f645]251 *handle = (devmap_handle_t) -1;
[1090b8c]252 return retval;
253 }
[cb41a5e]254
[1090b8c]255 if (handle != NULL)
[991f645]256 *handle = (devmap_handle_t) IPC_GET_ARG1(answer);
[cb41a5e]257
[1090b8c]258 return retval;
259}
260
[991f645]261devmap_handle_type_t devmap_handle_probe(devmap_handle_t handle)
[1313ee9]262{
263 int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
264
265 if (phone < 0)
266 return phone;
267
[96b02eb9]268 sysarg_t type;
[1313ee9]269 int retval = async_req_1_1(phone, DEVMAP_HANDLE_PROBE, handle, &type);
270 if (retval != EOK)
271 return DEV_HANDLE_NONE;
272
273 return (devmap_handle_type_t) type;
274}
275
[991f645]276int devmap_device_connect(devmap_handle_t handle, unsigned int flags)
[1090b8c]277{
278 int phone;
[cb41a5e]279
[1090b8c]280 if (flags & IPC_FLAG_BLOCKING) {
281 phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAP,
282 DEVMAP_CONNECT_TO_DEVICE, handle);
283 } else {
284 phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP,
285 DEVMAP_CONNECT_TO_DEVICE, handle);
286 }
[cb41a5e]287
[1090b8c]288 return phone;
289}
290
[7fcb74c]291int devmap_null_create(void)
292{
293 int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
294
295 if (phone < 0)
296 return -1;
297
[96b02eb9]298 sysarg_t null_id;
[1313ee9]299 int retval = async_req_0_1(phone, DEVMAP_NULL_CREATE, &null_id);
[7fcb74c]300 if (retval != EOK)
301 return -1;
302
303 return (int) null_id;
304}
305
306void devmap_null_destroy(int null_id)
307{
308 int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
309
310 if (phone < 0)
311 return;
312
[96b02eb9]313 async_req_1_0(phone, DEVMAP_NULL_DESTROY, (sysarg_t) null_id);
[7fcb74c]314}
315
[1313ee9]316static size_t devmap_count_namespaces_internal(int phone)
[1090b8c]317{
[96b02eb9]318 sysarg_t count;
[1313ee9]319 int retval = async_req_0_1(phone, DEVMAP_GET_NAMESPACE_COUNT, &count);
320 if (retval != EOK)
[cb41a5e]321 return 0;
322
[1313ee9]323 return count;
324}
325
[991f645]326static size_t devmap_count_devices_internal(int phone, devmap_handle_t ns_handle)
[1313ee9]327{
[96b02eb9]328 sysarg_t count;
[1313ee9]329 int retval = async_req_1_1(phone, DEVMAP_GET_DEVICE_COUNT, ns_handle, &count);
[cb41a5e]330 if (retval != EOK)
331 return 0;
332
333 return count;
334}
[1090b8c]335
[1313ee9]336size_t devmap_count_namespaces(void)
[cb41a5e]337{
338 int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
339
340 if (phone < 0)
341 return 0;
342
[1313ee9]343 return devmap_count_namespaces_internal(phone);
344}
345
[991f645]346size_t devmap_count_devices(devmap_handle_t ns_handle)
[1313ee9]347{
348 int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
[e77994dd]349
[1313ee9]350 if (phone < 0)
351 return 0;
[cb41a5e]352
[1313ee9]353 return devmap_count_devices_internal(phone, ns_handle);
354}
355
356size_t devmap_get_namespaces(dev_desc_t **data)
357{
358 int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
[cb41a5e]359
[1313ee9]360 if (phone < 0)
[cb41a5e]361 return 0;
362
[1313ee9]363 /* Loop until namespaces read succesful */
364 while (true) {
365 size_t count = devmap_count_namespaces_internal(phone);
366 if (count == 0)
367 return 0;
368
369 dev_desc_t *devs = (dev_desc_t *) calloc(count, sizeof(dev_desc_t));
370 if (devs == NULL)
371 return 0;
372
373 async_serialize_start();
374
375 ipc_call_t answer;
376 aid_t req = async_send_0(phone, DEVMAP_GET_NAMESPACES, &answer);
377
378 int rc = async_data_read_start(phone, devs, count * sizeof(dev_desc_t));
379 if (rc == EOVERFLOW) {
380 /*
381 * Number of namespaces has changed since
382 * the last call of DEVMAP_DEVICE_GET_NAMESPACE_COUNT
383 */
384 async_serialize_end();
385 free(devs);
386 continue;
387 }
388
389 if (rc != EOK) {
390 async_wait_for(req, NULL);
391 async_serialize_end();
392 free(devs);
393 return 0;
394 }
395
[96b02eb9]396 sysarg_t retval;
[1313ee9]397 async_wait_for(req, &retval);
398 async_serialize_end();
399
400 if (retval != EOK)
401 return 0;
402
403 *data = devs;
404 return count;
405 }
406}
407
[991f645]408size_t devmap_get_devices(devmap_handle_t ns_handle, dev_desc_t **data)
[1313ee9]409{
410 int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
[e77994dd]411
[1313ee9]412 if (phone < 0)
[cb41a5e]413 return 0;
414
[1313ee9]415 /* Loop until namespaces read succesful */
416 while (true) {
417 size_t count = devmap_count_devices_internal(phone, ns_handle);
418 if (count == 0)
419 return 0;
420
421 dev_desc_t *devs = (dev_desc_t *) calloc(count, sizeof(dev_desc_t));
422 if (devs == NULL)
423 return 0;
424
425 async_serialize_start();
426
427 ipc_call_t answer;
428 aid_t req = async_send_1(phone, DEVMAP_GET_DEVICES, ns_handle, &answer);
429
430 int rc = async_data_read_start(phone, devs, count * sizeof(dev_desc_t));
431 if (rc == EOVERFLOW) {
432 /*
433 * Number of devices has changed since
434 * the last call of DEVMAP_DEVICE_GET_DEVICE_COUNT
435 */
436 async_serialize_end();
437 free(devs);
438 continue;
439 }
440
441 if (rc != EOK) {
442 async_wait_for(req, NULL);
443 async_serialize_end();
444 free(devs);
445 return 0;
446 }
447
[96b02eb9]448 sysarg_t retval;
[1313ee9]449 async_wait_for(req, &retval);
450 async_serialize_end();
451
452 if (retval != EOK)
453 return 0;
454
455 *data = devs;
456 return count;
457 }
[1090b8c]458}
Note: See TracBrowser for help on using the repository browser.