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
Line 
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 <str.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>
37#include <malloc.h>
38#include <bool.h>
39
40static int devmap_phone_driver = -1;
41static int devmap_phone_client = -1;
42
43/** Get phone to device mapper task. */
44int devmap_get_phone(devmap_interface_t iface, unsigned int flags)
45{
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;
73 }
74}
75
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 }
94}
95
96/** Register new driver with devmap. */
97int devmap_driver_register(const char *name, async_client_conn_t conn)
98{
99 int phone = devmap_get_phone(DEVMAP_DRIVER, IPC_FLAG_BLOCKING);
100
101 if (phone < 0)
102 return phone;
103
104 async_serialize_start();
105
106 ipc_call_t answer;
107 aid_t req = async_send_2(phone, DEVMAP_DRIVER_REGISTER, 0, 0, &answer);
108
109 sysarg_t retval = async_data_write_start(phone, name, str_size(name));
110 if (retval != EOK) {
111 async_wait_for(req, NULL);
112 async_serialize_end();
113 return -1;
114 }
115
116 async_set_client_connection(conn);
117
118 sysarg_t callback_phonehash;
119 ipc_connect_to_me(phone, 0, 0, 0, &callback_phonehash);
120 async_wait_for(req, &retval);
121
122 async_serialize_end();
123
124 return retval;
125}
126
127/** Register new device.
128 *
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.
138 *
139 */
140int devmap_device_register_with_iface(const char *fqdn,
141 devmap_handle_t *handle, sysarg_t interface)
142{
143 int phone = devmap_get_phone(DEVMAP_DRIVER, IPC_FLAG_BLOCKING);
144
145 if (phone < 0)
146 return phone;
147
148 async_serialize_start();
149
150 ipc_call_t answer;
151 aid_t req = async_send_2(phone, DEVMAP_DEVICE_REGISTER, interface, 0,
152 &answer);
153
154 sysarg_t retval = async_data_write_start(phone, fqdn, str_size(fqdn));
155 if (retval != EOK) {
156 async_wait_for(req, NULL);
157 async_serialize_end();
158 return retval;
159 }
160
161 async_wait_for(req, &retval);
162
163 async_serialize_end();
164
165 if (retval != EOK) {
166 if (handle != NULL)
167 *handle = -1;
168 return retval;
169 }
170
171 if (handle != NULL)
172 *handle = (devmap_handle_t) IPC_GET_ARG1(answer);
173
174 return retval;
175}
176
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
189int devmap_device_get_handle(const char *fqdn, devmap_handle_t *handle, unsigned int flags)
190{
191 int phone = devmap_get_phone(DEVMAP_CLIENT, flags);
192
193 if (phone < 0)
194 return phone;
195
196 async_serialize_start();
197
198 ipc_call_t answer;
199 aid_t req = async_send_2(phone, DEVMAP_DEVICE_GET_HANDLE, flags, 0,
200 &answer);
201
202 sysarg_t retval = async_data_write_start(phone, fqdn, str_size(fqdn));
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)
215 *handle = (devmap_handle_t) -1;
216 return retval;
217 }
218
219 if (handle != NULL)
220 *handle = (devmap_handle_t) IPC_GET_ARG1(answer);
221
222 return retval;
223}
224
225int devmap_namespace_get_handle(const char *name, devmap_handle_t *handle, unsigned int flags)
226{
227 int phone = devmap_get_phone(DEVMAP_CLIENT, flags);
228
229 if (phone < 0)
230 return phone;
231
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
238 sysarg_t retval = async_data_write_start(phone, name, str_size(name));
239 if (retval != EOK) {
240 async_wait_for(req, NULL);
241 async_serialize_end();
242 return retval;
243 }
244
245 async_wait_for(req, &retval);
246
247 async_serialize_end();
248
249 if (retval != EOK) {
250 if (handle != NULL)
251 *handle = (devmap_handle_t) -1;
252 return retval;
253 }
254
255 if (handle != NULL)
256 *handle = (devmap_handle_t) IPC_GET_ARG1(answer);
257
258 return retval;
259}
260
261devmap_handle_type_t devmap_handle_probe(devmap_handle_t handle)
262{
263 int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
264
265 if (phone < 0)
266 return phone;
267
268 sysarg_t type;
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
276int devmap_device_connect(devmap_handle_t handle, unsigned int flags)
277{
278 int phone;
279
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 }
287
288 return phone;
289}
290
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
298 sysarg_t null_id;
299 int retval = async_req_0_1(phone, DEVMAP_NULL_CREATE, &null_id);
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
313 async_req_1_0(phone, DEVMAP_NULL_DESTROY, (sysarg_t) null_id);
314}
315
316static size_t devmap_count_namespaces_internal(int phone)
317{
318 sysarg_t count;
319 int retval = async_req_0_1(phone, DEVMAP_GET_NAMESPACE_COUNT, &count);
320 if (retval != EOK)
321 return 0;
322
323 return count;
324}
325
326static size_t devmap_count_devices_internal(int phone, devmap_handle_t ns_handle)
327{
328 sysarg_t count;
329 int retval = async_req_1_1(phone, DEVMAP_GET_DEVICE_COUNT, ns_handle, &count);
330 if (retval != EOK)
331 return 0;
332
333 return count;
334}
335
336size_t devmap_count_namespaces(void)
337{
338 int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
339
340 if (phone < 0)
341 return 0;
342
343 return devmap_count_namespaces_internal(phone);
344}
345
346size_t devmap_count_devices(devmap_handle_t ns_handle)
347{
348 int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
349
350 if (phone < 0)
351 return 0;
352
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);
359
360 if (phone < 0)
361 return 0;
362
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
396 sysarg_t retval;
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
408size_t devmap_get_devices(devmap_handle_t ns_handle, dev_desc_t **data)
409{
410 int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
411
412 if (phone < 0)
413 return 0;
414
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
448 sysarg_t retval;
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 }
458}
Note: See TracBrowser for help on using the repository browser.