Subversion Repositories HelenOS

Rev

Rev 4377 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4377 Rev 4692
Line 39... Line 39...
39
#include <ipc/ns.h>
39
#include <ipc/ns.h>
40
#include <async.h>
40
#include <async.h>
41
#include <stdio.h>
41
#include <stdio.h>
42
#include <errno.h>
42
#include <errno.h>
43
#include <bool.h>
43
#include <bool.h>
44
#include <futex.h>
44
#include <fibril_sync.h>
45
#include <stdlib.h>
45
#include <stdlib.h>
46
#include <string.h>
46
#include <string.h>
47
#include <ipc/devmap.h>
47
#include <ipc/devmap.h>
48
 
48
 
49
#define NAME  "devmap"
49
#define NAME          "devmap"
-
 
50
#define NULL_DEVICES  256
50
 
51
 
51
/** Pending lookup structure. */
52
/** Representation of device driver.
-
 
53
 *
-
 
54
 * Each driver is responsible for a set of devices.
-
 
55
 *
-
 
56
 */
52
typedef struct {
57
typedef struct {
-
 
58
    /** Pointers to previous and next drivers in linked list */
-
 
59
    link_t drivers;
-
 
60
    /** Pointer to the linked list of devices controlled by this driver */
53
    link_t link;
61
    link_t devices;
54
    char *name;              /**< Device name */
62
    /** Phone asociated with this driver */
-
 
63
    ipcarg_t phone;
-
 
64
    /** Device driver name */
-
 
65
    char *name;
55
    ipc_callid_t callid;     /**< Call ID waiting for the lookup */
66
    /** Fibril mutex for list of devices owned by this driver */
-
 
67
    fibril_mutex_t devices_mutex;
56
} pending_req_t;
68
} devmap_driver_t;
-
 
69
 
-
 
70
/** Info about registered device
-
 
71
 *
-
 
72
 */
-
 
73
typedef struct {
-
 
74
    /** Pointer to the previous and next device in the list of all devices */
-
 
75
    link_t devices;
-
 
76
    /** Pointer to the previous and next device in the list of devices
-
 
77
        owned by one driver */
-
 
78
    link_t driver_devices;
-
 
79
    /** Unique device identifier  */
-
 
80
    dev_handle_t handle;
-
 
81
    /** Device name */
-
 
82
    char *name;
-
 
83
    /** Device driver handling this device */
-
 
84
    devmap_driver_t *driver;
-
 
85
} devmap_device_t;
57
 
86
 
58
LIST_INITIALIZE(devices_list);
87
LIST_INITIALIZE(devices_list);
59
LIST_INITIALIZE(drivers_list);
88
LIST_INITIALIZE(drivers_list);
60
LIST_INITIALIZE(pending_req);
-
 
61
 
89
 
62
/* Locking order:
90
/* Locking order:
63
 *  drivers_list_futex
91
 *  drivers_list_mutex
64
 *  devices_list_futex
92
 *  devices_list_mutex
65
 *  (devmap_driver_t *)->devices_futex
93
 *  (devmap_driver_t *)->devices_mutex
66
 *  create_handle_futex
94
 *  create_handle_mutex
67
 **/
95
 **/
68
 
96
 
69
static atomic_t devices_list_futex = FUTEX_INITIALIZER;
97
static FIBRIL_MUTEX_INITIALIZE(devices_list_mutex);
-
 
98
static FIBRIL_CONDVAR_INITIALIZE(devices_list_cv);
70
static atomic_t drivers_list_futex = FUTEX_INITIALIZER;
99
static FIBRIL_MUTEX_INITIALIZE(drivers_list_mutex);
71
static atomic_t create_handle_futex = FUTEX_INITIALIZER;
100
static FIBRIL_MUTEX_INITIALIZE(create_handle_mutex);
-
 
101
static FIBRIL_MUTEX_INITIALIZE(null_devices_mutex);
72
 
102
 
-
 
103
static dev_handle_t last_handle = 0;
-
 
104
static devmap_device_t *null_devices[NULL_DEVICES];
-
 
105
 
73
static int devmap_create_handle(void)
106
static dev_handle_t devmap_create_handle(void)
74
{
107
{
75
    static int last_handle = 0;
-
 
76
    int handle;
-
 
77
   
-
 
78
    /* TODO: allow reusing old handles after their unregistration
108
    /* TODO: allow reusing old handles after their unregistration
79
     * and implement some version of LRU algorithm
109
     * and implement some version of LRU algorithm, avoid overflow
80
     */
110
     */
81
   
111
   
82
    /* FIXME: overflow */
-
 
83
    futex_down(&create_handle_futex);
112
    fibril_mutex_lock(&create_handle_mutex);
84
   
-
 
85
    last_handle += 1;
113
    last_handle++;
86
    handle = last_handle;
-
 
87
   
-
 
88
    futex_up(&create_handle_futex);
114
    fibril_mutex_unlock(&create_handle_mutex);
89
   
-
 
90
    return handle;
-
 
91
}
-
 
92
 
-
 
93
 
-
 
94
/** Initialize device mapper.
-
 
95
 *
-
 
96
 *
-
 
97
 */
-
 
98
static int devmap_init()
-
 
99
{
-
 
100
    /* TODO: */
-
 
101
   
115
   
102
    return EOK;
116
    return last_handle;
103
}
117
}
104
 
118
 
105
/** Find device with given name.
119
/** Find device with given name.
106
 *
120
 *
107
 */
121
 */
Line 110... Line 124...
110
    link_t *item = devices_list.next;
124
    link_t *item = devices_list.next;
111
    devmap_device_t *device = NULL;
125
    devmap_device_t *device = NULL;
112
   
126
   
113
    while (item != &devices_list) {
127
    while (item != &devices_list) {
114
        device = list_get_instance(item, devmap_device_t, devices);
128
        device = list_get_instance(item, devmap_device_t, devices);
115
        if (0 == str_cmp(device->name, name))
129
        if (str_cmp(device->name, name) == 0)
116
            break;
130
            break;
117
        item = item->next;
131
        item = item->next;
118
    }
132
    }
119
   
133
   
120
    if (item == &devices_list)
134
    if (item == &devices_list)
Line 127... Line 141...
127
/** Find device with given handle.
141
/** Find device with given handle.
128
 *
142
 *
129
 * @todo: use hash table
143
 * @todo: use hash table
130
 *
144
 *
131
 */
145
 */
132
static devmap_device_t *devmap_device_find_handle(int handle)
146
static devmap_device_t *devmap_device_find_handle(dev_handle_t handle)
133
{
147
{
134
    futex_down(&devices_list_futex);
148
    fibril_mutex_lock(&devices_list_mutex);
135
   
149
   
136
    link_t *item = (&devices_list)->next;
150
    link_t *item = (&devices_list)->next;
137
    devmap_device_t *device = NULL;
151
    devmap_device_t *device = NULL;
138
   
152
   
139
    while (item != &devices_list) {
153
    while (item != &devices_list) {
Line 142... Line 156...
142
            break;
156
            break;
143
        item = item->next;
157
        item = item->next;
144
    }
158
    }
145
   
159
   
146
    if (item == &devices_list) {
160
    if (item == &devices_list) {
147
        futex_up(&devices_list_futex);
161
        fibril_mutex_unlock(&devices_list_mutex);
148
        return NULL;
162
        return NULL;
149
    }
163
    }
150
   
164
   
151
    device = list_get_instance(item, devmap_device_t, devices);
165
    device = list_get_instance(item, devmap_device_t, devices);
152
   
166
   
153
    futex_up(&devices_list_futex);
167
    fibril_mutex_unlock(&devices_list_mutex);
154
   
168
   
155
    return device;
169
    return device;
156
}
170
}
157
 
171
 
158
/**
172
/**
159
 *
-
 
160
 * Unregister device and free it. It's assumed that driver's device list is
173
 * Unregister device and free it. It's assumed that driver's device list is
161
 * already locked.
174
 * already locked.
162
 *
-
 
163
 */
175
 */
164
static int devmap_device_unregister_core(devmap_device_t *device)
176
static int devmap_device_unregister_core(devmap_device_t *device)
165
{
177
{
166
    list_remove(&(device->devices));
178
    list_remove(&(device->devices));
167
    list_remove(&(device->driver_devices));
179
    list_remove(&(device->driver_devices));
Line 171... Line 183...
171
   
183
   
172
    return EOK;
184
    return EOK;
173
}
185
}
174
 
186
 
175
/**
187
/**
176
 *
-
 
177
 * Read info about new driver and add it into linked list of registered
188
 * Read info about new driver and add it into linked list of registered
178
 * drivers.
189
 * drivers.
179
 *
-
 
180
 */
190
 */
181
static void devmap_driver_register(devmap_driver_t **odriver)
191
static void devmap_driver_register(devmap_driver_t **odriver)
182
{
192
{
183
    *odriver = NULL;
193
    *odriver = NULL;
184
   
194
   
Line 228... Line 238...
228
    }
238
    }
229
   
239
   
230
    /*
240
    /*
231
     * Send confirmation to sender and get data into buffer.
241
     * Send confirmation to sender and get data into buffer.
232
     */
242
     */
233
    if (EOK != ipc_data_write_finalize(callid, driver->name, name_size)) {
243
    if (ipc_data_write_finalize(callid, driver->name, name_size) != EOK) {
234
        free(driver->name);
244
        free(driver->name);
235
        free(driver);
245
        free(driver);
236
        ipc_answer_0(iid, EREFUSED);
246
        ipc_answer_0(iid, EREFUSED);
237
        return;
247
        return;
238
    }
248
    }
239
   
249
   
240
    driver->name[name_size] = 0;
250
    driver->name[name_size] = 0;
241
   
251
   
242
    /* Initialize futex for list of devices owned by this driver */
252
    /* Initialize mutex for list of devices owned by this driver */
243
    futex_initialize(&(driver->devices_futex), 1);
253
    fibril_mutex_initialize(&driver->devices_mutex);
244
   
254
   
245
    /*
255
    /*
246
     * Initialize list of asociated devices
256
     * Initialize list of asociated devices
247
     */
257
     */
248
    list_initialize(&(driver->devices));
258
    list_initialize(&driver->devices);
249
   
259
   
250
    /*
260
    /*
251
     * Create connection to the driver
261
     * Create connection to the driver
252
     */
262
     */
253
    ipc_call_t call;
263
    ipc_call_t call;
254
    callid = async_get_call(&call);
264
    callid = async_get_call(&call);
255
   
265
   
256
    if (IPC_M_CONNECT_TO_ME != IPC_GET_METHOD(call)) {
266
    if (IPC_GET_METHOD(call) != IPC_M_CONNECT_TO_ME) {
257
        ipc_answer_0(callid, ENOTSUP);
267
        ipc_answer_0(callid, ENOTSUP);
258
       
268
       
259
        free(driver->name);
269
        free(driver->name);
260
        free(driver);
270
        free(driver);
261
        ipc_answer_0(iid, ENOTSUP);
271
        ipc_answer_0(iid, ENOTSUP);
Line 266... Line 276...
266
   
276
   
267
    ipc_answer_0(callid, EOK);
277
    ipc_answer_0(callid, EOK);
268
   
278
   
269
    list_initialize(&(driver->drivers));
279
    list_initialize(&(driver->drivers));
270
   
280
   
271
    futex_down(&drivers_list_futex);
281
    fibril_mutex_lock(&drivers_list_mutex);
272
   
282
   
273
    /* TODO:
283
    /* TODO:
274
     * check that no driver with name equal to driver->name is registered
284
     * check that no driver with name equal to driver->name is registered
275
     */
285
     */
276
   
286
   
277
    /*
287
    /*
278
     * Insert new driver into list of registered drivers
288
     * Insert new driver into list of registered drivers
279
     */
289
     */
280
    list_append(&(driver->drivers), &drivers_list);
290
    list_append(&(driver->drivers), &drivers_list);
281
    futex_up(&drivers_list_futex);
291
    fibril_mutex_unlock(&drivers_list_mutex);
282
   
292
   
283
    ipc_answer_0(iid, EOK);
293
    ipc_answer_0(iid, EOK);
284
   
294
   
285
    *odriver = driver;
295
    *odriver = driver;
286
}
296
}
Line 293... Line 303...
293
static int devmap_driver_unregister(devmap_driver_t *driver)
303
static int devmap_driver_unregister(devmap_driver_t *driver)
294
{
304
{
295
    if (driver == NULL)
305
    if (driver == NULL)
296
        return EEXISTS;
306
        return EEXISTS;
297
   
307
   
298
    futex_down(&drivers_list_futex);
308
    fibril_mutex_lock(&drivers_list_mutex);
299
   
309
   
-
 
310
    if (driver->phone != 0)
300
    ipc_hangup(driver->phone);
311
        ipc_hangup(driver->phone);
301
   
312
   
302
    /* remove it from list of drivers */
313
    /* Remove it from list of drivers */
303
    list_remove(&(driver->drivers));
314
    list_remove(&(driver->drivers));
304
   
315
   
305
    /* unregister all its devices */
316
    /* Unregister all its devices */
306
   
-
 
307
    futex_down(&devices_list_futex);
317
    fibril_mutex_lock(&devices_list_mutex);
308
    futex_down(&(driver->devices_futex));
318
    fibril_mutex_lock(&driver->devices_mutex);
309
   
319
   
310
    while (!list_empty(&(driver->devices))) {
320
    while (!list_empty(&(driver->devices))) {
311
        devmap_device_t *device = list_get_instance(driver->devices.next,
321
        devmap_device_t *device = list_get_instance(driver->devices.next,
312
            devmap_device_t, driver_devices);
322
            devmap_device_t, driver_devices);
313
        devmap_device_unregister_core(device);
323
        devmap_device_unregister_core(device);
314
    }
324
    }
315
   
325
   
316
    futex_up(&(driver->devices_futex));
326
    fibril_mutex_unlock(&driver->devices_mutex);
317
    futex_up(&devices_list_futex);
327
    fibril_mutex_unlock(&devices_list_mutex);
318
    futex_up(&drivers_list_futex);
328
    fibril_mutex_unlock(&drivers_list_mutex);
319
   
329
   
320
    /* free name and driver */
330
    /* free name and driver */
321
    if (NULL != driver->name)
331
    if (driver->name != NULL)
322
        free(driver->name);
332
        free(driver->name);
323
   
333
   
324
    free(driver);
334
    free(driver);
325
   
335
   
326
    return EOK;
336
    return EOK;
327
}
337
}
328
 
338
 
329
 
-
 
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
 
-
 
353
/** Register instance of device
339
/** Register instance of device
354
 *
340
 *
355
 */
341
 */
356
static void devmap_device_register(ipc_callid_t iid, ipc_call_t *icall,
342
static void devmap_device_register(ipc_callid_t iid, ipc_call_t *icall,
357
    devmap_driver_t *driver)
343
    devmap_driver_t *driver)
Line 398... Line 384...
398
    device->name[size] = 0;
384
    device->name[size] = 0;
399
   
385
   
400
    list_initialize(&(device->devices));
386
    list_initialize(&(device->devices));
401
    list_initialize(&(device->driver_devices));
387
    list_initialize(&(device->driver_devices));
402
   
388
   
403
    futex_down(&devices_list_futex);
389
    fibril_mutex_lock(&devices_list_mutex);
404
   
390
   
405
    /* Check that device with such name is not already registered */
391
    /* Check that device with such name is not already registered */
406
    if (NULL != devmap_device_find_name(device->name)) {
392
    if (NULL != devmap_device_find_name(device->name)) {
407
        printf(NAME ": Device '%s' already registered\n", device->name);
393
        printf(NAME ": Device '%s' already registered\n", device->name);
408
        futex_up(&devices_list_futex); 
394
        fibril_mutex_unlock(&devices_list_mutex);
409
        free(device->name);
395
        free(device->name);
410
        free(device);
396
        free(device);
411
        ipc_answer_0(iid, EEXISTS);
397
        ipc_answer_0(iid, EEXISTS);
412
        return;
398
        return;
413
    }
399
    }
Line 419... Line 405...
419
   
405
   
420
    /* Insert device into list of all devices  */
406
    /* Insert device into list of all devices  */
421
    list_append(&device->devices, &devices_list);
407
    list_append(&device->devices, &devices_list);
422
   
408
   
423
    /* Insert device into list of devices that belog to one driver */
409
    /* Insert device into list of devices that belog to one driver */
424
    futex_down(&device->driver->devices_futex);
410
    fibril_mutex_lock(&device->driver->devices_mutex);
425
   
411
   
426
    list_append(&device->driver_devices, &device->driver->devices);
412
    list_append(&device->driver_devices, &device->driver->devices);
427
   
413
   
428
    futex_up(&device->driver->devices_futex);
414
    fibril_mutex_unlock(&device->driver->devices_mutex);
-
 
415
    fibril_condvar_broadcast(&devices_list_cv);
429
    futex_up(&devices_list_futex);
416
    fibril_mutex_unlock(&devices_list_mutex);
430
   
417
   
431
    ipc_answer_1(iid, EOK, device->handle);
418
    ipc_answer_1(iid, EOK, device->handle);
432
   
-
 
433
    process_pending_lookup();
-
 
434
}
419
}
435
 
420
 
436
/**
421
/**
437
 *
422
 *
438
 */
423
 */
Line 452... Line 437...
452
static void devmap_forward(ipc_callid_t callid, ipc_call_t *call)
437
static void devmap_forward(ipc_callid_t callid, ipc_call_t *call)
453
{
438
{
454
    /*
439
    /*
455
     * Get handle from request
440
     * Get handle from request
456
     */
441
     */
457
    int handle = IPC_GET_ARG2(*call);
442
    dev_handle_t handle = IPC_GET_ARG2(*call);
458
    devmap_device_t *dev = devmap_device_find_handle(handle);
443
    devmap_device_t *dev = devmap_device_find_handle(handle);
459
   
444
   
460
    if (NULL == dev) {
445
    if ((dev == NULL) || (dev->driver == NULL) || (dev->driver->phone == 0)) {
461
        ipc_answer_0(callid, ENOENT);
446
        ipc_answer_0(callid, ENOENT);
462
        return;
447
        return;
463
    }
448
    }
464
   
449
   
465
    ipc_forward_fast(callid, dev->driver->phone, (ipcarg_t)(dev->handle),
450
    ipc_forward_fast(callid, dev->driver->phone, dev->handle,
466
        IPC_GET_ARG3(*call), 0, IPC_FF_NONE);
451
        IPC_GET_ARG3(*call), 0, IPC_FF_NONE);
467
}
452
}
468
 
453
 
469
/** Find handle for device instance identified by name.
454
/** Find handle for device instance identified by name.
470
 *
455
 *
Line 493... Line 478...
493
    }
478
    }
494
   
479
   
495
    /*
480
    /*
496
     * Allocate buffer for device name.
481
     * Allocate buffer for device name.
497
     */
482
     */
498
    char *name = (char *) malloc(size);
483
    char *name = (char *) malloc(size + 1);
499
    if (name == NULL) {
484
    if (name == NULL) {
500
        ipc_answer_0(callid, ENOMEM);
485
        ipc_answer_0(callid, ENOMEM);
501
        ipc_answer_0(iid, EREFUSED);
486
        ipc_answer_0(iid, EREFUSED);
502
        return;
487
        return;
503
    }
488
    }
Line 511... Line 496...
511
        free(name);
496
        free(name);
512
        return;
497
        return;
513
    }
498
    }
514
    name[size] = '\0';
499
    name[size] = '\0';
515
   
500
   
-
 
501
    fibril_mutex_lock(&devices_list_mutex);
-
 
502
    const devmap_device_t *dev;
-
 
503
recheck:
-
 
504
 
516
    /*
505
    /*
517
     * Find device name in linked list of known devices.
506
     * Find device name in the list of known devices.
518
     */
507
     */
519
    const devmap_device_t *dev = devmap_device_find_name(name);
508
    dev = devmap_device_find_name(name);
520
   
509
   
521
    /*
510
    /*
522
     * Device was not found.
511
     * Device was not found.
523
     */
512
     */
524
    if (dev == NULL) {
513
    if (dev == NULL) {
525
        if (IPC_GET_ARG1(*icall) & IPC_FLAG_BLOCKING) {
514
        if (IPC_GET_ARG1(*icall) & IPC_FLAG_BLOCKING) {
526
            /* Blocking lookup, add to pending list */
515
            /* Blocking lookup */
527
            pending_req_t *pr = (pending_req_t *) malloc(sizeof(pending_req_t));
-
 
528
            if (!pr) {
-
 
529
                ipc_answer_0(iid, ENOMEM);
516
            fibril_condvar_wait(&devices_list_cv,
530
                free(name);
517
                &devices_list_mutex);
531
                return;
518
            goto recheck;
532
            }
-
 
533
           
-
 
534
            pr->name = name;
-
 
535
            pr->callid = iid;
-
 
536
            list_append(&pr->link, &pending_req);
-
 
537
            return;
-
 
538
        }
519
        }
539
       
520
       
540
        ipc_answer_0(iid, ENOENT);
521
        ipc_answer_0(iid, ENOENT);
541
        free(name);
522
        free(name);
-
 
523
        fibril_mutex_unlock(&devices_list_mutex);
542
        return;
524
        return;
543
    }
525
    }
-
 
526
    fibril_mutex_unlock(&devices_list_mutex);
544
   
527
   
545
    ipc_answer_1(iid, EOK, dev->handle);
528
    ipc_answer_1(iid, EOK, dev->handle);
546
    free(name);
529
    free(name);
547
}
530
}
548
 
531
 
549
/** Find name of device identified by id and send it to caller.
532
/** Find name of device identified by id and send it to caller.
550
 *
533
 *
551
 */
534
 */
552
static void devmap_get_name(ipc_callid_t iid, ipc_call_t *icall)
535
static void devmap_get_name(ipc_callid_t iid, ipc_call_t *icall)
553
{
536
{
554
    const devmap_device_t *device = devmap_device_find_handle(IPC_GET_ARG1(*icall));
537
    const devmap_device_t *device = devmap_device_find_handle(IPC_GET_ARG1(*icall));
555
   
538
   
556
    /*
539
    /*
557
     * Device not found.
540
     * Device not found.
Line 561... Line 544...
561
        return;
544
        return;
562
    }
545
    }
563
   
546
   
564
    ipc_answer_0(iid, EOK);
547
    ipc_answer_0(iid, EOK);
565
   
548
   
566
    size_t name_size = str_size(device->name);
-
 
567
   
-
 
568
    /* FIXME:
549
    /* FIXME:
569
     * We have no channel from DEVMAP to client, therefore
550
     * We have no channel from DEVMAP to client, therefore
570
     * sending must be initiated by client.
551
     * sending must be initiated by client.
571
     *
552
     *
-
 
553
     * size_t name_size = str_size(device->name);
-
 
554
     *
572
     * int rc = ipc_data_write_send(phone, device->name, name_size);
555
     * int rc = ipc_data_write_send(phone, device->name, name_size);
573
     * if (rc != EOK) {
556
     * if (rc != EOK) {
574
     *     async_wait_for(req, NULL);
557
     *     async_wait_for(req, NULL);
575
     *     return rc;
558
     *     return rc;
576
     * }
559
     * }
577
     */
560
     */
578
   
561
   
579
    /* TODO: send name in response */
562
    /* TODO: send name in response */
580
}
563
}
581
 
564
 
-
 
565
static void devmap_get_count(ipc_callid_t iid, ipc_call_t *icall)
-
 
566
{
-
 
567
    fibril_mutex_lock(&devices_list_mutex);
-
 
568
    ipc_answer_1(iid, EOK, list_count(&devices_list));
-
 
569
    fibril_mutex_unlock(&devices_list_mutex);
-
 
570
}
-
 
571
 
-
 
572
static void devmap_get_devices(ipc_callid_t iid, ipc_call_t *icall)
-
 
573
{
-
 
574
    fibril_mutex_lock(&devices_list_mutex);
-
 
575
   
-
 
576
    ipc_callid_t callid;
-
 
577
    size_t size;
-
 
578
    if (!ipc_data_read_receive(&callid, &size)) {
-
 
579
        ipc_answer_0(callid, EREFUSED);
-
 
580
        ipc_answer_0(iid, EREFUSED);
-
 
581
        return;
-
 
582
    }
-
 
583
   
-
 
584
    if ((size % sizeof(dev_desc_t)) != 0) {
-
 
585
        ipc_answer_0(callid, EINVAL);
-
 
586
        ipc_answer_0(iid, EREFUSED);
-
 
587
        return;
-
 
588
    }
-
 
589
   
-
 
590
    size_t count = size / sizeof(dev_desc_t);
-
 
591
    dev_desc_t *desc = (dev_desc_t *) malloc(size);
-
 
592
    if (desc == NULL) {
-
 
593
        ipc_answer_0(callid, ENOMEM);
-
 
594
        ipc_answer_0(iid, EREFUSED);
-
 
595
        return;
-
 
596
    }
-
 
597
   
-
 
598
    size_t pos = 0;
-
 
599
    link_t *item = devices_list.next;
-
 
600
   
-
 
601
    while ((item != &devices_list) && (pos < count)) {
-
 
602
        devmap_device_t *device = list_get_instance(item, devmap_device_t, devices);
-
 
603
       
-
 
604
        desc[pos].handle = device->handle;
-
 
605
        str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, device->name);
-
 
606
        pos++;
-
 
607
        item = item->next;
-
 
608
    }
-
 
609
   
-
 
610
    ipcarg_t retval = ipc_data_read_finalize(callid, desc, pos * sizeof(dev_desc_t));
-
 
611
    if (retval != EOK) {
-
 
612
        ipc_answer_0(iid, EREFUSED);
-
 
613
        free(desc);
-
 
614
        return;
-
 
615
    }
-
 
616
   
-
 
617
    free(desc);
-
 
618
   
-
 
619
    fibril_mutex_unlock(&devices_list_mutex);
-
 
620
   
-
 
621
    ipc_answer_1(iid, EOK, pos);
-
 
622
}
-
 
623
 
-
 
624
static void devmap_null_create(ipc_callid_t iid, ipc_call_t *icall)
-
 
625
{
-
 
626
    fibril_mutex_lock(&null_devices_mutex);
-
 
627
   
-
 
628
    unsigned int i;
-
 
629
    bool fnd = false;
-
 
630
   
-
 
631
    for (i = 0; i < NULL_DEVICES; i++) {
-
 
632
        if (null_devices[i] == NULL) {
-
 
633
            fnd = true;
-
 
634
            break;
-
 
635
        }
-
 
636
    }
-
 
637
   
-
 
638
    if (!fnd) {
-
 
639
        fibril_mutex_unlock(&null_devices_mutex);
-
 
640
        ipc_answer_0(iid, ENOMEM);
-
 
641
        return;
-
 
642
    }
-
 
643
   
-
 
644
    /* Create NULL device entry */
-
 
645
    devmap_device_t *device = (devmap_device_t *) malloc(sizeof(devmap_device_t));
-
 
646
    if (device == NULL) {
-
 
647
        fibril_mutex_unlock(&null_devices_mutex);
-
 
648
        ipc_answer_0(iid, ENOMEM);
-
 
649
        return;
-
 
650
    }
-
 
651
   
-
 
652
    char null[DEVMAP_NAME_MAXLEN];
-
 
653
    snprintf(null, DEVMAP_NAME_MAXLEN, "null%u", i);
-
 
654
   
-
 
655
    device->name = str_dup(null);
-
 
656
    if (device->name == NULL) {
-
 
657
        fibril_mutex_unlock(&null_devices_mutex);
-
 
658
        free(device);
-
 
659
        ipc_answer_0(iid, ENOMEM);
-
 
660
        return;
-
 
661
    }
-
 
662
   
-
 
663
    list_initialize(&(device->devices));
-
 
664
    list_initialize(&(device->driver_devices));
-
 
665
   
-
 
666
    fibril_mutex_lock(&devices_list_mutex);
-
 
667
   
-
 
668
    /* Get unique device handle */
-
 
669
    device->handle = devmap_create_handle();
-
 
670
    device->driver = NULL;
-
 
671
   
-
 
672
    /* Insert device into list of all devices
-
 
673
       and into null devices array */
-
 
674
    list_append(&device->devices, &devices_list);
-
 
675
    null_devices[i] = device;
-
 
676
   
-
 
677
    fibril_mutex_unlock(&devices_list_mutex);
-
 
678
    fibril_mutex_unlock(&null_devices_mutex);
-
 
679
   
-
 
680
    ipc_answer_1(iid, EOK, (ipcarg_t) i);
-
 
681
}
-
 
682
 
-
 
683
static void devmap_null_destroy(ipc_callid_t iid, ipc_call_t *icall)
-
 
684
{
-
 
685
    fibril_mutex_lock(&null_devices_mutex);
-
 
686
   
-
 
687
    ipcarg_t i = IPC_GET_ARG1(*icall);
-
 
688
   
-
 
689
    if (null_devices[i] == NULL) {
-
 
690
        ipc_answer_0(iid, ENOENT);
-
 
691
        return;
-
 
692
    }
-
 
693
   
-
 
694
    devmap_device_unregister_core(null_devices[i]);
-
 
695
    null_devices[i] = NULL;
-
 
696
   
-
 
697
    fibril_mutex_unlock(&null_devices_mutex);
-
 
698
   
-
 
699
    ipc_answer_0(iid, EOK);
-
 
700
}
-
 
701
 
-
 
702
/** Initialize device mapper.
-
 
703
 *
-
 
704
 *
-
 
705
 */
-
 
706
static bool devmap_init(void)
-
 
707
{
-
 
708
    fibril_mutex_lock(&null_devices_mutex);
-
 
709
   
-
 
710
    unsigned int i;
-
 
711
    for (i = 0; i < NULL_DEVICES; i++)
-
 
712
        null_devices[i] = NULL;
-
 
713
   
-
 
714
    fibril_mutex_unlock(&null_devices_mutex);
-
 
715
   
-
 
716
    return true;
-
 
717
}
-
 
718
 
582
/** Handle connection with device driver.
719
/** Handle connection with device driver.
583
 *
720
 *
584
 */
721
 */
585
static void devmap_connection_driver(ipc_callid_t iid, ipc_call_t *icall)
722
static void devmap_connection_driver(ipc_callid_t iid, ipc_call_t *icall)
586
{
723
{
587
    /* Accept connection */
724
    /* Accept connection */
588
    ipc_answer_0(iid, EOK);
725
    ipc_answer_0(iid, EOK);
589
   
726
   
590
    devmap_driver_t *driver = NULL;
727
    devmap_driver_t *driver = NULL;
591
    devmap_driver_register(&driver);
728
    devmap_driver_register(&driver);
592
   
729
   
593
    if (NULL == driver)
730
    if (NULL == driver)
594
        return;
731
        return;
595
   
732
   
Line 599... Line 736...
599
        ipc_callid_t callid = async_get_call(&call);
736
        ipc_callid_t callid = async_get_call(&call);
600
       
737
       
601
        switch (IPC_GET_METHOD(call)) {
738
        switch (IPC_GET_METHOD(call)) {
602
        case IPC_M_PHONE_HUNGUP:
739
        case IPC_M_PHONE_HUNGUP:
603
            cont = false;
740
            cont = false;
604
            /* Exit thread */
-
 
605
            continue;
741
            continue;
606
        case DEVMAP_DRIVER_UNREGISTER:
742
        case DEVMAP_DRIVER_UNREGISTER:
607
            if (NULL == driver)
743
            if (NULL == driver)
608
                ipc_answer_0(callid, ENOENT);
744
                ipc_answer_0(callid, ENOENT);
609
            else
745
            else
Line 619... Line 755...
619
            break;
755
            break;
620
        case DEVMAP_DEVICE_GET_HANDLE:
756
        case DEVMAP_DEVICE_GET_HANDLE:
621
            devmap_get_handle(callid, &call);
757
            devmap_get_handle(callid, &call);
622
            break;
758
            break;
623
        case DEVMAP_DEVICE_GET_NAME:
759
        case DEVMAP_DEVICE_GET_NAME:
624
            devmap_get_handle(callid, &call);
760
            devmap_get_name(callid, &call);
625
            break;
761
            break;
626
        default:
762
        default:
627
            if (!(callid & IPC_CALLID_NOTIFICATION))
763
            if (!(callid & IPC_CALLID_NOTIFICATION))
628
                ipc_answer_0(callid, ENOENT);
764
                ipc_answer_0(callid, ENOENT);
629
        }
765
        }
630
    }
766
    }
631
   
767
   
632
    if (NULL != driver) {
768
    if (driver != NULL) {
633
        /*
769
        /*
634
         * Unregister the device driver and all its devices.
770
         * Unregister the device driver and all its devices.
635
         */
771
         */
636
        devmap_driver_unregister(driver);
772
        devmap_driver_unregister(driver);
637
        driver = NULL;
773
        driver = NULL;
Line 652... Line 788...
652
        ipc_callid_t callid = async_get_call(&call);
788
        ipc_callid_t callid = async_get_call(&call);
653
       
789
       
654
        switch (IPC_GET_METHOD(call)) {
790
        switch (IPC_GET_METHOD(call)) {
655
        case IPC_M_PHONE_HUNGUP:
791
        case IPC_M_PHONE_HUNGUP:
656
            cont = false;
792
            cont = false;
657
            /* Exit thread */
-
 
658
            continue;
793
            continue;
659
        case DEVMAP_DEVICE_GET_HANDLE:
794
        case DEVMAP_DEVICE_GET_HANDLE:
660
            devmap_get_handle(callid, &call);
795
            devmap_get_handle(callid, &call);
661
            break;
796
            break;
662
        case DEVMAP_DEVICE_GET_NAME:
797
        case DEVMAP_DEVICE_GET_NAME:
663
            /* TODO */
-
 
664
            devmap_get_name(callid, &call);
798
            devmap_get_name(callid, &call);
665
            break;
799
            break;
-
 
800
        case DEVMAP_DEVICE_NULL_CREATE:
-
 
801
            devmap_null_create(callid, &call);
-
 
802
            break;
-
 
803
        case DEVMAP_DEVICE_NULL_DESTROY:
-
 
804
            devmap_null_destroy(callid, &call);
-
 
805
            break;
-
 
806
        case DEVMAP_DEVICE_GET_COUNT:
-
 
807
            devmap_get_count(callid, &call);
-
 
808
            break;
-
 
809
        case DEVMAP_DEVICE_GET_DEVICES:
-
 
810
            devmap_get_devices(callid, &call);
-
 
811
            break;
666
        default:
812
        default:
667
            if (!(callid & IPC_CALLID_NOTIFICATION))
813
            if (!(callid & IPC_CALLID_NOTIFICATION))
668
                ipc_answer_0(callid, ENOENT);
814
                ipc_answer_0(callid, ENOENT);
669
        }
815
        }
670
    }
816
    }
Line 687... Line 833...
687
        /* Connect client to selected device */
833
        /* Connect client to selected device */
688
        devmap_forward(iid, icall);
834
        devmap_forward(iid, icall);
689
        break;
835
        break;
690
    default:
836
    default:
691
        /* No such interface */
837
        /* No such interface */
692
        ipc_answer_0(iid, ENOENT);
838
        ipc_answer_0(iid, ENOENT);
693
    }
839
    }
694
}
840
}
695
 
841
 
696
/**
842
/**
697
 *
843
 *
698
 */
844
 */
699
int main(int argc, char *argv[])
845
int main(int argc, char *argv[])
700
{
846
{
701
    printf(NAME ": HelenOS Device Mapper\n");
847
    printf(NAME ": HelenOS Device Mapper\n");
702
   
848
   
703
    if (devmap_init() != 0) {
849
    if (!devmap_init()) {
704
        printf(NAME ": Error while initializing service\n");
850
        printf(NAME ": Error while initializing service\n");
705
        return -1;
851
        return -1;
706
    }
852
    }
707
   
853
   
708
    /* Set a handler of incomming connections */
854
    /* Set a handler of incomming connections */