Subversion Repositories HelenOS-historic

Rev

Rev 1443 | Rev 1489 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1443 Rev 1463
1
/*
1
/*
2
 * Copyright (C) 2006 Ondrej Palkovsky
2
 * Copyright (C) 2006 Ondrej Palkovsky
3
 * All rights reserved.
3
 * All rights reserved.
4
 *
4
 *
5
 * Redistribution and use in source and binary forms, with or without
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
6
 * modification, are permitted provided that the following conditions
7
 * are met:
7
 * are met:
8
 *
8
 *
9
 * - Redistributions of source code must retain the above copyright
9
 * - Redistributions of source code must retain the above copyright
10
 *   notice, this list of conditions and the following disclaimer.
10
 *   notice, this list of conditions and the following disclaimer.
11
 * - Redistributions in binary form must reproduce the above copyright
11
 * - Redistributions in binary form must reproduce the above copyright
12
 *   notice, this list of conditions and the following disclaimer in the
12
 *   notice, this list of conditions and the following disclaimer in the
13
 *   documentation and/or other materials provided with the distribution.
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
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.
15
 *   derived from this software without specific prior written permission.
16
 *
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
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
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
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
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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
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.
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 */
27
 */
28
 
28
 
29
#include <ipc/ipc.h>
29
#include <ipc/ipc.h>
30
#include <libc.h>
30
#include <libc.h>
31
#include <malloc.h>
31
#include <malloc.h>
32
#include <errno.h>
32
#include <errno.h>
33
#include <libadt/list.h>
33
#include <libadt/list.h>
34
#include <stdio.h>
34
#include <stdio.h>
35
#include <unistd.h>
35
#include <unistd.h>
36
#include <futex.h>
36
#include <futex.h>
37
#include <kernel/synch/synch.h>
37
#include <kernel/synch/synch.h>
-
 
38
#include <async.h>
-
 
39
#include <psthread.h>
38
 
40
 
39
/** Structure used for keeping track of sent async msgs
41
/** Structure used for keeping track of sent async msgs
40
 * and queing unsent msgs
42
 * and queing unsent msgs
41
 *
43
 *
42
 */
44
 */
43
typedef struct {
45
typedef struct {
44
    link_t list;
46
    link_t list;
45
 
47
 
46
    ipc_async_callback_t callback;
48
    ipc_async_callback_t callback;
47
    void *private;
49
    void *private;
48
    union {
50
    union {
49
        ipc_callid_t callid;
51
        ipc_callid_t callid;
50
        struct {
52
        struct {
51
            ipc_call_t data;
53
            ipc_call_t data;
52
            int phoneid;
54
            int phoneid;
53
        } msg;
55
        } msg;
54
    }u;
56
    }u;
-
 
57
    pstid_t ptid;   /**< Thread waiting for sending this msg */
55
} async_call_t;
58
} async_call_t;
56
 
59
 
57
LIST_INITIALIZE(dispatched_calls);
60
LIST_INITIALIZE(dispatched_calls);
-
 
61
 
-
 
62
/* queued_calls is protcted by async_futex, because if the
-
 
63
 * call cannot be sent into kernel, async framework is used
-
 
64
 * automatically
-
 
65
 */
58
LIST_INITIALIZE(queued_calls);
66
LIST_INITIALIZE(queued_calls); /**< List of async calls that were not accepted
-
 
67
                *   by kernel */
59
 
68
 
60
static atomic_t ipc_futex = FUTEX_INITIALIZER;
69
static atomic_t ipc_futex = FUTEX_INITIALIZER;
61
 
70
 
62
int ipc_call_sync(int phoneid, ipcarg_t method, ipcarg_t arg1,
71
int ipc_call_sync(int phoneid, ipcarg_t method, ipcarg_t arg1,
63
          ipcarg_t *result)
72
          ipcarg_t *result)
64
{
73
{
65
    ipc_call_t resdata;
74
    ipc_call_t resdata;
66
    int callres;
75
    int callres;
67
   
76
   
68
    callres = __SYSCALL4(SYS_IPC_CALL_SYNC_FAST, phoneid, method, arg1,
77
    callres = __SYSCALL4(SYS_IPC_CALL_SYNC_FAST, phoneid, method, arg1,
69
                 (sysarg_t)&resdata);
78
                 (sysarg_t)&resdata);
70
    if (callres)
79
    if (callres)
71
        return callres;
80
        return callres;
72
    if (result)
81
    if (result)
73
        *result = IPC_GET_ARG1(resdata);
82
        *result = IPC_GET_ARG1(resdata);
74
    return IPC_GET_RETVAL(resdata);
83
    return IPC_GET_RETVAL(resdata);
75
}
84
}
76
 
85
 
77
int ipc_call_sync_3(int phoneid, ipcarg_t method, ipcarg_t arg1,
86
int ipc_call_sync_3(int phoneid, ipcarg_t method, ipcarg_t arg1,
78
            ipcarg_t arg2, ipcarg_t arg3,
87
            ipcarg_t arg2, ipcarg_t arg3,
79
            ipcarg_t *result1, ipcarg_t *result2, ipcarg_t *result3)
88
            ipcarg_t *result1, ipcarg_t *result2, ipcarg_t *result3)
80
{
89
{
81
    ipc_call_t data;
90
    ipc_call_t data;
82
    int callres;
91
    int callres;
83
 
92
 
84
    IPC_SET_METHOD(data, method);
93
    IPC_SET_METHOD(data, method);
85
    IPC_SET_ARG1(data, arg1);
94
    IPC_SET_ARG1(data, arg1);
86
    IPC_SET_ARG2(data, arg2);
95
    IPC_SET_ARG2(data, arg2);
87
    IPC_SET_ARG3(data, arg3);
96
    IPC_SET_ARG3(data, arg3);
88
 
97
 
89
    callres = __SYSCALL3(SYS_IPC_CALL_SYNC, phoneid, (sysarg_t)&data,
98
    callres = __SYSCALL3(SYS_IPC_CALL_SYNC, phoneid, (sysarg_t)&data,
90
                 (sysarg_t)&data);
99
                 (sysarg_t)&data);
91
    if (callres)
100
    if (callres)
92
        return callres;
101
        return callres;
93
 
102
 
94
    if (result1)
103
    if (result1)
95
        *result1 = IPC_GET_ARG1(data);
104
        *result1 = IPC_GET_ARG1(data);
96
    if (result2)
105
    if (result2)
97
        *result2 = IPC_GET_ARG2(data);
106
        *result2 = IPC_GET_ARG2(data);
98
    if (result3)
107
    if (result3)
99
        *result3 = IPC_GET_ARG3(data);
108
        *result3 = IPC_GET_ARG3(data);
100
    return IPC_GET_RETVAL(data);
109
    return IPC_GET_RETVAL(data);
101
}
110
}
102
 
111
 
103
/** Syscall to send asynchronous message */
112
/** Syscall to send asynchronous message */
104
static  ipc_callid_t _ipc_call_async(int phoneid, ipc_call_t *data)
113
static  ipc_callid_t _ipc_call_async(int phoneid, ipc_call_t *data)
105
{
114
{
106
    return __SYSCALL2(SYS_IPC_CALL_ASYNC, phoneid, (sysarg_t)data);
115
    return __SYSCALL2(SYS_IPC_CALL_ASYNC, phoneid, (sysarg_t)data);
107
}
116
}
108
 
117
 
109
/** Send asynchronous message
118
/** Send asynchronous message
110
 *
119
 *
111
 * - if fatal error, call callback handler with proper error code
120
 * - if fatal error, call callback handler with proper error code
112
 * - if message cannot be temporarily sent, add to queue
121
 * - if message cannot be temporarily sent, add to queue
113
 */
122
 */
114
void ipc_call_async_2(int phoneid, ipcarg_t method, ipcarg_t arg1,
123
void ipc_call_async_2(int phoneid, ipcarg_t method, ipcarg_t arg1,
115
              ipcarg_t arg2, void *private,
124
              ipcarg_t arg2, void *private,
116
              ipc_async_callback_t callback)
125
              ipc_async_callback_t callback)
117
{
126
{
118
    async_call_t *call;
127
    async_call_t *call;
119
    ipc_callid_t callid;
128
    ipc_callid_t callid;
120
 
129
 
121
    call = malloc(sizeof(*call));
130
    call = malloc(sizeof(*call));
122
    if (!call) {
131
    if (!call) {
123
        if (callback)
132
        if (callback)
124
            callback(private, ENOMEM, NULL);
133
            callback(private, ENOMEM, NULL);
125
        return;
134
        return;
126
    }
135
    }
-
 
136
 
-
 
137
    call->callback = callback;
-
 
138
    call->private = private;
127
       
139
 
-
 
140
    /* We need to make sure that we get callid before
-
 
141
     * another thread accesses the queue again */
-
 
142
    futex_down(&ipc_futex);
128
    callid = __SYSCALL4(SYS_IPC_CALL_ASYNC_FAST, phoneid, method, arg1, arg2);
143
    callid = __SYSCALL4(SYS_IPC_CALL_ASYNC_FAST, phoneid, method, arg1, arg2);
129
    if (callid == IPC_CALLRET_FATAL) {
144
    if (callid == IPC_CALLRET_FATAL) {
-
 
145
        futex_up(&ipc_futex);
130
        /* Call asynchronous handler with error code */
146
        /* Call asynchronous handler with error code */
131
        if (callback)
147
        if (callback)
132
            callback(private, ENOENT, NULL);
148
            callback(private, ENOENT, NULL);
133
        free(call);
149
        free(call);
134
        return;
150
        return;
135
    }
151
    }
136
 
152
 
137
    call->callback = callback;
-
 
138
    call->private = private;
-
 
139
 
-
 
140
    if (callid == IPC_CALLRET_TEMPORARY) {
153
    if (callid == IPC_CALLRET_TEMPORARY) {
141
        /* Add asynchronous call to queue of non-dispatched async calls */
154
        futex_up(&ipc_futex);
-
 
155
 
142
        call->u.msg.phoneid = phoneid;
156
        call->u.msg.phoneid = phoneid;
143
        IPC_SET_METHOD(call->u.msg.data, method);
157
        IPC_SET_METHOD(call->u.msg.data, method);
144
        IPC_SET_ARG1(call->u.msg.data, arg1);
158
        IPC_SET_ARG1(call->u.msg.data, arg1);
145
        IPC_SET_ARG2(call->u.msg.data, arg2);
159
        IPC_SET_ARG2(call->u.msg.data, arg2);
146
       
160
 
-
 
161
        call->ptid = psthread_get_id();
147
        futex_down(&ipc_futex);
162
        futex_down(&async_futex);
148
        list_append(&call->list, &queued_calls);
163
        list_append(&call->list, &queued_calls);
-
 
164
 
149
        futex_up(&ipc_futex);
165
        psthread_schedule_next_adv(PS_TO_MANAGER);
-
 
166
        /* Async futex unlocked by previous call */
150
        return;
167
        return;
151
    }
168
    }
152
    call->u.callid = callid;
169
    call->u.callid = callid;
153
    /* Add call to list of dispatched calls */
170
    /* Add call to list of dispatched calls */
154
    futex_down(&ipc_futex);
-
 
155
    list_append(&call->list, &dispatched_calls);
171
    list_append(&call->list, &dispatched_calls);
156
    futex_up(&ipc_futex);
172
    futex_up(&ipc_futex);
157
}
173
}
158
 
174
 
159
 
175
 
160
/** Send a fast answer to a received call.
176
/** Send a fast answer to a received call.
161
 *
177
 *
162
 * The fast answer makes use of passing retval and first two arguments in registers.
178
 * The fast answer makes use of passing retval and first two arguments in registers.
163
 * If you need to return more, use the ipc_answer() instead.
179
 * If you need to return more, use the ipc_answer() instead.
164
 *
180
 *
165
 * @param callid ID of the call being answered.
181
 * @param callid ID of the call being answered.
166
 * @param retval Return value.
182
 * @param retval Return value.
167
 * @param arg1 First return argument.
183
 * @param arg1 First return argument.
168
 * @param arg2 Second return argument.
184
 * @param arg2 Second return argument.
169
 *
185
 *
170
 * @return Zero on success or a value from @ref errno.h on failure.
186
 * @return Zero on success or a value from @ref errno.h on failure.
171
 */
187
 */
172
ipcarg_t ipc_answer_fast(ipc_callid_t callid, ipcarg_t retval, ipcarg_t arg1,
188
ipcarg_t ipc_answer_fast(ipc_callid_t callid, ipcarg_t retval, ipcarg_t arg1,
173
        ipcarg_t arg2)
189
        ipcarg_t arg2)
174
{
190
{
175
    return __SYSCALL4(SYS_IPC_ANSWER_FAST, callid, retval, arg1, arg2);
191
    return __SYSCALL4(SYS_IPC_ANSWER_FAST, callid, retval, arg1, arg2);
176
}
192
}
177
 
193
 
178
/** Send a full answer to a received call.
194
/** Send a full answer to a received call.
179
 *
195
 *
180
 * @param callid ID of the call being answered.
196
 * @param callid ID of the call being answered.
181
 * @param call Call data. Must be already initialized by the responder.
197
 * @param call Call data. Must be already initialized by the responder.
182
 *
198
 *
183
 * @return Zero on success or a value from @ref errno.h on failure.
199
 * @return Zero on success or a value from @ref errno.h on failure.
184
 */
200
 */
185
ipcarg_t ipc_answer(ipc_callid_t callid, ipc_call_t *call)
201
ipcarg_t ipc_answer(ipc_callid_t callid, ipc_call_t *call)
186
{
202
{
187
    return __SYSCALL2(SYS_IPC_ANSWER, callid, (sysarg_t) call);
203
    return __SYSCALL2(SYS_IPC_ANSWER, callid, (sysarg_t) call);
188
}
204
}
189
 
205
 
190
 
206
 
191
/** Try to dispatch queed calls from async queue */
207
/** Try to dispatch queed calls from async queue */
192
static void try_dispatch_queued_calls(void)
208
static void try_dispatch_queued_calls(void)
193
{
209
{
194
    async_call_t *call;
210
    async_call_t *call;
195
    ipc_callid_t callid;
211
    ipc_callid_t callid;
196
 
212
 
-
 
213
    /* TODO: integrate intelligently ipc_futex, so that it
-
 
214
     * is locked during ipc_call_async, until it is added
-
 
215
     * to dispatched_calls
-
 
216
     */
197
    futex_down(&ipc_futex);
217
    futex_down(&async_futex);
198
    while (!list_empty(&queued_calls)) {
218
    while (!list_empty(&queued_calls)) {
199
        call = list_get_instance(queued_calls.next, async_call_t,
219
        call = list_get_instance(queued_calls.next, async_call_t,
200
                     list);
220
                     list);
201
 
221
 
202
        callid = _ipc_call_async(call->u.msg.phoneid,
222
        callid = _ipc_call_async(call->u.msg.phoneid,
203
                     &call->u.msg.data);
223
                     &call->u.msg.data);
204
        if (callid == IPC_CALLRET_TEMPORARY)
224
        if (callid == IPC_CALLRET_TEMPORARY) {
205
            break;
225
            break;
-
 
226
        }
206
        list_remove(&call->list);
227
        list_remove(&call->list);
207
 
228
 
-
 
229
        futex_up(&async_futex);
-
 
230
        psthread_add_ready(call->ptid);
-
 
231
       
208
        if (callid == IPC_CALLRET_FATAL) {
232
        if (callid == IPC_CALLRET_FATAL) {
209
            futex_up(&ipc_futex);
-
 
210
            if (call->callback)
233
            if (call->callback)
211
                call->callback(call->private, ENOENT, NULL);
234
                call->callback(call->private, ENOENT, NULL);
212
            free(call);
235
            free(call);
213
            futex_down(&ipc_futex);
-
 
214
        } else {
236
        } else {
215
            call->u.callid = callid;
237
            call->u.callid = callid;
-
 
238
            futex_down(&ipc_futex);
216
            list_append(&call->list, &dispatched_calls);
239
            list_append(&call->list, &dispatched_calls);
-
 
240
            futex_up(&ipc_futex);
217
        }
241
        }
-
 
242
        futex_down(&async_futex);
218
    }
243
    }
219
    futex_up(&ipc_futex);
244
    futex_up(&async_futex);
220
}
245
}
221
 
246
 
222
/** Handle received answer
247
/** Handle received answer
223
 *
248
 *
224
 * TODO: Make it use hash table
249
 * TODO: Make it use hash table
225
 *
250
 *
226
 * @param callid Callid (with first bit set) of the answered call
251
 * @param callid Callid (with first bit set) of the answered call
227
 */
252
 */
228
static void handle_answer(ipc_callid_t callid, ipc_call_t *data)
253
static void handle_answer(ipc_callid_t callid, ipc_call_t *data)
229
{
254
{
230
    link_t *item;
255
    link_t *item;
231
    async_call_t *call;
256
    async_call_t *call;
232
 
257
 
233
    callid &= ~IPC_CALLID_ANSWERED;
258
    callid &= ~IPC_CALLID_ANSWERED;
234
   
259
   
235
    futex_down(&ipc_futex);
260
    futex_down(&ipc_futex);
236
    for (item = dispatched_calls.next; item != &dispatched_calls;
261
    for (item = dispatched_calls.next; item != &dispatched_calls;
237
         item = item->next) {
262
         item = item->next) {
238
        call = list_get_instance(item, async_call_t, list);
263
        call = list_get_instance(item, async_call_t, list);
239
        if (call->u.callid == callid) {
264
        if (call->u.callid == callid) {
240
            list_remove(&call->list);
265
            list_remove(&call->list);
241
            futex_up(&ipc_futex);
266
            futex_up(&ipc_futex);
242
            if (call->callback)
267
            if (call->callback)
243
                call->callback(call->private,
268
                call->callback(call->private,
244
                           IPC_GET_RETVAL(*data),
269
                           IPC_GET_RETVAL(*data),
245
                           data);
270
                           data);
246
            free(call);
271
            free(call);
247
            return;
272
            return;
248
        }
273
        }
249
    }
274
    }
250
    futex_up(&ipc_futex);
275
    futex_up(&ipc_futex);
251
    printf("Received unidentified answer: %P!!!\n", callid);
276
    printf("Received unidentified answer: %P!!!\n", callid);
252
}
277
}
253
 
278
 
254
 
279
 
255
/** One cycle of ipc wait for call call
280
/** One cycle of ipc wait for call call
256
 *
281
 *
257
 * - dispatch ASYNC reoutines in the background
282
 * - dispatch ASYNC reoutines in the background
258
 * @param call Space where the message is stored
283
 * @param call Space where the message is stored
259
 * @param usec Timeout in microseconds
284
 * @param usec Timeout in microseconds
260
 * @param flags Flags passed to SYS_IPC_WAIT (blocking, nonblocking)
285
 * @param flags Flags passed to SYS_IPC_WAIT (blocking, nonblocking)
261
 * @return Callid of the answer.
286
 * @return Callid of the answer.
262
 */
287
 */
263
ipc_callid_t ipc_wait_cycle(ipc_call_t *call, uint32_t usec, int flags)
288
ipc_callid_t ipc_wait_cycle(ipc_call_t *call, uint32_t usec, int flags)
264
{
289
{
265
    ipc_callid_t callid;
290
    ipc_callid_t callid;
266
 
291
 
267
    try_dispatch_queued_calls();
-
 
268
   
-
 
269
    callid = __SYSCALL3(SYS_IPC_WAIT, (sysarg_t) call, usec, flags);
292
    callid = __SYSCALL3(SYS_IPC_WAIT, (sysarg_t) call, usec, flags);
270
    /* Handle received answers */
293
    /* Handle received answers */
271
    if (callid & IPC_CALLID_ANSWERED)
294
    if (callid & IPC_CALLID_ANSWERED) {
272
        handle_answer(callid, call);
295
        handle_answer(callid, call);
-
 
296
        try_dispatch_queued_calls();
-
 
297
    }
273
 
298
 
274
    return callid;
299
    return callid;
275
}
300
}
276
 
301
 
277
/** Wait some time for an IPC call.
302
/** Wait some time for an IPC call.
278
 *
303
 *
279
 * - dispatch ASYNC reoutines in the background
304
 * - dispatch ASYNC reoutines in the background
280
 * @param call Space where the message is stored
305
 * @param call Space where the message is stored
281
 * @param usec Timeout in microseconds.
306
 * @param usec Timeout in microseconds.
282
 * @return Callid of the answer.
307
 * @return Callid of the answer.
283
 */
308
 */
284
ipc_callid_t ipc_wait_for_call_timeout(ipc_call_t *call, uint32_t usec)
309
ipc_callid_t ipc_wait_for_call_timeout(ipc_call_t *call, uint32_t usec)
285
{
310
{
286
    ipc_callid_t callid;
311
    ipc_callid_t callid;
287
 
312
 
288
    do {
313
    do {
289
        callid = ipc_wait_cycle(call, usec, SYNCH_BLOCKING);
314
        callid = ipc_wait_cycle(call, usec, SYNCH_BLOCKING);
290
    } while (callid & IPC_CALLID_ANSWERED);
315
    } while (callid & IPC_CALLID_ANSWERED);
291
 
316
 
292
    return callid;
317
    return callid;
293
}
318
}
294
 
319
 
295
/** Check if there is an IPC call waiting to be picked up.
320
/** Check if there is an IPC call waiting to be picked up.
296
 *
321
 *
297
 * - dispatch ASYNC reoutines in the background
322
 * - dispatch ASYNC reoutines in the background
298
 * @param call Space where the message is stored
323
 * @param call Space where the message is stored
299
 * @return Callid of the answer.
324
 * @return Callid of the answer.
300
 */
325
 */
301
ipc_callid_t ipc_trywait_for_call(ipc_call_t *call)
326
ipc_callid_t ipc_trywait_for_call(ipc_call_t *call)
302
{
327
{
303
    ipc_callid_t callid;
328
    ipc_callid_t callid;
304
 
329
 
305
    do {
330
    do {
306
        callid = ipc_wait_cycle(call, SYNCH_NO_TIMEOUT, SYNCH_NON_BLOCKING);
331
        callid = ipc_wait_cycle(call, SYNCH_NO_TIMEOUT, SYNCH_NON_BLOCKING);
307
    } while (callid & IPC_CALLID_ANSWERED);
332
    } while (callid & IPC_CALLID_ANSWERED);
308
 
333
 
309
    return callid;
334
    return callid;
310
}
335
}
311
 
336
 
312
/** Ask destination to do a callback connection
337
/** Ask destination to do a callback connection
313
 *
338
 *
314
 * @return 0 - OK, error code
339
 * @return 0 - OK, error code
315
 */
340
 */
316
int ipc_connect_to_me(int phoneid, int arg1, int arg2, ipcarg_t *phone)
341
int ipc_connect_to_me(int phoneid, int arg1, int arg2, ipcarg_t *phone)
317
{
342
{
318
    return ipc_call_sync_3(phoneid, IPC_M_CONNECT_TO_ME, arg1,
343
    return ipc_call_sync_3(phoneid, IPC_M_CONNECT_TO_ME, arg1,
319
                   arg2, 0, 0, 0, phone);
344
                   arg2, 0, 0, 0, phone);
320
}
345
}
321
 
346
 
322
/** Ask through phone for a new connection to some service
347
/** Ask through phone for a new connection to some service
323
 *
348
 *
324
 * @return new phoneid - OK, error code
349
 * @return new phoneid - OK, error code
325
 */
350
 */
326
int ipc_connect_me_to(int phoneid, int arg1, int arg2)
351
int ipc_connect_me_to(int phoneid, int arg1, int arg2)
327
{
352
{
328
    ipcarg_t newphid;
353
    ipcarg_t newphid;
329
    int res;
354
    int res;
330
 
355
 
331
    res =  ipc_call_sync_3(phoneid, IPC_M_CONNECT_ME_TO, arg1,
356
    res =  ipc_call_sync_3(phoneid, IPC_M_CONNECT_ME_TO, arg1,
332
                   arg2, 0, 0, 0, &newphid);
357
                   arg2, 0, 0, 0, &newphid);
333
    if (res)
358
    if (res)
334
        return res;
359
        return res;
335
    return newphid;
360
    return newphid;
336
}
361
}
337
 
362
 
338
/* Hang up specified phone */
363
/* Hang up specified phone */
339
int ipc_hangup(int phoneid)
364
int ipc_hangup(int phoneid)
340
{
365
{
341
    return __SYSCALL1(SYS_IPC_HANGUP, phoneid);
366
    return __SYSCALL1(SYS_IPC_HANGUP, phoneid);
342
}
367
}
343
 
368
 
344
int ipc_register_irq(int irq, irq_code_t *ucode)
369
int ipc_register_irq(int irq, irq_code_t *ucode)
345
{
370
{
346
    return __SYSCALL2(SYS_IPC_REGISTER_IRQ, irq, (sysarg_t) ucode);
371
    return __SYSCALL2(SYS_IPC_REGISTER_IRQ, irq, (sysarg_t) ucode);
347
}
372
}
348
 
373
 
349
int ipc_unregister_irq(int irq)
374
int ipc_unregister_irq(int irq)
350
{
375
{
351
    return __SYSCALL1(SYS_IPC_UNREGISTER_IRQ, irq);
376
    return __SYSCALL1(SYS_IPC_UNREGISTER_IRQ, irq);
352
}
377
}
353
 
378
 
354
int ipc_forward_fast(ipc_callid_t callid, int phoneid, int method, ipcarg_t arg1)
379
int ipc_forward_fast(ipc_callid_t callid, int phoneid, int method, ipcarg_t arg1)
355
{
380
{
356
    return __SYSCALL4(SYS_IPC_FORWARD_FAST, callid, phoneid, method, arg1);
381
    return __SYSCALL4(SYS_IPC_FORWARD_FAST, callid, phoneid, method, arg1);
357
}
382
}
358
 
383
 
359
 
384
 
360
/** Open shared memory connection over specified phoneid
385
/** Open shared memory connection over specified phoneid
361
 *
386
 *
362
 *
387
 *
363
 * Allocate as_area, notify the other side about our intention
388
 * Allocate as_area, notify the other side about our intention
364
 * to open the connection
389
 * to open the connection
365
 *
390
 *
366
 * @return Connection id identifying this connection
391
 * @return Connection id identifying this connection
367
 */
392
 */
368
//int ipc_dgr_open(int pohoneid, size_t bufsize)
393
//int ipc_dgr_open(int pohoneid, size_t bufsize)
369
//{
394
//{
370
    /* Find new file descriptor in local descriptor table */
395
    /* Find new file descriptor in local descriptor table */
371
    /* Create AS_area, initialize structures */
396
    /* Create AS_area, initialize structures */
372
    /* Send AS to other side, handle error states */
397
    /* Send AS to other side, handle error states */
373
 
398
 
374
//}
399
//}
375
/*
400
/*
376
void ipc_dgr_close(int cid)
401
void ipc_dgr_close(int cid)
377
{
402
{
378
}
403
}
379
 
404
 
380
void * ipc_dgr_alloc(int cid, size_t size)
405
void * ipc_dgr_alloc(int cid, size_t size)
381
{
406
{
382
}
407
}
383
 
408
 
384
void ipc_dgr_free(int cid, void *area)
409
void ipc_dgr_free(int cid, void *area)
385
{
410
{
386
 
411
 
387
}
412
}
388
 
413
 
389
int ipc_dgr_send(int cid, void *area)
414
int ipc_dgr_send(int cid, void *area)
390
{
415
{
391
}
416
}
392
 
417
 
393
 
418
 
394
int ipc_dgr_send_data(int cid, void *data, size_t size)
419
int ipc_dgr_send_data(int cid, void *data, size_t size)
395
{
420
{
396
}
421
}
397
 
422
 
398
*/
423
*/
399
 
424