Rev 3022 | Rev 4420 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 3022 | Rev 4055 | ||
|---|---|---|---|
| Line 40... | Line 40... | ||
| 40 | #include <debug.h> |
40 | #include <debug.h> |
| 41 | #include <ipc/ipc.h> |
41 | #include <ipc/ipc.h> |
| 42 | #include <ipc/sysipc.h> |
42 | #include <ipc/sysipc.h> |
| 43 | #include <ipc/irq.h> |
43 | #include <ipc/irq.h> |
| 44 | #include <ipc/ipcrsc.h> |
44 | #include <ipc/ipcrsc.h> |
| - | 45 | #include <ipc/kbox.h> |
|
| - | 46 | #include <udebug/udebug_ipc.h> |
|
| 45 | #include <arch/interrupt.h> |
47 | #include <arch/interrupt.h> |
| 46 | #include <print.h> |
- | |
| 47 | #include <syscall/copy.h> |
48 | #include <syscall/copy.h> |
| 48 | #include <security/cap.h> |
49 | #include <security/cap.h> |
| 49 | #include <mm/as.h> |
50 | #include <mm/as.h> |
| 50 | #include <print.h> |
51 | #include <print.h> |
| 51 | 52 | ||
| Line 268... | Line 269... | ||
| 268 | ASSERT(answer->buffer); |
269 | ASSERT(answer->buffer); |
| 269 | if (!IPC_GET_RETVAL(answer->data)) { |
270 | if (!IPC_GET_RETVAL(answer->data)) { |
| 270 | /* The recipient agreed to receive data. */ |
271 | /* The recipient agreed to receive data. */ |
| 271 | int rc; |
272 | int rc; |
| 272 | uintptr_t dst; |
273 | uintptr_t dst; |
| 273 | uintptr_t size; |
274 | size_t size; |
| 274 | uintptr_t max_size; |
275 | size_t max_size; |
| 275 | 276 | ||
| 276 | dst = IPC_GET_ARG1(answer->data); |
277 | dst = (uintptr_t)IPC_GET_ARG1(answer->data); |
| 277 | size = IPC_GET_ARG2(answer->data); |
278 | size = (size_t)IPC_GET_ARG2(answer->data); |
| 278 | max_size = IPC_GET_ARG2(*olddata); |
279 | max_size = (size_t)IPC_GET_ARG2(*olddata); |
| 279 | 280 | ||
| 280 | if (size <= max_size) { |
281 | if (size <= max_size) { |
| 281 | rc = copy_to_uspace((void *) dst, |
282 | rc = copy_to_uspace((void *) dst, |
| 282 | answer->buffer, size); |
283 | answer->buffer, size); |
| 283 | if (rc) |
284 | if (rc) |
| Line 293... | Line 294... | ||
| 293 | } |
294 | } |
| 294 | 295 | ||
| 295 | /** Called before the request is sent. |
296 | /** Called before the request is sent. |
| 296 | * |
297 | * |
| 297 | * @param call Call structure with the request. |
298 | * @param call Call structure with the request. |
| - | 299 | * @param phone Phone that the call will be sent through. |
|
| 298 | * |
300 | * |
| 299 | * @return Return 0 on success, ELIMIT or EPERM on error. |
301 | * @return Return 0 on success, ELIMIT or EPERM on error. |
| 300 | */ |
302 | */ |
| 301 | static int request_preprocess(call_t *call) |
303 | static int request_preprocess(call_t *call, phone_t *phone) |
| 302 | { |
304 | { |
| 303 | int newphid; |
305 | int newphid; |
| 304 | size_t size; |
306 | size_t size; |
| 305 | uintptr_t src; |
307 | uintptr_t src; |
| 306 | int rc; |
308 | int rc; |
| Line 338... | Line 340... | ||
| 338 | if (rc != 0) { |
340 | if (rc != 0) { |
| 339 | free(call->buffer); |
341 | free(call->buffer); |
| 340 | return rc; |
342 | return rc; |
| 341 | } |
343 | } |
| 342 | break; |
344 | break; |
| - | 345 | #ifdef CONFIG_UDEBUG |
|
| - | 346 | case IPC_M_DEBUG_ALL: |
|
| - | 347 | return udebug_request_preprocess(call, phone); |
|
| - | 348 | #endif |
|
| 343 | default: |
349 | default: |
| 344 | break; |
350 | break; |
| 345 | } |
351 | } |
| 346 | return 0; |
352 | return 0; |
| 347 | } |
353 | } |
| Line 367... | Line 373... | ||
| 367 | IPC_SET_ARG5(call->data, call->priv); |
373 | IPC_SET_ARG5(call->data, call->priv); |
| 368 | } |
374 | } |
| 369 | 375 | ||
| 370 | if (call->buffer) { |
376 | if (call->buffer) { |
| 371 | /* This must be an affirmative answer to IPC_M_DATA_READ. */ |
377 | /* This must be an affirmative answer to IPC_M_DATA_READ. */ |
| - | 378 | /* or IPC_M_DEBUG_ALL/UDEBUG_M_MEM_READ... */ |
|
| 372 | uintptr_t dst = IPC_GET_ARG1(call->data); |
379 | uintptr_t dst = IPC_GET_ARG1(call->data); |
| 373 | size_t size = IPC_GET_ARG2(call->data); |
380 | size_t size = IPC_GET_ARG2(call->data); |
| 374 | int rc = copy_to_uspace((void *) dst, call->buffer, size); |
381 | int rc = copy_to_uspace((void *) dst, call->buffer, size); |
| 375 | if (rc) |
382 | if (rc) |
| 376 | IPC_SET_RETVAL(call->data, rc); |
383 | IPC_SET_RETVAL(call->data, rc); |
| Line 397... | Line 404... | ||
| 397 | IPC_SET_RETVAL(call->data, ELIMIT); |
404 | IPC_SET_RETVAL(call->data, ELIMIT); |
| 398 | ipc_answer(box, call); |
405 | ipc_answer(box, call); |
| 399 | return -1; |
406 | return -1; |
| 400 | } |
407 | } |
| 401 | IPC_SET_ARG5(call->data, phoneid); |
408 | IPC_SET_ARG5(call->data, phoneid); |
| 402 | } |
409 | } |
| - | 410 | switch (IPC_GET_METHOD(call->data)) { |
|
| - | 411 | case IPC_M_DEBUG_ALL: |
|
| - | 412 | return -1; |
|
| - | 413 | default: |
|
| - | 414 | break; |
|
| - | 415 | } |
|
| 403 | return 0; |
416 | return 0; |
| 404 | } |
417 | } |
| 405 | 418 | ||
| 406 | /** Make a fast call over IPC, wait for reply and return to user. |
419 | /** Make a fast call over IPC, wait for reply and return to user. |
| 407 | * |
420 | * |
| Line 424... | Line 437... | ||
| 424 | { |
437 | { |
| 425 | call_t call; |
438 | call_t call; |
| 426 | phone_t *phone; |
439 | phone_t *phone; |
| 427 | int res; |
440 | int res; |
| 428 | int rc; |
441 | int rc; |
| 429 | 442 | ||
| 430 | GET_CHECK_PHONE(phone, phoneid, return ENOENT); |
443 | GET_CHECK_PHONE(phone, phoneid, return ENOENT); |
| 431 | 444 | ||
| 432 | ipc_call_static_init(&call); |
445 | ipc_call_static_init(&call); |
| 433 | IPC_SET_METHOD(call.data, method); |
446 | IPC_SET_METHOD(call.data, method); |
| 434 | IPC_SET_ARG1(call.data, arg1); |
447 | IPC_SET_ARG1(call.data, arg1); |
| Line 439... | Line 452... | ||
| 439 | * the limits of the fast version. |
452 | * the limits of the fast version. |
| 440 | */ |
453 | */ |
| 441 | IPC_SET_ARG4(call.data, 0); |
454 | IPC_SET_ARG4(call.data, 0); |
| 442 | IPC_SET_ARG5(call.data, 0); |
455 | IPC_SET_ARG5(call.data, 0); |
| 443 | 456 | ||
| 444 | if (!(res = request_preprocess(&call))) { |
457 | if (!(res = request_preprocess(&call, phone))) { |
| - | 458 | #ifdef CONFIG_UDEBUG |
|
| - | 459 | udebug_stoppable_begin(); |
|
| - | 460 | #endif |
|
| 445 | ipc_call_sync(phone, &call); |
461 | rc = ipc_call_sync(phone, &call); |
| - | 462 | #ifdef CONFIG_UDEBUG |
|
| - | 463 | udebug_stoppable_end(); |
|
| - | 464 | #endif |
|
| - | 465 | if (rc != EOK) |
|
| - | 466 | return rc; |
|
| 446 | process_answer(&call); |
467 | process_answer(&call); |
| - | 468 | ||
| 447 | } else { |
469 | } else { |
| 448 | IPC_SET_RETVAL(call.data, res); |
470 | IPC_SET_RETVAL(call.data, res); |
| 449 | } |
471 | } |
| 450 | rc = STRUCT_TO_USPACE(&data->args, &call.data.args); |
472 | rc = STRUCT_TO_USPACE(&data->args, &call.data.args); |
| 451 | if (rc != 0) |
473 | if (rc != 0) |
| Line 477... | Line 499... | ||
| 477 | if (rc != 0) |
499 | if (rc != 0) |
| 478 | return (unative_t) rc; |
500 | return (unative_t) rc; |
| 479 | 501 | ||
| 480 | GET_CHECK_PHONE(phone, phoneid, return ENOENT); |
502 | GET_CHECK_PHONE(phone, phoneid, return ENOENT); |
| 481 | 503 | ||
| 482 | if (!(res = request_preprocess(&call))) { |
504 | if (!(res = request_preprocess(&call, phone))) { |
| - | 505 | #ifdef CONFIG_UDEBUG |
|
| - | 506 | udebug_stoppable_begin(); |
|
| - | 507 | #endif |
|
| 483 | ipc_call_sync(phone, &call); |
508 | rc = ipc_call_sync(phone, &call); |
| - | 509 | #ifdef CONFIG_UDEBUG |
|
| - | 510 | udebug_stoppable_end(); |
|
| - | 511 | #endif |
|
| - | 512 | if (rc != EOK) |
|
| - | 513 | return rc; |
|
| 484 | process_answer(&call); |
514 | process_answer(&call); |
| 485 | } else |
515 | } else |
| 486 | IPC_SET_RETVAL(call.data, res); |
516 | IPC_SET_RETVAL(call.data, res); |
| 487 | 517 | ||
| 488 | rc = STRUCT_TO_USPACE(&reply->args, &call.data.args); |
518 | rc = STRUCT_TO_USPACE(&reply->args, &call.data.args); |
| Line 544... | Line 574... | ||
| 544 | * To achieve deterministic behavior, zero out arguments that are beyond |
574 | * To achieve deterministic behavior, zero out arguments that are beyond |
| 545 | * the limits of the fast version. |
575 | * the limits of the fast version. |
| 546 | */ |
576 | */ |
| 547 | IPC_SET_ARG5(call->data, 0); |
577 | IPC_SET_ARG5(call->data, 0); |
| 548 | 578 | ||
| 549 | if (!(res = request_preprocess(call))) |
579 | if (!(res = request_preprocess(call, phone))) |
| 550 | ipc_call(phone, call); |
580 | ipc_call(phone, call); |
| 551 | else |
581 | else |
| 552 | ipc_backsend_err(phone, call, res); |
582 | ipc_backsend_err(phone, call, res); |
| 553 | 583 | ||
| 554 | return (unative_t) call; |
584 | return (unative_t) call; |
| Line 578... | Line 608... | ||
| 578 | sizeof(call->data.args)); |
608 | sizeof(call->data.args)); |
| 579 | if (rc != 0) { |
609 | if (rc != 0) { |
| 580 | ipc_call_free(call); |
610 | ipc_call_free(call); |
| 581 | return (unative_t) rc; |
611 | return (unative_t) rc; |
| 582 | } |
612 | } |
| 583 | if (!(res = request_preprocess(call))) |
613 | if (!(res = request_preprocess(call, phone))) |
| 584 | ipc_call(phone, call); |
614 | ipc_call(phone, call); |
| 585 | else |
615 | else |
| 586 | ipc_backsend_err(phone, call, res); |
616 | ipc_backsend_err(phone, call, res); |
| 587 | 617 | ||
| 588 | return (unative_t) call; |
618 | return (unative_t) call; |
| 589 | } |
619 | } |
| 590 | 620 | ||
| 591 | /** Forward a received call to another destination. |
621 | /** Forward a received call to another destination - common code for both the |
| - | 622 | * fast and the slow version. |
|
| 592 | * |
623 | * |
| 593 | * @param callid Hash of the call to forward. |
624 | * @param callid Hash of the call to forward. |
| 594 | * @param phoneid Phone handle to use for forwarding. |
625 | * @param phoneid Phone handle to use for forwarding. |
| 595 | * @param method New method to use for the forwarded call. |
626 | * @param method New method to use for the forwarded call. |
| 596 | * @param arg1 New value of the first argument for the forwarded call. |
627 | * @param arg1 New value of the first argument for the forwarded call. |
| 597 | * @param arg2 New value of the second argument for the forwarded call. |
628 | * @param arg2 New value of the second argument for the forwarded call. |
| - | 629 | * @param arg3 New value of the third argument for the forwarded call. |
|
| - | 630 | * @param arg4 New value of the fourth argument for the forwarded call. |
|
| - | 631 | * @param arg5 New value of the fifth argument for the forwarded call. |
|
| 598 | * @param mode Flags that specify mode of the forward operation. |
632 | * @param mode Flags that specify mode of the forward operation. |
| - | 633 | * @param slow If true, arg3, arg4 and arg5 are considered. Otherwise |
|
| - | 634 | * the function considers only the fast version arguments: |
|
| - | 635 | * i.e. arg1 and arg2. |
|
| 599 | * |
636 | * |
| 600 | * @return Return 0 on succes, otherwise return an error code. |
637 | * @return Return 0 on succes, otherwise return an error code. |
| 601 | * |
638 | * |
| 602 | * In case the original method is a system method, ARG1, ARG2 and ARG3 are |
- | |
| 603 | * overwritten in the forwarded message with the new method and the new arg1 and |
- | |
| 604 | * arg2, respectively. Otherwise the METHOD, ARG1 and ARG2 are rewritten with |
- | |
| 605 | * the new method, arg1 and arg2, respectively. Also note there is a set of |
- | |
| 606 | * immutable methods, for which the new method and argument is not set and |
- | |
| 607 | * these values are ignored. |
- | |
| 608 | * |
- | |
| 609 | * Warning: When implementing support for changing additional payload |
- | |
| 610 | * arguments, make sure that ARG5 is not rewritten for certain |
639 | * Warning: Make sure that ARG5 is not rewritten for certain system IPC |
| 611 | * system IPC |
- | |
| 612 | */ |
640 | */ |
| 613 | unative_t sys_ipc_forward_fast(unative_t callid, unative_t phoneid, |
641 | static unative_t sys_ipc_forward_common(unative_t callid, unative_t phoneid, |
| 614 | unative_t method, unative_t arg1, unative_t arg2, int mode) |
642 | unative_t method, unative_t arg1, unative_t arg2, unative_t arg3, |
| - | 643 | unative_t arg4, unative_t arg5, int mode, bool slow) |
|
| 615 | { |
644 | { |
| 616 | call_t *call; |
645 | call_t *call; |
| 617 | phone_t *phone; |
646 | phone_t *phone; |
| 618 | 647 | ||
| 619 | call = get_call(callid); |
648 | call = get_call(callid); |
| 620 | if (!call) |
649 | if (!call) |
| 621 | return ENOENT; |
650 | return ENOENT; |
| 622 | 651 | ||
| 623 | call->flags |= IPC_CALL_FORWARDED; |
652 | call->flags |= IPC_CALL_FORWARDED; |
| 624 | 653 | ||
| 625 | GET_CHECK_PHONE(phone, phoneid, { |
654 | GET_CHECK_PHONE(phone, phoneid, { |
| 626 | IPC_SET_RETVAL(call->data, EFORWARD); |
655 | IPC_SET_RETVAL(call->data, EFORWARD); |
| 627 | ipc_answer(&TASK->answerbox, call); |
656 | ipc_answer(&TASK->answerbox, call); |
| 628 | return ENOENT; |
657 | return ENOENT; |
| 629 | }); |
658 | }); |
| 630 | 659 | ||
| 631 | if (!method_is_forwardable(IPC_GET_METHOD(call->data))) { |
660 | if (!method_is_forwardable(IPC_GET_METHOD(call->data))) { |
| 632 | IPC_SET_RETVAL(call->data, EFORWARD); |
661 | IPC_SET_RETVAL(call->data, EFORWARD); |
| 633 | ipc_answer(&TASK->answerbox, call); |
662 | ipc_answer(&TASK->answerbox, call); |
| 634 | return EPERM; |
663 | return EPERM; |
| 635 | } |
664 | } |
| 636 | 665 | ||
| 637 | /* |
666 | /* |
| 638 | * Userspace is not allowed to change method of system methods on |
667 | * Userspace is not allowed to change method of system methods on |
| 639 | * forward, allow changing ARG1, ARG2 and ARG3 by means of method, |
668 | * forward, allow changing ARG1, ARG2, ARG3 and ARG4 by means of method, |
| 640 | * arg1 and arg2. |
669 | * arg1, arg2 and arg3. |
| 641 | * If the method is immutable, don't change anything. |
670 | * If the method is immutable, don't change anything. |
| 642 | */ |
671 | */ |
| 643 | if (!method_is_immutable(IPC_GET_METHOD(call->data))) { |
672 | if (!method_is_immutable(IPC_GET_METHOD(call->data))) { |
| 644 | if (method_is_system(IPC_GET_METHOD(call->data))) { |
673 | if (method_is_system(IPC_GET_METHOD(call->data))) { |
| 645 | if (IPC_GET_METHOD(call->data) == IPC_M_CONNECT_TO_ME) |
674 | if (IPC_GET_METHOD(call->data) == IPC_M_CONNECT_TO_ME) |
| 646 | phone_dealloc(IPC_GET_ARG5(call->data)); |
675 | phone_dealloc(IPC_GET_ARG5(call->data)); |
| 647 | 676 | ||
| 648 | IPC_SET_ARG1(call->data, method); |
677 | IPC_SET_ARG1(call->data, method); |
| 649 | IPC_SET_ARG2(call->data, arg1); |
678 | IPC_SET_ARG2(call->data, arg1); |
| 650 | IPC_SET_ARG3(call->data, arg2); |
679 | IPC_SET_ARG3(call->data, arg2); |
| - | 680 | if (slow) { |
|
| - | 681 | IPC_SET_ARG4(call->data, arg3); |
|
| - | 682 | /* |
|
| - | 683 | * For system methods we deliberately don't |
|
| - | 684 | * overwrite ARG5. |
|
| - | 685 | */ |
|
| - | 686 | } |
|
| 651 | } else { |
687 | } else { |
| 652 | IPC_SET_METHOD(call->data, method); |
688 | IPC_SET_METHOD(call->data, method); |
| 653 | IPC_SET_ARG1(call->data, arg1); |
689 | IPC_SET_ARG1(call->data, arg1); |
| 654 | IPC_SET_ARG2(call->data, arg2); |
690 | IPC_SET_ARG2(call->data, arg2); |
| - | 691 | if (slow) { |
|
| - | 692 | IPC_SET_ARG3(call->data, arg3); |
|
| - | 693 | IPC_SET_ARG4(call->data, arg4); |
|
| - | 694 | IPC_SET_ARG5(call->data, arg5); |
|
| - | 695 | } |
|
| 655 | } |
696 | } |
| 656 | } |
697 | } |
| 657 | 698 | ||
| 658 | return ipc_forward(call, phone, &TASK->answerbox, mode); |
699 | return ipc_forward(call, phone, &TASK->answerbox, mode); |
| 659 | } |
700 | } |
| 660 | 701 | ||
| - | 702 | /** Forward a received call to another destination - fast version. |
|
| - | 703 | * |
|
| - | 704 | * @param callid Hash of the call to forward. |
|
| - | 705 | * @param phoneid Phone handle to use for forwarding. |
|
| - | 706 | * @param method New method to use for the forwarded call. |
|
| - | 707 | * @param arg1 New value of the first argument for the forwarded call. |
|
| - | 708 | * @param arg2 New value of the second argument for the forwarded call. |
|
| - | 709 | * @param mode Flags that specify mode of the forward operation. |
|
| - | 710 | * |
|
| - | 711 | * @return Return 0 on succes, otherwise return an error code. |
|
| - | 712 | * |
|
| - | 713 | * In case the original method is a system method, ARG1, ARG2 and ARG3 are |
|
| - | 714 | * overwritten in the forwarded message with the new method and the new |
|
| - | 715 | * arg1 and arg2, respectively. Otherwise the METHOD, ARG1 and ARG2 are |
|
| - | 716 | * rewritten with the new method, arg1 and arg2, respectively. Also note there |
|
| - | 717 | * is a set of immutable methods, for which the new method and arguments are not |
|
| - | 718 | * set and these values are ignored. |
|
| - | 719 | */ |
|
| - | 720 | unative_t sys_ipc_forward_fast(unative_t callid, unative_t phoneid, |
|
| - | 721 | unative_t method, unative_t arg1, unative_t arg2, int mode) |
|
| - | 722 | { |
|
| - | 723 | return sys_ipc_forward_common(callid, phoneid, method, arg1, arg2, 0, 0, |
|
| - | 724 | 0, mode, false); |
|
| - | 725 | } |
|
| - | 726 | ||
| - | 727 | /** Forward a received call to another destination - slow version. |
|
| - | 728 | * |
|
| - | 729 | * @param callid Hash of the call to forward. |
|
| - | 730 | * @param phoneid Phone handle to use for forwarding. |
|
| - | 731 | * @param data Userspace address of the new IPC data. |
|
| - | 732 | * @param mode Flags that specify mode of the forward operation. |
|
| - | 733 | * |
|
| - | 734 | * @return Return 0 on succes, otherwise return an error code. |
|
| - | 735 | * |
|
| - | 736 | * This function is the slow verision of the sys_ipc_forward_fast interface. |
|
| - | 737 | * It can copy all five new arguments and the new method from the userspace. |
|
| - | 738 | * It naturally extends the functionality of the fast version. For system |
|
| - | 739 | * methods, it additionally stores the new value of arg3 to ARG4. For non-system |
|
| - | 740 | * methods, it additionally stores the new value of arg3, arg4 and arg5, |
|
| - | 741 | * respectively, to ARG3, ARG4 and ARG5, respectively. |
|
| - | 742 | */ |
|
| - | 743 | unative_t sys_ipc_forward_slow(unative_t callid, unative_t phoneid, |
|
| - | 744 | ipc_data_t *data, int mode) |
|
| - | 745 | { |
|
| - | 746 | ipc_data_t newdata; |
|
| - | 747 | int rc; |
|
| - | 748 | ||
| - | 749 | rc = copy_from_uspace(&newdata.args, &data->args, |
|
| - | 750 | sizeof(newdata.args)); |
|
| - | 751 | if (rc != 0) |
|
| - | 752 | return (unative_t) rc; |
|
| - | 753 | ||
| - | 754 | return sys_ipc_forward_common(callid, phoneid, |
|
| - | 755 | IPC_GET_METHOD(newdata), IPC_GET_ARG1(newdata), |
|
| - | 756 | IPC_GET_ARG2(newdata), IPC_GET_ARG3(newdata), |
|
| - | 757 | IPC_GET_ARG4(newdata), IPC_GET_ARG5(newdata), mode, true); |
|
| - | 758 | } |
|
| - | 759 | ||
| 661 | /** Answer an IPC call - fast version. |
760 | /** Answer an IPC call - fast version. |
| 662 | * |
761 | * |
| 663 | * This function can handle only two return arguments of payload, but is faster |
762 | * This function can handle only two return arguments of payload, but is faster |
| 664 | * than the generic sys_ipc_answer(). |
763 | * than the generic sys_ipc_answer(). |
| 665 | * |
764 | * |
| Line 779... | Line 878... | ||
| 779 | */ |
878 | */ |
| 780 | unative_t sys_ipc_wait_for_call(ipc_data_t *calldata, uint32_t usec, int flags) |
879 | unative_t sys_ipc_wait_for_call(ipc_data_t *calldata, uint32_t usec, int flags) |
| 781 | { |
880 | { |
| 782 | call_t *call; |
881 | call_t *call; |
| 783 | 882 | ||
| 784 | restart: |
883 | restart: |
| - | 884 | ||
| - | 885 | #ifdef CONFIG_UDEBUG |
|
| - | 886 | udebug_stoppable_begin(); |
|
| - | 887 | #endif |
|
| 785 | call = ipc_wait_for_call(&TASK->answerbox, usec, |
888 | call = ipc_wait_for_call(&TASK->answerbox, usec, |
| 786 | flags | SYNCH_FLAGS_INTERRUPTIBLE); |
889 | flags | SYNCH_FLAGS_INTERRUPTIBLE); |
| - | 890 | ||
| - | 891 | #ifdef CONFIG_UDEBUG |
|
| - | 892 | udebug_stoppable_end(); |
|
| - | 893 | #endif |
|
| 787 | if (!call) |
894 | if (!call) |
| 788 | return 0; |
895 | return 0; |
| 789 | 896 | ||
| 790 | if (call->flags & IPC_CALL_NOTIF) { |
897 | if (call->flags & IPC_CALL_NOTIF) { |
| 791 | ASSERT(! (call->flags & IPC_CALL_STATIC_ALLOC)); |
898 | ASSERT(! (call->flags & IPC_CALL_STATIC_ALLOC)); |
| Line 803... | Line 910... | ||
| 803 | if (call->flags & IPC_CALL_ANSWERED) { |
910 | if (call->flags & IPC_CALL_ANSWERED) { |
| 804 | process_answer(call); |
911 | process_answer(call); |
| 805 | 912 | ||
| 806 | ASSERT(! (call->flags & IPC_CALL_STATIC_ALLOC)); |
913 | ASSERT(! (call->flags & IPC_CALL_STATIC_ALLOC)); |
| 807 | 914 | ||
| 808 | atomic_dec(&TASK->active_calls); |
- | |
| 809 | - | ||
| 810 | if (call->flags & IPC_CALL_DISCARD_ANSWER) { |
915 | if (call->flags & IPC_CALL_DISCARD_ANSWER) { |
| 811 | ipc_call_free(call); |
916 | ipc_call_free(call); |
| 812 | goto restart; |
917 | goto restart; |
| - | 918 | } else { |
|
| - | 919 | /* |
|
| - | 920 | * Decrement the counter of active calls only if the |
|
| - | 921 | * call is not an answer to IPC_M_PHONE_HUNGUP, |
|
| - | 922 | * which doesn't contribute to the counter. |
|
| - | 923 | */ |
|
| - | 924 | atomic_dec(&TASK->active_calls); |
|
| 813 | } |
925 | } |
| 814 | 926 | ||
| 815 | STRUCT_TO_USPACE(&calldata->args, &call->data.args); |
927 | STRUCT_TO_USPACE(&calldata->args, &call->data.args); |
| 816 | ipc_call_free(call); |
928 | ipc_call_free(call); |
| 817 | 929 | ||
| Line 822... | Line 934... | ||
| 822 | goto restart; |
934 | goto restart; |
| 823 | 935 | ||
| 824 | /* Include phone address('id') of the caller in the request, |
936 | /* Include phone address('id') of the caller in the request, |
| 825 | * copy whole call->data, not only call->data.args */ |
937 | * copy whole call->data, not only call->data.args */ |
| 826 | if (STRUCT_TO_USPACE(calldata, &call->data)) { |
938 | if (STRUCT_TO_USPACE(calldata, &call->data)) { |
| - | 939 | /* |
|
| - | 940 | * The callee will not receive this call and no one else has |
|
| - | 941 | * a chance to answer it. Reply with the EPARTY error code. |
|
| - | 942 | */ |
|
| - | 943 | ipc_data_t saved_data; |
|
| - | 944 | int saveddata = 0; |
|
| - | 945 | ||
| - | 946 | if (answer_need_old(call)) { |
|
| - | 947 | memcpy(&saved_data, &call->data, sizeof(call->data)); |
|
| - | 948 | saveddata = 1; |
|
| - | 949 | } |
|
| - | 950 | ||
| - | 951 | IPC_SET_RETVAL(call->data, EPARTY); |
|
| - | 952 | (void) answer_preprocess(call, saveddata ? &saved_data : NULL); |
|
| - | 953 | ipc_answer(&TASK->answerbox, call); |
|
| 827 | return 0; |
954 | return 0; |
| 828 | } |
955 | } |
| 829 | return (unative_t)call; |
956 | return (unative_t)call; |
| 830 | } |
957 | } |
| 831 | 958 | ||
| Line 862... | Line 989... | ||
| 862 | ipc_irq_unregister(&TASK->answerbox, inr, devno); |
989 | ipc_irq_unregister(&TASK->answerbox, inr, devno); |
| 863 | 990 | ||
| 864 | return 0; |
991 | return 0; |
| 865 | } |
992 | } |
| 866 | 993 | ||
| - | 994 | #include <console/console.h> |
|
| - | 995 | ||
| - | 996 | /** |
|
| - | 997 | * Syscall connect to a task by id. |
|
| - | 998 | * |
|
| - | 999 | * @return Phone id on success, or negative error code. |
|
| - | 1000 | */ |
|
| - | 1001 | unative_t sys_ipc_connect_kbox(sysarg64_t *uspace_taskid_arg) |
|
| - | 1002 | { |
|
| - | 1003 | #ifdef CONFIG_UDEBUG |
|
| - | 1004 | sysarg64_t taskid_arg; |
|
| - | 1005 | int rc; |
|
| - | 1006 | ||
| - | 1007 | rc = copy_from_uspace(&taskid_arg, uspace_taskid_arg, sizeof(sysarg64_t)); |
|
| - | 1008 | if (rc != 0) |
|
| - | 1009 | return (unative_t) rc; |
|
| - | 1010 | ||
| - | 1011 | LOG("sys_ipc_connect_kbox(%" PRIu64 ")\n", taskid_arg.value); |
|
| - | 1012 | ||
| - | 1013 | return ipc_connect_kbox(taskid_arg.value); |
|
| - | 1014 | #else |
|
| - | 1015 | return (unative_t) ENOTSUP; |
|
| - | 1016 | #endif |
|
| - | 1017 | } |
|
| - | 1018 | ||
| 867 | /** @} |
1019 | /** @} |
| 868 | */ |
1020 | */ |