source: mainline/kernel/generic/src/ipc/sysipc.c@ f39d5c2

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since f39d5c2 was 53af6e8c, checked in by Jakub Jermar <jakub@…>, 13 years ago

No need to hold the sender task when the call is going to be answered.
The sender may no longer forget the call and, in fact, must wait for it.

  • Property mode set to 100644
File size: 21.9 KB
Line 
1/*
2 * Copyright (c) 2006 Ondrej Palkovsky
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup genericipc
30 * @{
31 */
32/** @file
33 */
34
35#include <arch.h>
36#include <errno.h>
37#include <memstr.h>
38#include <ipc/ipc.h>
39#include <abi/ipc/methods.h>
40#include <ipc/sysipc.h>
41#include <ipc/sysipc_ops.h>
42#include <ipc/irq.h>
43#include <ipc/ipcrsc.h>
44#include <ipc/event.h>
45#include <ipc/kbox.h>
46#include <synch/waitq.h>
47#include <arch/interrupt.h>
48#include <syscall/copy.h>
49#include <security/cap.h>
50#include <console/console.h>
51#include <print.h>
52#include <macros.h>
53
54#define STRUCT_TO_USPACE(dst, src) copy_to_uspace((dst), (src), sizeof(*(src)))
55
56/** Decide if the interface and method is a system method.
57 *
58 * @param imethod Interface and method to be decided.
59 *
60 * @return True if the interface and method is a system
61 * interface and method.
62 *
63 */
64static inline bool method_is_system(sysarg_t imethod)
65{
66 if (imethod <= IPC_M_LAST_SYSTEM)
67 return true;
68
69 return false;
70}
71
72/** Decide if the message with this interface and method is forwardable.
73 *
74 * Some system messages may be forwarded, for some of them
75 * it is useless.
76 *
77 * @param imethod Interface and method to be decided.
78 *
79 * @return True if the interface and method is forwardable.
80 *
81 */
82static inline bool method_is_forwardable(sysarg_t imethod)
83{
84 switch (imethod) {
85 case IPC_M_CONNECTION_CLONE:
86 case IPC_M_CLONE_ESTABLISH:
87 case IPC_M_PHONE_HUNGUP:
88 /* This message is meant only for the original recipient. */
89 return false;
90 default:
91 return true;
92 }
93}
94
95/** Decide if the message with this interface and method is immutable on forward.
96 *
97 * Some system messages may be forwarded but their content cannot be altered.
98 *
99 * @param imethod Interface and method to be decided.
100 *
101 * @return True if the interface and method is immutable on forward.
102 *
103 */
104static inline bool method_is_immutable(sysarg_t imethod)
105{
106 switch (imethod) {
107 case IPC_M_SHARE_OUT:
108 case IPC_M_SHARE_IN:
109 case IPC_M_DATA_WRITE:
110 case IPC_M_DATA_READ:
111 case IPC_M_STATE_CHANGE_AUTHORIZE:
112 return true;
113 default:
114 return false;
115 }
116}
117
118
119/***********************************************************************
120 * Functions that preprocess answer before sending it to the recepient.
121 ***********************************************************************/
122
123/** Decide if the caller (e.g. ipc_answer()) should save the old call contents
124 * for answer_preprocess().
125 *
126 * @param call Call structure to be decided.
127 *
128 * @return true if the old call contents should be saved.
129 *
130 */
131static inline bool answer_need_old(call_t *call)
132{
133 switch (IPC_GET_IMETHOD(call->data)) {
134 case IPC_M_CONNECTION_CLONE:
135 case IPC_M_CLONE_ESTABLISH:
136 case IPC_M_CONNECT_TO_ME:
137 case IPC_M_CONNECT_ME_TO:
138 case IPC_M_SHARE_OUT:
139 case IPC_M_SHARE_IN:
140 case IPC_M_DATA_WRITE:
141 case IPC_M_DATA_READ:
142 case IPC_M_STATE_CHANGE_AUTHORIZE:
143 return true;
144 default:
145 return false;
146 }
147}
148
149/** Interpret process answer as control information.
150 *
151 * This function is called directly after sys_ipc_answer().
152 *
153 * @param answer Call structure with the answer.
154 * @param olddata Saved data of the request.
155 *
156 * @return Return EOK on success or a negative error code.
157 *
158 */
159static int answer_preprocess(call_t *answer, ipc_data_t *olddata)
160{
161 int rc = EOK;
162 sysipc_ops_t *ops;
163
164 spinlock_lock(&answer->forget_lock);
165 if (answer->forget) {
166 /*
167 * This is a forgotten call and answer->sender is not valid.
168 */
169 spinlock_unlock(&answer->forget_lock);
170
171 ops = sysipc_ops_get(answer->request_method);
172 if (ops->answer_cleanup)
173 ops->answer_cleanup(answer, olddata);
174
175 return rc;
176 } else {
177 ASSERT(answer->active);
178
179 /*
180 * Mark the call as inactive to prevent _ipc_answer_free_call()
181 * from attempting to remove the call from the active list
182 * itself.
183 */
184 answer->active = false;
185
186 /*
187 * Remove the call from the sender's active call list.
188 * We enforce this locking order so that any potential
189 * concurrently executing forget operation is forced to
190 * release its active_calls_lock and lose the race to
191 * forget this soon to be answered call.
192 */
193 spinlock_lock(&answer->sender->active_calls_lock);
194 list_remove(&answer->ta_link);
195 spinlock_unlock(&answer->sender->active_calls_lock);
196 }
197 spinlock_unlock(&answer->forget_lock);
198
199 if ((native_t) IPC_GET_RETVAL(answer->data) == EHANGUP) {
200 /* In case of forward, hangup the forwared phone,
201 * not the originator
202 */
203 mutex_lock(&answer->data.phone->lock);
204 irq_spinlock_lock(&TASK->answerbox.lock, true);
205 if (answer->data.phone->state == IPC_PHONE_CONNECTED) {
206 list_remove(&answer->data.phone->link);
207 answer->data.phone->state = IPC_PHONE_SLAMMED;
208 }
209 irq_spinlock_unlock(&TASK->answerbox.lock, true);
210 mutex_unlock(&answer->data.phone->lock);
211 }
212
213 if (!olddata)
214 return rc;
215
216 ops = sysipc_ops_get(answer->request_method);
217 if (ops->answer_preprocess)
218 rc = ops->answer_preprocess(answer, olddata);
219
220 return rc;
221}
222
223/** Called before the request is sent.
224 *
225 * @param call Call structure with the request.
226 * @param phone Phone that the call will be sent through.
227 *
228 * @return Return 0 on success, ELIMIT or EPERM on error.
229 *
230 */
231static int request_preprocess(call_t *call, phone_t *phone)
232{
233 int rc = EOK;
234
235 call->request_method = IPC_GET_IMETHOD(call->data);
236
237 sysipc_ops_t *ops = sysipc_ops_get(call->request_method);
238 if (ops->request_preprocess)
239 rc = ops->request_preprocess(call, phone);
240
241 return rc;
242}
243
244/*******************************************************************************
245 * Functions called to process received call/answer before passing it to uspace.
246 *******************************************************************************/
247
248/** Do basic kernel processing of received call answer.
249 *
250 * @param call Call structure with the answer.
251 *
252 */
253static void process_answer(call_t *call)
254{
255 if (((native_t) IPC_GET_RETVAL(call->data) == EHANGUP) &&
256 (call->flags & IPC_CALL_FORWARDED))
257 IPC_SET_RETVAL(call->data, EFORWARD);
258
259 sysipc_ops_t *ops = sysipc_ops_get(call->request_method);
260 if (ops->answer_process)
261 (void) ops->answer_process(call);
262}
263
264
265/** Do basic kernel processing of received call request.
266 *
267 * @param box Destination answerbox structure.
268 * @param call Call structure with the request.
269 *
270 * @return 0 if the call should be passed to userspace.
271 * @return -1 if the call should be ignored.
272 *
273 */
274static int process_request(answerbox_t *box, call_t *call)
275{
276 int rc = EOK;
277
278 sysipc_ops_t *ops = sysipc_ops_get(call->request_method);
279 if (ops->request_process)
280 rc = ops->request_process(call, box);
281
282 return rc;
283}
284
285/** Check that the task did not exceed the allowed limit of asynchronous calls
286 * made over a phone.
287 *
288 * @param phone Phone to check the limit against.
289 *
290 * @return 0 if limit not reached or -1 if limit exceeded.
291 *
292 */
293static int check_call_limit(phone_t *phone)
294{
295 if (atomic_get(&phone->active_calls) >= IPC_MAX_ASYNC_CALLS)
296 return -1;
297
298 return 0;
299}
300
301/** Make a fast asynchronous call over IPC.
302 *
303 * This function can only handle four arguments of payload, but is faster than
304 * the generic function sys_ipc_call_async_slow().
305 *
306 * @param phoneid Phone handle for the call.
307 * @param imethod Interface and method of the call.
308 * @param arg1 Service-defined payload argument.
309 * @param arg2 Service-defined payload argument.
310 * @param arg3 Service-defined payload argument.
311 * @param arg4 Service-defined payload argument.
312 *
313 * @return Call hash on success.
314 * @return IPC_CALLRET_FATAL in case of a fatal error.
315 * @return IPC_CALLRET_TEMPORARY if there are too many pending
316 * asynchronous requests; answers should be handled first.
317 *
318 */
319sysarg_t sys_ipc_call_async_fast(sysarg_t phoneid, sysarg_t imethod,
320 sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4)
321{
322 phone_t *phone;
323 if (phone_get(phoneid, &phone) != EOK)
324 return IPC_CALLRET_FATAL;
325
326 if (check_call_limit(phone))
327 return IPC_CALLRET_TEMPORARY;
328
329 call_t *call = ipc_call_alloc(0);
330 IPC_SET_IMETHOD(call->data, imethod);
331 IPC_SET_ARG1(call->data, arg1);
332 IPC_SET_ARG2(call->data, arg2);
333 IPC_SET_ARG3(call->data, arg3);
334 IPC_SET_ARG4(call->data, arg4);
335
336 /*
337 * To achieve deterministic behavior, zero out arguments that are beyond
338 * the limits of the fast version.
339 */
340 IPC_SET_ARG5(call->data, 0);
341
342 int res = request_preprocess(call, phone);
343
344 if (!res)
345 ipc_call(phone, call);
346 else
347 ipc_backsend_err(phone, call, res);
348
349 return (sysarg_t) call;
350}
351
352/** Make an asynchronous IPC call allowing to transmit the entire payload.
353 *
354 * @param phoneid Phone handle for the call.
355 * @param data Userspace address of call data with the request.
356 *
357 * @return See sys_ipc_call_async_fast().
358 *
359 */
360sysarg_t sys_ipc_call_async_slow(sysarg_t phoneid, ipc_data_t *data)
361{
362 phone_t *phone;
363 if (phone_get(phoneid, &phone) != EOK)
364 return IPC_CALLRET_FATAL;
365
366 if (check_call_limit(phone))
367 return IPC_CALLRET_TEMPORARY;
368
369 call_t *call = ipc_call_alloc(0);
370 int rc = copy_from_uspace(&call->data.args, &data->args,
371 sizeof(call->data.args));
372 if (rc != 0) {
373 ipc_call_free(call);
374 return (sysarg_t) rc;
375 }
376
377 int res = request_preprocess(call, phone);
378
379 if (!res)
380 ipc_call(phone, call);
381 else
382 ipc_backsend_err(phone, call, res);
383
384 return (sysarg_t) call;
385}
386
387/** Forward a received call to another destination
388 *
389 * Common code for both the fast and the slow version.
390 *
391 * @param callid Hash of the call to forward.
392 * @param phoneid Phone handle to use for forwarding.
393 * @param imethod New interface and method to use for the forwarded call.
394 * @param arg1 New value of the first argument for the forwarded call.
395 * @param arg2 New value of the second argument for the forwarded call.
396 * @param arg3 New value of the third argument for the forwarded call.
397 * @param arg4 New value of the fourth argument for the forwarded call.
398 * @param arg5 New value of the fifth argument for the forwarded call.
399 * @param mode Flags that specify mode of the forward operation.
400 * @param slow If true, arg3, arg4 and arg5 are considered. Otherwise
401 * the function considers only the fast version arguments:
402 * i.e. arg1 and arg2.
403 *
404 * @return 0 on succes, otherwise an error code.
405 *
406 * Warning: Make sure that ARG5 is not rewritten for certain system IPC
407 *
408 */
409static sysarg_t sys_ipc_forward_common(sysarg_t callid, sysarg_t phoneid,
410 sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3,
411 sysarg_t arg4, sysarg_t arg5, unsigned int mode, bool slow)
412{
413 call_t *call = get_call(callid);
414 if (!call)
415 return ENOENT;
416
417 call->flags |= IPC_CALL_FORWARDED;
418
419 phone_t *phone;
420 if (phone_get(phoneid, &phone) != EOK) {
421 IPC_SET_RETVAL(call->data, EFORWARD);
422 ipc_answer(&TASK->answerbox, call);
423 return ENOENT;
424 }
425
426 if (!method_is_forwardable(IPC_GET_IMETHOD(call->data))) {
427 IPC_SET_RETVAL(call->data, EFORWARD);
428 ipc_answer(&TASK->answerbox, call);
429 return EPERM;
430 }
431
432 /*
433 * User space is not allowed to change interface and method of system
434 * methods on forward, allow changing ARG1, ARG2, ARG3 and ARG4 by
435 * means of imethod, arg1, arg2 and arg3.
436 * If the interface and method is immutable, don't change anything.
437 */
438 if (!method_is_immutable(IPC_GET_IMETHOD(call->data))) {
439 if (method_is_system(IPC_GET_IMETHOD(call->data))) {
440 if (IPC_GET_IMETHOD(call->data) == IPC_M_CONNECT_TO_ME)
441 phone_dealloc(IPC_GET_ARG5(call->data));
442
443 IPC_SET_ARG1(call->data, imethod);
444 IPC_SET_ARG2(call->data, arg1);
445 IPC_SET_ARG3(call->data, arg2);
446
447 if (slow)
448 IPC_SET_ARG4(call->data, arg3);
449
450 /*
451 * For system methods we deliberately don't
452 * overwrite ARG5.
453 */
454 } else {
455 IPC_SET_IMETHOD(call->data, imethod);
456 IPC_SET_ARG1(call->data, arg1);
457 IPC_SET_ARG2(call->data, arg2);
458 if (slow) {
459 IPC_SET_ARG3(call->data, arg3);
460 IPC_SET_ARG4(call->data, arg4);
461 IPC_SET_ARG5(call->data, arg5);
462 }
463 }
464 }
465
466 return ipc_forward(call, phone, &TASK->answerbox, mode);
467}
468
469/** Forward a received call to another destination - fast version.
470 *
471 * In case the original interface and method is a system method, ARG1, ARG2
472 * and ARG3 are overwritten in the forwarded message with the new method and
473 * the new arg1 and arg2, respectively. Otherwise the IMETHOD, ARG1 and ARG2
474 * are rewritten with the new interface and method, arg1 and arg2, respectively.
475 * Also note there is a set of immutable methods, for which the new method and
476 * arguments are not set and these values are ignored.
477 *
478 * @param callid Hash of the call to forward.
479 * @param phoneid Phone handle to use for forwarding.
480 * @param imethod New interface and method to use for the forwarded call.
481 * @param arg1 New value of the first argument for the forwarded call.
482 * @param arg2 New value of the second argument for the forwarded call.
483 * @param mode Flags that specify mode of the forward operation.
484 *
485 * @return 0 on succes, otherwise an error code.
486 *
487 */
488sysarg_t sys_ipc_forward_fast(sysarg_t callid, sysarg_t phoneid,
489 sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, unsigned int mode)
490{
491 return sys_ipc_forward_common(callid, phoneid, imethod, arg1, arg2, 0, 0,
492 0, mode, false);
493}
494
495/** Forward a received call to another destination - slow version.
496 *
497 * This function is the slow verision of the sys_ipc_forward_fast interface.
498 * It can copy all five new arguments and the new interface and method from
499 * the userspace. It naturally extends the functionality of the fast version.
500 * For system methods, it additionally stores the new value of arg3 to ARG4.
501 * For non-system methods, it additionally stores the new value of arg3, arg4
502 * and arg5, respectively, to ARG3, ARG4 and ARG5, respectively.
503 *
504 * @param callid Hash of the call to forward.
505 * @param phoneid Phone handle to use for forwarding.
506 * @param data Userspace address of the new IPC data.
507 * @param mode Flags that specify mode of the forward operation.
508 *
509 * @return 0 on succes, otherwise an error code.
510 *
511 */
512sysarg_t sys_ipc_forward_slow(sysarg_t callid, sysarg_t phoneid,
513 ipc_data_t *data, unsigned int mode)
514{
515 ipc_data_t newdata;
516 int rc = copy_from_uspace(&newdata.args, &data->args,
517 sizeof(newdata.args));
518 if (rc != 0)
519 return (sysarg_t) rc;
520
521 return sys_ipc_forward_common(callid, phoneid,
522 IPC_GET_IMETHOD(newdata), IPC_GET_ARG1(newdata),
523 IPC_GET_ARG2(newdata), IPC_GET_ARG3(newdata),
524 IPC_GET_ARG4(newdata), IPC_GET_ARG5(newdata), mode, true);
525}
526
527/** Answer an IPC call - fast version.
528 *
529 * This function can handle only two return arguments of payload, but is faster
530 * than the generic sys_ipc_answer().
531 *
532 * @param callid Hash of the call to be answered.
533 * @param retval Return value of the answer.
534 * @param arg1 Service-defined return value.
535 * @param arg2 Service-defined return value.
536 * @param arg3 Service-defined return value.
537 * @param arg4 Service-defined return value.
538 *
539 * @return 0 on success, otherwise an error code.
540 *
541 */
542sysarg_t sys_ipc_answer_fast(sysarg_t callid, sysarg_t retval,
543 sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4)
544{
545 /* Do not answer notification callids */
546 if (callid & IPC_CALLID_NOTIFICATION)
547 return 0;
548
549 call_t *call = get_call(callid);
550 if (!call)
551 return ENOENT;
552
553 ipc_data_t saved_data;
554 bool saved;
555
556 if (answer_need_old(call)) {
557 memcpy(&saved_data, &call->data, sizeof(call->data));
558 saved = true;
559 } else
560 saved = false;
561
562 IPC_SET_RETVAL(call->data, retval);
563 IPC_SET_ARG1(call->data, arg1);
564 IPC_SET_ARG2(call->data, arg2);
565 IPC_SET_ARG3(call->data, arg3);
566 IPC_SET_ARG4(call->data, arg4);
567
568 /*
569 * To achieve deterministic behavior, zero out arguments that are beyond
570 * the limits of the fast version.
571 */
572 IPC_SET_ARG5(call->data, 0);
573 int rc = answer_preprocess(call, saved ? &saved_data : NULL);
574
575 ipc_answer(&TASK->answerbox, call);
576 return rc;
577}
578
579/** Answer an IPC call.
580 *
581 * @param callid Hash of the call to be answered.
582 * @param data Userspace address of call data with the answer.
583 *
584 * @return 0 on success, otherwise an error code.
585 *
586 */
587sysarg_t sys_ipc_answer_slow(sysarg_t callid, ipc_data_t *data)
588{
589 /* Do not answer notification callids */
590 if (callid & IPC_CALLID_NOTIFICATION)
591 return 0;
592
593 call_t *call = get_call(callid);
594 if (!call)
595 return ENOENT;
596
597 ipc_data_t saved_data;
598 bool saved;
599
600 if (answer_need_old(call)) {
601 memcpy(&saved_data, &call->data, sizeof(call->data));
602 saved = true;
603 } else
604 saved = false;
605
606 int rc = copy_from_uspace(&call->data.args, &data->args,
607 sizeof(call->data.args));
608 if (rc != 0)
609 return rc;
610
611 rc = answer_preprocess(call, saved ? &saved_data : NULL);
612
613 ipc_answer(&TASK->answerbox, call);
614 return rc;
615}
616
617/** Hang up a phone.
618 *
619 * @param Phone handle of the phone to be hung up.
620 *
621 * @return 0 on success or an error code.
622 *
623 */
624sysarg_t sys_ipc_hangup(sysarg_t phoneid)
625{
626 phone_t *phone;
627
628 if (phone_get(phoneid, &phone) != EOK)
629 return ENOENT;
630
631 if (ipc_phone_hangup(phone))
632 return -1;
633
634 return 0;
635}
636
637/** Wait for an incoming IPC call or an answer.
638 *
639 * @param calldata Pointer to buffer where the call/answer data is stored.
640 * @param usec Timeout. See waitq_sleep_timeout() for explanation.
641 * @param flags Select mode of sleep operation. See waitq_sleep_timeout()
642 * for explanation.
643 *
644 * @return Hash of the call.
645 * If IPC_CALLID_NOTIFICATION bit is set in the hash, the
646 * call is a notification. IPC_CALLID_ANSWERED denotes an
647 * answer.
648 *
649 */
650sysarg_t sys_ipc_wait_for_call(ipc_data_t *calldata, uint32_t usec,
651 unsigned int flags)
652{
653 call_t *call;
654
655restart:
656
657#ifdef CONFIG_UDEBUG
658 udebug_stoppable_begin();
659#endif
660
661 call = ipc_wait_for_call(&TASK->answerbox, usec,
662 flags | SYNCH_FLAGS_INTERRUPTIBLE);
663
664#ifdef CONFIG_UDEBUG
665 udebug_stoppable_end();
666#endif
667
668 if (!call)
669 return 0;
670
671 if (call->flags & IPC_CALL_NOTIF) {
672 /* Set in_phone_hash to the interrupt counter */
673 call->data.phone = (void *) call->priv;
674
675 STRUCT_TO_USPACE(calldata, &call->data);
676
677 ipc_call_free(call);
678
679 return ((sysarg_t) call) | IPC_CALLID_NOTIFICATION;
680 }
681
682 if (call->flags & IPC_CALL_ANSWERED) {
683 process_answer(call);
684
685 if (call->flags & IPC_CALL_DISCARD_ANSWER) {
686 ipc_call_free(call);
687 goto restart;
688 }
689
690 STRUCT_TO_USPACE(&calldata->args, &call->data.args);
691 ipc_call_free(call);
692
693 return ((sysarg_t) call) | IPC_CALLID_ANSWERED;
694 }
695
696 if (process_request(&TASK->answerbox, call))
697 goto restart;
698
699 /* Include phone address('id') of the caller in the request,
700 * copy whole call->data, not only call->data.args */
701 if (STRUCT_TO_USPACE(calldata, &call->data)) {
702 /*
703 * The callee will not receive this call and no one else has
704 * a chance to answer it. Reply with the EPARTY error code.
705 */
706 ipc_data_t saved_data;
707 bool saved;
708
709 if (answer_need_old(call)) {
710 memcpy(&saved_data, &call->data, sizeof(call->data));
711 saved = true;
712 } else
713 saved = false;
714
715 IPC_SET_RETVAL(call->data, EPARTY);
716 (void) answer_preprocess(call, saved ? &saved_data : NULL);
717 ipc_answer(&TASK->answerbox, call);
718 return 0;
719 }
720
721 return (sysarg_t) call;
722}
723
724/** Interrupt one thread from sys_ipc_wait_for_call().
725 *
726 */
727sysarg_t sys_ipc_poke(void)
728{
729 waitq_unsleep(&TASK->answerbox.wq);
730 return EOK;
731}
732
733/** Connect an IRQ handler to a task.
734 *
735 * @param inr IRQ number.
736 * @param devno Device number.
737 * @param imethod Interface and method to be associated with the notification.
738 * @param ucode Uspace pointer to the top-half pseudocode.
739 *
740 * @return EPERM or a return code returned by ipc_irq_register().
741 *
742 */
743sysarg_t sys_irq_register(inr_t inr, devno_t devno, sysarg_t imethod,
744 irq_code_t *ucode)
745{
746 if (!(cap_get(TASK) & CAP_IRQ_REG))
747 return EPERM;
748
749 return ipc_irq_register(&TASK->answerbox, inr, devno, imethod, ucode);
750}
751
752/** Disconnect an IRQ handler from a task.
753 *
754 * @param inr IRQ number.
755 * @param devno Device number.
756 *
757 * @return Zero on success or EPERM on error.
758 *
759 */
760sysarg_t sys_irq_unregister(inr_t inr, devno_t devno)
761{
762 if (!(cap_get(TASK) & CAP_IRQ_REG))
763 return EPERM;
764
765 ipc_irq_unregister(&TASK->answerbox, inr, devno);
766
767 return 0;
768}
769
770#ifdef __32_BITS__
771
772/** Syscall connect to a task by ID (32 bits)
773 *
774 * @return Phone id on success, or negative error code.
775 *
776 */
777sysarg_t sys_ipc_connect_kbox(sysarg64_t *uspace_taskid)
778{
779#ifdef CONFIG_UDEBUG
780 sysarg64_t taskid;
781 int rc = copy_from_uspace(&taskid, uspace_taskid, sizeof(sysarg64_t));
782 if (rc != 0)
783 return (sysarg_t) rc;
784
785 return ipc_connect_kbox((task_id_t) taskid);
786#else
787 return (sysarg_t) ENOTSUP;
788#endif
789}
790
791#endif /* __32_BITS__ */
792
793#ifdef __64_BITS__
794
795/** Syscall connect to a task by ID (64 bits)
796 *
797 * @return Phone id on success, or negative error code.
798 *
799 */
800sysarg_t sys_ipc_connect_kbox(sysarg_t taskid)
801{
802#ifdef CONFIG_UDEBUG
803 return ipc_connect_kbox((task_id_t) taskid);
804#else
805 return (sysarg_t) ENOTSUP;
806#endif
807}
808
809#endif /* __64_BITS__ */
810
811/** @}
812 */
Note: See TracBrowser for help on using the repository browser.