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

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

introduce device namespaces

  • add support for explicit open in libfs (needed by devfs, but also possibly for other filesystems which need to track some stateful information)
  • extend libfs to be more generic, make proper adjustments to libc, tmpfs and fat
  • various updates to make use of the device namespaces
  • code cleanup
  • Property mode set to 100644
File size: 10.0 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
30#include <string.h>
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
[1313ee9]109 ipcarg_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
118 ipcarg_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 *
[1313ee9]129 * @param namespace Namespace name.
130 * @param fqdn Fully qualified device name.
131 * @param handle Output: Handle to the created instance of device.
[cb41a5e]132 *
133 */
[1313ee9]134int devmap_device_register(const char *fqdn, dev_handle_t *handle)
[1090b8c]135{
[cb41a5e]136 int phone = devmap_get_phone(DEVMAP_DRIVER, IPC_FLAG_BLOCKING);
137
138 if (phone < 0)
139 return phone;
140
[e77994dd]141 async_serialize_start();
142
[1090b8c]143 ipc_call_t answer;
[cb41a5e]144 aid_t req = async_send_2(phone, DEVMAP_DEVICE_REGISTER, 0, 0,
145 &answer);
146
[1313ee9]147 ipcarg_t retval = async_data_write_start(phone, fqdn, str_size(fqdn));
[cb41a5e]148 if (retval != EOK) {
149 async_wait_for(req, NULL);
[e77994dd]150 async_serialize_end();
[cb41a5e]151 return retval;
152 }
153
154 async_wait_for(req, &retval);
155
[e77994dd]156 async_serialize_end();
157
[cb41a5e]158 if (retval != EOK) {
159 if (handle != NULL)
160 *handle = -1;
161 return retval;
162 }
163
164 if (handle != NULL)
165 *handle = (dev_handle_t) IPC_GET_ARG1(answer);
166
167 return retval;
168}
[1090b8c]169
[1313ee9]170int devmap_device_get_handle(const char *fqdn, dev_handle_t *handle, unsigned int flags)
[cb41a5e]171{
172 int phone = devmap_get_phone(DEVMAP_CLIENT, flags);
173
[1090b8c]174 if (phone < 0)
175 return phone;
[cb41a5e]176
[e77994dd]177 async_serialize_start();
178
[cb41a5e]179 ipc_call_t answer;
180 aid_t req = async_send_2(phone, DEVMAP_DEVICE_GET_HANDLE, flags, 0,
[1090b8c]181 &answer);
[cb41a5e]182
[1313ee9]183 ipcarg_t retval = async_data_write_start(phone, fqdn, str_size(fqdn));
184 if (retval != EOK) {
185 async_wait_for(req, NULL);
186 async_serialize_end();
187 return retval;
188 }
189
190 async_wait_for(req, &retval);
191
192 async_serialize_end();
193
194 if (retval != EOK) {
195 if (handle != NULL)
196 *handle = (dev_handle_t) -1;
197 return retval;
198 }
199
200 if (handle != NULL)
201 *handle = (dev_handle_t) IPC_GET_ARG1(answer);
202
203 return retval;
204}
205
206int devmap_namespace_get_handle(const char *name, dev_handle_t *handle, unsigned int flags)
207{
208 int phone = devmap_get_phone(DEVMAP_CLIENT, flags);
209
210 if (phone < 0)
211 return phone;
[cb41a5e]212
[1313ee9]213 async_serialize_start();
214
215 ipc_call_t answer;
216 aid_t req = async_send_2(phone, DEVMAP_NAMESPACE_GET_HANDLE, flags, 0,
217 &answer);
218
219 ipcarg_t retval = async_data_write_start(phone, name, str_size(name));
[1090b8c]220 if (retval != EOK) {
221 async_wait_for(req, NULL);
[e77994dd]222 async_serialize_end();
[1090b8c]223 return retval;
224 }
[cb41a5e]225
[1090b8c]226 async_wait_for(req, &retval);
[cb41a5e]227
[e77994dd]228 async_serialize_end();
229
[1090b8c]230 if (retval != EOK) {
231 if (handle != NULL)
[62140db]232 *handle = (dev_handle_t) -1;
[1090b8c]233 return retval;
234 }
[cb41a5e]235
[1090b8c]236 if (handle != NULL)
[cb41a5e]237 *handle = (dev_handle_t) IPC_GET_ARG1(answer);
238
[1090b8c]239 return retval;
240}
241
[1313ee9]242devmap_handle_type_t devmap_handle_probe(dev_handle_t handle)
243{
244 int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
245
246 if (phone < 0)
247 return phone;
248
249 ipcarg_t type;
250 int retval = async_req_1_1(phone, DEVMAP_HANDLE_PROBE, handle, &type);
251 if (retval != EOK)
252 return DEV_HANDLE_NONE;
253
254 return (devmap_handle_type_t) type;
255}
256
[1090b8c]257int devmap_device_connect(dev_handle_t handle, unsigned int flags)
258{
259 int phone;
[cb41a5e]260
[1090b8c]261 if (flags & IPC_FLAG_BLOCKING) {
262 phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAP,
263 DEVMAP_CONNECT_TO_DEVICE, handle);
264 } else {
265 phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP,
266 DEVMAP_CONNECT_TO_DEVICE, handle);
267 }
[cb41a5e]268
[1090b8c]269 return phone;
270}
271
[7fcb74c]272int devmap_null_create(void)
273{
274 int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
275
276 if (phone < 0)
277 return -1;
278
279 ipcarg_t null_id;
[1313ee9]280 int retval = async_req_0_1(phone, DEVMAP_NULL_CREATE, &null_id);
[7fcb74c]281 if (retval != EOK)
282 return -1;
283
284 return (int) null_id;
285}
286
287void devmap_null_destroy(int null_id)
288{
289 int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
290
291 if (phone < 0)
292 return;
293
[1313ee9]294 async_req_1_0(phone, DEVMAP_NULL_DESTROY, (ipcarg_t) null_id);
[7fcb74c]295}
296
[1313ee9]297static size_t devmap_count_namespaces_internal(int phone)
[1090b8c]298{
[1313ee9]299 ipcarg_t count;
300 int retval = async_req_0_1(phone, DEVMAP_GET_NAMESPACE_COUNT, &count);
301 if (retval != EOK)
[cb41a5e]302 return 0;
303
[1313ee9]304 return count;
305}
306
307static size_t devmap_count_devices_internal(int phone, dev_handle_t ns_handle)
308{
[cb41a5e]309 ipcarg_t count;
[1313ee9]310 int retval = async_req_1_1(phone, DEVMAP_GET_DEVICE_COUNT, ns_handle, &count);
[cb41a5e]311 if (retval != EOK)
312 return 0;
313
314 return count;
315}
[1090b8c]316
[1313ee9]317size_t devmap_count_namespaces(void)
[cb41a5e]318{
319 int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
320
321 if (phone < 0)
322 return 0;
323
[1313ee9]324 return devmap_count_namespaces_internal(phone);
325}
326
327size_t devmap_count_devices(dev_handle_t ns_handle)
328{
329 int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
[e77994dd]330
[1313ee9]331 if (phone < 0)
332 return 0;
[cb41a5e]333
[1313ee9]334 return devmap_count_devices_internal(phone, ns_handle);
335}
336
337size_t devmap_get_namespaces(dev_desc_t **data)
338{
339 int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
[cb41a5e]340
[1313ee9]341 if (phone < 0)
[cb41a5e]342 return 0;
343
[1313ee9]344 /* Loop until namespaces read succesful */
345 while (true) {
346 size_t count = devmap_count_namespaces_internal(phone);
347 if (count == 0)
348 return 0;
349
350 dev_desc_t *devs = (dev_desc_t *) calloc(count, sizeof(dev_desc_t));
351 if (devs == NULL)
352 return 0;
353
354 async_serialize_start();
355
356 ipc_call_t answer;
357 aid_t req = async_send_0(phone, DEVMAP_GET_NAMESPACES, &answer);
358
359 int rc = async_data_read_start(phone, devs, count * sizeof(dev_desc_t));
360 if (rc == EOVERFLOW) {
361 /*
362 * Number of namespaces has changed since
363 * the last call of DEVMAP_DEVICE_GET_NAMESPACE_COUNT
364 */
365 async_serialize_end();
366 free(devs);
367 continue;
368 }
369
370 if (rc != EOK) {
371 async_wait_for(req, NULL);
372 async_serialize_end();
373 free(devs);
374 return 0;
375 }
376
377 ipcarg_t retval;
378 async_wait_for(req, &retval);
379 async_serialize_end();
380
381 if (retval != EOK)
382 return 0;
383
384 *data = devs;
385 return count;
386 }
387}
388
389size_t devmap_get_devices(dev_handle_t ns_handle, dev_desc_t **data)
390{
391 int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
[e77994dd]392
[1313ee9]393 if (phone < 0)
[cb41a5e]394 return 0;
395
[1313ee9]396 /* Loop until namespaces read succesful */
397 while (true) {
398 size_t count = devmap_count_devices_internal(phone, ns_handle);
399 if (count == 0)
400 return 0;
401
402 dev_desc_t *devs = (dev_desc_t *) calloc(count, sizeof(dev_desc_t));
403 if (devs == NULL)
404 return 0;
405
406 async_serialize_start();
407
408 ipc_call_t answer;
409 aid_t req = async_send_1(phone, DEVMAP_GET_DEVICES, ns_handle, &answer);
410
411 int rc = async_data_read_start(phone, devs, count * sizeof(dev_desc_t));
412 if (rc == EOVERFLOW) {
413 /*
414 * Number of devices has changed since
415 * the last call of DEVMAP_DEVICE_GET_DEVICE_COUNT
416 */
417 async_serialize_end();
418 free(devs);
419 continue;
420 }
421
422 if (rc != EOK) {
423 async_wait_for(req, NULL);
424 async_serialize_end();
425 free(devs);
426 return 0;
427 }
428
429 ipcarg_t retval;
430 async_wait_for(req, &retval);
431 async_serialize_end();
432
433 if (retval != EOK)
434 return 0;
435
436 *data = devs;
437 return count;
438 }
[1090b8c]439}
Note: See TracBrowser for help on using the repository browser.