2
* Copyright (c) 2006 Ondrej Palkovsky
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
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.
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.
29
/** @addtogroup genericipc
38
/* Length of data being transfered with IPC call */
39
/* - the uspace may not be able to utilize full length */
40
#define IPC_CALL_LEN 6
42
/** Maximum active async calls per thread */
44
#define IPC_MAX_ASYNC_CALLS 4
46
#define IPC_MAX_ASYNC_CALLS 4000
51
/** This is answer to a call */
52
#define IPC_CALL_ANSWERED (1 << 0)
53
/** This call will not be freed on error */
54
#define IPC_CALL_STATIC_ALLOC (1 << 1)
55
/** Answer will not be passed to userspace, will be discarded */
56
#define IPC_CALL_DISCARD_ANSWER (1 << 2)
57
/** Call was forwarded */
58
#define IPC_CALL_FORWARDED (1 << 3)
59
/** Identify connect_me_to answer */
60
#define IPC_CALL_CONN_ME_TO (1 << 4)
61
/** Interrupt notification */
62
#define IPC_CALL_NOTIF (1 << 5)
65
* Bits used in call hashes.
66
* The addresses are aligned at least to 4 that is why we can use the 2 least
67
* significant bits of the call address.
69
/** Type of this call is 'answer' */
70
#define IPC_CALLID_ANSWERED 1
71
/** Type of this call is 'notification' */
72
#define IPC_CALLID_NOTIFICATION 2
74
/* Return values from sys_ipc_call_async(). */
75
#define IPC_CALLRET_FATAL -1
76
#define IPC_CALLRET_TEMPORARY -2
79
/* Macros for manipulating calling data */
80
#define IPC_SET_RETVAL(data, retval) ((data).args[0] = (retval))
81
#define IPC_SET_METHOD(data, val) ((data).args[0] = (val))
82
#define IPC_SET_ARG1(data, val) ((data).args[1] = (val))
83
#define IPC_SET_ARG2(data, val) ((data).args[2] = (val))
84
#define IPC_SET_ARG3(data, val) ((data).args[3] = (val))
85
#define IPC_SET_ARG4(data, val) ((data).args[4] = (val))
86
#define IPC_SET_ARG5(data, val) ((data).args[5] = (val))
88
#define IPC_GET_METHOD(data) ((data).args[0])
89
#define IPC_GET_RETVAL(data) ((data).args[0])
91
#define IPC_GET_ARG1(data) ((data).args[1])
92
#define IPC_GET_ARG2(data) ((data).args[2])
93
#define IPC_GET_ARG3(data) ((data).args[3])
94
#define IPC_GET_ARG4(data) ((data).args[4])
95
#define IPC_GET_ARG5(data) ((data).args[5])
97
/* Well known phone descriptors */
100
/* Forwarding flags. */
101
#define IPC_FF_NONE 0
103
* The call will be routed as though it was initially sent via the phone used to
104
* forward it. This feature is intended to support the situation in which the
105
* forwarded call needs to be handled by the same connection fibril as any other
106
* calls that were initially sent by the forwarder to the same destination. This
107
* flag has no imapct on routing replies.
109
#define IPC_FF_ROUTE_FROM_ME (1 << 0)
111
/* System-specific methods - only through special syscalls
112
* These methods have special behaviour
114
/** Clone connection.
116
* The calling task clones one of its phones for the callee.
118
* - ARG1 - The caller sets ARG1 to the phone of the cloned connection.
119
* - The callee gets the new phone from ARG1.
120
* - on answer, the callee acknowledges the new connection by sending EOK back
121
* or the kernel closes it
123
#define IPC_M_CONNECTION_CLONE 1
124
/** Protocol for CONNECT - ME
126
* Through this call, the recipient learns about the new cloned connection.
128
* - ARG5 - the kernel sets ARG5 to contain the hash of the used phone
129
* - on asnwer, the callee acknowledges the new connection by sending EOK back
130
* or the kernel closes it
132
#define IPC_M_CONNECT_ME 2
133
/** Protocol for CONNECT - TO - ME
135
* Calling process asks the callee to create a callback connection,
136
* so that it can start initiating new messages.
138
* The protocol for negotiating is:
139
* - sys_connect_to_me - sends a message IPC_M_CONNECT_TO_ME
140
* - recipient - upon receipt tries to allocate new phone
141
* - if it fails, responds with ELIMIT
142
* - passes call to userspace. If userspace
143
* responds with error, phone is deallocated and
144
* error is sent back to caller. Otherwise
145
* the call is accepted and the response is sent back.
146
* - the allocated phoneid is passed to userspace
147
* (on the receiving side) as ARG5 of the call.
149
#define IPC_M_CONNECT_TO_ME 3
150
/** Protocol for CONNECT - ME - TO
152
* Calling process asks the callee to create for him a new connection.
153
* E.g. the caller wants a name server to connect him to print server.
155
* The protocol for negotiating is:
156
* - sys_connect_me_to - send a synchronous message to name server
157
* indicating that it wants to be connected to some
159
* - arg1/2/3 are user specified, arg5 contains
160
* address of the phone that should be connected
161
* (TODO: it leaks to userspace)
162
* - recipient - if ipc_answer == 0, then accept connection
163
* - otherwise connection refused
164
* - recepient may forward message.
167
#define IPC_M_CONNECT_ME_TO 4
168
/** This message is sent to answerbox when the phone
171
#define IPC_M_PHONE_HUNGUP 5
173
/** Send as_area over IPC.
174
* - ARG1 - source as_area base address
175
* - ARG2 - size of source as_area (filled automatically by kernel)
176
* - ARG3 - flags of the as_area being sent
178
* on answer, the recipient must set:
179
* - ARG1 - dst as_area base adress
181
#define IPC_M_SHARE_OUT 6
183
/** Receive as_area over IPC.
184
* - ARG1 - destination as_area base address
185
* - ARG2 - destination as_area size
186
* - ARG3 - user defined argument
188
* on answer, the recipient must set:
190
* - ARG1 - source as_area base address
191
* - ARG2 - flags that will be used for sharing
193
#define IPC_M_SHARE_IN 7
195
/** Send data to another address space over IPC.
196
* - ARG1 - source address space virtual address
197
* - ARG2 - size of data to be copied, may be overriden by the recipient
199
* on answer, the recipient must set:
201
* - ARG1 - final destination address space virtual address
202
* - ARG2 - final size of data to be copied
204
#define IPC_M_DATA_WRITE 8
206
/** Receive data from another address space over IPC.
207
* - ARG1 - destination virtual address in the source address space
208
* - ARG2 - size of data to be received, may be cropped by the recipient
210
* on answer, the recipient must set:
212
* - ARG1 - source virtual address in the destination address space
213
* - ARG2 - final size of data to be copied
215
#define IPC_M_DATA_READ 9
217
/** Debug the recipient.
218
* - ARG1 - specifies the debug method (from udebug_method_t)
219
* - other arguments are specific to the debug method
221
#define IPC_M_DEBUG_ALL 10
223
/* Well-known methods */
224
#define IPC_M_LAST_SYSTEM 511
225
#define IPC_M_PING 512
227
#define IPC_FIRST_USER_METHOD 1024
231
#define IPC_MAX_PHONES 16
233
#include <synch/spinlock.h>
234
#include <synch/mutex.h>
235
#include <synch/waitq.h>
241
/** Phone is free and can be allocated */
243
/** Phone is connecting somewhere */
244
IPC_PHONE_CONNECTING,
245
/** Phone is connected */
247
/** Phone is hung up, waiting for answers to come */
249
/** Phone was hungup from server */
253
/** Structure identifying phone (in TASK structure) */
257
struct answerbox *callee;
258
ipc_phone_state_t state;
259
atomic_t active_calls;
262
typedef struct answerbox {
263
SPINLOCK_DECLARE(lock);
269
/** Phones connected to this answerbox. */
270
link_t connected_phones;
271
/** Received calls. */
273
link_t dispatched_calls; /* Should be hash table in the future */
275
/** Answered calls. */
278
SPINLOCK_DECLARE(irq_lock);
279
/** Notifications from IRQ handlers. */
281
/** IRQs with notifications to this answerbox. */
286
unative_t args[IPC_CALL_LEN];
295
/** Identification of the caller. */
297
/** The caller box is different from sender->answerbox for synchronous
299
answerbox_t *callerbox;
301
/** Private data to internal IPC. */
304
/** Data passed from/to userspace. */
307
/** Buffer for IPC_M_DATA_WRITE and IPC_M_DATA_READ. */
311
* The forward operation can masquerade the caller phone. For those
312
* cases, we must keep it aside so that the answer is processed
315
phone_t *caller_phone;
318
extern void ipc_init(void);
319
extern call_t * ipc_wait_for_call(answerbox_t *, uint32_t, int);
320
extern void ipc_answer(answerbox_t *, call_t *);
321
extern int ipc_call(phone_t *, call_t *);
322
extern int ipc_call_sync(phone_t *, call_t *);
323
extern void ipc_phone_init(phone_t *);
324
extern void ipc_phone_connect(phone_t *, answerbox_t *);
325
extern void ipc_call_free(call_t *);
326
extern call_t * ipc_call_alloc(int);
327
extern void ipc_answerbox_init(answerbox_t *, struct task *);
328
extern void ipc_call_static_init(call_t *);
329
extern void task_print_list(void);
330
extern int ipc_forward(call_t *, phone_t *, answerbox_t *, int);
331
extern void ipc_cleanup(void);
332
extern int ipc_phone_hangup(phone_t *);
333
extern void ipc_backsend_err(phone_t *, call_t *, unative_t);
334
extern void ipc_print_task(task_id_t);
335
extern void ipc_answerbox_slam_phones(answerbox_t *, bool);
336
extern void ipc_cleanup_call_list(link_t *);
338
extern answerbox_t *ipc_phone_0;