source: mainline/uspace/lib/c/generic/devmap.c@ 21cb3ac

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 21cb3ac was 64d2b10, checked in by Martin Decky <martin@…>, 14 years ago

libc: do not intermix low-level IPC methods with async framework methods

  • 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/services.h>
[007e6efa]32#include <ipc/ns.h>
[1090b8c]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)
[007e6efa]52 devmap_phone_driver = service_connect_blocking(SERVICE_DEVMAP,
53 DEVMAP_DRIVER, 0);
[cb41a5e]54 else
[007e6efa]55 devmap_phone_driver = service_connect(SERVICE_DEVMAP,
56 DEVMAP_DRIVER, 0);
[cb41a5e]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)
[007e6efa]64 devmap_phone_client = service_connect_blocking(SERVICE_DEVMAP,
65 DEVMAP_CLIENT, 0);
[cb41a5e]66 else
[007e6efa]67 devmap_phone_client = service_connect(SERVICE_DEVMAP,
68 DEVMAP_CLIENT, 0);
[cb41a5e]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) {
[64d2b10]81 async_hangup(devmap_phone_driver);
[cb41a5e]82 devmap_phone_driver = -1;
83 }
84 break;
85 case DEVMAP_CLIENT:
86 if (devmap_phone_client >= 0) {
[64d2b10]87 async_hangup(devmap_phone_client);
[cb41a5e]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
[64d2b10]118 async_connect_to_me(phone, 0, 0, 0, NULL);
[1090b8c]119 async_wait_for(req, &retval);
[cb41a5e]120
[e77994dd]121 async_serialize_end();
122
[cb41a5e]123 return retval;
[1090b8c]124}
125
[cb41a5e]126/** Register new device.
127 *
[47a7174f]128 * The @p interface is used when forwarding connection to the driver.
129 * If not 0, the first argument is the interface and the second argument
130 * is the devmap handle of the device.
131 * When the interface is zero (default), the first argument is directly
132 * the handle (to ensure backward compatibility).
133 *
134 * @param fqdn Fully qualified device name.
135 * @param[out] handle Handle to the created instance of device.
136 * @param interface Interface when forwarding.
[cb41a5e]137 *
138 */
[47a7174f]139int devmap_device_register_with_iface(const char *fqdn,
140 devmap_handle_t *handle, sysarg_t interface)
[1090b8c]141{
[cb41a5e]142 int phone = devmap_get_phone(DEVMAP_DRIVER, IPC_FLAG_BLOCKING);
143
144 if (phone < 0)
145 return phone;
146
[e77994dd]147 async_serialize_start();
148
[1090b8c]149 ipc_call_t answer;
[47a7174f]150 aid_t req = async_send_2(phone, DEVMAP_DEVICE_REGISTER, interface, 0,
[cb41a5e]151 &answer);
152
[96b02eb9]153 sysarg_t retval = async_data_write_start(phone, fqdn, str_size(fqdn));
[cb41a5e]154 if (retval != EOK) {
155 async_wait_for(req, NULL);
[e77994dd]156 async_serialize_end();
[cb41a5e]157 return retval;
158 }
159
160 async_wait_for(req, &retval);
161
[e77994dd]162 async_serialize_end();
163
[cb41a5e]164 if (retval != EOK) {
165 if (handle != NULL)
166 *handle = -1;
167 return retval;
168 }
169
170 if (handle != NULL)
[991f645]171 *handle = (devmap_handle_t) IPC_GET_ARG1(answer);
[cb41a5e]172
173 return retval;
174}
[1090b8c]175
[47a7174f]176/** Register new device.
177 *
178 * @param fqdn Fully qualified device name.
179 * @param handle Output: Handle to the created instance of device.
180 *
181 */
182int devmap_device_register(const char *fqdn, devmap_handle_t *handle)
183{
184 return devmap_device_register_with_iface(fqdn, handle, 0);
185}
186
187
[991f645]188int devmap_device_get_handle(const char *fqdn, devmap_handle_t *handle, unsigned int flags)
[cb41a5e]189{
190 int phone = devmap_get_phone(DEVMAP_CLIENT, flags);
191
[1090b8c]192 if (phone < 0)
193 return phone;
[cb41a5e]194
[e77994dd]195 async_serialize_start();
196
[cb41a5e]197 ipc_call_t answer;
198 aid_t req = async_send_2(phone, DEVMAP_DEVICE_GET_HANDLE, flags, 0,
[1090b8c]199 &answer);
[cb41a5e]200
[96b02eb9]201 sysarg_t retval = async_data_write_start(phone, fqdn, str_size(fqdn));
[1313ee9]202 if (retval != EOK) {
203 async_wait_for(req, NULL);
204 async_serialize_end();
205 return retval;
206 }
207
208 async_wait_for(req, &retval);
209
210 async_serialize_end();
211
212 if (retval != EOK) {
213 if (handle != NULL)
[991f645]214 *handle = (devmap_handle_t) -1;
[1313ee9]215 return retval;
216 }
217
218 if (handle != NULL)
[991f645]219 *handle = (devmap_handle_t) IPC_GET_ARG1(answer);
[1313ee9]220
221 return retval;
222}
223
[991f645]224int devmap_namespace_get_handle(const char *name, devmap_handle_t *handle, unsigned int flags)
[1313ee9]225{
226 int phone = devmap_get_phone(DEVMAP_CLIENT, flags);
227
228 if (phone < 0)
229 return phone;
[cb41a5e]230
[1313ee9]231 async_serialize_start();
232
233 ipc_call_t answer;
234 aid_t req = async_send_2(phone, DEVMAP_NAMESPACE_GET_HANDLE, flags, 0,
235 &answer);
236
[96b02eb9]237 sysarg_t retval = async_data_write_start(phone, name, str_size(name));
[1090b8c]238 if (retval != EOK) {
239 async_wait_for(req, NULL);
[e77994dd]240 async_serialize_end();
[1090b8c]241 return retval;
242 }
[cb41a5e]243
[1090b8c]244 async_wait_for(req, &retval);
[cb41a5e]245
[e77994dd]246 async_serialize_end();
247
[1090b8c]248 if (retval != EOK) {
249 if (handle != NULL)
[991f645]250 *handle = (devmap_handle_t) -1;
[1090b8c]251 return retval;
252 }
[cb41a5e]253
[1090b8c]254 if (handle != NULL)
[991f645]255 *handle = (devmap_handle_t) IPC_GET_ARG1(answer);
[cb41a5e]256
[1090b8c]257 return retval;
258}
259
[991f645]260devmap_handle_type_t devmap_handle_probe(devmap_handle_t handle)
[1313ee9]261{
262 int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
263
264 if (phone < 0)
265 return phone;
266
[96b02eb9]267 sysarg_t type;
[1313ee9]268 int retval = async_req_1_1(phone, DEVMAP_HANDLE_PROBE, handle, &type);
269 if (retval != EOK)
270 return DEV_HANDLE_NONE;
271
272 return (devmap_handle_type_t) type;
273}
274
[991f645]275int devmap_device_connect(devmap_handle_t handle, unsigned int flags)
[1090b8c]276{
277 int phone;
[cb41a5e]278
[1090b8c]279 if (flags & IPC_FLAG_BLOCKING) {
[9476f4f]280 phone = async_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAP,
[1090b8c]281 DEVMAP_CONNECT_TO_DEVICE, handle);
282 } else {
[9476f4f]283 phone = async_connect_me_to(PHONE_NS, SERVICE_DEVMAP,
[1090b8c]284 DEVMAP_CONNECT_TO_DEVICE, handle);
285 }
[cb41a5e]286
[1090b8c]287 return phone;
288}
289
[7fcb74c]290int devmap_null_create(void)
291{
292 int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
293
294 if (phone < 0)
295 return -1;
296
[96b02eb9]297 sysarg_t null_id;
[1313ee9]298 int retval = async_req_0_1(phone, DEVMAP_NULL_CREATE, &null_id);
[7fcb74c]299 if (retval != EOK)
300 return -1;
301
302 return (int) null_id;
303}
304
305void devmap_null_destroy(int null_id)
306{
307 int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
308
309 if (phone < 0)
310 return;
311
[96b02eb9]312 async_req_1_0(phone, DEVMAP_NULL_DESTROY, (sysarg_t) null_id);
[7fcb74c]313}
314
[1313ee9]315static size_t devmap_count_namespaces_internal(int phone)
[1090b8c]316{
[96b02eb9]317 sysarg_t count;
[1313ee9]318 int retval = async_req_0_1(phone, DEVMAP_GET_NAMESPACE_COUNT, &count);
319 if (retval != EOK)
[cb41a5e]320 return 0;
321
[1313ee9]322 return count;
323}
324
[991f645]325static size_t devmap_count_devices_internal(int phone, devmap_handle_t ns_handle)
[1313ee9]326{
[96b02eb9]327 sysarg_t count;
[1313ee9]328 int retval = async_req_1_1(phone, DEVMAP_GET_DEVICE_COUNT, ns_handle, &count);
[cb41a5e]329 if (retval != EOK)
330 return 0;
331
332 return count;
333}
[1090b8c]334
[1313ee9]335size_t devmap_count_namespaces(void)
[cb41a5e]336{
337 int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
338
339 if (phone < 0)
340 return 0;
341
[1313ee9]342 return devmap_count_namespaces_internal(phone);
343}
344
[991f645]345size_t devmap_count_devices(devmap_handle_t ns_handle)
[1313ee9]346{
347 int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
[e77994dd]348
[1313ee9]349 if (phone < 0)
350 return 0;
[cb41a5e]351
[1313ee9]352 return devmap_count_devices_internal(phone, ns_handle);
353}
354
355size_t devmap_get_namespaces(dev_desc_t **data)
356{
357 int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
[cb41a5e]358
[1313ee9]359 if (phone < 0)
[cb41a5e]360 return 0;
361
[1313ee9]362 /* Loop until namespaces read succesful */
363 while (true) {
364 size_t count = devmap_count_namespaces_internal(phone);
365 if (count == 0)
366 return 0;
367
368 dev_desc_t *devs = (dev_desc_t *) calloc(count, sizeof(dev_desc_t));
369 if (devs == NULL)
370 return 0;
371
372 async_serialize_start();
373
374 ipc_call_t answer;
375 aid_t req = async_send_0(phone, DEVMAP_GET_NAMESPACES, &answer);
376
377 int rc = async_data_read_start(phone, devs, count * sizeof(dev_desc_t));
378 if (rc == EOVERFLOW) {
379 /*
380 * Number of namespaces has changed since
381 * the last call of DEVMAP_DEVICE_GET_NAMESPACE_COUNT
382 */
383 async_serialize_end();
384 free(devs);
385 continue;
386 }
387
388 if (rc != EOK) {
389 async_wait_for(req, NULL);
390 async_serialize_end();
391 free(devs);
392 return 0;
393 }
394
[96b02eb9]395 sysarg_t retval;
[1313ee9]396 async_wait_for(req, &retval);
397 async_serialize_end();
398
399 if (retval != EOK)
400 return 0;
401
402 *data = devs;
403 return count;
404 }
405}
406
[991f645]407size_t devmap_get_devices(devmap_handle_t ns_handle, dev_desc_t **data)
[1313ee9]408{
409 int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
[e77994dd]410
[1313ee9]411 if (phone < 0)
[cb41a5e]412 return 0;
413
[1313ee9]414 /* Loop until namespaces read succesful */
415 while (true) {
416 size_t count = devmap_count_devices_internal(phone, ns_handle);
417 if (count == 0)
418 return 0;
419
420 dev_desc_t *devs = (dev_desc_t *) calloc(count, sizeof(dev_desc_t));
421 if (devs == NULL)
422 return 0;
423
424 async_serialize_start();
425
426 ipc_call_t answer;
427 aid_t req = async_send_1(phone, DEVMAP_GET_DEVICES, ns_handle, &answer);
428
429 int rc = async_data_read_start(phone, devs, count * sizeof(dev_desc_t));
430 if (rc == EOVERFLOW) {
431 /*
432 * Number of devices has changed since
433 * the last call of DEVMAP_DEVICE_GET_DEVICE_COUNT
434 */
435 async_serialize_end();
436 free(devs);
437 continue;
438 }
439
440 if (rc != EOK) {
441 async_wait_for(req, NULL);
442 async_serialize_end();
443 free(devs);
444 return 0;
445 }
446
[96b02eb9]447 sysarg_t retval;
[1313ee9]448 async_wait_for(req, &retval);
449 async_serialize_end();
450
451 if (retval != EOK)
452 return 0;
453
454 *data = devs;
455 return count;
456 }
[1090b8c]457}
Note: See TracBrowser for help on using the repository browser.