Subversion Repositories HelenOS

Rev

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

Rev 4419 Rev 4420
Line 46... Line 46...
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
 
50
 
-
 
51
/** Representation of device driver.
-
 
52
 *
-
 
53
 * Each driver is responsible for a set of devices.
-
 
54
 *
-
 
55
 */
-
 
56
typedef struct {
-
 
57
    /** Pointers to previous and next drivers in linked list */
-
 
58
    link_t drivers;
-
 
59
    /** Pointer to the linked list of devices controlled by this driver */
-
 
60
    link_t devices;
-
 
61
    /** Phone asociated with this driver */
-
 
62
    ipcarg_t phone;
-
 
63
    /** Device driver name */
-
 
64
    char *name;
-
 
65
    /** Futex for list of devices owned by this driver */
-
 
66
    atomic_t devices_futex;
-
 
67
} devmap_driver_t;
-
 
68
 
-
 
69
/** Info about registered device
-
 
70
 *
-
 
71
 */
-
 
72
typedef struct {
-
 
73
    /** Pointer to the previous and next device in the list of all devices */
-
 
74
    link_t devices;
-
 
75
    /** Pointer to the previous and next device in the list of devices
-
 
76
        owned by one driver */
-
 
77
    link_t driver_devices;
-
 
78
    /** Unique device identifier  */
-
 
79
    dev_handle_t handle;
-
 
80
    /** Device name */
-
 
81
    char *name;
-
 
82
    /** Device driver handling this device */
-
 
83
    devmap_driver_t *driver;
-
 
84
} devmap_device_t;
-
 
85
 
51
/** Pending lookup structure. */
86
/** Pending lookup structure. */
52
typedef struct {
87
typedef struct {
53
    link_t link;
88
    link_t link;
54
    char *name;              /**< Device name */
89
    char *name;              /**< Device name */
55
    ipc_callid_t callid;     /**< Call ID waiting for the lookup */
90
    ipc_callid_t callid;     /**< Call ID waiting for the lookup */
Line 68... Line 103...
68
 
103
 
69
static atomic_t devices_list_futex = FUTEX_INITIALIZER;
104
static atomic_t devices_list_futex = FUTEX_INITIALIZER;
70
static atomic_t drivers_list_futex = FUTEX_INITIALIZER;
105
static atomic_t drivers_list_futex = FUTEX_INITIALIZER;
71
static atomic_t create_handle_futex = FUTEX_INITIALIZER;
106
static atomic_t create_handle_futex = FUTEX_INITIALIZER;
72
 
107
 
-
 
108
static dev_handle_t last_handle = 0;
-
 
109
 
73
static int devmap_create_handle(void)
110
static dev_handle_t devmap_create_handle(void)
74
{
111
{
75
    static int last_handle = 0;
-
 
76
    int handle;
-
 
77
   
-
 
78
    /* TODO: allow reusing old handles after their unregistration
112
    /* TODO: allow reusing old handles after their unregistration
79
     * and implement some version of LRU algorithm
113
     * and implement some version of LRU algorithm
80
     */
114
     */
81
   
115
   
82
    /* FIXME: overflow */
116
    /* FIXME: overflow */
83
    futex_down(&create_handle_futex);
117
    futex_down(&create_handle_futex);
84
   
-
 
85
    last_handle += 1;
118
    last_handle++;
86
    handle = last_handle;
-
 
87
   
-
 
88
    futex_up(&create_handle_futex);
119
    futex_up(&create_handle_futex);
89
   
120
   
90
    return handle;
121
    return last_handle;
91
}
-
 
92
 
-
 
93
 
-
 
94
/** Initialize device mapper.
-
 
95
 *
-
 
96
 *
-
 
97
 */
-
 
98
static int devmap_init()
-
 
99
{
-
 
100
    /* TODO: */
-
 
101
   
-
 
102
    return EOK;
-
 
103
}
122
}
104
 
123
 
105
/** Find device with given name.
124
/** Find device with given name.
106
 *
125
 *
107
 */
126
 */
Line 127... Line 146...
127
/** Find device with given handle.
146
/** Find device with given handle.
128
 *
147
 *
129
 * @todo: use hash table
148
 * @todo: use hash table
130
 *
149
 *
131
 */
150
 */
132
static devmap_device_t *devmap_device_find_handle(int handle)
151
static devmap_device_t *devmap_device_find_handle(dev_handle_t handle)
133
{
152
{
134
    futex_down(&devices_list_futex);
153
    futex_down(&devices_list_futex);
135
   
154
   
136
    link_t *item = (&devices_list)->next;
155
    link_t *item = (&devices_list)->next;
137
    devmap_device_t *device = NULL;
156
    devmap_device_t *device = NULL;
Line 295... Line 314...
295
    if (driver == NULL)
314
    if (driver == NULL)
296
        return EEXISTS;
315
        return EEXISTS;
297
   
316
   
298
    futex_down(&drivers_list_futex);
317
    futex_down(&drivers_list_futex);
299
   
318
   
-
 
319
    if (driver->phone != 0)
300
    ipc_hangup(driver->phone);
320
        ipc_hangup(driver->phone);
301
   
321
   
302
    /* remove it from list of drivers */
322
    /* Remove it from list of drivers */
303
    list_remove(&(driver->drivers));
323
    list_remove(&(driver->drivers));
304
   
324
   
305
    /* unregister all its devices */
325
    /* Unregister all its devices */
306
   
-
 
307
    futex_down(&devices_list_futex);
326
    futex_down(&devices_list_futex);
308
    futex_down(&(driver->devices_futex));
327
    futex_down(&(driver->devices_futex));
309
   
328
   
310
    while (!list_empty(&(driver->devices))) {
329
    while (!list_empty(&(driver->devices))) {
311
        devmap_device_t *device = list_get_instance(driver->devices.next,
330
        devmap_device_t *device = list_get_instance(driver->devices.next,
Line 316... Line 335...
316
    futex_up(&(driver->devices_futex));
335
    futex_up(&(driver->devices_futex));
317
    futex_up(&devices_list_futex);
336
    futex_up(&devices_list_futex);
318
    futex_up(&drivers_list_futex);
337
    futex_up(&drivers_list_futex);
319
   
338
   
320
    /* free name and driver */
339
    /* free name and driver */
321
    if (NULL != driver->name)
340
    if (driver->name != NULL)
322
        free(driver->name);
341
        free(driver->name);
323
   
342
   
324
    free(driver);
343
    free(driver);
325
   
344
   
326
    return EOK;
345
    return EOK;
Line 452... Line 471...
452
static void devmap_forward(ipc_callid_t callid, ipc_call_t *call)
471
static void devmap_forward(ipc_callid_t callid, ipc_call_t *call)
453
{
472
{
454
    /*
473
    /*
455
     * Get handle from request
474
     * Get handle from request
456
     */
475
     */
457
    int handle = IPC_GET_ARG2(*call);
476
    dev_handle_t handle = IPC_GET_ARG2(*call);
458
    devmap_device_t *dev = devmap_device_find_handle(handle);
477
    devmap_device_t *dev = devmap_device_find_handle(handle);
459
   
478
   
460
    if (NULL == dev) {
479
    if ((dev == NULL) || (dev->driver == NULL) || (dev->driver->phone == 0)) {
461
        ipc_answer_0(callid, ENOENT);
480
        ipc_answer_0(callid, ENOENT);
462
        return;
481
        return;
463
    }
482
    }
464
   
483
   
465
    ipc_forward_fast(callid, dev->driver->phone, (ipcarg_t)(dev->handle),
484
    ipc_forward_fast(callid, dev->driver->phone, dev->handle,
466
        IPC_GET_ARG3(*call), 0, IPC_FF_NONE);
485
        IPC_GET_ARG3(*call), 0, IPC_FF_NONE);
467
}
486
}
468
 
487
 
469
/** Find handle for device instance identified by name.
488
/** Find handle for device instance identified by name.
470
 *
489
 *
Line 493... Line 512...
493
    }
512
    }
494
   
513
   
495
    /*
514
    /*
496
     * Allocate buffer for device name.
515
     * Allocate buffer for device name.
497
     */
516
     */
498
    char *name = (char *) malloc(size);
517
    char *name = (char *) malloc(size + 1);
499
    if (name == NULL) {
518
    if (name == NULL) {
500
        ipc_answer_0(callid, ENOMEM);
519
        ipc_answer_0(callid, ENOMEM);
501
        ipc_answer_0(iid, EREFUSED);
520
        ipc_answer_0(iid, EREFUSED);
502
        return;
521
        return;
503
    }
522
    }
Line 547... Line 566...
547
}
566
}
548
 
567
 
549
/** Find name of device identified by id and send it to caller.
568
/** Find name of device identified by id and send it to caller.
550
 *
569
 *
551
 */
570
 */
552
static void devmap_get_name(ipc_callid_t iid, ipc_call_t *icall)
571
static void devmap_get_name(ipc_callid_t iid, ipc_call_t *icall)
553
{
572
{
554
    const devmap_device_t *device = devmap_device_find_handle(IPC_GET_ARG1(*icall));
573
    const devmap_device_t *device = devmap_device_find_handle(IPC_GET_ARG1(*icall));
555
   
574
   
556
    /*
575
    /*
557
     * Device not found.
576
     * Device not found.
Line 577... Line 596...
577
     */
596
     */
578
   
597
   
579
    /* TODO: send name in response */
598
    /* TODO: send name in response */
580
}
599
}
581
 
600
 
-
 
601
static void devmap_get_count(ipc_callid_t iid, ipc_call_t *icall)
-
 
602
{
-
 
603
    futex_down(&devices_list_futex);
-
 
604
    ipc_answer_1(iid, EOK, list_count(&devices_list));
-
 
605
    futex_up(&devices_list_futex);
-
 
606
}
-
 
607
 
-
 
608
static void devmap_get_devices(ipc_callid_t iid, ipc_call_t *icall)
-
 
609
{
-
 
610
    futex_down(&devices_list_futex);
-
 
611
   
-
 
612
    ipc_callid_t callid;
-
 
613
    size_t size;
-
 
614
    if (!ipc_data_read_receive(&callid, &size)) {
-
 
615
        ipc_answer_0(callid, EREFUSED);
-
 
616
        ipc_answer_0(iid, EREFUSED);
-
 
617
        return;
-
 
618
    }
-
 
619
   
-
 
620
    if ((size % sizeof(dev_desc_t)) != 0) {
-
 
621
        ipc_answer_0(callid, EINVAL);
-
 
622
        ipc_answer_0(iid, EREFUSED);
-
 
623
        return;
-
 
624
    }
-
 
625
   
-
 
626
    count_t count = size / sizeof(dev_desc_t);
-
 
627
    dev_desc_t *desc = (dev_desc_t *) malloc(size);
-
 
628
    if (desc == NULL) {
-
 
629
        ipc_answer_0(callid, ENOMEM);
-
 
630
        ipc_answer_0(iid, EREFUSED);
-
 
631
        return;
-
 
632
    }
-
 
633
   
-
 
634
    count_t pos = 0;
-
 
635
    link_t *item = devices_list.next;
-
 
636
   
-
 
637
    while ((item != &devices_list) && (pos < count)) {
-
 
638
        devmap_device_t *device = list_get_instance(item, devmap_device_t, devices);
-
 
639
       
-
 
640
        desc[pos].handle = device->handle;
-
 
641
        str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, device->name);
-
 
642
        pos++;
-
 
643
        item = item->next;
-
 
644
    }
-
 
645
   
-
 
646
    ipcarg_t retval = ipc_data_read_finalize(callid, desc, pos * sizeof(dev_desc_t));
-
 
647
    if (retval != EOK) {
-
 
648
        ipc_answer_0(iid, EREFUSED);
-
 
649
        free(desc);
-
 
650
        return;
-
 
651
    }
-
 
652
   
-
 
653
    free(desc);
-
 
654
   
-
 
655
    futex_up(&devices_list_futex);
-
 
656
   
-
 
657
    ipc_answer_1(iid, EOK, pos);
-
 
658
}
-
 
659
 
-
 
660
/** Initialize device mapper.
-
 
661
 *
-
 
662
 *
-
 
663
 */
-
 
664
static bool devmap_init()
-
 
665
{
-
 
666
    /* Create NULL device entry */
-
 
667
    devmap_device_t *device = (devmap_device_t *) malloc(sizeof(devmap_device_t));
-
 
668
    if (device == NULL)
-
 
669
        return false;
-
 
670
   
-
 
671
    device->name = str_dup("null");
-
 
672
    if (device->name == NULL) {
-
 
673
        free(device);
-
 
674
        return false;
-
 
675
    }
-
 
676
   
-
 
677
    list_initialize(&(device->devices));
-
 
678
    list_initialize(&(device->driver_devices));
-
 
679
   
-
 
680
    futex_down(&devices_list_futex);
-
 
681
   
-
 
682
    /* Get unique device handle */
-
 
683
    device->handle = devmap_create_handle();
-
 
684
    device->driver = NULL;
-
 
685
   
-
 
686
    /* Insert device into list of all devices  */
-
 
687
    list_append(&device->devices, &devices_list);
-
 
688
   
-
 
689
    futex_up(&devices_list_futex);
-
 
690
   
-
 
691
    return true;
-
 
692
}
-
 
693
 
582
/** Handle connection with device driver.
694
/** Handle connection with device driver.
583
 *
695
 *
584
 */
696
 */
585
static void devmap_connection_driver(ipc_callid_t iid, ipc_call_t *icall)
697
static void devmap_connection_driver(ipc_callid_t iid, ipc_call_t *icall)
586
{
698
{
Line 619... Line 731...
619
            break;
731
            break;
620
        case DEVMAP_DEVICE_GET_HANDLE:
732
        case DEVMAP_DEVICE_GET_HANDLE:
621
            devmap_get_handle(callid, &call);
733
            devmap_get_handle(callid, &call);
622
            break;
734
            break;
623
        case DEVMAP_DEVICE_GET_NAME:
735
        case DEVMAP_DEVICE_GET_NAME:
624
            devmap_get_handle(callid, &call);
736
            devmap_get_name(callid, &call);
625
            break;
737
            break;
626
        default:
738
        default:
627
            if (!(callid & IPC_CALLID_NOTIFICATION))
739
            if (!(callid & IPC_CALLID_NOTIFICATION))
628
                ipc_answer_0(callid, ENOENT);
740
                ipc_answer_0(callid, ENOENT);
629
        }
741
        }
Line 658... Line 770...
658
            continue;
770
            continue;
659
        case DEVMAP_DEVICE_GET_HANDLE:
771
        case DEVMAP_DEVICE_GET_HANDLE:
660
            devmap_get_handle(callid, &call);
772
            devmap_get_handle(callid, &call);
661
            break;
773
            break;
662
        case DEVMAP_DEVICE_GET_NAME:
774
        case DEVMAP_DEVICE_GET_NAME:
663
            /* TODO */
-
 
664
            devmap_get_name(callid, &call);
775
            devmap_get_name(callid, &call);
665
            break;
776
            break;
-
 
777
        case DEVMAP_DEVICE_GET_COUNT:
-
 
778
            devmap_get_count(callid, &call);
-
 
779
            break;
-
 
780
        case DEVMAP_DEVICE_GET_DEVICES:
-
 
781
            devmap_get_devices(callid, &call);
-
 
782
            break;
666
        default:
783
        default:
667
            if (!(callid & IPC_CALLID_NOTIFICATION))
784
            if (!(callid & IPC_CALLID_NOTIFICATION))
668
                ipc_answer_0(callid, ENOENT);
785
                ipc_answer_0(callid, ENOENT);
669
        }
786
        }
670
    }
787
    }
Line 698... Line 815...
698
 */
815
 */
699
int main(int argc, char *argv[])
816
int main(int argc, char *argv[])
700
{
817
{
701
    printf(NAME ": HelenOS Device Mapper\n");
818
    printf(NAME ": HelenOS Device Mapper\n");
702
   
819
   
703
    if (devmap_init() != 0) {
820
    if (!devmap_init()) {
704
        printf(NAME ": Error while initializing service\n");
821
        printf(NAME ": Error while initializing service\n");
705
        return -1;
822
        return -1;
706
    }
823
    }
707
   
824
   
708
    /* Set a handler of incomming connections */
825
    /* Set a handler of incomming connections */