Subversion Repositories HelenOS

Rev

Rev 4458 | Rev 4540 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4458 Rev 4524
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 <fibril_sync.h>
44
#include <stdlib.h>
45
#include <stdlib.h>
45
#include <string.h>
46
#include <string.h>
46
#include <ipc/devmap.h>
47
#include <ipc/devmap.h>
47
 
48
 
48
#define NAME  "devmap"
49
#define NAME  "devmap"
Line 59... Line 60...
59
    link_t devices;
60
    link_t devices;
60
    /** Phone asociated with this driver */
61
    /** Phone asociated with this driver */
61
    ipcarg_t phone;
62
    ipcarg_t phone;
62
    /** Device driver name */
63
    /** Device driver name */
63
    char *name;
64
    char *name;
-
 
65
    /** Fibril mutex for list of devices owned by this driver */
-
 
66
    fibril_mutex_t devices_mutex;
64
} devmap_driver_t;
67
} devmap_driver_t;
65
 
68
 
66
/** Info about registered device
69
/** Info about registered device
67
 *
70
 *
68
 */
71
 */
Line 89... Line 92...
89
 
92
 
90
LIST_INITIALIZE(devices_list);
93
LIST_INITIALIZE(devices_list);
91
LIST_INITIALIZE(drivers_list);
94
LIST_INITIALIZE(drivers_list);
92
LIST_INITIALIZE(pending_req);
95
LIST_INITIALIZE(pending_req);
93
 
96
 
-
 
97
/* Locking order:
-
 
98
 *  drivers_list_mutex
-
 
99
 *  devices_list_mutex
-
 
100
 *  (devmap_driver_t *)->devices_mutex
-
 
101
 *  create_handle_mutex
-
 
102
 **/
-
 
103
 
-
 
104
static FIBRIL_MUTEX_INITIALIZE(devices_list_mutex);
-
 
105
static FIBRIL_MUTEX_INITIALIZE(drivers_list_mutex);
-
 
106
static FIBRIL_MUTEX_INITIALIZE(create_handle_mutex);
-
 
107
 
94
static dev_handle_t last_handle = 0;
108
static dev_handle_t last_handle = 0;
95
 
109
 
96
static dev_handle_t devmap_create_handle(void)
110
static dev_handle_t devmap_create_handle(void)
97
{
111
{
98
    /* TODO: allow reusing old handles after their unregistration
112
    /* TODO: allow reusing old handles after their unregistration
99
     * and implement some version of LRU algorithm, avoid overflow
113
     * and implement some version of LRU algorithm, avoid overflow
100
     */
114
     */
101
   
115
   
-
 
116
    fibril_mutex_lock(&create_handle_mutex);
102
    last_handle++;
117
    last_handle++;
-
 
118
    fibril_mutex_unlock(&create_handle_mutex);
103
   
119
   
104
    return last_handle;
120
    return last_handle;
105
}
121
}
106
 
122
 
107
/** Find device with given name.
123
/** Find device with given name.
Line 131... Line 147...
131
 * @todo: use hash table
147
 * @todo: use hash table
132
 *
148
 *
133
 */
149
 */
134
static devmap_device_t *devmap_device_find_handle(dev_handle_t handle)
150
static devmap_device_t *devmap_device_find_handle(dev_handle_t handle)
135
{
151
{
-
 
152
    fibril_mutex_lock(&devices_list_mutex);
-
 
153
   
136
    link_t *item = (&devices_list)->next;
154
    link_t *item = (&devices_list)->next;
137
    devmap_device_t *device = NULL;
155
    devmap_device_t *device = NULL;
138
   
156
   
139
    while (item != &devices_list) {
157
    while (item != &devices_list) {
140
        device = list_get_instance(item, devmap_device_t, devices);
158
        device = list_get_instance(item, devmap_device_t, devices);
141
        if (device->handle == handle)
159
        if (device->handle == handle)
142
            break;
160
            break;
143
        item = item->next;
161
        item = item->next;
144
    }
162
    }
145
   
163
   
146
    if (item == &devices_list)
164
    if (item == &devices_list) {
-
 
165
        fibril_mutex_unlock(&devices_list_mutex);
147
        return NULL;
166
        return NULL;
-
 
167
    }
148
   
168
   
149
    device = list_get_instance(item, devmap_device_t, devices);
169
    device = list_get_instance(item, devmap_device_t, devices);
150
   
170
   
-
 
171
    fibril_mutex_unlock(&devices_list_mutex);
-
 
172
   
151
    return device;
173
    return device;
152
}
174
}
153
 
175
 
154
/**
176
/**
155
 *
177
 *
Line 233... Line 255...
233
        return;
255
        return;
234
    }
256
    }
235
   
257
   
236
    driver->name[name_size] = 0;
258
    driver->name[name_size] = 0;
237
   
259
   
-
 
260
    /* Initialize mutex for list of devices owned by this driver */
-
 
261
    fibril_mutex_initialize(&driver->devices_mutex);
-
 
262
   
238
    /*
263
    /*
239
     * Initialize list of asociated devices
264
     * Initialize list of asociated devices
240
     */
265
     */
241
    list_initialize(&(driver->devices));
266
    list_initialize(&driver->devices);
242
   
267
   
243
    /*
268
    /*
244
     * Create connection to the driver
269
     * Create connection to the driver
245
     */
270
     */
246
    ipc_call_t call;
271
    ipc_call_t call;
Line 259... Line 284...
259
   
284
   
260
    ipc_answer_0(callid, EOK);
285
    ipc_answer_0(callid, EOK);
261
   
286
   
262
    list_initialize(&(driver->drivers));
287
    list_initialize(&(driver->drivers));
263
   
288
   
-
 
289
    fibril_mutex_lock(&drivers_list_mutex);
-
 
290
   
264
    /* TODO:
291
    /* TODO:
265
     * check that no driver with name equal to driver->name is registered
292
     * check that no driver with name equal to driver->name is registered
266
     */
293
     */
267
   
294
   
268
    /*
295
    /*
269
     * Insert new driver into list of registered drivers
296
     * Insert new driver into list of registered drivers
270
     */
297
     */
271
    list_append(&(driver->drivers), &drivers_list);
298
    list_append(&(driver->drivers), &drivers_list);
-
 
299
    fibril_mutex_unlock(&drivers_list_mutex);
272
   
300
   
273
    ipc_answer_0(iid, EOK);
301
    ipc_answer_0(iid, EOK);
274
   
302
   
275
    *odriver = driver;
303
    *odriver = driver;
276
}
304
}
Line 283... Line 311...
283
static int devmap_driver_unregister(devmap_driver_t *driver)
311
static int devmap_driver_unregister(devmap_driver_t *driver)
284
{
312
{
285
    if (driver == NULL)
313
    if (driver == NULL)
286
        return EEXISTS;
314
        return EEXISTS;
287
   
315
   
-
 
316
    fibril_mutex_lock(&drivers_list_mutex);
-
 
317
   
288
    if (driver->phone != 0)
318
    if (driver->phone != 0)
289
        ipc_hangup(driver->phone);
319
        ipc_hangup(driver->phone);
290
   
320
   
291
    /* Remove it from list of drivers */
321
    /* Remove it from list of drivers */
292
    list_remove(&(driver->drivers));
322
    list_remove(&(driver->drivers));
293
   
323
   
-
 
324
    /* Unregister all its devices */
-
 
325
    fibril_mutex_lock(&devices_list_mutex);
-
 
326
    fibril_mutex_lock(&driver->devices_mutex);
-
 
327
   
294
    while (!list_empty(&(driver->devices))) {
328
    while (!list_empty(&(driver->devices))) {
295
        devmap_device_t *device = list_get_instance(driver->devices.next,
329
        devmap_device_t *device = list_get_instance(driver->devices.next,
296
            devmap_device_t, driver_devices);
330
            devmap_device_t, driver_devices);
297
        devmap_device_unregister_core(device);
331
        devmap_device_unregister_core(device);
298
    }
332
    }
299
   
333
   
-
 
334
    fibril_mutex_unlock(&driver->devices_mutex);
-
 
335
    fibril_mutex_unlock(&devices_list_mutex);
-
 
336
    fibril_mutex_unlock(&drivers_list_mutex);
-
 
337
   
300
    /* free name and driver */
338
    /* free name and driver */
301
    if (driver->name != NULL)
339
    if (driver->name != NULL)
302
        free(driver->name);
340
        free(driver->name);
303
   
341
   
304
    free(driver);
342
    free(driver);
Line 308... Line 346...
308
 
346
 
309
 
347
 
310
/** Process pending lookup requests */
348
/** Process pending lookup requests */
311
static void process_pending_lookup(void)
349
static void process_pending_lookup(void)
312
{
350
{
313
    async_serialize_start();
-
 
314
   
-
 
315
    link_t *cur;
351
    link_t *cur;
316
   
352
   
317
loop:
353
loop:
318
    for (cur = pending_req.next; cur != &pending_req; cur = cur->next) {
354
    for (cur = pending_req.next; cur != &pending_req; cur = cur->next) {
319
        pending_req_t *pr = list_get_instance(cur, pending_req_t, link);
355
        pending_req_t *pr = list_get_instance(cur, pending_req_t, link);
Line 328... Line 364...
328
        list_remove(cur);
364
        list_remove(cur);
329
        free(pr);
365
        free(pr);
330
       
366
       
331
        goto loop;
367
        goto loop;
332
    }
368
    }
333
   
-
 
334
    async_serialize_end();
-
 
335
}
369
}
336
 
370
 
337
 
371
 
338
/** Register instance of device
372
/** Register instance of device
339
 *
373
 *
Line 383... Line 417...
383
    device->name[size] = 0;
417
    device->name[size] = 0;
384
   
418
   
385
    list_initialize(&(device->devices));
419
    list_initialize(&(device->devices));
386
    list_initialize(&(device->driver_devices));
420
    list_initialize(&(device->driver_devices));
387
   
421
   
-
 
422
    fibril_mutex_lock(&devices_list_mutex);
-
 
423
   
388
    /* Check that device with such name is not already registered */
424
    /* Check that device with such name is not already registered */
389
    if (NULL != devmap_device_find_name(device->name)) {
425
    if (NULL != devmap_device_find_name(device->name)) {
390
        printf(NAME ": Device '%s' already registered\n", device->name);
426
        printf(NAME ": Device '%s' already registered\n", device->name);
-
 
427
        fibril_mutex_unlock(&devices_list_mutex);
391
        free(device->name);
428
        free(device->name);
392
        free(device);
429
        free(device);
393
        ipc_answer_0(iid, EEXISTS);
430
        ipc_answer_0(iid, EEXISTS);
394
        return;
431
        return;
395
    }
432
    }
Line 400... Line 437...
400
    device->driver = driver;
437
    device->driver = driver;
401
   
438
   
402
    /* Insert device into list of all devices  */
439
    /* Insert device into list of all devices  */
403
    list_append(&device->devices, &devices_list);
440
    list_append(&device->devices, &devices_list);
404
   
441
   
-
 
442
    /* Insert device into list of devices that belog to one driver */
-
 
443
    fibril_mutex_lock(&device->driver->devices_mutex);
-
 
444
   
405
    list_append(&device->driver_devices, &device->driver->devices);
445
    list_append(&device->driver_devices, &device->driver->devices);
406
   
446
   
-
 
447
    fibril_mutex_unlock(&device->driver->devices_mutex);
-
 
448
    fibril_mutex_unlock(&devices_list_mutex);
-
 
449
   
407
    ipc_answer_1(iid, EOK, device->handle);
450
    ipc_answer_1(iid, EOK, device->handle);
408
}
451
}
409
 
452
 
410
/**
453
/**
411
 *
454
 *
Line 553... Line 596...
553
    /* TODO: send name in response */
596
    /* TODO: send name in response */
554
}
597
}
555
 
598
 
556
static void devmap_get_count(ipc_callid_t iid, ipc_call_t *icall)
599
static void devmap_get_count(ipc_callid_t iid, ipc_call_t *icall)
557
{
600
{
-
 
601
    fibril_mutex_lock(&devices_list_mutex);
558
    ipc_answer_1(iid, EOK, list_count(&devices_list));
602
    ipc_answer_1(iid, EOK, list_count(&devices_list));
-
 
603
    fibril_mutex_unlock(&devices_list_mutex);
559
}
604
}
560
 
605
 
561
static void devmap_get_devices(ipc_callid_t iid, ipc_call_t *icall)
606
static void devmap_get_devices(ipc_callid_t iid, ipc_call_t *icall)
562
{
607
{
-
 
608
    fibril_mutex_lock(&devices_list_mutex);
-
 
609
   
563
    ipc_callid_t callid;
610
    ipc_callid_t callid;
564
    size_t size;
611
    size_t size;
565
    if (!ipc_data_read_receive(&callid, &size)) {
612
    if (!ipc_data_read_receive(&callid, &size)) {
566
        ipc_answer_0(callid, EREFUSED);
613
        ipc_answer_0(callid, EREFUSED);
567
        ipc_answer_0(iid, EREFUSED);
614
        ipc_answer_0(iid, EREFUSED);
Line 601... Line 648...
601
        return;
648
        return;
602
    }
649
    }
603
   
650
   
604
    free(desc);
651
    free(desc);
605
   
652
   
-
 
653
    fibril_mutex_unlock(&devices_list_mutex);
-
 
654
   
606
    ipc_answer_1(iid, EOK, pos);
655
    ipc_answer_1(iid, EOK, pos);
607
}
656
}
608
 
657
 
609
/** Initialize device mapper.
658
/** Initialize device mapper.
610
 *
659
 *
Line 624... Line 673...
624
    }
673
    }
625
   
674
   
626
    list_initialize(&(device->devices));
675
    list_initialize(&(device->devices));
627
    list_initialize(&(device->driver_devices));
676
    list_initialize(&(device->driver_devices));
628
   
677
   
-
 
678
    fibril_mutex_lock(&devices_list_mutex);
-
 
679
   
629
    /* Get unique device handle */
680
    /* Get unique device handle */
630
    device->handle = devmap_create_handle();
681
    device->handle = devmap_create_handle();
631
    device->driver = NULL;
682
    device->driver = NULL;
632
   
683
   
633
    /* Insert device into list of all devices  */
684
    /* Insert device into list of all devices  */
634
    list_append(&device->devices, &devices_list);
685
    list_append(&device->devices, &devices_list);
635
   
686
   
-
 
687
    fibril_mutex_unlock(&devices_list_mutex);
-
 
688
   
636
    return true;
689
    return true;
637
}
690
}
638
 
691
 
639
/** Handle connection with device driver.
692
/** Handle connection with device driver.
640
 *
693
 *
Line 653... Line 706...
653
    bool cont = true;
706
    bool cont = true;
654
    while (cont) {
707
    while (cont) {
655
        ipc_call_t call;
708
        ipc_call_t call;
656
        ipc_callid_t callid = async_get_call(&call);
709
        ipc_callid_t callid = async_get_call(&call);
657
       
710
       
658
        async_serialize_start();
-
 
659
       
-
 
660
        switch (IPC_GET_METHOD(call)) {
711
        switch (IPC_GET_METHOD(call)) {
661
        case IPC_M_PHONE_HUNGUP:
712
        case IPC_M_PHONE_HUNGUP:
662
            cont = false;
713
            cont = false;
663
            async_serialize_end();
-
 
664
            continue;
714
            continue;
665
        case DEVMAP_DRIVER_UNREGISTER:
715
        case DEVMAP_DRIVER_UNREGISTER:
666
            if (NULL == driver)
716
            if (NULL == driver)
667
                ipc_answer_0(callid, ENOENT);
717
                ipc_answer_0(callid, ENOENT);
668
            else
718
            else
Line 684... Line 734...
684
            break;
734
            break;
685
        default:
735
        default:
686
            if (!(callid & IPC_CALLID_NOTIFICATION))
736
            if (!(callid & IPC_CALLID_NOTIFICATION))
687
                ipc_answer_0(callid, ENOENT);
737
                ipc_answer_0(callid, ENOENT);
688
        }
738
        }
689
       
-
 
690
        async_serialize_end();
-
 
691
    }
739
    }
692
   
740
   
693
    if (NULL != driver) {
741
    if (NULL != driver) {
694
        /*
742
        /*
695
         * Unregister the device driver and all its devices.
743
         * Unregister the device driver and all its devices.
696
         */
744
         */
697
       
-
 
698
        async_serialize_start();
-
 
699
       
-
 
700
        devmap_driver_unregister(driver);
745
        devmap_driver_unregister(driver);
701
        driver = NULL;
746
        driver = NULL;
702
       
-
 
703
        async_serialize_end();
-
 
704
    }
747
    }
705
}
748
}
706
 
749
 
707
/** Handle connection with device client.
750
/** Handle connection with device client.
708
 *
751
 *
Line 715... Line 758...
715
    bool cont = true;
758
    bool cont = true;
716
    while (cont) {
759
    while (cont) {
717
        ipc_call_t call;
760
        ipc_call_t call;
718
        ipc_callid_t callid = async_get_call(&call);
761
        ipc_callid_t callid = async_get_call(&call);
719
       
762
       
720
        async_serialize_start();
-
 
721
       
-
 
722
        switch (IPC_GET_METHOD(call)) {
763
        switch (IPC_GET_METHOD(call)) {
723
        case IPC_M_PHONE_HUNGUP:
764
        case IPC_M_PHONE_HUNGUP:
724
            cont = false;
765
            cont = false;
725
            async_serialize_end();
-
 
726
            continue;
766
            continue;
727
        case DEVMAP_DEVICE_GET_HANDLE:
767
        case DEVMAP_DEVICE_GET_HANDLE:
728
            devmap_get_handle(callid, &call);
768
            devmap_get_handle(callid, &call);
729
            break;
769
            break;
730
        case DEVMAP_DEVICE_GET_NAME:
770
        case DEVMAP_DEVICE_GET_NAME:
Line 738... Line 778...
738
            break;
778
            break;
739
        default:
779
        default:
740
            if (!(callid & IPC_CALLID_NOTIFICATION))
780
            if (!(callid & IPC_CALLID_NOTIFICATION))
741
                ipc_answer_0(callid, ENOENT);
781
                ipc_answer_0(callid, ENOENT);
742
        }
782
        }
743
       
-
 
744
        async_serialize_end();
-
 
745
    }
783
    }
746
}
784
}
747
 
785
 
748
/** Function for handling connections to devmap
786
/** Function for handling connections to devmap
749
 *
787
 *