Subversion Repositories HelenOS

Rev

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

Rev 2678 Rev 3080
Line 42... Line 42...
42
#include <errno.h>
42
#include <errno.h>
43
#include <bool.h>
43
#include <bool.h>
44
#include <futex.h>
44
#include <futex.h>
45
#include <stdlib.h>
45
#include <stdlib.h>
46
#include <string.h>
46
#include <string.h>
-
 
47
#include <ipc/devmap.h>
47
 
48
 
48
#include "devmap.h"
49
#define NAME "devmap"
49
 
50
 
50
 
51
 
51
LIST_INITIALIZE(devices_list);
52
LIST_INITIALIZE(devices_list);
52
LIST_INITIALIZE(drivers_list);
53
LIST_INITIALIZE(drivers_list);
53
 
54
 
Line 110... Line 111...
110
            break;
111
            break;
111
        }
112
        }
112
        item = item->next;
113
        item = item->next;
113
    }
114
    }
114
 
115
 
115
    if (item == &devices_list) {
116
    if (item == &devices_list)
116
        printf("DEVMAP: no device named %s.\n", name);
-
 
117
        return NULL;
117
        return NULL;
118
    }
-
 
119
 
118
 
120
    device = list_get_instance(item, devmap_device_t, devices);
119
    device = list_get_instance(item, devmap_device_t, devices);
121
    return device;
120
    return device;
122
}
121
}
123
 
122
 
Line 201... Line 200...
201
 
200
 
202
    /*
201
    /*
203
     * Get driver name
202
     * Get driver name
204
     */
203
     */
205
    if (!ipc_data_write_receive(&callid, &name_size)) {
204
    if (!ipc_data_write_receive(&callid, &name_size)) {
206
        printf("Unexpected request.\n");
-
 
207
        free(driver);
205
        free(driver);
208
        ipc_answer_0(callid, EREFUSED);
206
        ipc_answer_0(callid, EREFUSED);
209
        ipc_answer_0(iid, EREFUSED);
207
        ipc_answer_0(iid, EREFUSED);
210
        return;
208
        return;
211
    }
209
    }
212
 
210
 
213
    if (name_size > DEVMAP_NAME_MAXLEN) {
211
    if (name_size > DEVMAP_NAME_MAXLEN) {
214
        printf("Too logn name: %u: maximum is %u.\n", name_size,
-
 
215
            DEVMAP_NAME_MAXLEN);
-
 
216
        free(driver);
212
        free(driver);
217
        ipc_answer_0(callid, EINVAL);
213
        ipc_answer_0(callid, EINVAL);
218
        ipc_answer_0(iid, EREFUSED);
214
        ipc_answer_0(iid, EREFUSED);
219
        return;
215
        return;
220
    }
216
    }
221
 
217
 
222
    /*
218
    /*
223
     * Allocate buffer for device name.
219
     * Allocate buffer for device name.
224
     */
220
     */
225
    if (NULL == (driver->name = (char *)malloc(name_size + 1))) {
221
    if (NULL == (driver->name = (char *)malloc(name_size + 1))) {
226
        printf("Cannot allocate space for driver name.\n");
-
 
227
        free(driver);
222
        free(driver);
228
        ipc_answer_0(callid, ENOMEM);
223
        ipc_answer_0(callid, ENOMEM);
229
        ipc_answer_0(iid, EREFUSED);
224
        ipc_answer_0(iid, EREFUSED);
230
        return;
225
        return;
231
    }  
226
    }  
232
 
227
 
233
    /*
228
    /*
234
     * Send confirmation to sender and get data into buffer.
229
     * Send confirmation to sender and get data into buffer.
235
     */
230
     */
236
    if (EOK != ipc_data_write_finalize(callid, driver->name, name_size)) {
231
    if (EOK != ipc_data_write_finalize(callid, driver->name, name_size)) {
237
        printf("Cannot read driver name.\n");
-
 
238
        free(driver->name);
232
        free(driver->name);
239
        free(driver);
233
        free(driver);
240
        ipc_answer_0(iid, EREFUSED);
234
        ipc_answer_0(iid, EREFUSED);
241
        return;
235
        return;
242
    }
236
    }
243
 
237
 
244
    driver->name[name_size] = 0;
238
    driver->name[name_size] = 0;
245
 
239
 
246
    printf("Read driver name: '%s'.\n", driver->name);
-
 
247
 
-
 
248
    /* Initialize futex for list of devices owned by this driver */
240
    /* Initialize futex for list of devices owned by this driver */
249
    futex_initialize(&(driver->devices_futex), 1);
241
    futex_initialize(&(driver->devices_futex), 1);
250
 
242
 
251
    /*
243
    /*
252
     * Initialize list of asociated devices
244
     * Initialize list of asociated devices
Line 257... Line 249...
257
     * Create connection to the driver
249
     * Create connection to the driver
258
     */
250
     */
259
    callid = async_get_call(&call);
251
    callid = async_get_call(&call);
260
 
252
 
261
    if (IPC_M_CONNECT_TO_ME != IPC_GET_METHOD(call)) {
253
    if (IPC_M_CONNECT_TO_ME != IPC_GET_METHOD(call)) {
262
        printf("DEVMAP: Unexpected method: %u.\n",
-
 
263
            IPC_GET_METHOD(call));
-
 
264
        ipc_answer_0(callid, ENOTSUP);
254
        ipc_answer_0(callid, ENOTSUP);
265
       
255
       
266
        free(driver->name);
256
        free(driver->name);
267
        free(driver);
257
        free(driver);
268
        ipc_answer_0(iid, ENOTSUP);
258
        ipc_answer_0(iid, ENOTSUP);
Line 286... Line 276...
286
     */
276
     */
287
    list_append(&(driver->drivers), &drivers_list);
277
    list_append(&(driver->drivers), &drivers_list);
288
    futex_up(&drivers_list_futex); 
278
    futex_up(&drivers_list_futex); 
289
   
279
   
290
    ipc_answer_0(iid, EOK);
280
    ipc_answer_0(iid, EOK);
291
    printf("Driver registered.\n");
-
 
292
 
281
 
293
    *odriver = driver;
282
    *odriver = driver;
294
    return;
-
 
295
}
283
}
296
 
284
 
297
/** Unregister device driver, unregister all its devices and free driver
285
/** Unregister device driver, unregister all its devices and free driver
298
 * structure.
286
 * structure.
299
 */
287
 */
300
static int devmap_driver_unregister(devmap_driver_t *driver)
288
static int devmap_driver_unregister(devmap_driver_t *driver)
301
{
289
{
302
    devmap_device_t *device;
290
    devmap_device_t *device;
303
 
291
 
304
    if (NULL == driver) {
292
    if (NULL == driver)
305
        printf("Error: driver == NULL.\n");
-
 
306
        return EEXISTS;
293
        return EEXISTS;
307
    }
294
   
308
 
-
 
309
    printf("Unregister driver '%s'.\n", driver->name);
-
 
310
    futex_down(&drivers_list_futex);   
295
    futex_down(&drivers_list_futex);   
311
 
296
 
312
    ipc_hangup(driver->phone);
297
    ipc_hangup(driver->phone);
313
   
298
   
314
    /* remove it from list of drivers */
299
    /* remove it from list of drivers */
Line 320... Line 305...
320
    futex_down(&(driver->devices_futex));
305
    futex_down(&(driver->devices_futex));
321
 
306
 
322
    while (!list_empty(&(driver->devices))) {
307
    while (!list_empty(&(driver->devices))) {
323
        device = list_get_instance(driver->devices.next,
308
        device = list_get_instance(driver->devices.next,
324
            devmap_device_t, driver_devices);
309
            devmap_device_t, driver_devices);
325
        printf("Unregister device '%s'.\n", device->name);
-
 
326
        devmap_device_unregister_core(device);
310
        devmap_device_unregister_core(device);
327
    }
311
    }
328
   
312
   
329
    futex_up(&(driver->devices_futex));
313
    futex_up(&(driver->devices_futex));
330
    futex_up(&devices_list_futex); 
314
    futex_up(&devices_list_futex); 
Line 335... Line 319...
335
        free(driver->name);
319
        free(driver->name);
336
    }
320
    }
337
 
321
 
338
    free(driver);
322
    free(driver);
339
 
323
 
340
    printf("Driver unregistered.\n");
-
 
341
 
-
 
342
    return EOK;
324
    return EOK;
343
}
325
}
344
 
326
 
345
 
327
 
346
/** Register instance of device
328
/** Register instance of device
Line 352... Line 334...
352
    ipc_callid_t callid;
334
    ipc_callid_t callid;
353
    size_t size;
335
    size_t size;
354
    devmap_device_t *device;
336
    devmap_device_t *device;
355
 
337
 
356
    if (NULL == driver) {
338
    if (NULL == driver) {
357
        printf("Invalid driver registration.\n");
-
 
358
        ipc_answer_0(iid, EREFUSED);
339
        ipc_answer_0(iid, EREFUSED);
359
        return;
340
        return;
360
    }
341
    }
361
   
342
   
362
    /* Create new device entry */
343
    /* Create new device entry */
363
    if (NULL ==
344
    if (NULL ==
364
        (device = (devmap_device_t *)malloc(sizeof(devmap_device_t)))) {
345
        (device = (devmap_device_t *) malloc(sizeof(devmap_device_t)))) {
365
        printf("Cannot allocate new device.\n");
-
 
366
        ipc_answer_0(iid, ENOMEM);
346
        ipc_answer_0(iid, ENOMEM);
367
        return;
347
        return;
368
    }
348
    }
369
   
349
   
370
    /* Get device name */
350
    /* Get device name */
371
    if (!ipc_data_write_receive(&callid, &size)) {
351
    if (!ipc_data_write_receive(&callid, &size)) {
372
        free(device);
352
        free(device);
373
        printf("Cannot read device name.\n");
-
 
374
        ipc_answer_0(iid, EREFUSED);
353
        ipc_answer_0(iid, EREFUSED);
375
        return;
354
        return;
376
    }
355
    }
377
 
356
 
378
    if (size > DEVMAP_NAME_MAXLEN) {
357
    if (size > DEVMAP_NAME_MAXLEN) {
379
        printf("Too long device name: %u.\n", size);
-
 
380
        free(device);
358
        free(device);
381
        ipc_answer_0(callid, EINVAL);
359
        ipc_answer_0(callid, EINVAL);
382
        ipc_answer_0(iid, EREFUSED);
360
        ipc_answer_0(iid, EREFUSED);
383
        return;
361
        return;
384
    }
362
    }
385
 
363
   
386
        /* +1 for terminating \0 */
364
    /* +1 for terminating \0 */
387
    device->name = (char *)malloc(size + 1);
365
    device->name = (char *) malloc(size + 1);
388
 
366
 
389
    if (NULL == device->name) {
367
    if (NULL == device->name) {
390
        printf("Cannot read device name.\n");
-
 
391
        free(device);
368
        free(device);
392
        ipc_answer_0(callid, ENOMEM);
369
        ipc_answer_0(callid, ENOMEM);
393
        ipc_answer_0(iid, EREFUSED);
370
        ipc_answer_0(iid, EREFUSED);
394
        return;
371
        return;
395
    }
372
    }
Line 402... Line 379...
402
 
379
 
403
    futex_down(&devices_list_futex);   
380
    futex_down(&devices_list_futex);   
404
 
381
 
405
    /* Check that device with such name is not already registered */
382
    /* Check that device with such name is not already registered */
406
    if (NULL != devmap_device_find_name(device->name)) {
383
    if (NULL != devmap_device_find_name(device->name)) {
407
        printf("Device '%s' already registered.\n", device->name);
384
        printf(NAME ": Device '%s' already registered\n", device->name);
408
        futex_up(&devices_list_futex); 
385
        futex_up(&devices_list_futex); 
409
        free(device->name);
386
        free(device->name);
410
        free(device);
387
        free(device);
411
        ipc_answer_0(iid, EEXISTS);
388
        ipc_answer_0(iid, EEXISTS);
412
        return;
389
        return;
Line 426... Line 403...
426
    list_append(&device->driver_devices, &device->driver->devices);
403
    list_append(&device->driver_devices, &device->driver->devices);
427
   
404
   
428
    futex_up(&device->driver->devices_futex);  
405
    futex_up(&device->driver->devices_futex);  
429
    futex_up(&devices_list_futex); 
406
    futex_up(&devices_list_futex); 
430
 
407
 
431
    printf("Device '%s' registered.\n", device->name); 
-
 
432
    ipc_answer_1(iid, EOK, device->handle);
408
    ipc_answer_1(iid, EOK, device->handle);
433
 
-
 
434
    return;
-
 
435
}
409
}
436
 
410
 
437
/**
411
/**
438
 *
412
 *
439
 */
413
 */
Line 459... Line 433...
459
     */
433
     */
460
    handle = IPC_GET_ARG2(*call);
434
    handle = IPC_GET_ARG2(*call);
461
    dev = devmap_device_find_handle(handle);
435
    dev = devmap_device_find_handle(handle);
462
 
436
 
463
    if (NULL == dev) {
437
    if (NULL == dev) {
464
        printf("DEVMAP: No registered device with handle %d.\n",
-
 
465
            handle);
-
 
466
        ipc_answer_0(callid, ENOENT);
438
        ipc_answer_0(callid, ENOENT);
467
        return;
439
        return;
468
    }
440
    }
469
 
441
 
470
    ipc_forward_fast(callid, dev->driver->phone, (ipcarg_t)(dev->handle),
442
    ipc_forward_fast(callid, dev->driver->phone, (ipcarg_t)(dev->handle),
471
        IPC_GET_ARG3(*call), 0, IPC_FF_NONE);
443
        IPC_GET_ARG3(*call), 0, IPC_FF_NONE);
472
    return;
-
 
473
}
444
}
474
 
445
 
475
/** Find handle for device instance identified by name.
446
/** Find handle for device instance identified by name.
476
 * In answer will be send EOK and device handle in arg1 or a error
447
 * In answer will be send EOK and device handle in arg1 or a error
477
 * code from errno.h.
448
 * code from errno.h.
Line 482... Line 453...
482
    size_t name_size;
453
    size_t name_size;
483
    const devmap_device_t *dev;
454
    const devmap_device_t *dev;
484
    ipc_callid_t callid;
455
    ipc_callid_t callid;
485
    ipcarg_t retval;
456
    ipcarg_t retval;
486
   
457
   
487
   
-
 
488
    /*
458
    /*
489
     * Wait for incoming message with device name (but do not
459
     * Wait for incoming message with device name (but do not
490
     * read the name itself until the buffer is allocated).
460
     * read the name itself until the buffer is allocated).
491
     */
461
     */
492
    if (!ipc_data_write_receive(&callid, &name_size)) {
462
    if (!ipc_data_write_receive(&callid, &name_size)) {
Line 526... Line 496...
526
 
496
 
527
    /*
497
    /*
528
     * Device was not found.
498
     * Device was not found.
529
     */
499
     */
530
    if (NULL == dev) {
500
    if (NULL == dev) {
531
        printf("DEVMAP: device %s has not been registered.\n", name);
-
 
532
        ipc_answer_0(iid, ENOENT);
501
        ipc_answer_0(iid, ENOENT);
533
        return;
502
        return;
534
    }
503
    }
535
 
504
 
536
    printf("DEVMAP: device %s has handler %d.\n", name, dev->handle);
-
 
537
       
-
 
538
    ipc_answer_1(iid, EOK, dev->handle);
505
    ipc_answer_1(iid, EOK, dev->handle);
539
 
-
 
540
    return;
-
 
541
}
506
}
542
 
507
 
543
/** Find name of device identified by id and send it to caller.
508
/** Find name of device identified by id and send it to caller.
544
 *
509
 *
545
 */
510
 */
Line 572... Line 537...
572
        async_wait_for(req, NULL);
537
        async_wait_for(req, NULL);
573
        return rc;
538
        return rc;
574
    }
539
    }
575
*/ 
540
*/ 
576
    /* TODO: send name in response */
541
    /* TODO: send name in response */
577
 
-
 
578
    return;
-
 
579
}
542
}
580
 
543
 
581
/** Handle connection with device driver.
544
/** Handle connection with device driver.
582
 *
545
 *
583
 */
546
 */
584
static void
-
 
585
devmap_connection_driver(ipc_callid_t iid, ipc_call_t *icall)
547
static void devmap_connection_driver(ipc_callid_t iid, ipc_call_t *icall)
586
{
548
{
587
    ipc_callid_t callid;
549
    ipc_callid_t callid;
588
    ipc_call_t call;
550
    ipc_call_t call;
589
    bool cont = true;
551
    bool cont = true;
590
    devmap_driver_t *driver = NULL;
552
    devmap_driver_t *driver = NULL;
591
 
553
 
592
    ipc_answer_0(iid, EOK);
554
    ipc_answer_0(iid, EOK);
593
 
555
 
594
    devmap_driver_register(&driver);
556
    devmap_driver_register(&driver);
595
 
557
 
596
    if (NULL == driver) {
558
    if (NULL == driver)
597
        printf("DEVMAP: driver registration failed.\n");
-
 
598
        return;
559
        return;
599
    }
-
 
600
   
560
   
601
    while (cont) {
561
    while (cont) {
602
        callid = async_get_call(&call);
562
        callid = async_get_call(&call);
603
 
563
 
604
        switch (IPC_GET_METHOD(call)) {
564
        switch (IPC_GET_METHOD(call)) {
605
        case IPC_M_PHONE_HUNGUP:
565
        case IPC_M_PHONE_HUNGUP:
606
            printf("DEVMAP: connection hung up.\n");
-
 
607
            cont = false;
566
            cont = false;
608
            continue; /* Exit thread */
567
            continue; /* Exit thread */
609
        case DEVMAP_DRIVER_UNREGISTER:
568
        case DEVMAP_DRIVER_UNREGISTER:
610
            printf("DEVMAP: unregister driver.\n");
-
 
611
            if (NULL == driver) {
569
            if (NULL == driver) {
612
                printf("DEVMAP: driver was not registered!\n");
-
 
613
                ipc_answer_0(callid, ENOENT);
570
                ipc_answer_0(callid, ENOENT);
614
            } else {
571
            } else {
615
                ipc_answer_0(callid, EOK);
572
                ipc_answer_0(callid, EOK);
616
            }
573
            }
617
            break;
574
            break;
Line 647... Line 604...
647
}
604
}
648
 
605
 
649
/** Handle connection with device client.
606
/** Handle connection with device client.
650
 *
607
 *
651
 */
608
 */
652
static void
-
 
653
devmap_connection_client(ipc_callid_t iid, ipc_call_t *icall)
609
static void devmap_connection_client(ipc_callid_t iid, ipc_call_t *icall)
654
{
610
{
655
    ipc_callid_t callid;
611
    ipc_callid_t callid;
656
    ipc_call_t call;
612
    ipc_call_t call;
657
    bool cont = true;
613
    bool cont = true;
658
 
614
 
Line 661... Line 617...
661
    while (cont) {
617
    while (cont) {
662
        callid = async_get_call(&call);
618
        callid = async_get_call(&call);
663
 
619
 
664
        switch (IPC_GET_METHOD(call)) {
620
        switch (IPC_GET_METHOD(call)) {
665
        case IPC_M_PHONE_HUNGUP:
621
        case IPC_M_PHONE_HUNGUP:
666
            printf("DEVMAP: connection hung up.\n");
-
 
667
            cont = false;
622
            cont = false;
668
            continue; /* Exit thread */
623
            continue; /* Exit thread */
669
 
624
 
670
        case DEVMAP_DEVICE_GET_HANDLE:
625
        case DEVMAP_DEVICE_GET_HANDLE:
671
            devmap_get_handle(callid, &call);
626
            devmap_get_handle(callid, &call);
Line 684... Line 639...
684
}
639
}
685
 
640
 
686
/** Function for handling connections to devmap
641
/** Function for handling connections to devmap
687
 *
642
 *
688
 */
643
 */
689
static void
-
 
690
devmap_connection(ipc_callid_t iid, ipc_call_t *icall)
644
static void devmap_connection(ipc_callid_t iid, ipc_call_t *icall)
691
{
645
{
692
 
-
 
693
    printf("DEVMAP: new connection.\n");
-
 
694
 
-
 
695
        /* Select interface */
646
    /* Select interface */
696
    switch ((ipcarg_t)(IPC_GET_ARG1(*icall))) {
647
    switch ((ipcarg_t) (IPC_GET_ARG1(*icall))) {
697
    case DEVMAP_DRIVER:
648
    case DEVMAP_DRIVER:
698
        devmap_connection_driver(iid, icall);
649
        devmap_connection_driver(iid, icall);
699
        break;
650
        break;
700
    case DEVMAP_CLIENT:
651
    case DEVMAP_CLIENT:
701
        devmap_connection_client(iid, icall);
652
        devmap_connection_client(iid, icall);
702
        break;
653
        break;
703
    case DEVMAP_CONNECT_TO_DEVICE:
654
    case DEVMAP_CONNECT_TO_DEVICE:
704
            /* Connect client to selected device */
655
        /* Connect client to selected device */
705
        printf("DEVMAP: connect to device %d.\n",
-
 
706
            IPC_GET_ARG2(*icall));
-
 
707
        devmap_forward(iid, icall);
656
        devmap_forward(iid, icall);
708
        break;
657
        break;
709
    default:
658
    default:
710
        ipc_answer_0(iid, ENOENT); /* No such interface */
659
        ipc_answer_0(iid, ENOENT); /* No such interface */
711
        printf("DEVMAP: Unknown interface %u.\n",
-
 
712
            (ipcarg_t)(IPC_GET_ARG1(*icall)));
-
 
713
    }
660
    }
714
 
661
 
715
    /* Cleanup */
662
    /* Cleanup */
716
   
-
 
717
    printf("DEVMAP: connection closed.\n");
-
 
718
    return;
-
 
719
}
663
}
720
 
664
 
721
/**
665
/**
722
 *
666
 *
723
 */
667
 */
724
int main(int argc, char *argv[])
668
int main(int argc, char *argv[])
725
{
669
{
-
 
670
    printf(NAME ": HelenOS Device Mapper\n");
-
 
671
   
726
    ipcarg_t phonead;
672
    ipcarg_t phonead;
727
 
673
 
728
    printf("DEVMAP: HelenOS device mapper.\n");
-
 
729
 
-
 
730
    if (devmap_init() != 0) {
674
    if (devmap_init() != 0) {
731
        printf("Error while initializing DEVMAP service.\n");
675
        printf(NAME ": Error while initializing service\n");
732
        return -1;
676
        return -1;
733
    }
677
    }
734
 
678
   
735
        /* Set a handler of incomming connections */
679
    /* Set a handler of incomming connections */
736
    async_set_client_connection(devmap_connection);
680
    async_set_client_connection(devmap_connection);
737
 
681
 
738
    /* Register device mapper at naming service */
682
    /* Register device mapper at naming service */
739
    if (ipc_connect_to_me(PHONE_NS, SERVICE_DEVMAP, 0, 0, &phonead) != 0)
683
    if (ipc_connect_to_me(PHONE_NS, SERVICE_DEVMAP, 0, 0, &phonead) != 0)
740
        return -1;
684
        return -1;
741
   
685
   
-
 
686
    printf(NAME ": Accepting connections\n");
742
    async_manager();
687
    async_manager();
743
    /* Never reached */
688
    /* Never reached */
744
    return 0;
689
    return 0;
745
}
690
}
746
 
691
 
747
/**
692
/**
748
 * @}
693
 * @}
749
 */
694
 */
750
 
-