49,23 → 49,14 |
#include <mm/as.h> |
#include <print.h> |
|
#define GET_CHECK_PHONE(phone, phoneid, err) \ |
{ \ |
if (phoneid > IPC_MAX_PHONES) { \ |
err; \ |
} \ |
phone = &TASK->phones[phoneid]; \ |
#define GET_CHECK_PHONE(phone, phoneid, err) { \ |
if (phoneid > IPC_MAX_PHONES) { err; } \ |
phone = &TASK->phones[phoneid]; \ |
} |
|
#define STRUCT_TO_USPACE(dst, src) copy_to_uspace(dst, src, sizeof(*(src))) |
#define STRUCT_TO_USPACE(dst, src) copy_to_uspace(dst, src, sizeof(*(src))) |
|
/** Decide if the method is a system method. |
* |
* @param method Method to be decided. |
* |
* @return Return 1 if the method is a system method. |
* Otherwise return 0. |
*/ |
/** Return true if the method is a system method */ |
static inline int is_system_method(unative_t method) |
{ |
if (method <= IPC_M_LAST_SYSTEM) |
73,15 → 64,10 |
return 0; |
} |
|
/** Decide if the message with this method is forwardable. |
/** Return true if the message with this method is forwardable |
* |
* - some system messages may be forwarded, for some of them |
* it is useless |
* |
* @param method Method to be decided. |
* |
* @return Return 1 if the method is forwardable. |
* Otherwise return 0. |
*/ |
static inline int is_forwardable(unative_t method) |
{ |
91,18 → 77,13 |
return 1; |
} |
|
/****************************************************/ |
/* Functions that preprocess answer before sending |
* it to the recepient |
*/ |
|
/*********************************************************************** |
* Functions that preprocess answer before sending it to the recepient. |
***********************************************************************/ |
|
/** Decide if the caller (e.g. ipc_answer()) should save the old call contents |
* for answer_preprocess(). |
* |
* @param call Call structure to be decided. |
* |
* @return Return 1 if the old call contents should be saved. |
* Return 0 otherwise. |
/** Return true if the caller (ipc_answer) should save |
* the old call contents for answer_preprocess |
*/ |
static inline int answer_need_old(call_t *call) |
{ |
117,14 → 98,9 |
return 0; |
} |
|
/** Interpret process answer as control information. |
/** Interpret process answer as control information |
* |
* This function is called directly after sys_ipc_answer(). |
* |
* @param answer Call structure with the answer. |
* @param olddata Saved data of the request. |
* |
* @return Return 0 on success or an error code. |
* This function is called directly after sys_ipc_answer |
*/ |
static inline int answer_preprocess(call_t *answer, ipc_data_t *olddata) |
{ |
155,7 → 131,7 |
} else { |
/* The connection was accepted */ |
phone_connect(phoneid, &answer->sender->answerbox); |
/* Set 'phone hash' as arg3 of response */ |
/* Set 'phone identification' as arg3 of response */ |
IPC_SET_ARG3(answer->data, |
(unative_t) &TASK->phones[phoneid]); |
} |
205,11 → 181,9 |
return 0; |
} |
|
/** Called before the request is sent. |
/** Called before the request is sent |
* |
* @param call Call structure with the request. |
* |
* @return Return 0 on success, ELIMIT or EPERM on error. |
* @return 0 - no error, -1 - report error to user |
*/ |
static int request_preprocess(call_t *call) |
{ |
228,8 → 202,9 |
break; |
case IPC_M_AS_AREA_SEND: |
size = as_get_size(IPC_GET_ARG1(call->data)); |
if (!size) |
if (!size) { |
return EPERM; |
} |
IPC_SET_ARG2(call->data, size); |
break; |
default: |
238,14 → 213,12 |
return 0; |
} |
|
/******************************************************************************* |
* Functions called to process received call/answer before passing it to uspace. |
*******************************************************************************/ |
/****************************************************/ |
/* Functions called to process received call/answer |
* before passing to uspace |
*/ |
|
/** Do basic kernel processing of received call answer. |
* |
* @param call Call structure with the answer. |
*/ |
/** Do basic kernel processing of received call answer */ |
static void process_answer(call_t *call) |
{ |
if (IPC_GET_RETVAL(call->data) == EHANGUP && |
260,13 → 233,9 |
} |
} |
|
/** Do basic kernel processing of received call request. |
/** Do basic kernel processing of received call request |
* |
* @param box Destination answerbox structure. |
* @param call Call structure with the request. |
* |
* @return Return 0 if the call should be passed to userspace. |
* Return -1 if the call should be ignored. |
* @return 0 - the call should be passed to userspace, 1 - ignore call |
*/ |
static int process_request(answerbox_t *box, call_t *call) |
{ |
276,7 → 245,7 |
phoneid = phone_alloc(); |
if (phoneid < 0) { /* Failed to allocate phone */ |
IPC_SET_RETVAL(call->data, ELIMIT); |
ipc_answer(box, call); |
ipc_answer(box,call); |
return -1; |
} |
IPC_SET_ARG3(call->data, phoneid); |
284,19 → 253,10 |
return 0; |
} |
|
/** Make a fast call over IPC, wait for reply and return to user. |
/** Send a call over IPC, wait for reply, return to user |
* |
* This function can handle only one argument of payload, but is faster than |
* the generic function (i.e. sys_ipc_call_sync()). |
* |
* @param phoneid Phone handle for the call. |
* @param method Method of the call. |
* @param arg1 Service-defined payload argument. |
* @param data Address of userspace structure where the reply call will |
* be stored. |
* |
* @return Returns 0 on success. |
* Return ENOENT if there is no such phone handle. |
* @return Call identification, returns -1 on fatal error, |
-2 on 'Too many async request, handle answers first |
*/ |
unative_t sys_ipc_call_sync_fast(unative_t phoneid, unative_t method, |
unative_t arg1, ipc_data_t *data) |
311,25 → 271,17 |
IPC_SET_METHOD(call.data, method); |
IPC_SET_ARG1(call.data, arg1); |
|
if (!(res = request_preprocess(&call))) { |
if (!(res=request_preprocess(&call))) { |
ipc_call_sync(phone, &call); |
process_answer(&call); |
} else { |
} else |
IPC_SET_RETVAL(call.data, res); |
} |
STRUCT_TO_USPACE(&data->args, &call.data.args); |
|
return 0; |
} |
|
/** Make a synchronous IPC call allowing to transmit the entire payload. |
* |
* @param phoneid Phone handle for the call. |
* @param question Userspace address of call data with the request. |
* @param reply Userspace address of call data where to store the answer. |
* |
* @return Zero on success or an error code. |
*/ |
/** Synchronous IPC call allowing to send whole message */ |
unative_t sys_ipc_call_sync(unative_t phoneid, ipc_data_t *question, |
ipc_data_t *reply) |
{ |
346,7 → 298,7 |
|
GET_CHECK_PHONE(phone, phoneid, return ENOENT); |
|
if (!(res = request_preprocess(&call))) { |
if (!(res=request_preprocess(&call))) { |
ipc_call_sync(phone, &call); |
process_answer(&call); |
} else |
359,9 → 311,9 |
return 0; |
} |
|
/** Check that the task did not exceed the allowed limit of asynchronous calls. |
/** Check that the task did not exceed allowed limit |
* |
* @return Return 0 if limit not reached or -1 if limit exceeded. |
* @return 0 - Limit OK, -1 - limit exceeded |
*/ |
static int check_call_limit(void) |
{ |
372,20 → 324,10 |
return 0; |
} |
|
/** Make a fast asynchronous call over IPC. |
/** Send an asynchronous call over ipc |
* |
* This function can only handle two arguments of payload, but is faster than |
* the generic function sys_ipc_call_async(). |
* |
* @param phoneid Phone handle for the call. |
* @param method Method of the call. |
* @param arg1 Service-defined payload argument. |
* @param arg2 Service-defined payload argument. |
* |
* @return Return call hash on success. |
* Return IPC_CALLRET_FATAL in case of a fatal error and |
* IPC_CALLRET_TEMPORARY if there are too many pending |
* asynchronous requests; answers should be handled first. |
* @return Call identification, returns -1 on fatal error, |
-2 on 'Too many async request, handle answers first |
*/ |
unative_t sys_ipc_call_async_fast(unative_t phoneid, unative_t method, |
unative_t arg1, unative_t arg2) |
413,12 → 355,9 |
return (unative_t) call; |
} |
|
/** Make an asynchronous IPC call allowing to transmit the entire payload. |
/** Synchronous IPC call allowing to send whole message |
* |
* @param phoneid Phone handle for the call. |
* @param data Userspace address of call data with the request. |
* |
* @return See sys_ipc_call_async_fast(). |
* @return The same as sys_ipc_call_async |
*/ |
unative_t sys_ipc_call_async(unative_t phoneid, ipc_data_t *data) |
{ |
447,22 → 386,12 |
return (unative_t) call; |
} |
|
/** Forward a received call to another destination. |
/** Forward received call to another destination |
* |
* @param callid Hash of the call to forward. |
* @param phoneid Phone handle to use for forwarding. |
* @param method New method to use for the forwarded call. |
* @param arg1 New value of the first argument for the forwarded call. |
* The arg1 and arg2 are changed in the forwarded message |
* |
* @return Return 0 on succes, otherwise return an error code. |
* |
* In case the original method is a system method, ARG1 and ARG2 are overwritten |
* in the forwarded message with the new method and the new arg1, respectively. |
* Otherwise the METHOD and ARG1 are rewritten with the new method and arg1, |
* respectively. |
* |
* Warning: If implementing non-fast version, make sure that |
* ARG3 is not rewritten for certain system IPC |
* arg3 is not rewritten for certain system IPC |
*/ |
unative_t sys_ipc_forward_fast(unative_t callid, unative_t phoneid, |
unative_t method, unative_t arg1) |
505,18 → 434,7 |
return ipc_forward(call, phone, &TASK->answerbox); |
} |
|
/** Answer an IPC call - fast version. |
* |
* This function can handle only two return arguments of payload, but is faster |
* than the generic sys_ipc_answer(). |
* |
* @param callid Hash of the call to be answered. |
* @param retval Return value of the answer. |
* @param arg1 Service-defined return value. |
* @param arg2 Service-defined return value. |
* |
* @return Return 0 on success, otherwise return an error code. |
*/ |
/** Send IPC answer */ |
unative_t sys_ipc_answer_fast(unative_t callid, unative_t retval, |
unative_t arg1, unative_t arg2) |
{ |
547,13 → 465,7 |
return rc; |
} |
|
/** Answer an IPC call. |
* |
* @param callid Hash of the call to be answered. |
* @param data Userspace address of call data with the answer. |
* |
* @return Return 0 on success, otherwise return an error code. |
*/ |
/** Send IPC answer */ |
unative_t sys_ipc_answer(unative_t callid, ipc_data_t *data) |
{ |
call_t *call; |
585,11 → 497,8 |
return rc; |
} |
|
/** Hang up a phone. |
/** Hang up the phone |
* |
* @param Phone handle of the phone to be hung up. |
* |
* @return Return 0 on success or an error code. |
*/ |
unative_t sys_ipc_hangup(int phoneid) |
{ |
603,7 → 512,7 |
return 0; |
} |
|
/** Wait for an incoming IPC call or an answer. |
/** Wait for incoming ipc call or answer |
* |
* @param calldata Pointer to buffer where the call/answer data is stored. |
* @param usec Timeout. See waitq_sleep_timeout() for explanation. |
610,10 → 519,7 |
* @param flags Select mode of sleep operation. See waitq_sleep_timeout() |
* for explanation. |
* |
* @return Hash of the call. |
* If IPC_CALLID_NOTIFICATION bit is set in the hash, the |
* call is a notification. IPC_CALLID_ANSWERED denotes an |
* answer. |
* @return Callid, if callid & 1, then the call is answer |
*/ |
unative_t sys_ipc_wait_for_call(ipc_data_t *calldata, uint32_t usec, int flags) |
{ |
635,7 → 541,7 |
|
ipc_call_free(call); |
|
return ((unative_t) call) | IPC_CALLID_NOTIFICATION; |
return ((unative_t)call) | IPC_CALLID_NOTIFICATION; |
} |
|
if (call->flags & IPC_CALL_ANSWERED) { |
653,7 → 559,7 |
STRUCT_TO_USPACE(&calldata->args, &call->data.args); |
ipc_call_free(call); |
|
return ((unative_t) call) | IPC_CALLID_ANSWERED; |
return ((unative_t)call) | IPC_CALLID_ANSWERED; |
} |
|
if (process_request(&TASK->answerbox, call)) |
667,14 → 573,14 |
return (unative_t)call; |
} |
|
/** Connect an IRQ handler to a task. |
/** Connect irq handler to task. |
* |
* @param inr IRQ number. |
* @param devno Device number. |
* @param method Method to be associated with the notification. |
* @param ucode Uspace pointer to the top-half pseudocode. |
* @param inr IRQ number. |
* @param devno Device number. |
* @param method Method to be associated with the notification. |
* @param ucode Uspace pointer to the top-half pseudocode. |
* |
* @return EPERM or a return code returned by ipc_irq_register(). |
* @return EPERM or a return code returned by ipc_irq_register(). |
*/ |
unative_t sys_ipc_register_irq(inr_t inr, devno_t devno, unative_t method, |
irq_code_t *ucode) |
685,12 → 591,10 |
return ipc_irq_register(&TASK->answerbox, inr, devno, method, ucode); |
} |
|
/** Disconnect an IRQ handler from a task. |
/** Disconnect irq handler from task. |
* |
* @param inr IRQ number. |
* @param devno Device number. |
* |
* @return Zero on success or EPERM on error.. |
* @param inr IRQ number. |
* @param devno Device number. |
*/ |
unative_t sys_ipc_unregister_irq(inr_t inr, devno_t devno) |
{ |