source: mainline/uspace/srv/devmap/devmap.c@ 5d0e461

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

remove futex (devmap is not multithreaded), use fibril serialization instead

  • Property mode set to 100644
File size: 17.2 KB
RevLine 
[13125d3]1/*
2 * Copyright (c) 2007 Josef Cejka
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/**
30 * @defgroup devmap Device mapper.
[6519d6f]31 * @brief HelenOS device mapper.
[13125d3]32 * @{
[6519d6f]33 */
[13125d3]34
35/** @file
36 */
37
38#include <ipc/services.h>
39#include <ipc/ns.h>
40#include <async.h>
41#include <stdio.h>
42#include <errno.h>
[07e4a3c]43#include <bool.h>
[798f364]44#include <stdlib.h>
45#include <string.h>
[21c5d41]46#include <ipc/devmap.h>
[13125d3]47
[6519d6f]48#define NAME "devmap"
[13125d3]49
[cb41a5e]50/** Representation of device driver.
51 *
52 * Each driver is responsible for a set of devices.
53 *
54 */
55typedef struct {
56 /** Pointers to previous and next drivers in linked list */
57 link_t drivers;
58 /** Pointer to the linked list of devices controlled by this driver */
59 link_t devices;
60 /** Phone asociated with this driver */
61 ipcarg_t phone;
62 /** Device driver name */
63 char *name;
64} devmap_driver_t;
65
66/** Info about registered device
67 *
68 */
69typedef struct {
70 /** Pointer to the previous and next device in the list of all devices */
71 link_t devices;
72 /** Pointer to the previous and next device in the list of devices
73 owned by one driver */
74 link_t driver_devices;
75 /** Unique device identifier */
76 dev_handle_t handle;
77 /** Device name */
78 char *name;
79 /** Device driver handling this device */
80 devmap_driver_t *driver;
81} devmap_device_t;
82
[6519d6f]83/** Pending lookup structure. */
84typedef struct {
85 link_t link;
86 char *name; /**< Device name */
87 ipc_callid_t callid; /**< Call ID waiting for the lookup */
88} pending_req_t;
[07e4a3c]89
[798f364]90LIST_INITIALIZE(devices_list);
91LIST_INITIALIZE(drivers_list);
[6519d6f]92LIST_INITIALIZE(pending_req);
[798f364]93
[cb41a5e]94static dev_handle_t last_handle = 0;
95
96static dev_handle_t devmap_create_handle(void)
[798f364]97{
98 /* TODO: allow reusing old handles after their unregistration
[5d0e461]99 * and implement some version of LRU algorithm, avoid overflow
[6519d6f]100 */
101
[cb41a5e]102 last_handle++;
[6519d6f]103
[cb41a5e]104 return last_handle;
[13125d3]105}
106
[798f364]107/** Find device with given name.
108 *
109 */
110static devmap_device_t *devmap_device_find_name(const char *name)
[07e4a3c]111{
[6519d6f]112 link_t *item = devices_list.next;
[798f364]113 devmap_device_t *device = NULL;
[6519d6f]114
[798f364]115 while (item != &devices_list) {
116 device = list_get_instance(item, devmap_device_t, devices);
[5d0e461]117 if (str_cmp(device->name, name) == 0)
[798f364]118 break;
119 item = item->next;
120 }
[6519d6f]121
[21c5d41]122 if (item == &devices_list)
[798f364]123 return NULL;
[6519d6f]124
[798f364]125 device = list_get_instance(item, devmap_device_t, devices);
126 return device;
127}
128
129/** Find device with given handle.
[6519d6f]130 *
[798f364]131 * @todo: use hash table
[6519d6f]132 *
[798f364]133 */
[cb41a5e]134static devmap_device_t *devmap_device_find_handle(dev_handle_t handle)
[798f364]135{
[6519d6f]136 link_t *item = (&devices_list)->next;
[798f364]137 devmap_device_t *device = NULL;
138
139 while (item != &devices_list) {
140 device = list_get_instance(item, devmap_device_t, devices);
[6519d6f]141 if (device->handle == handle)
[798f364]142 break;
143 item = item->next;
144 }
[6519d6f]145
[5d0e461]146 if (item == &devices_list)
[798f364]147 return NULL;
[6519d6f]148
[798f364]149 device = list_get_instance(item, devmap_device_t, devices);
150
151 return device;
152}
153
[7f3e3e7]154/**
[6519d6f]155 *
[7f3e3e7]156 * Unregister device and free it. It's assumed that driver's device list is
157 * already locked.
[6519d6f]158 *
[798f364]159 */
160static int devmap_device_unregister_core(devmap_device_t *device)
161{
162 list_remove(&(device->devices));
163 list_remove(&(device->driver_devices));
[6519d6f]164
165 free(device->name);
[798f364]166 free(device);
[6519d6f]167
[798f364]168 return EOK;
169}
170
[7f3e3e7]171/**
[6519d6f]172 *
[7f3e3e7]173 * Read info about new driver and add it into linked list of registered
174 * drivers.
[6519d6f]175 *
[798f364]176 */
177static void devmap_driver_register(devmap_driver_t **odriver)
178{
179 *odriver = NULL;
[07e4a3c]180
[6519d6f]181 ipc_call_t icall;
182 ipc_callid_t iid = async_get_call(&icall);
183
[798f364]184 if (IPC_GET_METHOD(icall) != DEVMAP_DRIVER_REGISTER) {
[b74959bd]185 ipc_answer_0(iid, EREFUSED);
[798f364]186 return;
[6519d6f]187 }
188
189 devmap_driver_t *driver = (devmap_driver_t *) malloc(sizeof(devmap_driver_t));
190
191 if (driver == NULL) {
[b74959bd]192 ipc_answer_0(iid, ENOMEM);
[798f364]193 return;
[07e4a3c]194 }
[6519d6f]195
196 /*
[798f364]197 * Get driver name
198 */
[6519d6f]199 ipc_callid_t callid;
200 size_t name_size;
[3115355]201 if (!ipc_data_write_receive(&callid, &name_size)) {
[798f364]202 free(driver);
[b74959bd]203 ipc_answer_0(callid, EREFUSED);
204 ipc_answer_0(iid, EREFUSED);
[798f364]205 return;
[07e4a3c]206 }
[6519d6f]207
[798f364]208 if (name_size > DEVMAP_NAME_MAXLEN) {
209 free(driver);
[b74959bd]210 ipc_answer_0(callid, EINVAL);
211 ipc_answer_0(iid, EREFUSED);
[798f364]212 return;
213 }
[6519d6f]214
[798f364]215 /*
216 * Allocate buffer for device name.
217 */
[6519d6f]218 driver->name = (char *) malloc(name_size + 1);
219 if (driver->name == NULL) {
[798f364]220 free(driver);
[b74959bd]221 ipc_answer_0(callid, ENOMEM);
222 ipc_answer_0(iid, EREFUSED);
[798f364]223 return;
[6519d6f]224 }
225
[798f364]226 /*
227 * Send confirmation to sender and get data into buffer.
228 */
[5d0e461]229 if (ipc_data_write_finalize(callid, driver->name, name_size) != EOK) {
[798f364]230 free(driver->name);
231 free(driver);
[b74959bd]232 ipc_answer_0(iid, EREFUSED);
[798f364]233 return;
234 }
[6519d6f]235
[798f364]236 driver->name[name_size] = 0;
[6519d6f]237
238 /*
[798f364]239 * Initialize list of asociated devices
[b74959bd]240 */
[798f364]241 list_initialize(&(driver->devices));
[6519d6f]242
243 /*
[5d0e461]244 * Create connection to the driver
[798f364]245 */
[6519d6f]246 ipc_call_t call;
[798f364]247 callid = async_get_call(&call);
[6519d6f]248
[5d0e461]249 if (IPC_GET_METHOD(call) != IPC_M_CONNECT_TO_ME) {
[b74959bd]250 ipc_answer_0(callid, ENOTSUP);
[798f364]251
252 free(driver->name);
253 free(driver);
[b74959bd]254 ipc_answer_0(iid, ENOTSUP);
[798f364]255 return;
256 }
[6519d6f]257
[38c706cc]258 driver->phone = IPC_GET_ARG5(call);
[798f364]259
[b74959bd]260 ipc_answer_0(callid, EOK);
[798f364]261
262 list_initialize(&(driver->drivers));
[6519d6f]263
[7f3e3e7]264 /* TODO:
265 * check that no driver with name equal to driver->name is registered
266 */
[6519d6f]267
268 /*
[798f364]269 * Insert new driver into list of registered drivers
270 */
271 list_append(&(driver->drivers), &drivers_list);
272
[b74959bd]273 ipc_answer_0(iid, EOK);
[6519d6f]274
[798f364]275 *odriver = driver;
[07e4a3c]276}
277
[6519d6f]278/**
279 * Unregister device driver, unregister all its devices and free driver
[b74959bd]280 * structure.
[6519d6f]281 *
[798f364]282 */
283static int devmap_driver_unregister(devmap_driver_t *driver)
[07e4a3c]284{
[6519d6f]285 if (driver == NULL)
[798f364]286 return EEXISTS;
[21c5d41]287
[cb41a5e]288 if (driver->phone != 0)
289 ipc_hangup(driver->phone);
[798f364]290
[cb41a5e]291 /* Remove it from list of drivers */
[798f364]292 list_remove(&(driver->drivers));
[6519d6f]293
[798f364]294 while (!list_empty(&(driver->devices))) {
[6519d6f]295 devmap_device_t *device = list_get_instance(driver->devices.next,
[7f3e3e7]296 devmap_device_t, driver_devices);
[798f364]297 devmap_device_unregister_core(device);
298 }
299
300 /* free name and driver */
[cb41a5e]301 if (driver->name != NULL)
[798f364]302 free(driver->name);
[6519d6f]303
[798f364]304 free(driver);
[6519d6f]305
[07e4a3c]306 return EOK;
307}
308
[798f364]309
[6519d6f]310/** Process pending lookup requests */
[5d0e461]311static void process_pending_lookup(void)
[6519d6f]312{
[5d0e461]313 async_serialize_start();
314
[6519d6f]315 link_t *cur;
316
317loop:
318 for (cur = pending_req.next; cur != &pending_req; cur = cur->next) {
319 pending_req_t *pr = list_get_instance(cur, pending_req_t, link);
320
321 const devmap_device_t *dev = devmap_device_find_name(pr->name);
322 if (!dev)
323 continue;
324
325 ipc_answer_1(pr->callid, EOK, dev->handle);
326
327 free(pr->name);
328 list_remove(cur);
329 free(pr);
[5d0e461]330
[6519d6f]331 goto loop;
332 }
[5d0e461]333
334 async_serialize_end();
[6519d6f]335}
336
337
[798f364]338/** Register instance of device
339 *
340 */
341static void devmap_device_register(ipc_callid_t iid, ipc_call_t *icall,
[b74959bd]342 devmap_driver_t *driver)
[07e4a3c]343{
[6519d6f]344 if (driver == NULL) {
[b74959bd]345 ipc_answer_0(iid, EREFUSED);
[798f364]346 return;
347 }
348
349 /* Create new device entry */
[6519d6f]350 devmap_device_t *device = (devmap_device_t *) malloc(sizeof(devmap_device_t));
351 if (device == NULL) {
[b74959bd]352 ipc_answer_0(iid, ENOMEM);
[798f364]353 return;
354 }
355
356 /* Get device name */
[6519d6f]357 ipc_callid_t callid;
358 size_t size;
[3115355]359 if (!ipc_data_write_receive(&callid, &size)) {
[798f364]360 free(device);
[b74959bd]361 ipc_answer_0(iid, EREFUSED);
[798f364]362 return;
363 }
[6519d6f]364
[798f364]365 if (size > DEVMAP_NAME_MAXLEN) {
366 free(device);
[b74959bd]367 ipc_answer_0(callid, EINVAL);
368 ipc_answer_0(iid, EREFUSED);
[798f364]369 return;
370 }
[21c5d41]371
372 /* +1 for terminating \0 */
373 device->name = (char *) malloc(size + 1);
[6519d6f]374
375 if (device->name == NULL) {
[798f364]376 free(device);
[b74959bd]377 ipc_answer_0(callid, ENOMEM);
378 ipc_answer_0(iid, EREFUSED);
[798f364]379 return;
[07e4a3c]380 }
[798f364]381
[215e375]382 ipc_data_write_finalize(callid, device->name, size);
[798f364]383 device->name[size] = 0;
[6519d6f]384
[798f364]385 list_initialize(&(device->devices));
386 list_initialize(&(device->driver_devices));
[6519d6f]387
[798f364]388 /* Check that device with such name is not already registered */
389 if (NULL != devmap_device_find_name(device->name)) {
[21c5d41]390 printf(NAME ": Device '%s' already registered\n", device->name);
[798f364]391 free(device->name);
392 free(device);
[b74959bd]393 ipc_answer_0(iid, EEXISTS);
[798f364]394 return;
[07e4a3c]395 }
[6519d6f]396
[798f364]397 /* Get unique device handle */
[6519d6f]398 device->handle = devmap_create_handle();
399
[798f364]400 device->driver = driver;
[07e4a3c]401
[798f364]402 /* Insert device into list of all devices */
[b74959bd]403 list_append(&device->devices, &devices_list);
[6519d6f]404
[b74959bd]405 list_append(&device->driver_devices, &device->driver->devices);
[798f364]406
[b74959bd]407 ipc_answer_1(iid, EOK, device->handle);
[07e4a3c]408}
409
[798f364]410/**
411 *
412 */
413static int devmap_device_unregister(ipc_callid_t iid, ipc_call_t *icall,
[b74959bd]414 devmap_driver_t *driver)
[07e4a3c]415{
[798f364]416 /* TODO */
[07e4a3c]417 return EOK;
418}
[13125d3]419
[798f364]420/** Connect client to the device.
[6519d6f]421 *
[798f364]422 * Find device driver owning requested device and forward
423 * the message to it.
[6519d6f]424 *
[798f364]425 */
426static void devmap_forward(ipc_callid_t callid, ipc_call_t *call)
427{
428 /*
429 * Get handle from request
430 */
[cb41a5e]431 dev_handle_t handle = IPC_GET_ARG2(*call);
[6519d6f]432 devmap_device_t *dev = devmap_device_find_handle(handle);
433
[cb41a5e]434 if ((dev == NULL) || (dev->driver == NULL) || (dev->driver->phone == 0)) {
[b74959bd]435 ipc_answer_0(callid, ENOENT);
[798f364]436 return;
[6519d6f]437 }
438
[cb41a5e]439 ipc_forward_fast(callid, dev->driver->phone, dev->handle,
[b61d47d]440 IPC_GET_ARG3(*call), 0, IPC_FF_NONE);
[798f364]441}
442
443/** Find handle for device instance identified by name.
[6519d6f]444 *
[798f364]445 * In answer will be send EOK and device handle in arg1 or a error
[6519d6f]446 * code from errno.h.
447 *
[798f364]448 */
449static void devmap_get_handle(ipc_callid_t iid, ipc_call_t *icall)
450{
[6519d6f]451 /*
[798f364]452 * Wait for incoming message with device name (but do not
453 * read the name itself until the buffer is allocated).
454 */
[6519d6f]455 ipc_callid_t callid;
456 size_t size;
457 if (!ipc_data_write_receive(&callid, &size)) {
[b74959bd]458 ipc_answer_0(callid, EREFUSED);
459 ipc_answer_0(iid, EREFUSED);
[798f364]460 return;
461 }
[6519d6f]462
463 if ((size < 1) || (size > DEVMAP_NAME_MAXLEN)) {
[b74959bd]464 ipc_answer_0(callid, EINVAL);
465 ipc_answer_0(iid, EREFUSED);
[798f364]466 return;
467 }
[6519d6f]468
[798f364]469 /*
470 * Allocate buffer for device name.
471 */
[cb41a5e]472 char *name = (char *) malloc(size + 1);
[6519d6f]473 if (name == NULL) {
[b74959bd]474 ipc_answer_0(callid, ENOMEM);
475 ipc_answer_0(iid, EREFUSED);
[798f364]476 return;
[6519d6f]477 }
478
[798f364]479 /*
480 * Send confirmation to sender and get data into buffer.
481 */
[6519d6f]482 ipcarg_t retval = ipc_data_write_finalize(callid, name, size);
483 if (retval != EOK) {
[b74959bd]484 ipc_answer_0(iid, EREFUSED);
[6519d6f]485 free(name);
[798f364]486 return;
487 }
[6519d6f]488 name[size] = '\0';
489
[798f364]490 /*
491 * Find device name in linked list of known devices.
492 */
[6519d6f]493 const devmap_device_t *dev = devmap_device_find_name(name);
494
[798f364]495 /*
496 * Device was not found.
497 */
[6519d6f]498 if (dev == NULL) {
499 if (IPC_GET_ARG1(*icall) & IPC_FLAG_BLOCKING) {
500 /* Blocking lookup, add to pending list */
501 pending_req_t *pr = (pending_req_t *) malloc(sizeof(pending_req_t));
502 if (!pr) {
503 ipc_answer_0(iid, ENOMEM);
504 free(name);
505 return;
506 }
507
508 pr->name = name;
509 pr->callid = iid;
510 list_append(&pr->link, &pending_req);
511 return;
512 }
513
[b74959bd]514 ipc_answer_0(iid, ENOENT);
[6519d6f]515 free(name);
[798f364]516 return;
517 }
[6519d6f]518
[b74959bd]519 ipc_answer_1(iid, EOK, dev->handle);
[6519d6f]520 free(name);
[798f364]521}
522
[6519d6f]523/** Find name of device identified by id and send it to caller.
[798f364]524 *
525 */
[cb41a5e]526static void devmap_get_name(ipc_callid_t iid, ipc_call_t *icall)
[798f364]527{
[6519d6f]528 const devmap_device_t *device = devmap_device_find_handle(IPC_GET_ARG1(*icall));
529
[798f364]530 /*
531 * Device not found.
532 */
[6519d6f]533 if (device == NULL) {
[b74959bd]534 ipc_answer_0(iid, ENOENT);
[798f364]535 return;
536 }
[6519d6f]537
538 ipc_answer_0(iid, EOK);
539
[92fd52d7]540 size_t name_size = str_size(device->name);
[6519d6f]541
542 /* FIXME:
543 * We have no channel from DEVMAP to client, therefore
544 * sending must be initiated by client.
545 *
546 * int rc = ipc_data_write_send(phone, device->name, name_size);
547 * if (rc != EOK) {
548 * async_wait_for(req, NULL);
549 * return rc;
550 * }
551 */
552
[798f364]553 /* TODO: send name in response */
554}
555
[cb41a5e]556static void devmap_get_count(ipc_callid_t iid, ipc_call_t *icall)
557{
558 ipc_answer_1(iid, EOK, list_count(&devices_list));
559}
560
561static void devmap_get_devices(ipc_callid_t iid, ipc_call_t *icall)
562{
563 ipc_callid_t callid;
564 size_t size;
565 if (!ipc_data_read_receive(&callid, &size)) {
566 ipc_answer_0(callid, EREFUSED);
567 ipc_answer_0(iid, EREFUSED);
568 return;
569 }
570
571 if ((size % sizeof(dev_desc_t)) != 0) {
572 ipc_answer_0(callid, EINVAL);
573 ipc_answer_0(iid, EREFUSED);
574 return;
575 }
576
[5d0e461]577 size_t count = size / sizeof(dev_desc_t);
[cb41a5e]578 dev_desc_t *desc = (dev_desc_t *) malloc(size);
579 if (desc == NULL) {
580 ipc_answer_0(callid, ENOMEM);
581 ipc_answer_0(iid, EREFUSED);
582 return;
583 }
584
[5d0e461]585 size_t pos = 0;
[cb41a5e]586 link_t *item = devices_list.next;
587
588 while ((item != &devices_list) && (pos < count)) {
589 devmap_device_t *device = list_get_instance(item, devmap_device_t, devices);
590
591 desc[pos].handle = device->handle;
592 str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, device->name);
593 pos++;
594 item = item->next;
595 }
596
597 ipcarg_t retval = ipc_data_read_finalize(callid, desc, pos * sizeof(dev_desc_t));
598 if (retval != EOK) {
599 ipc_answer_0(iid, EREFUSED);
600 free(desc);
601 return;
602 }
603
604 free(desc);
605
606 ipc_answer_1(iid, EOK, pos);
607}
608
609/** Initialize device mapper.
610 *
611 *
612 */
613static bool devmap_init()
614{
615 /* Create NULL device entry */
616 devmap_device_t *device = (devmap_device_t *) malloc(sizeof(devmap_device_t));
617 if (device == NULL)
618 return false;
619
620 device->name = str_dup("null");
621 if (device->name == NULL) {
622 free(device);
623 return false;
624 }
625
626 list_initialize(&(device->devices));
627 list_initialize(&(device->driver_devices));
628
629 /* Get unique device handle */
630 device->handle = devmap_create_handle();
631 device->driver = NULL;
632
633 /* Insert device into list of all devices */
634 list_append(&device->devices, &devices_list);
635
636 return true;
637}
638
[798f364]639/** Handle connection with device driver.
[13125d3]640 *
641 */
[21c5d41]642static void devmap_connection_driver(ipc_callid_t iid, ipc_call_t *icall)
[13125d3]643{
[6519d6f]644 /* Accept connection */
645 ipc_answer_0(iid, EOK);
646
[5d0e461]647 devmap_driver_t *driver = NULL;
[798f364]648 devmap_driver_register(&driver);
[6519d6f]649
[21c5d41]650 if (NULL == driver)
[798f364]651 return;
652
[6519d6f]653 bool cont = true;
[07e4a3c]654 while (cont) {
[6519d6f]655 ipc_call_t call;
656 ipc_callid_t callid = async_get_call(&call);
657
[5d0e461]658 async_serialize_start();
659
[6519d6f]660 switch (IPC_GET_METHOD(call)) {
[13125d3]661 case IPC_M_PHONE_HUNGUP:
[07e4a3c]662 cont = false;
[5d0e461]663 async_serialize_end();
[6519d6f]664 continue;
[798f364]665 case DEVMAP_DRIVER_UNREGISTER:
[6519d6f]666 if (NULL == driver)
[b74959bd]667 ipc_answer_0(callid, ENOENT);
[6519d6f]668 else
[b74959bd]669 ipc_answer_0(callid, EOK);
[07e4a3c]670 break;
[798f364]671 case DEVMAP_DEVICE_REGISTER:
672 /* Register one instance of device */
673 devmap_device_register(callid, &call, driver);
[07e4a3c]674 break;
[798f364]675 case DEVMAP_DEVICE_UNREGISTER:
676 /* Remove instance of device identified by handler */
677 devmap_device_unregister(callid, &call, driver);
678 break;
679 case DEVMAP_DEVICE_GET_HANDLE:
680 devmap_get_handle(callid, &call);
681 break;
682 case DEVMAP_DEVICE_GET_NAME:
[cb41a5e]683 devmap_get_name(callid, &call);
[798f364]684 break;
685 default:
[6519d6f]686 if (!(callid & IPC_CALLID_NOTIFICATION))
[b74959bd]687 ipc_answer_0(callid, ENOENT);
[798f364]688 }
[5d0e461]689
690 async_serialize_end();
[798f364]691 }
692
693 if (NULL != driver) {
[6519d6f]694 /*
[b74959bd]695 * Unregister the device driver and all its devices.
696 */
[5d0e461]697
698 async_serialize_start();
699
[798f364]700 devmap_driver_unregister(driver);
701 driver = NULL;
[5d0e461]702
703 async_serialize_end();
[798f364]704 }
705}
706
707/** Handle connection with device client.
708 *
709 */
[21c5d41]710static void devmap_connection_client(ipc_callid_t iid, ipc_call_t *icall)
[798f364]711{
[6519d6f]712 /* Accept connection */
713 ipc_answer_0(iid, EOK);
714
[798f364]715 bool cont = true;
716 while (cont) {
[6519d6f]717 ipc_call_t call;
718 ipc_callid_t callid = async_get_call(&call);
719
[5d0e461]720 async_serialize_start();
721
[6519d6f]722 switch (IPC_GET_METHOD(call)) {
[798f364]723 case IPC_M_PHONE_HUNGUP:
[07e4a3c]724 cont = false;
[5d0e461]725 async_serialize_end();
[6519d6f]726 continue;
[798f364]727 case DEVMAP_DEVICE_GET_HANDLE:
[6519d6f]728 devmap_get_handle(callid, &call);
[07e4a3c]729 break;
[798f364]730 case DEVMAP_DEVICE_GET_NAME:
731 devmap_get_name(callid, &call);
[13125d3]732 break;
[cb41a5e]733 case DEVMAP_DEVICE_GET_COUNT:
734 devmap_get_count(callid, &call);
735 break;
736 case DEVMAP_DEVICE_GET_DEVICES:
737 devmap_get_devices(callid, &call);
738 break;
[13125d3]739 default:
[6519d6f]740 if (!(callid & IPC_CALLID_NOTIFICATION))
[b74959bd]741 ipc_answer_0(callid, ENOENT);
[13125d3]742 }
[5d0e461]743
744 async_serialize_end();
[13125d3]745 }
746}
747
[6519d6f]748/** Function for handling connections to devmap
[798f364]749 *
750 */
[21c5d41]751static void devmap_connection(ipc_callid_t iid, ipc_call_t *icall)
[798f364]752{
[21c5d41]753 /* Select interface */
754 switch ((ipcarg_t) (IPC_GET_ARG1(*icall))) {
[7f3e3e7]755 case DEVMAP_DRIVER:
756 devmap_connection_driver(iid, icall);
757 break;
758 case DEVMAP_CLIENT:
759 devmap_connection_client(iid, icall);
760 break;
[b61d47d]761 case DEVMAP_CONNECT_TO_DEVICE:
[21c5d41]762 /* Connect client to selected device */
[b61d47d]763 devmap_forward(iid, icall);
764 break;
[7f3e3e7]765 default:
[6519d6f]766 /* No such interface */
[5d0e461]767 ipc_answer_0(iid, ENOENT);
[798f364]768 }
769}
[13125d3]770
[798f364]771/**
772 *
773 */
[13125d3]774int main(int argc, char *argv[])
775{
[21c5d41]776 printf(NAME ": HelenOS Device Mapper\n");
777
[cb41a5e]778 if (!devmap_init()) {
[21c5d41]779 printf(NAME ": Error while initializing service\n");
[13125d3]780 return -1;
781 }
[21c5d41]782
[5d0e461]783 /* Set a handler of incomming connections and
784 pending operations */
785 async_set_pending(process_pending_lookup);
[798f364]786 async_set_client_connection(devmap_connection);
[6519d6f]787
[7f3e3e7]788 /* Register device mapper at naming service */
[6519d6f]789 ipcarg_t phonead;
[38c706cc]790 if (ipc_connect_to_me(PHONE_NS, SERVICE_DEVMAP, 0, 0, &phonead) != 0)
[13125d3]791 return -1;
792
[21c5d41]793 printf(NAME ": Accepting connections\n");
[13125d3]794 async_manager();
[6519d6f]795
[13125d3]796 /* Never reached */
797 return 0;
798}
799
800/**
801 * @}
802 */
Note: See TracBrowser for help on using the repository browser.