Subversion Repositories HelenOS

Rev

Rev 2359 | Go to most recent revision | Show entire file | Ignore 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 64... Line 63...
64
        ipc_callid_t callid;
63
        ipc_callid_t callid;
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,
91
                 (sysarg_t)&resdata);
102
        (sysarg_t) &resdata);
92
    if (callres)
103
    if (callres)
93
        return callres;
104
        return callres;
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);
107
    IPC_SET_ARG1(data, arg1);
131
    IPC_SET_ARG1(data, arg1);
108
    IPC_SET_ARG2(data, arg2);
132
    IPC_SET_ARG2(data, arg2);
109
    IPC_SET_ARG3(data, arg3);
133
    IPC_SET_ARG3(data, arg3);
110
 
134
 
111
    callres = __SYSCALL3(SYS_IPC_CALL_SYNC, phoneid, (sysarg_t)&data,
135
    callres = __SYSCALL3(SYS_IPC_CALL_SYNC, phoneid, (sysarg_t) &data,
112
                 (sysarg_t)&data);
136
        (sysarg_t) &data);
113
    if (callres)
137
    if (callres)
114
        return callres;
138
        return callres;
115
 
139
 
116
    if (result1)
140
    if (result1)
117
        *result1 = IPC_GET_ARG1(data);
141
        *result1 = IPC_GET_ARG1(data);
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);
154
        return;
198
        return;
155
    }
199
    }
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.
192
 *
236
 *
-
 
237
 * This function can only handle two arguments of payload. It is, however,
-
 
238
 * faster than the more generic ipc_call_async_3().
-
 
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.
267
 */
345
 */
268
ipcarg_t ipc_answer_fast(ipc_callid_t callid, ipcarg_t retval, ipcarg_t arg1,
346
ipcarg_t ipc_answer_fast(ipc_callid_t callid, ipcarg_t retval, ipcarg_t arg1,
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;
338
 
419
 
339
    callid &= ~IPC_CALLID_ANSWERED;
420
    callid &= ~IPC_CALLID_ANSWERED;
340
   
421
   
341
    futex_down(&ipc_futex);
422
    futex_down(&ipc_futex);
342
    for (item = dispatched_calls.next; item != &dispatched_calls;
423
    for (item = dispatched_calls.next; item != &dispatched_calls;
343
         item = item->next) {
424
        item = item->next) {
344
        call = list_get_instance(item, async_call_t, list);
425
        call = list_get_instance(item, async_call_t, list);
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
 
462
/** Register IRQ notification.
551
/** Register IRQ notification.
463
 *
552
 *
464
 * @param inr IRQ number.
553
 * @param inr       IRQ number.
465
 * @param devno Device number of the device generating inr.
554
 * @param devno     Device number of the device generating inr.
466
 * @param method Use this method for notifying me.
555
 * @param method    Use this method for notifying me.
467
 * @param ucode Top-half pseudocode handler.
556
 * @param ucode     Top-half pseudocode handler.
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.
479
 * @param devno Device number of the device generating inr.
569
 * @param devno     Device number of the device generating inr.
480
 *
570
 *
481
 * @return Value returned by the kernel.
571
 * @return      Value returned by the kernel.
482
 */
572
 */
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