Rev 2359 | Rev 2479 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2359 | Rev 2471 | ||
---|---|---|---|
Line 49... | Line 49... | ||
49 | #include <futex.h> |
49 | #include <futex.h> |
50 | #include <kernel/synch/synch.h> |
50 | #include <kernel/synch/synch.h> |
51 | #include <async.h> |
51 | #include <async.h> |
52 | #include <psthread.h> |
52 | #include <psthread.h> |
53 | 53 | ||
54 | /** Structure used for keeping track of sent async msgs |
54 | /** Structure used for keeping track of sent asynchronous calls and queing |
55 | * and queing unsent msgs |
55 | * unsent calls. |
56 | * |
- | |
57 | */ |
56 | */ |
58 | typedef struct { |
57 | typedef struct { |
59 | link_t list; |
58 | link_t list; |
60 | 59 | ||
61 | ipc_async_callback_t callback; |
60 | ipc_async_callback_t callback; |
Line 65... | Line 64... | ||
65 | struct { |
64 | struct { |
66 | ipc_call_t data; |
65 | ipc_call_t data; |
67 | int phoneid; |
66 | int phoneid; |
68 | } msg; |
67 | } msg; |
69 | }u; |
68 | } u; |
70 | pstid_t ptid; /**< Thread waiting for sending this msg */ |
69 | pstid_t ptid; /**< Pseudothread waiting for sending this call. */ |
71 | } async_call_t; |
70 | } async_call_t; |
72 | 71 | ||
73 | LIST_INITIALIZE(dispatched_calls); |
72 | LIST_INITIALIZE(dispatched_calls); |
74 | 73 | ||
75 | /* queued_calls is protcted by async_futex, because if the |
74 | /** List of asynchronous calls that were not accepted by kernel. |
- | 75 | * |
|
76 | * call cannot be sent into kernel, async framework is used |
76 | * It is protected by async_futex, because if the call cannot be sent into the |
77 | * automatically |
77 | * kernel, the async framework is used automatically. |
78 | */ |
78 | */ |
79 | LIST_INITIALIZE(queued_calls); /**< List of async calls that were not accepted |
79 | LIST_INITIALIZE(queued_calls); |
80 | * by kernel */ |
- | |
81 | 80 | ||
82 | static atomic_t ipc_futex = FUTEX_INITIALIZER; |
81 | static atomic_t ipc_futex = FUTEX_INITIALIZER; |
83 | 82 | ||
- | 83 | /** Make a fast synchronous call. |
|
- | 84 | * |
|
- | 85 | * Only one payload argument can be passed using this function. However, this |
|
84 | int ipc_call_sync(int phoneid, ipcarg_t method, ipcarg_t arg1, |
86 | * function is faster than the generic ipc_call_sync_3(). |
- | 87 | * |
|
- | 88 | * @param phoneid Phone handle for the call. |
|
85 | ipcarg_t *result) |
89 | * @param method Requested method. |
- | 90 | * @param arg1 Service-defined payload argument. |
|
- | 91 | * @param result If non-NULL, the return ARG1 will be stored there. |
|
- | 92 | * |
|
- | 93 | * @return Negative values represent errors returned by IPC. |
|
- | 94 | * Otherwise the RETVAL of the answer is returned. |
|
- | 95 | */ |
|
- | 96 | int ipc_call_sync(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t *result) |
|
86 | { |
97 | { |
87 | ipc_call_t resdata; |
98 | ipc_call_t resdata; |
88 | int callres; |
99 | int callres; |
89 | 100 | ||
90 | callres = __SYSCALL4(SYS_IPC_CALL_SYNC_FAST, phoneid, method, arg1, |
101 | callres = __SYSCALL4(SYS_IPC_CALL_SYNC_FAST, phoneid, method, arg1, |
Line 94... | Line 105... | ||
94 | if (result) |
105 | if (result) |
95 | *result = IPC_GET_ARG1(resdata); |
106 | *result = IPC_GET_ARG1(resdata); |
96 | return IPC_GET_RETVAL(resdata); |
107 | return IPC_GET_RETVAL(resdata); |
97 | } |
108 | } |
98 | 109 | ||
- | 110 | /** Make a synchronous call transmitting 3 arguments of payload. |
|
- | 111 | * |
|
- | 112 | * @param phoneid Phone handle for the call. |
|
- | 113 | * @param method Requested method. |
|
- | 114 | * @param arg1 Service-defined payload argument. |
|
- | 115 | * @param arg2 Service-defined payload argument. |
|
- | 116 | * @param arg3 Service-defined payload argument. |
|
- | 117 | * @param result1 If non-NULL, storage for the first return argument. |
|
- | 118 | * @param result2 If non-NULL, storage for the second return argument. |
|
99 | int ipc_call_sync_3(int phoneid, ipcarg_t method, ipcarg_t arg1, |
119 | * @param result3 If non-NULL, storage for the third return argument. |
- | 120 | * |
|
- | 121 | * @return Negative value means IPC error. |
|
- | 122 | * Otherwise the RETVAL of the answer. |
|
- | 123 | */ |
|
100 | ipcarg_t arg2, ipcarg_t arg3, |
124 | int ipc_call_sync_3(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2, |
101 | ipcarg_t *result1, ipcarg_t *result2, ipcarg_t *result3) |
125 | ipcarg_t arg3, ipcarg_t *result1, ipcarg_t *result2, ipcarg_t *result3) |
102 | { |
126 | { |
103 | ipc_call_t data; |
127 | ipc_call_t data; |
104 | int callres; |
128 | int callres; |
105 | 129 | ||
106 | IPC_SET_METHOD(data, method); |
130 | IPC_SET_METHOD(data, method); |
Line 120... | Line 144... | ||
120 | if (result3) |
144 | if (result3) |
121 | *result3 = IPC_GET_ARG3(data); |
145 | *result3 = IPC_GET_ARG3(data); |
122 | return IPC_GET_RETVAL(data); |
146 | return IPC_GET_RETVAL(data); |
123 | } |
147 | } |
124 | 148 | ||
125 | /** Syscall to send asynchronous message */ |
149 | /** Syscall to send asynchronous message. |
- | 150 | * |
|
- | 151 | * @param phoneid Phone handle for the call. |
|
- | 152 | * @param data Call data with the request. |
|
- | 153 | * |
|
- | 154 | * @return Hash of the call or an error code. |
|
- | 155 | */ |
|
126 | static ipc_callid_t _ipc_call_async(int phoneid, ipc_call_t *data) |
156 | static ipc_callid_t _ipc_call_async(int phoneid, ipc_call_t *data) |
127 | { |
157 | { |
128 | return __SYSCALL2(SYS_IPC_CALL_ASYNC, phoneid, (sysarg_t)data); |
158 | return __SYSCALL2(SYS_IPC_CALL_ASYNC, phoneid, (sysarg_t) data); |
129 | } |
159 | } |
130 | 160 | ||
131 | /** Prolog to ipc_async_send functions */ |
161 | /** Prolog to ipc_call_async_*() functions. |
- | 162 | * |
|
- | 163 | * @param private Argument for the answer/error callback. |
|
- | 164 | * @param callback Answer/error callback. |
|
- | 165 | * |
|
- | 166 | * @return New, partially initialized async_call structure or NULL. |
|
- | 167 | */ |
|
132 | static inline async_call_t *ipc_prepare_async(void *private, ipc_async_callback_t callback) |
168 | static inline async_call_t *ipc_prepare_async(void *private, |
- | 169 | ipc_async_callback_t callback) |
|
133 | { |
170 | { |
134 | async_call_t *call; |
171 | async_call_t *call; |
135 | 172 | ||
136 | call = malloc(sizeof(*call)); |
173 | call = malloc(sizeof(*call)); |
137 | if (!call) { |
174 | if (!call) { |
Line 143... | Line 180... | ||
143 | call->private = private; |
180 | call->private = private; |
144 | 181 | ||
145 | return call; |
182 | return call; |
146 | } |
183 | } |
147 | 184 | ||
148 | /** Epilogue of ipc_async_send functions */ |
185 | /** Epilogue of ipc_call_async_*() functions. |
- | 186 | * |
|
- | 187 | * @param callid Value returned by the SYS_IPC_CALL_ASYNC_* syscall. |
|
- | 188 | * @param phoneid Phone handle through which the call was made. |
|
- | 189 | * @param call async_call structure returned by ipc_prepare_async(). |
|
- | 190 | * @param can_preempt If non-zero, the current pseudo thread can be preempted |
|
- | 191 | * in this call. |
|
- | 192 | */ |
|
149 | static inline void ipc_finish_async(ipc_callid_t callid, int phoneid, |
193 | static inline void ipc_finish_async(ipc_callid_t callid, int phoneid, |
150 | async_call_t *call, int can_preempt) |
194 | async_call_t *call, int can_preempt) |
151 | { |
195 | { |
152 | if (!call) { /* Nothing to do regardless if failed or not */ |
196 | if (!call) { /* Nothing to do regardless if failed or not */ |
153 | futex_up(&ipc_futex); |
197 | futex_up(&ipc_futex); |
Line 180... | Line 224... | ||
180 | futex_up(&async_futex); |
224 | futex_up(&async_futex); |
181 | } |
225 | } |
182 | return; |
226 | return; |
183 | } |
227 | } |
184 | call->u.callid = callid; |
228 | call->u.callid = callid; |
185 | /* Add call to list of dispatched calls */ |
229 | /* Add call to the list of dispatched calls */ |
186 | list_append(&call->list, &dispatched_calls); |
230 | list_append(&call->list, &dispatched_calls); |
187 | futex_up(&ipc_futex); |
231 | futex_up(&ipc_futex); |
188 | 232 | ||
189 | } |
233 | } |
190 | 234 | ||
191 | /** Send asynchronous message |
235 | /** Make a fast asynchronous call. |
- | 236 | * |
|
- | 237 | * This function can only handle two arguments of payload. It is, however, |
|
- | 238 | * faster than the more generic ipc_call_async_3(). |
|
192 | * |
239 | * |
- | 240 | * Note that this function is a void function. |
|
- | 241 | * During normal opertation, answering this call will trigger the callback. |
|
193 | * - if fatal error, call callback handler with proper error code |
242 | * In case of fatal error, call the callback handler with the proper error code. |
194 | * - if message cannot be temporarily sent, add to queue |
243 | * If the call cannot be temporarily made, queue it. |
- | 244 | * |
|
- | 245 | * @param phoneid Phone handle for the call. |
|
- | 246 | * @param method Requested method. |
|
- | 247 | * @param arg1 Service-defined payload argument. |
|
- | 248 | * @param arg2 Service-defined payload argument. |
|
- | 249 | * @param private Argument to be passed to the answer/error callback. |
|
- | 250 | * @param callback Answer or error callback. |
|
- | 251 | * @param can_preempt If non-zero, the current pseudo thread will be preempted |
|
- | 252 | * in case the kernel temporarily refuses to accept more |
|
- | 253 | * asynchronous calls. |
|
195 | */ |
254 | */ |
196 | void ipc_call_async_2(int phoneid, ipcarg_t method, ipcarg_t arg1, |
255 | void ipc_call_async_2(int phoneid, ipcarg_t method, ipcarg_t arg1, |
197 | ipcarg_t arg2, void *private, |
256 | ipcarg_t arg2, void *private, ipc_async_callback_t callback, |
198 | ipc_async_callback_t callback, int can_preempt) |
257 | int can_preempt) |
199 | { |
258 | { |
200 | async_call_t *call = NULL; |
259 | async_call_t *call = NULL; |
201 | ipc_callid_t callid; |
260 | ipc_callid_t callid; |
202 | 261 | ||
203 | if (callback) { |
262 | if (callback) { |
204 | call = ipc_prepare_async(private, callback); |
263 | call = ipc_prepare_async(private, callback); |
205 | if (!call) |
264 | if (!call) |
206 | return; |
265 | return; |
207 | } |
266 | } |
208 | 267 | ||
- | 268 | /* |
|
209 | /* We need to make sure that we get callid before |
269 | * We need to make sure that we get callid before another thread |
210 | * another thread accesses the queue again */ |
270 | * accesses the queue again. |
- | 271 | */ |
|
211 | futex_down(&ipc_futex); |
272 | futex_down(&ipc_futex); |
212 | callid = __SYSCALL4(SYS_IPC_CALL_ASYNC_FAST, phoneid, method, arg1, arg2); |
273 | callid = __SYSCALL4(SYS_IPC_CALL_ASYNC_FAST, phoneid, method, arg1, |
- | 274 | arg2); |
|
213 | 275 | ||
214 | if (callid == IPC_CALLRET_TEMPORARY) { |
276 | if (callid == IPC_CALLRET_TEMPORARY) { |
215 | if (!call) { |
277 | if (!call) { |
216 | call = ipc_prepare_async(private, callback); |
278 | call = ipc_prepare_async(private, callback); |
217 | if (!call) |
279 | if (!call) |
Line 222... | Line 284... | ||
222 | IPC_SET_ARG2(call->u.msg.data, arg2); |
284 | IPC_SET_ARG2(call->u.msg.data, arg2); |
223 | } |
285 | } |
224 | ipc_finish_async(callid, phoneid, call, can_preempt); |
286 | ipc_finish_async(callid, phoneid, call, can_preempt); |
225 | } |
287 | } |
226 | 288 | ||
- | 289 | /** Make an asynchronous call transmitting the entire payload. |
|
- | 290 | * |
|
- | 291 | * Note that this function is a void function. |
|
- | 292 | * During normal opertation, answering this call will trigger the callback. |
|
- | 293 | * In case of fatal error, call the callback handler with the proper error code. |
|
- | 294 | * If the call cannot be temporarily made, queue it. |
|
- | 295 | * |
|
- | 296 | * @param phoneid Phone handle for the call. |
|
- | 297 | * @param method Requested method. |
|
- | 298 | * @param arg1 Service-defined payload argument. |
|
- | 299 | * @param arg2 Service-defined payload argument. |
|
- | 300 | * @param arg3 Service-defined payload argument. |
|
- | 301 | * @param private Argument to be passed to the answer/error callback. |
|
- | 302 | * @param callback Answer or error callback. |
|
- | 303 | * @param can_preempt If non-zero, the current pseudo thread will be preempted |
|
- | 304 | * in case the kernel temporarily refuses to accept more |
|
227 | /** Send asynchronous message |
305 | * asynchronous calls. |
228 | * |
306 | * |
229 | * - if fatal error, call callback handler with proper error code |
- | |
230 | * - if message cannot be temporarily sent, add to queue |
- | |
231 | */ |
307 | */ |
232 | void ipc_call_async_3(int phoneid, ipcarg_t method, ipcarg_t arg1, |
308 | void ipc_call_async_3(int phoneid, ipcarg_t method, ipcarg_t arg1, |
233 | ipcarg_t arg2, ipcarg_t arg3, void *private, |
309 | ipcarg_t arg2, ipcarg_t arg3, void *private, ipc_async_callback_t callback, |
234 | ipc_async_callback_t callback, int can_preempt) |
310 | int can_preempt) |
235 | { |
311 | { |
236 | async_call_t *call; |
312 | async_call_t *call; |
237 | ipc_callid_t callid; |
313 | ipc_callid_t callid; |
238 | 314 | ||
239 | call = ipc_prepare_async(private, callback); |
315 | call = ipc_prepare_async(private, callback); |
Line 242... | Line 318... | ||
242 | 318 | ||
243 | IPC_SET_METHOD(call->u.msg.data, method); |
319 | IPC_SET_METHOD(call->u.msg.data, method); |
244 | IPC_SET_ARG1(call->u.msg.data, arg1); |
320 | IPC_SET_ARG1(call->u.msg.data, arg1); |
245 | IPC_SET_ARG2(call->u.msg.data, arg2); |
321 | IPC_SET_ARG2(call->u.msg.data, arg2); |
246 | IPC_SET_ARG3(call->u.msg.data, arg3); |
322 | IPC_SET_ARG3(call->u.msg.data, arg3); |
- | 323 | /* |
|
247 | /* We need to make sure that we get callid before |
324 | * We need to make sure that we get callid before another thread accesses |
248 | * another thread accesses the queue again */ |
325 | * the queue again. |
- | 326 | */ |
|
249 | futex_down(&ipc_futex); |
327 | futex_down(&ipc_futex); |
250 | callid = _ipc_call_async(phoneid, &call->u.msg.data); |
328 | callid = _ipc_call_async(phoneid, &call->u.msg.data); |
251 | 329 | ||
252 | ipc_finish_async(callid, phoneid, call, can_preempt); |
330 | ipc_finish_async(callid, phoneid, call, can_preempt); |
253 | } |
331 | } |
254 | 332 | ||
255 | 333 | ||
256 | /** Send a fast answer to a received call. |
334 | /** Answer a received call - fast version. |
257 | * |
335 | * |
258 | * The fast answer makes use of passing retval and first two arguments in registers. |
336 | * The fast answer makes use of passing retval and first two arguments in |
259 | * If you need to return more, use the ipc_answer() instead. |
337 | * registers. If you need to return more, use the ipc_answer() instead. |
260 | * |
338 | * |
261 | * @param callid ID of the call being answered. |
339 | * @param callid Hash of the call being answered. |
262 | * @param retval Return value. |
340 | * @param retval Return value. |
263 | * @param arg1 First return argument. |
341 | * @param arg1 First return argument. |
264 | * @param arg2 Second return argument. |
342 | * @param arg2 Second return argument. |
265 | * |
343 | * |
266 | * @return Zero on success or a value from @ref errno.h on failure. |
344 | * @return Zero on success or a value from @ref errno.h on failure. |
Line 269... | Line 347... | ||
269 | ipcarg_t arg2) |
347 | ipcarg_t arg2) |
270 | { |
348 | { |
271 | return __SYSCALL4(SYS_IPC_ANSWER_FAST, callid, retval, arg1, arg2); |
349 | return __SYSCALL4(SYS_IPC_ANSWER_FAST, callid, retval, arg1, arg2); |
272 | } |
350 | } |
273 | 351 | ||
274 | /** Send a full answer to a received call. |
352 | /** Answer a received call - full version. |
275 | * |
353 | * |
276 | * @param callid ID of the call being answered. |
354 | * @param callid Hash of the call being answered. |
- | 355 | * @param call Call structure with the answer. |
|
277 | * @param call Call data. Must be already initialized by the responder. |
356 | * Must be already initialized by the responder. |
278 | * |
357 | * |
279 | * @return Zero on success or a value from @ref errno.h on failure. |
358 | * @return Zero on success or a value from @ref errno.h on failure. |
280 | */ |
359 | */ |
281 | ipcarg_t ipc_answer(ipc_callid_t callid, ipc_call_t *call) |
360 | ipcarg_t ipc_answer(ipc_callid_t callid, ipc_call_t *call) |
282 | { |
361 | { |
283 | return __SYSCALL2(SYS_IPC_ANSWER, callid, (sysarg_t) call); |
362 | return __SYSCALL2(SYS_IPC_ANSWER, callid, (sysarg_t) call); |
284 | } |
363 | } |
285 | 364 | ||
286 | 365 | ||
287 | /** Try to dispatch queed calls from async queue */ |
366 | /** Try to dispatch queued calls from the async queue. */ |
288 | static void try_dispatch_queued_calls(void) |
367 | static void try_dispatch_queued_calls(void) |
289 | { |
368 | { |
290 | async_call_t *call; |
369 | async_call_t *call; |
291 | ipc_callid_t callid; |
370 | ipc_callid_t callid; |
292 | 371 | ||
- | 372 | /** @todo |
|
293 | /* TODO: integrate intelligently ipc_futex, so that it |
373 | * Integrate intelligently ipc_futex, so that it is locked during |
294 | * is locked during ipc_call_async, until it is added |
374 | * ipc_call_async_*(), until it is added to dispatched_calls. |
295 | * to dispatched_calls |
- | |
296 | */ |
375 | */ |
297 | futex_down(&async_futex); |
376 | futex_down(&async_futex); |
298 | while (!list_empty(&queued_calls)) { |
377 | while (!list_empty(&queued_calls)) { |
299 | call = list_get_instance(queued_calls.next, async_call_t, |
378 | call = list_get_instance(queued_calls.next, async_call_t, list); |
300 | list); |
- | |
301 | - | ||
302 | callid = _ipc_call_async(call->u.msg.phoneid, |
379 | callid = _ipc_call_async(call->u.msg.phoneid, &call->u.msg.data); |
303 | &call->u.msg.data); |
- | |
304 | if (callid == IPC_CALLRET_TEMPORARY) { |
380 | if (callid == IPC_CALLRET_TEMPORARY) { |
305 | break; |
381 | break; |
306 | } |
382 | } |
307 | list_remove(&call->list); |
383 | list_remove(&call->list); |
308 | 384 | ||
Line 323... | Line 399... | ||
323 | futex_down(&async_futex); |
399 | futex_down(&async_futex); |
324 | } |
400 | } |
325 | futex_up(&async_futex); |
401 | futex_up(&async_futex); |
326 | } |
402 | } |
327 | 403 | ||
328 | /** Handle received answer |
404 | /** Handle a received answer. |
- | 405 | * |
|
- | 406 | * Find the hash of the answer and call the answer callback. |
|
329 | * |
407 | * |
330 | * TODO: Make it use hash table |
408 | * @todo Make it use hash table. |
331 | * |
409 | * |
332 | * @param callid Callid (with first bit set) of the answered call |
410 | * @param callid Hash of the received answer. |
- | 411 | * The answer has the same hash as the request OR'ed with |
|
- | 412 | * the IPC_CALLID_ANSWERED bit. |
|
- | 413 | * @param data Call data of the answer. |
|
333 | */ |
414 | */ |
334 | static void handle_answer(ipc_callid_t callid, ipc_call_t *data) |
415 | static void handle_answer(ipc_callid_t callid, ipc_call_t *data) |
335 | { |
416 | { |
336 | link_t *item; |
417 | link_t *item; |
337 | async_call_t *call; |
418 | async_call_t *call; |
Line 345... | Line 426... | ||
345 | if (call->u.callid == callid) { |
426 | if (call->u.callid == callid) { |
346 | list_remove(&call->list); |
427 | list_remove(&call->list); |
347 | futex_up(&ipc_futex); |
428 | futex_up(&ipc_futex); |
348 | if (call->callback) |
429 | if (call->callback) |
349 | call->callback(call->private, |
430 | call->callback(call->private, |
350 | IPC_GET_RETVAL(*data), |
431 | IPC_GET_RETVAL(*data), data); |
351 | data); |
- | |
352 | free(call); |
432 | free(call); |
353 | return; |
433 | return; |
354 | } |
434 | } |
355 | } |
435 | } |
356 | futex_up(&ipc_futex); |
436 | futex_up(&ipc_futex); |
357 | /* We may get here after async_msg, which doesn't register any callback */ |
- | |
358 | } |
437 | } |
359 | 438 | ||
360 | 439 | ||
361 | /** One cycle of ipc wait for call call |
440 | /** Wait for a first call to come. |
362 | * |
441 | * |
363 | * - dispatch ASYNC reoutines in the background |
- | |
364 | * @param call Space where the message is stored |
442 | * @param call Storage where the incoming call data will be stored. |
365 | * @param usec Timeout in microseconds |
443 | * @param usec Timeout in microseconds |
366 | * @param flags Flags passed to SYS_IPC_WAIT (blocking, nonblocking) |
444 | * @param flags Flags passed to SYS_IPC_WAIT (blocking, nonblocking). |
- | 445 | * |
|
367 | * @return Callid of the answer. |
446 | * @return Hash of the call. Note that certain bits have special |
- | 447 | * meaning. IPC_CALLID_ANSWERED will be set in an answer |
|
- | 448 | * and IPC_CALLID_NOTIFICATION is used for notifications. |
|
- | 449 | * |
|
368 | */ |
450 | */ |
369 | ipc_callid_t ipc_wait_cycle(ipc_call_t *call, uint32_t usec, int flags) |
451 | ipc_callid_t ipc_wait_cycle(ipc_call_t *call, uint32_t usec, int flags) |
370 | { |
452 | { |
371 | ipc_callid_t callid; |
453 | ipc_callid_t callid; |
372 | 454 | ||
Line 380... | Line 462... | ||
380 | return callid; |
462 | return callid; |
381 | } |
463 | } |
382 | 464 | ||
383 | /** Wait some time for an IPC call. |
465 | /** Wait some time for an IPC call. |
384 | * |
466 | * |
385 | * - dispatch ASYNC reoutines in the background |
467 | * The call will return after an answer is received. |
386 | * |
468 | * |
387 | * @param call Space where the message is stored |
469 | * @param call Storage where the incoming call data will be stored. |
388 | * @param usec Timeout in microseconds. |
470 | * @param usec Timeout in microseconds. |
- | 471 | * |
|
389 | * @return Callid of the answer. |
472 | * @return Hash of the answer. |
390 | */ |
473 | */ |
391 | ipc_callid_t ipc_wait_for_call_timeout(ipc_call_t *call, uint32_t usec) |
474 | ipc_callid_t ipc_wait_for_call_timeout(ipc_call_t *call, uint32_t usec) |
392 | { |
475 | { |
393 | ipc_callid_t callid; |
476 | ipc_callid_t callid; |
394 | 477 | ||
Line 399... | Line 482... | ||
399 | return callid; |
482 | return callid; |
400 | } |
483 | } |
401 | 484 | ||
402 | /** Check if there is an IPC call waiting to be picked up. |
485 | /** Check if there is an IPC call waiting to be picked up. |
403 | * |
486 | * |
404 | * - dispatch ASYNC reoutines in the background |
- | |
405 | * |
- | |
406 | * @param call Space where the message is stored |
487 | * @param call Storage where the incoming call will be stored. |
407 | * @return Callid of the answer. |
488 | * @return Hash of the answer. |
408 | */ |
489 | */ |
409 | ipc_callid_t ipc_trywait_for_call(ipc_call_t *call) |
490 | ipc_callid_t ipc_trywait_for_call(ipc_call_t *call) |
410 | { |
491 | { |
411 | ipc_callid_t callid; |
492 | ipc_callid_t callid; |
412 | 493 | ||
413 | do { |
494 | do { |
414 | callid = ipc_wait_cycle(call, SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NON_BLOCKING); |
495 | callid = ipc_wait_cycle(call, SYNCH_NO_TIMEOUT, |
- | 496 | SYNCH_FLAGS_NON_BLOCKING); |
|
415 | } while (callid & IPC_CALLID_ANSWERED); |
497 | } while (callid & IPC_CALLID_ANSWERED); |
416 | 498 | ||
417 | return callid; |
499 | return callid; |
418 | } |
500 | } |
419 | 501 | ||
420 | /** Ask destination to do a callback connection. |
502 | /** Ask destination to do a callback connection. |
421 | * |
503 | * |
422 | * @param phoneid Phone ID used for contacting the other side. |
504 | * @param phoneid Phone handle used for contacting the other side. |
423 | * @param arg1 User defined argument. |
505 | * @param arg1 Service-defined argument. |
424 | * @param arg2 User defined argument. |
506 | * @param arg2 Service-defined argument. |
425 | * @param phonehash Pointer to a place where the library will store an opaque |
507 | * @param phonehash Storage where the library will store an opaque |
426 | * identifier of the phone that will be used for incoming |
508 | * identifier of the phone that will be used for incoming |
- | 509 | * calls. This identifier can be used for connection |
|
427 | * calls. |
510 | * tracking. |
- | 511 | * |
|
428 | * @return Zero on success or a negative error code. |
512 | * @return Zero on success or a negative error code. |
429 | */ |
513 | */ |
430 | int ipc_connect_to_me(int phoneid, int arg1, int arg2, ipcarg_t *phonehash) |
514 | int ipc_connect_to_me(int phoneid, int arg1, int arg2, ipcarg_t *phonehash) |
431 | { |
515 | { |
432 | return ipc_call_sync_3(phoneid, IPC_M_CONNECT_TO_ME, arg1, arg2, 0, 0, 0, |
516 | return ipc_call_sync_3(phoneid, IPC_M_CONNECT_TO_ME, arg1, arg2, 0, 0, 0, |
433 | phonehash); |
517 | phonehash); |
434 | } |
518 | } |
435 | 519 | ||
436 | /** Ask through phone for a new connection to some service. |
520 | /** Ask through phone for a new connection to some service. |
437 | * |
521 | * |
438 | * @param phoneid Phone ID used for contacting the other side. |
522 | * @param phoneid Phone handle used for contacting the other side. |
439 | * @param arg1 User defined argument. |
523 | * @param arg1 User defined argument. |
440 | * @param arg2 User defined argument. |
524 | * @param arg2 User defined argument. |
441 | * |
525 | * |
442 | * @return New phone ID on success or a negative error code. |
526 | * @return New phone handle on success or a negative error code. |
443 | */ |
527 | */ |
444 | int ipc_connect_me_to(int phoneid, int arg1, int arg2) |
528 | int ipc_connect_me_to(int phoneid, int arg1, int arg2) |
445 | { |
529 | { |
446 | ipcarg_t newphid; |
530 | ipcarg_t newphid; |
447 | int res; |
531 | int res; |
Line 451... | Line 535... | ||
451 | if (res) |
535 | if (res) |
452 | return res; |
536 | return res; |
453 | return newphid; |
537 | return newphid; |
454 | } |
538 | } |
455 | 539 | ||
456 | /* Hang up specified phone */ |
540 | /** Hang up a phone. |
- | 541 | * |
|
- | 542 | * @param phoneid Handle of the phone to be hung up. |
|
- | 543 | * |
|
- | 544 | * @return Zero on success or a negative error code. |
|
- | 545 | */ |
|
457 | int ipc_hangup(int phoneid) |
546 | int ipc_hangup(int phoneid) |
458 | { |
547 | { |
459 | return __SYSCALL1(SYS_IPC_HANGUP, phoneid); |
548 | return __SYSCALL1(SYS_IPC_HANGUP, phoneid); |
460 | } |
549 | } |
461 | 550 | ||
Line 468... | Line 557... | ||
468 | * |
557 | * |
469 | * @return Value returned by the kernel. |
558 | * @return Value returned by the kernel. |
470 | */ |
559 | */ |
471 | int ipc_register_irq(int inr, int devno, int method, irq_code_t *ucode) |
560 | int ipc_register_irq(int inr, int devno, int method, irq_code_t *ucode) |
472 | { |
561 | { |
473 | return __SYSCALL4(SYS_IPC_REGISTER_IRQ, inr, devno, method, (sysarg_t) ucode); |
562 | return __SYSCALL4(SYS_IPC_REGISTER_IRQ, inr, devno, method, |
- | 563 | (sysarg_t) ucode); |
|
474 | } |
564 | } |
475 | 565 | ||
476 | /** Unregister IRQ notification. |
566 | /** Unregister IRQ notification. |
477 | * |
567 | * |
478 | * @param inr IRQ number. |
568 | * @param inr IRQ number. |
Line 483... | Line 573... | ||
483 | int ipc_unregister_irq(int inr, int devno) |
573 | int ipc_unregister_irq(int inr, int devno) |
484 | { |
574 | { |
485 | return __SYSCALL2(SYS_IPC_UNREGISTER_IRQ, inr, devno); |
575 | return __SYSCALL2(SYS_IPC_UNREGISTER_IRQ, inr, devno); |
486 | } |
576 | } |
487 | 577 | ||
- | 578 | /** Forward a received call to another destination. |
|
- | 579 | * |
|
- | 580 | * @param callid Hash of the call to forward. |
|
- | 581 | * @param phoneid Phone handle to use for forwarding. |
|
- | 582 | * @param method New method for the forwarded call. |
|
- | 583 | * @param arg1 New value of the first argument for the forwarded call. |
|
- | 584 | * |
|
- | 585 | * @return Zero on success or an error code. |
|
- | 586 | * |
|
- | 587 | * For non-system methods, the old method and arg1 are rewritten by the new |
|
- | 588 | * values. For system methods, the new method and arg1 are written to the old |
|
- | 589 | * arg1 and arg2, respectivelly. |
|
- | 590 | */ |
|
488 | int ipc_forward_fast(ipc_callid_t callid, int phoneid, int method, ipcarg_t arg1) |
591 | int ipc_forward_fast(ipc_callid_t callid, int phoneid, int method, ipcarg_t arg1) |
489 | { |
592 | { |
490 | return __SYSCALL4(SYS_IPC_FORWARD_FAST, callid, phoneid, method, arg1); |
593 | return __SYSCALL4(SYS_IPC_FORWARD_FAST, callid, phoneid, method, arg1); |
491 | } |
594 | } |
492 | 595 |