Subversion Repositories HelenOS

Rev

Rev 4009 | Rev 4264 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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