Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/ipc/sysipc.c

    r057d21a r8add9ca5  
    4949#include <syscall/copy.h>
    5050#include <security/cap.h>
     51#include <console/console.h>
    5152#include <mm/as.h>
    5253#include <print.h>
     
    5657 * requests.
    5758 */
    58 #define DATA_XFER_LIMIT         (64 * 1024)
    59 
    60 #define GET_CHECK_PHONE(phone, phoneid, err) \
    61 { \
    62         if (phoneid > IPC_MAX_PHONES) { \
    63                 err; \
    64         } \
    65         phone = &TASK->phones[phoneid]; \
    66 }
    67 
    68 #define STRUCT_TO_USPACE(dst, src)      copy_to_uspace(dst, src, sizeof(*(src)))
    69 
    70 /** Decide if the method is a system method.
    71  *
    72  * @param method        Method to be decided.
    73  *
    74  * @return              Return 1 if the method is a system method.
    75  *                      Otherwise return 0.
    76  */
    77 static inline int method_is_system(unative_t method)
    78 {
    79         if (method <= IPC_M_LAST_SYSTEM)
    80                 return 1;
    81         return 0;
    82 }
    83 
    84 /** Decide if the message with this method is forwardable.
    85  *
    86  * - some system messages may be forwarded, for some of them
    87  *   it is useless
    88  *
    89  * @param method        Method to be decided.
    90  *
    91  * @return              Return 1 if the method is forwardable.
    92  *                      Otherwise return 0.
    93  */
    94 static inline int method_is_forwardable(unative_t method)
    95 {
    96         switch (method) {
     59#define DATA_XFER_LIMIT  (64 * 1024)
     60
     61#define STRUCT_TO_USPACE(dst, src)  copy_to_uspace((dst), (src), sizeof(*(src)))
     62
     63/** Get phone from the current task by ID.
     64 *
     65 * @param phoneid Phone ID.
     66 * @param phone   Place to store pointer to phone.
     67 *
     68 * @return EOK on success, EINVAL if ID is invalid.
     69 *
     70 */
     71static int phone_get(sysarg_t phoneid, phone_t **phone)
     72{
     73        if (phoneid >= IPC_MAX_PHONES)
     74                return EINVAL;
     75       
     76        *phone = &TASK->phones[phoneid];
     77        return EOK;
     78}
     79
     80/** Decide if the interface and method is a system method.
     81 *
     82 * @param imethod Interface and method to be decided.
     83 *
     84 * @return True if the interface and method is a system
     85 *         interface and method.
     86 *
     87 */
     88static inline bool method_is_system(sysarg_t imethod)
     89{
     90        if (imethod <= IPC_M_LAST_SYSTEM)
     91                return true;
     92       
     93        return false;
     94}
     95
     96/** Decide if the message with this interface and method is forwardable.
     97 *
     98 * Some system messages may be forwarded, for some of them
     99 * it is useless.
     100 *
     101 * @param imethod Interface and method to be decided.
     102 *
     103 * @return True if the interface and method is forwardable.
     104 *
     105 */
     106static inline bool method_is_forwardable(sysarg_t imethod)
     107{
     108        switch (imethod) {
    97109        case IPC_M_CONNECTION_CLONE:
    98110        case IPC_M_CONNECT_ME:
    99111        case IPC_M_PHONE_HUNGUP:
    100112                /* This message is meant only for the original recipient. */
    101                 return 0;
     113                return false;
    102114        default:
    103                 return 1;
    104         }
    105 }
    106 
    107 /** Decide if the message with this method is immutable on forward.
    108  *
    109  * - some system messages may be forwarded but their content cannot be altered
    110  *
    111  * @param method        Method to be decided.
    112  *
    113  * @return              Return 1 if the method is immutable on forward.
    114  *                      Otherwise return 0.
    115  */
    116 static inline int method_is_immutable(unative_t method)
    117 {
    118         switch (method) {
     115                return true;
     116        }
     117}
     118
     119/** Decide if the message with this interface and method is immutable on forward.
     120 *
     121 * Some system messages may be forwarded but their content cannot be altered.
     122 *
     123 * @param imethod Interface and method to be decided.
     124 *
     125 * @return True if the interface and method is immutable on forward.
     126 *
     127 */
     128static inline bool method_is_immutable(sysarg_t imethod)
     129{
     130        switch (imethod) {
    119131        case IPC_M_SHARE_OUT:
    120132        case IPC_M_SHARE_IN:
    121133        case IPC_M_DATA_WRITE:
    122134        case IPC_M_DATA_READ:
    123                 return 1;
    124                 break;
     135                return true;
    125136        default:
    126                 return 0;
     137                return false;
    127138        }
    128139}
     
    136147 * for answer_preprocess().
    137148 *
    138  * @param call          Call structure to be decided.
    139  *
    140  * @return              Return 1 if the old call contents should be saved.
    141  *                      Return 0 otherwise.
    142  */
    143 static inline int answer_need_old(call_t *call)
    144 {
    145         switch (IPC_GET_METHOD(call->data)) {
     149 * @param call Call structure to be decided.
     150 *
     151 * @return true if the old call contents should be saved.
     152 *
     153 */
     154static inline bool answer_need_old(call_t *call)
     155{
     156        switch (IPC_GET_IMETHOD(call->data)) {
    146157        case IPC_M_CONNECTION_CLONE:
    147158        case IPC_M_CONNECT_ME:
     
    152163        case IPC_M_DATA_WRITE:
    153164        case IPC_M_DATA_READ:
    154                 return 1;
     165                return true;
    155166        default:
    156                 return 0;
     167                return false;
    157168        }
    158169}
     
    162173 * This function is called directly after sys_ipc_answer().
    163174 *
    164  * @param answer        Call structure with the answer.
    165  * @param olddata       Saved data of the request.
    166  *
    167  * @return              Return 0 on success or an error code.
     175 * @param answer  Call structure with the answer.
     176 * @param olddata Saved data of the request.
     177 *
     178 * @return Return 0 on success or an error code.
     179 *
    168180 */
    169181static inline int answer_preprocess(call_t *answer, ipc_data_t *olddata)
    170182{
    171         int phoneid;
    172 
    173183        if ((native_t) IPC_GET_RETVAL(answer->data) == EHANGUP) {
    174184                /* In case of forward, hangup the forwared phone,
     
    176186                 */
    177187                mutex_lock(&answer->data.phone->lock);
    178                 spinlock_lock(&TASK->answerbox.lock);
     188                irq_spinlock_lock(&TASK->answerbox.lock, true);
    179189                if (answer->data.phone->state == IPC_PHONE_CONNECTED) {
    180190                        list_remove(&answer->data.phone->link);
    181191                        answer->data.phone->state = IPC_PHONE_SLAMMED;
    182192                }
    183                 spinlock_unlock(&TASK->answerbox.lock);
     193                irq_spinlock_unlock(&TASK->answerbox.lock, true);
    184194                mutex_unlock(&answer->data.phone->lock);
    185195        }
    186 
     196       
    187197        if (!olddata)
    188198                return 0;
    189 
    190         if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECTION_CLONE) {
    191                 phoneid = IPC_GET_ARG1(*olddata);
    192                 phone_t *phone = &TASK->phones[phoneid];
     199       
     200        if (IPC_GET_IMETHOD(*olddata) == IPC_M_CONNECTION_CLONE) {
     201                int phoneid = IPC_GET_ARG1(*olddata);
     202                phone_t *phone = &TASK->phones[phoneid];
     203               
    193204                if (IPC_GET_RETVAL(answer->data) != EOK) {
    194205                        /*
     
    202213                        mutex_lock(&phone->lock);
    203214                        if (phone->state == IPC_PHONE_CONNECTED) {
    204                                 spinlock_lock(&phone->callee->lock);
     215                                irq_spinlock_lock(&phone->callee->lock, true);
    205216                                list_remove(&phone->link);
    206217                                phone->state = IPC_PHONE_SLAMMED;
    207                                 spinlock_unlock(&phone->callee->lock);
     218                                irq_spinlock_unlock(&phone->callee->lock, true);
    208219                        }
    209220                        mutex_unlock(&phone->lock);
    210221                }
    211         } else if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_ME) {
    212                 phone_t *phone = (phone_t *)IPC_GET_ARG5(*olddata);
     222        } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_CONNECT_ME) {
     223                phone_t *phone = (phone_t *) IPC_GET_ARG5(*olddata);
     224               
    213225                if (IPC_GET_RETVAL(answer->data) != EOK) {
    214226                        /*
     
    220232                        mutex_lock(&phone->lock);
    221233                        if (phone->state == IPC_PHONE_CONNECTED) {
    222                                 spinlock_lock(&phone->callee->lock);
     234                                irq_spinlock_lock(&phone->callee->lock, true);
    223235                                list_remove(&phone->link);
    224236                                phone->state = IPC_PHONE_SLAMMED;
    225                                 spinlock_unlock(&phone->callee->lock);
     237                                irq_spinlock_unlock(&phone->callee->lock, true);
    226238                        }
    227239                        mutex_unlock(&phone->lock);
    228240                }
    229         } else if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_TO_ME) {
    230                 phoneid = IPC_GET_ARG5(*olddata);
     241        } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_CONNECT_TO_ME) {
     242                int phoneid = IPC_GET_ARG5(*olddata);
     243               
    231244                if (IPC_GET_RETVAL(answer->data) != EOK) {
    232245                        /* The connection was not accepted */
     
    235248                        /* The connection was accepted */
    236249                        phone_connect(phoneid, &answer->sender->answerbox);
     250                        /* Set 'task hash' as arg4 of response */
     251                        IPC_SET_ARG4(answer->data, (sysarg_t) TASK);
    237252                        /* Set 'phone hash' as arg5 of response */
    238253                        IPC_SET_ARG5(answer->data,
    239                             (unative_t) &TASK->phones[phoneid]);
    240                 }
    241         } else if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_ME_TO) {
     254                            (sysarg_t) &TASK->phones[phoneid]);
     255                }
     256        } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_CONNECT_ME_TO) {
    242257                /* If the users accepted call, connect */
    243258                if (IPC_GET_RETVAL(answer->data) == EOK) {
     
    245260                            &TASK->answerbox);
    246261                }
    247         } else if (IPC_GET_METHOD(*olddata) == IPC_M_SHARE_OUT) {
     262        } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_SHARE_OUT) {
    248263                if (!IPC_GET_RETVAL(answer->data)) {
    249264                        /* Accepted, handle as_area receipt */
    250                         ipl_t ipl;
    251                         int rc;
    252                         as_t *as;
    253265                       
    254                         ipl = interrupts_disable();
    255                         spinlock_lock(&answer->sender->lock);
    256                         as = answer->sender->as;
    257                         spinlock_unlock(&answer->sender->lock);
    258                         interrupts_restore(ipl);
     266                        irq_spinlock_lock(&answer->sender->lock, true);
     267                        as_t *as = answer->sender->as;
     268                        irq_spinlock_unlock(&answer->sender->lock, true);
    259269                       
    260                         rc = as_area_share(as, IPC_GET_ARG1(*olddata),
     270                        int rc = as_area_share(as, IPC_GET_ARG1(*olddata),
    261271                            IPC_GET_ARG2(*olddata), AS,
    262272                            IPC_GET_ARG1(answer->data), IPC_GET_ARG3(*olddata));
     
    264274                        return rc;
    265275                }
    266         } else if (IPC_GET_METHOD(*olddata) == IPC_M_SHARE_IN) {
     276        } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_SHARE_IN) {
    267277                if (!IPC_GET_RETVAL(answer->data)) {
    268                         ipl_t ipl;
    269                         as_t *as;
    270                         int rc;
     278                        irq_spinlock_lock(&answer->sender->lock, true);
     279                        as_t *as = answer->sender->as;
     280                        irq_spinlock_unlock(&answer->sender->lock, true);
    271281                       
    272                         ipl = interrupts_disable();
    273                         spinlock_lock(&answer->sender->lock);
    274                         as = answer->sender->as;
    275                         spinlock_unlock(&answer->sender->lock);
    276                         interrupts_restore(ipl);
    277                        
    278                         rc = as_area_share(AS, IPC_GET_ARG1(answer->data),
     282                        int rc = as_area_share(AS, IPC_GET_ARG1(answer->data),
    279283                            IPC_GET_ARG2(*olddata), as, IPC_GET_ARG1(*olddata),
    280284                            IPC_GET_ARG2(answer->data));
    281285                        IPC_SET_RETVAL(answer->data, rc);
    282286                }
    283         } else if (IPC_GET_METHOD(*olddata) == IPC_M_DATA_READ) {
     287        } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_DATA_READ) {
    284288                ASSERT(!answer->buffer);
    285289                if (!IPC_GET_RETVAL(answer->data)) {
     
    295299                                 */
    296300                                IPC_SET_ARG1(answer->data, dst);
    297 
     301                               
    298302                                answer->buffer = malloc(size, 0);
    299303                                int rc = copy_from_uspace(answer->buffer,
     
    310314                        }
    311315                }
    312         } else if (IPC_GET_METHOD(*olddata) == IPC_M_DATA_WRITE) {
     316        } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_DATA_WRITE) {
    313317                ASSERT(answer->buffer);
    314318                if (!IPC_GET_RETVAL(answer->data)) {
    315319                        /* The recipient agreed to receive data. */
    316                         int rc;
    317                         uintptr_t dst;
    318                         size_t size;
    319                         size_t max_size;
    320 
    321                         dst = (uintptr_t)IPC_GET_ARG1(answer->data);
    322                         size = (size_t)IPC_GET_ARG2(answer->data);
    323                         max_size = (size_t)IPC_GET_ARG2(*olddata);
    324 
     320                        uintptr_t dst = (uintptr_t)IPC_GET_ARG1(answer->data);
     321                        size_t size = (size_t)IPC_GET_ARG2(answer->data);
     322                        size_t max_size = (size_t)IPC_GET_ARG2(*olddata);
     323                       
    325324                        if (size <= max_size) {
    326                                 rc = copy_to_uspace((void *) dst,
     325                                int rc = copy_to_uspace((void *) dst,
    327326                                    answer->buffer, size);
    328327                                if (rc)
     
    335334                answer->buffer = NULL;
    336335        }
     336       
    337337        return 0;
    338338}
     
    346346                mutex_lock(&p2->lock);
    347347                mutex_lock(&p1->lock);
    348         } else {
     348        } else
    349349                mutex_lock(&p1->lock);
    350         }
    351350}
    352351
     
    360359/** Called before the request is sent.
    361360 *
    362  * @param call          Call structure with the request.
    363  * @param phone         Phone that the call will be sent through.
    364  *
    365  * @return              Return 0 on success, ELIMIT or EPERM on error.
     361 * @param call  Call structure with the request.
     362 * @param phone Phone that the call will be sent through.
     363 *
     364 * @return Return 0 on success, ELIMIT or EPERM on error.
     365 *
    366366 */
    367367static int request_preprocess(call_t *call, phone_t *phone)
    368368{
    369         int newphid;
    370         size_t size;
    371         uintptr_t src;
    372         int rc;
    373 
    374         switch (IPC_GET_METHOD(call->data)) {
     369        switch (IPC_GET_IMETHOD(call->data)) {
    375370        case IPC_M_CONNECTION_CLONE: {
    376371                phone_t *cloned_phone;
    377                 GET_CHECK_PHONE(cloned_phone, IPC_GET_ARG1(call->data),
    378                     return ENOENT);
     372                if (phone_get(IPC_GET_ARG1(call->data), &cloned_phone) != EOK)
     373                        return ENOENT;
     374               
    379375                phones_lock(cloned_phone, phone);
     376               
    380377                if ((cloned_phone->state != IPC_PHONE_CONNECTED) ||
    381378                    phone->state != IPC_PHONE_CONNECTED) {
     
    383380                        return EINVAL;
    384381                }
     382               
    385383                /*
    386384                 * We can be pretty sure now that both tasks exist and we are
     
    388386                 * we are effectively preventing them from finishing their
    389387                 * potential cleanup.
     388                 *
    390389                 */
    391                 newphid = phone_alloc(phone->callee->task);
     390                int newphid = phone_alloc(phone->callee->task);
    392391                if (newphid < 0) {
    393392                        phones_unlock(cloned_phone, phone);
    394393                        return ELIMIT;
    395394                }
     395               
    396396                ipc_phone_connect(&phone->callee->task->phones[newphid],
    397397                    cloned_phone->callee);
    398398                phones_unlock(cloned_phone, phone);
     399               
    399400                /* Set the new phone for the callee. */
    400401                IPC_SET_ARG1(call->data, newphid);
     
    402403        }
    403404        case IPC_M_CONNECT_ME:
    404                 IPC_SET_ARG5(call->data, (unative_t) phone);
     405                IPC_SET_ARG5(call->data, (sysarg_t) phone);
    405406                break;
    406         case IPC_M_CONNECT_ME_TO:
    407                 newphid = phone_alloc(TASK);
     407        case IPC_M_CONNECT_ME_TO: {
     408                int newphid = phone_alloc(TASK);
    408409                if (newphid < 0)
    409410                        return ELIMIT;
     411               
    410412                /* Set arg5 for server */
    411                 IPC_SET_ARG5(call->data, (unative_t) &TASK->phones[newphid]);
     413                IPC_SET_ARG5(call->data, (sysarg_t) &TASK->phones[newphid]);
    412414                call->flags |= IPC_CALL_CONN_ME_TO;
    413415                call->priv = newphid;
    414416                break;
    415         case IPC_M_SHARE_OUT:
    416                 size = as_area_get_size(IPC_GET_ARG1(call->data));
     417        }
     418        case IPC_M_SHARE_OUT: {
     419                size_t size = as_area_get_size(IPC_GET_ARG1(call->data));
    417420                if (!size)
    418421                        return EPERM;
     422               
    419423                IPC_SET_ARG2(call->data, size);
    420424                break;
    421         case IPC_M_DATA_READ:
    422                 size = IPC_GET_ARG2(call->data);
     425        }
     426        case IPC_M_DATA_READ: {
     427                size_t size = IPC_GET_ARG2(call->data);
    423428                if ((size <= 0 || (size > DATA_XFER_LIMIT)))
    424429                        return ELIMIT;
     430               
    425431                break;
    426         case IPC_M_DATA_WRITE:
    427                 src = IPC_GET_ARG1(call->data);
    428                 size = IPC_GET_ARG2(call->data);
     432        }
     433        case IPC_M_DATA_WRITE: {
     434                uintptr_t src = IPC_GET_ARG1(call->data);
     435                size_t size = IPC_GET_ARG2(call->data);
    429436               
    430437                if (size > DATA_XFER_LIMIT)
     
    432439               
    433440                call->buffer = (uint8_t *) malloc(size, 0);
    434                 rc = copy_from_uspace(call->buffer, (void *) src, size);
     441                int rc = copy_from_uspace(call->buffer, (void *) src, size);
    435442                if (rc != 0) {
    436443                        free(call->buffer);
    437444                        return rc;
    438445                }
     446               
    439447                break;
     448        }
    440449#ifdef CONFIG_UDEBUG
    441450        case IPC_M_DEBUG_ALL:
     
    445454                break;
    446455        }
     456       
    447457        return 0;
    448458}
     
    454464/** Do basic kernel processing of received call answer.
    455465 *
    456  * @param call          Call structure with the answer.
     466 * @param call Call structure with the answer.
     467 *
    457468 */
    458469static void process_answer(call_t *call)
     
    461472            (call->flags & IPC_CALL_FORWARDED))
    462473                IPC_SET_RETVAL(call->data, EFORWARD);
    463 
     474       
    464475        if (call->flags & IPC_CALL_CONN_ME_TO) {
    465476                if (IPC_GET_RETVAL(call->data))
     
    468479                        IPC_SET_ARG5(call->data, call->priv);
    469480        }
    470 
     481       
    471482        if (call->buffer) {
    472                 /* This must be an affirmative answer to IPC_M_DATA_READ. */
    473                 /* or IPC_M_DEBUG_ALL/UDEBUG_M_MEM_READ... */
     483                /*
     484                 * This must be an affirmative answer to IPC_M_DATA_READ
     485                 * or IPC_M_DEBUG_ALL/UDEBUG_M_MEM_READ...
     486                 *
     487                 */
    474488                uintptr_t dst = IPC_GET_ARG1(call->data);
    475489                size_t size = IPC_GET_ARG2(call->data);
     
    484498/** Do basic kernel processing of received call request.
    485499 *
    486  * @param box           Destination answerbox structure.
    487  * @param call          Call structure with the request.
    488  *
    489  * @return              Return 0 if the call should be passed to userspace.
    490  *                      Return -1 if the call should be ignored.
     500 * @param box  Destination answerbox structure.
     501 * @param call Call structure with the request.
     502 *
     503 * @return 0 if the call should be passed to userspace.
     504 * @return -1 if the call should be ignored.
     505 *
    491506 */
    492507static int process_request(answerbox_t *box, call_t *call)
    493508{
    494         int phoneid;
    495 
    496         if (IPC_GET_METHOD(call->data) == IPC_M_CONNECT_TO_ME) {
    497                 phoneid = phone_alloc(TASK);
     509        if (IPC_GET_IMETHOD(call->data) == IPC_M_CONNECT_TO_ME) {
     510                int phoneid = phone_alloc(TASK);
    498511                if (phoneid < 0) { /* Failed to allocate phone */
    499512                        IPC_SET_RETVAL(call->data, ELIMIT);
     
    501514                        return -1;
    502515                }
     516               
    503517                IPC_SET_ARG5(call->data, phoneid);
    504518        }
    505         switch (IPC_GET_METHOD(call->data)) {
     519       
     520        switch (IPC_GET_IMETHOD(call->data)) {
    506521        case IPC_M_DEBUG_ALL:
    507522                return -1;
     
    509524                break;
    510525        }
     526       
    511527        return 0;
    512528}
     
    517533 * the generic function (i.e. sys_ipc_call_sync_slow()).
    518534 *
    519  * @param phoneid       Phone handle for the call.
    520  * @param method        Method of the call.
    521  * @param arg1          Service-defined payload argument.
    522  * @param arg2          Service-defined payload argument.
    523  * @param arg3          Service-defined payload argument.
    524  * @param data          Address of userspace structure where the reply call will
    525  *                      be stored.
    526  *
    527  * @return              Returns 0 on success.
    528  *                      Return ENOENT if there is no such phone handle.
    529  */
    530 unative_t sys_ipc_call_sync_fast(unative_t phoneid, unative_t method,
    531     unative_t arg1, unative_t arg2, unative_t arg3, ipc_data_t *data)
    532 {
    533         call_t call;
     535 * @param phoneid Phone handle for the call.
     536 * @param imethod Interface and method of the call.
     537 * @param arg1    Service-defined payload argument.
     538 * @param arg2    Service-defined payload argument.
     539 * @param arg3    Service-defined payload argument.
     540 * @param data    Address of user-space structure where the reply call will
     541 *                be stored.
     542 *
     543 * @return 0 on success.
     544 * @return ENOENT if there is no such phone handle.
     545 *
     546 */
     547sysarg_t sys_ipc_call_sync_fast(sysarg_t phoneid, sysarg_t imethod,
     548    sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, ipc_data_t *data)
     549{
    534550        phone_t *phone;
    535         int res;
    536         int rc;
    537        
    538         GET_CHECK_PHONE(phone, phoneid, return ENOENT);
    539 
    540         ipc_call_static_init(&call);
    541         IPC_SET_METHOD(call.data, method);
    542         IPC_SET_ARG1(call.data, arg1);
    543         IPC_SET_ARG2(call.data, arg2);
    544         IPC_SET_ARG3(call.data, arg3);
     551        if (phone_get(phoneid, &phone) != EOK)
     552                return ENOENT;
     553       
     554        call_t *call = ipc_call_alloc(0);
     555        IPC_SET_IMETHOD(call->data, imethod);
     556        IPC_SET_ARG1(call->data, arg1);
     557        IPC_SET_ARG2(call->data, arg2);
     558        IPC_SET_ARG3(call->data, arg3);
     559       
    545560        /*
    546561         * To achieve deterministic behavior, zero out arguments that are beyond
    547562         * the limits of the fast version.
    548563         */
    549         IPC_SET_ARG4(call.data, 0);
    550         IPC_SET_ARG5(call.data, 0);
    551 
    552         if (!(res = request_preprocess(&call, phone))) {
     564        IPC_SET_ARG4(call->data, 0);
     565        IPC_SET_ARG5(call->data, 0);
     566       
     567        int res = request_preprocess(call, phone);
     568        int rc;
     569       
     570        if (!res) {
    553571#ifdef CONFIG_UDEBUG
    554572                udebug_stoppable_begin();
    555573#endif
    556                 rc = ipc_call_sync(phone, &call);
     574                rc = ipc_call_sync(phone, call);
    557575#ifdef CONFIG_UDEBUG
    558576                udebug_stoppable_end();
    559577#endif
    560                 if (rc != EOK)
     578               
     579                if (rc != EOK) {
     580                        /* The call will be freed by ipc_cleanup(). */
    561581                        return rc;
    562                 process_answer(&call);
    563 
    564         } else {
    565                 IPC_SET_RETVAL(call.data, res);
    566         }
    567         rc = STRUCT_TO_USPACE(&data->args, &call.data.args);
     582                }
     583               
     584                process_answer(call);
     585        } else
     586                IPC_SET_RETVAL(call->data, res);
     587       
     588        rc = STRUCT_TO_USPACE(&data->args, &call->data.args);
     589        ipc_call_free(call);
    568590        if (rc != 0)
    569591                return rc;
    570 
     592       
    571593        return 0;
    572594}
     
    574596/** Make a synchronous IPC call allowing to transmit the entire payload.
    575597 *
    576  * @param phoneid       Phone handle for the call.
    577  * @param question      Userspace address of call data with the request.
    578  * @param reply         Userspace address of call data where to store the
    579  *                      answer.
    580  *
    581  * @return              Zero on success or an error code.
    582  */
    583 unative_t sys_ipc_call_sync_slow(unative_t phoneid, ipc_data_t *question,
     598 * @param phoneid Phone handle for the call.
     599 * @param request User-space address of call data with the request.
     600 * @param reply   User-space address of call data where to store the
     601 *                answer.
     602 *
     603 * @return Zero on success or an error code.
     604 *
     605 */
     606sysarg_t sys_ipc_call_sync_slow(sysarg_t phoneid, ipc_data_t *request,
    584607    ipc_data_t *reply)
    585608{
    586         call_t call;
    587609        phone_t *phone;
    588         int res;
    589         int rc;
    590 
    591         ipc_call_static_init(&call);
    592         rc = copy_from_uspace(&call.data.args, &question->args,
    593             sizeof(call.data.args));
    594         if (rc != 0)
    595                 return (unative_t) rc;
    596 
    597         GET_CHECK_PHONE(phone, phoneid, return ENOENT);
    598 
    599         if (!(res = request_preprocess(&call, phone))) {
     610        if (phone_get(phoneid, &phone) != EOK)
     611                return ENOENT;
     612       
     613        call_t *call = ipc_call_alloc(0);
     614        int rc = copy_from_uspace(&call->data.args, &request->args,
     615            sizeof(call->data.args));
     616        if (rc != 0) {
     617                ipc_call_free(call);
     618                return (sysarg_t) rc;
     619        }
     620       
     621        int res = request_preprocess(call, phone);
     622       
     623        if (!res) {
    600624#ifdef CONFIG_UDEBUG
    601625                udebug_stoppable_begin();
    602626#endif
    603                 rc = ipc_call_sync(phone, &call);
     627                rc = ipc_call_sync(phone, call);
    604628#ifdef CONFIG_UDEBUG
    605629                udebug_stoppable_end();
    606630#endif
    607                 if (rc != EOK)
     631               
     632                if (rc != EOK) {
     633                        /* The call will be freed by ipc_cleanup(). */
    608634                        return rc;
    609                 process_answer(&call);
    610         } else
    611                 IPC_SET_RETVAL(call.data, res);
    612 
    613         rc = STRUCT_TO_USPACE(&reply->args, &call.data.args);
     635                }
     636               
     637                process_answer(call);
     638        } else
     639                IPC_SET_RETVAL(call->data, res);
     640       
     641        rc = STRUCT_TO_USPACE(&reply->args, &call->data.args);
     642        ipc_call_free(call);
    614643        if (rc != 0)
    615644                return rc;
    616 
     645       
    617646        return 0;
    618647}
    619648
    620 /** Check that the task did not exceed the allowed limit of asynchronous calls.
    621  *
    622  * @return              Return 0 if limit not reached or -1 if limit exceeded.
    623  */
    624 static int check_call_limit(void)
    625 {
    626         if (atomic_preinc(&TASK->active_calls) > IPC_MAX_ASYNC_CALLS) {
    627                 atomic_dec(&TASK->active_calls);
     649/** Check that the task did not exceed the allowed limit of asynchronous calls
     650 * made over a phone.
     651 *
     652 * @param phone Phone to check the limit against.
     653 *
     654 * @return 0 if limit not reached or -1 if limit exceeded.
     655 *
     656 */
     657static int check_call_limit(phone_t *phone)
     658{
     659        if (atomic_get(&phone->active_calls) >= IPC_MAX_ASYNC_CALLS)
    628660                return -1;
    629         }
     661       
    630662        return 0;
    631663}
     
    636668 * the generic function sys_ipc_call_async_slow().
    637669 *
    638  * @param phoneid       Phone handle for the call.
    639  * @param method        Method of the call.
    640  * @param arg1          Service-defined payload argument.
    641  * @param arg2          Service-defined payload argument.
    642  * @param arg3          Service-defined payload argument.
    643  * @param arg4          Service-defined payload argument.
    644  *
    645  * @return              Return call hash on success.
    646  *                      Return IPC_CALLRET_FATAL in case of a fatal error and
    647  *                      IPC_CALLRET_TEMPORARY if there are too many pending
    648  *                      asynchronous requests; answers should be handled first.
    649  */
    650 unative_t sys_ipc_call_async_fast(unative_t phoneid, unative_t method,
    651     unative_t arg1, unative_t arg2, unative_t arg3, unative_t arg4)
    652 {
    653         call_t *call;
     670 * @param phoneid Phone handle for the call.
     671 * @param imethod Interface and method of the call.
     672 * @param arg1    Service-defined payload argument.
     673 * @param arg2    Service-defined payload argument.
     674 * @param arg3    Service-defined payload argument.
     675 * @param arg4    Service-defined payload argument.
     676 *
     677 * @return Call hash on success.
     678 * @return IPC_CALLRET_FATAL in case of a fatal error.
     679 * @return IPC_CALLRET_TEMPORARY if there are too many pending
     680 *         asynchronous requests; answers should be handled first.
     681 *
     682 */
     683sysarg_t sys_ipc_call_async_fast(sysarg_t phoneid, sysarg_t imethod,
     684    sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4)
     685{
    654686        phone_t *phone;
    655         int res;
    656 
    657         if (check_call_limit())
     687        if (phone_get(phoneid, &phone) != EOK)
     688                return IPC_CALLRET_FATAL;
     689       
     690        if (check_call_limit(phone))
    658691                return IPC_CALLRET_TEMPORARY;
    659 
    660         GET_CHECK_PHONE(phone, phoneid, return IPC_CALLRET_FATAL);
    661 
    662         call = ipc_call_alloc(0);
    663         IPC_SET_METHOD(call->data, method);
     692       
     693        call_t *call = ipc_call_alloc(0);
     694        IPC_SET_IMETHOD(call->data, imethod);
    664695        IPC_SET_ARG1(call->data, arg1);
    665696        IPC_SET_ARG2(call->data, arg2);
    666697        IPC_SET_ARG3(call->data, arg3);
    667698        IPC_SET_ARG4(call->data, arg4);
     699       
    668700        /*
    669701         * To achieve deterministic behavior, zero out arguments that are beyond
     
    671703         */
    672704        IPC_SET_ARG5(call->data, 0);
    673 
    674         if (!(res = request_preprocess(call, phone)))
     705       
     706        int res = request_preprocess(call, phone);
     707       
     708        if (!res)
    675709                ipc_call(phone, call);
    676710        else
    677711                ipc_backsend_err(phone, call, res);
    678 
    679         return (unative_t) call;
     712       
     713        return (sysarg_t) call;
    680714}
    681715
    682716/** Make an asynchronous IPC call allowing to transmit the entire payload.
    683717 *
    684  * @param phoneid       Phone handle for the call.
    685  * @param data          Userspace address of call data with the request.
    686  *
    687  * @return              See sys_ipc_call_async_fast().
    688  */
    689 unative_t sys_ipc_call_async_slow(unative_t phoneid, ipc_data_t *data)
    690 {
    691         call_t *call;
     718 * @param phoneid Phone handle for the call.
     719 * @param data    Userspace address of call data with the request.
     720 *
     721 * @return See sys_ipc_call_async_fast().
     722 *
     723 */
     724sysarg_t sys_ipc_call_async_slow(sysarg_t phoneid, ipc_data_t *data)
     725{
    692726        phone_t *phone;
    693         int res;
    694         int rc;
    695 
    696         if (check_call_limit())
     727        if (phone_get(phoneid, &phone) != EOK)
     728                return IPC_CALLRET_FATAL;
     729
     730        if (check_call_limit(phone))
    697731                return IPC_CALLRET_TEMPORARY;
    698732
    699         GET_CHECK_PHONE(phone, phoneid, return IPC_CALLRET_FATAL);
    700 
    701         call = ipc_call_alloc(0);
    702         rc = copy_from_uspace(&call->data.args, &data->args,
     733        call_t *call = ipc_call_alloc(0);
     734        int rc = copy_from_uspace(&call->data.args, &data->args,
    703735            sizeof(call->data.args));
    704736        if (rc != 0) {
    705737                ipc_call_free(call);
    706                 return (unative_t) rc;
    707         }
    708         if (!(res = request_preprocess(call, phone)))
     738                return (sysarg_t) rc;
     739        }
     740       
     741        int res = request_preprocess(call, phone);
     742       
     743        if (!res)
    709744                ipc_call(phone, call);
    710745        else
    711746                ipc_backsend_err(phone, call, res);
    712 
    713         return (unative_t) call;
    714 }
    715 
    716 /** Forward a received call to another destination - common code for both the
    717  * fast and the slow version.
    718  *
    719  * @param callid        Hash of the call to forward.
    720  * @param phoneid       Phone handle to use for forwarding.
    721  * @param method        New method to use for the forwarded call.
    722  * @param arg1          New value of the first argument for the forwarded call.
    723  * @param arg2          New value of the second argument for the forwarded call.
    724  * @param arg3          New value of the third argument for the forwarded call.
    725  * @param arg4          New value of the fourth argument for the forwarded call.
    726  * @param arg5          New value of the fifth argument for the forwarded call.
    727  * @param mode          Flags that specify mode of the forward operation.
    728  * @param slow          If true, arg3, arg4 and arg5 are considered. Otherwise
    729  *                      the function considers only the fast version arguments:
    730  *                      i.e. arg1 and arg2.
    731  *
    732  * @return              Return 0 on succes, otherwise return an error code.
    733  *
    734  * Warning:     Make sure that ARG5 is not rewritten for certain system IPC
    735  */
    736 static unative_t sys_ipc_forward_common(unative_t callid, unative_t phoneid,
    737     unative_t method, unative_t arg1, unative_t arg2, unative_t arg3,
    738     unative_t arg4, unative_t arg5, int mode, bool slow)
    739 {
    740         call_t *call;
    741         phone_t *phone;
    742 
    743         call = get_call(callid);
     747       
     748        return (sysarg_t) call;
     749}
     750
     751/** Forward a received call to another destination
     752 *
     753 * Common code for both the fast and the slow version.
     754 *
     755 * @param callid  Hash of the call to forward.
     756 * @param phoneid Phone handle to use for forwarding.
     757 * @param imethod New interface and method to use for the forwarded call.
     758 * @param arg1    New value of the first argument for the forwarded call.
     759 * @param arg2    New value of the second argument for the forwarded call.
     760 * @param arg3    New value of the third argument for the forwarded call.
     761 * @param arg4    New value of the fourth argument for the forwarded call.
     762 * @param arg5    New value of the fifth argument for the forwarded call.
     763 * @param mode    Flags that specify mode of the forward operation.
     764 * @param slow    If true, arg3, arg4 and arg5 are considered. Otherwise
     765 *                the function considers only the fast version arguments:
     766 *                i.e. arg1 and arg2.
     767 *
     768 * @return 0 on succes, otherwise an error code.
     769 *
     770 * Warning: Make sure that ARG5 is not rewritten for certain system IPC
     771 *
     772 */
     773static sysarg_t sys_ipc_forward_common(sysarg_t callid, sysarg_t phoneid,
     774    sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3,
     775    sysarg_t arg4, sysarg_t arg5, unsigned int mode, bool slow)
     776{
     777        call_t *call = get_call(callid);
    744778        if (!call)
    745779                return ENOENT;
    746780       
    747781        call->flags |= IPC_CALL_FORWARDED;
    748 
    749         GET_CHECK_PHONE(phone, phoneid, {
     782       
     783        phone_t *phone;
     784        if (phone_get(phoneid, &phone) != EOK) {
    750785                IPC_SET_RETVAL(call->data, EFORWARD);
    751786                ipc_answer(&TASK->answerbox, call);
    752787                return ENOENT;
    753         });
    754 
    755         if (!method_is_forwardable(IPC_GET_METHOD(call->data))) {
     788        }
     789       
     790        if (!method_is_forwardable(IPC_GET_IMETHOD(call->data))) {
    756791                IPC_SET_RETVAL(call->data, EFORWARD);
    757792                ipc_answer(&TASK->answerbox, call);
    758793                return EPERM;
    759794        }
    760 
     795       
    761796        /*
    762          * Userspace is not allowed to change method of system methods on
    763          * forward, allow changing ARG1, ARG2, ARG3 and ARG4 by means of method,
    764          * arg1, arg2 and arg3.
    765          * If the method is immutable, don't change anything.
     797         * Userspace is not allowed to change interface and method of system
     798         * methods on forward, allow changing ARG1, ARG2, ARG3 and ARG4 by
     799         * means of method, arg1, arg2 and arg3.
     800         * If the interface and method is immutable, don't change anything.
    766801         */
    767         if (!method_is_immutable(IPC_GET_METHOD(call->data))) {
    768                 if (method_is_system(IPC_GET_METHOD(call->data))) {
    769                         if (IPC_GET_METHOD(call->data) == IPC_M_CONNECT_TO_ME)
     802        if (!method_is_immutable(IPC_GET_IMETHOD(call->data))) {
     803                if (method_is_system(IPC_GET_IMETHOD(call->data))) {
     804                        if (IPC_GET_IMETHOD(call->data) == IPC_M_CONNECT_TO_ME)
    770805                                phone_dealloc(IPC_GET_ARG5(call->data));
    771 
    772                         IPC_SET_ARG1(call->data, method);
     806                       
     807                        IPC_SET_ARG1(call->data, imethod);
    773808                        IPC_SET_ARG2(call->data, arg1);
    774809                        IPC_SET_ARG3(call->data, arg2);
     810                       
    775811                        if (slow) {
    776812                                IPC_SET_ARG4(call->data, arg3);
     
    781817                        }
    782818                } else {
    783                         IPC_SET_METHOD(call->data, method);
     819                        IPC_SET_IMETHOD(call->data, imethod);
    784820                        IPC_SET_ARG1(call->data, arg1);
    785821                        IPC_SET_ARG2(call->data, arg2);
     
    791827                }
    792828        }
    793 
     829       
    794830        return ipc_forward(call, phone, &TASK->answerbox, mode);
    795831}
     
    797833/** Forward a received call to another destination - fast version.
    798834 *
    799  * @param callid        Hash of the call to forward.
    800  * @param phoneid       Phone handle to use for forwarding.
    801  * @param method        New method to use for the forwarded call.
    802  * @param arg1          New value of the first argument for the forwarded call.
    803  * @param arg2          New value of the second argument for the forwarded call.
    804  * @param mode          Flags that specify mode of the forward operation.
    805  *
    806  * @return              Return 0 on succes, otherwise return an error code.
    807  *
    808  * In case the original method is a system method, ARG1, ARG2 and ARG3 are
    809  * overwritten in the forwarded message with the new method and the new
    810  * arg1 and arg2, respectively. Otherwise the METHOD, ARG1 and ARG2 are
    811  * rewritten with the new method, arg1 and arg2, respectively. Also note there
    812  * is a set of immutable methods, for which the new method and arguments are not
    813  * set and these values are ignored.
    814  */
    815 unative_t sys_ipc_forward_fast(unative_t callid, unative_t phoneid,
    816     unative_t method, unative_t arg1, unative_t arg2, int mode)
    817 {
    818         return sys_ipc_forward_common(callid, phoneid, method, arg1, arg2, 0, 0,
     835 * In case the original interface and method is a system method, ARG1, ARG2
     836 * and ARG3 are overwritten in the forwarded message with the new method and
     837 * the new arg1 and arg2, respectively. Otherwise the IMETHOD, ARG1 and ARG2
     838 * are rewritten with the new interface and method, arg1 and arg2, respectively.
     839 * Also note there is a set of immutable methods, for which the new method and
     840 * arguments are not set and these values are ignored.
     841 *
     842 * @param callid  Hash of the call to forward.
     843 * @param phoneid Phone handle to use for forwarding.
     844 * @param imethod New interface and method to use for the forwarded call.
     845 * @param arg1    New value of the first argument for the forwarded call.
     846 * @param arg2    New value of the second argument for the forwarded call.
     847 * @param mode    Flags that specify mode of the forward operation.
     848 *
     849 * @return 0 on succes, otherwise an error code.
     850 *
     851 */
     852sysarg_t sys_ipc_forward_fast(sysarg_t callid, sysarg_t phoneid,
     853    sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, unsigned int mode)
     854{
     855        return sys_ipc_forward_common(callid, phoneid, imethod, arg1, arg2, 0, 0,
    819856            0, mode, false);
    820857}
     
    822859/** Forward a received call to another destination - slow version.
    823860 *
    824  * @param callid        Hash of the call to forward.
    825  * @param phoneid       Phone handle to use for forwarding.
    826  * @param data          Userspace address of the new IPC data.
    827  * @param mode          Flags that specify mode of the forward operation.
    828  *
    829  * @return              Return 0 on succes, otherwise return an error code.
    830  *
    831861 * This function is the slow verision of the sys_ipc_forward_fast interface.
    832  * It can copy all five new arguments and the new method from the userspace.
    833  * It naturally extends the functionality of the fast version. For system
    834  * methods, it additionally stores the new value of arg3 to ARG4. For non-system
    835  * methods, it additionally stores the new value of arg3, arg4 and arg5,
    836  * respectively, to ARG3, ARG4 and ARG5, respectively.
    837  */
    838 unative_t sys_ipc_forward_slow(unative_t callid, unative_t phoneid,
    839     ipc_data_t *data, int mode)
     862 * It can copy all five new arguments and the new interface and method from
     863 * the userspace. It naturally extends the functionality of the fast version.
     864 * For system methods, it additionally stores the new value of arg3 to ARG4.
     865 * For non-system methods, it additionally stores the new value of arg3, arg4
     866 * and arg5, respectively, to ARG3, ARG4 and ARG5, respectively.
     867 *
     868 * @param callid  Hash of the call to forward.
     869 * @param phoneid Phone handle to use for forwarding.
     870 * @param data    Userspace address of the new IPC data.
     871 * @param mode    Flags that specify mode of the forward operation.
     872 *
     873 * @return 0 on succes, otherwise an error code.
     874 *
     875 */
     876sysarg_t sys_ipc_forward_slow(sysarg_t callid, sysarg_t phoneid,
     877    ipc_data_t *data, unsigned int mode)
    840878{
    841879        ipc_data_t newdata;
    842         int rc;
    843 
    844         rc = copy_from_uspace(&newdata.args, &data->args,
     880        int rc = copy_from_uspace(&newdata.args, &data->args,
    845881            sizeof(newdata.args));
    846         if (rc != 0) 
    847                 return (unative_t) rc;
    848 
     882        if (rc != 0)
     883                return (sysarg_t) rc;
     884       
    849885        return sys_ipc_forward_common(callid, phoneid,
    850             IPC_GET_METHOD(newdata), IPC_GET_ARG1(newdata),
     886            IPC_GET_IMETHOD(newdata), IPC_GET_ARG1(newdata),
    851887            IPC_GET_ARG2(newdata), IPC_GET_ARG3(newdata),
    852888            IPC_GET_ARG4(newdata), IPC_GET_ARG5(newdata), mode, true);
     
    858894 * than the generic sys_ipc_answer().
    859895 *
    860  * @param callid        Hash of the call to be answered.
    861  * @param retval        Return value of the answer.
    862  * @param arg1          Service-defined return value.
    863  * @param arg2          Service-defined return value.
    864  * @param arg3          Service-defined return value.
    865  * @param arg4          Service-defined return value.
    866  *
    867  * @return              Return 0 on success, otherwise return an error code.   
    868  */
    869 unative_t sys_ipc_answer_fast(unative_t callid, unative_t retval,
    870     unative_t arg1, unative_t arg2, unative_t arg3, unative_t arg4)
    871 {
    872         call_t *call;
    873         ipc_data_t saved_data;
    874         int saveddata = 0;
    875         int rc;
    876 
     896 * @param callid Hash of the call to be answered.
     897 * @param retval Return value of the answer.
     898 * @param arg1   Service-defined return value.
     899 * @param arg2   Service-defined return value.
     900 * @param arg3   Service-defined return value.
     901 * @param arg4   Service-defined return value.
     902 *
     903 * @return 0 on success, otherwise an error code.
     904 *
     905 */
     906sysarg_t sys_ipc_answer_fast(sysarg_t callid, sysarg_t retval,
     907    sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4)
     908{
    877909        /* Do not answer notification callids */
    878910        if (callid & IPC_CALLID_NOTIFICATION)
    879911                return 0;
    880 
    881         call = get_call(callid);
     912       
     913        call_t *call = get_call(callid);
    882914        if (!call)
    883915                return ENOENT;
    884 
     916       
     917        ipc_data_t saved_data;
     918        bool saved;
     919       
    885920        if (answer_need_old(call)) {
    886921                memcpy(&saved_data, &call->data, sizeof(call->data));
    887                 saveddata = 1;
    888         }
    889 
     922                saved = true;
     923        } else
     924                saved = false;
     925       
    890926        IPC_SET_RETVAL(call->data, retval);
    891927        IPC_SET_ARG1(call->data, arg1);
     
    893929        IPC_SET_ARG3(call->data, arg3);
    894930        IPC_SET_ARG4(call->data, arg4);
     931       
    895932        /*
    896933         * To achieve deterministic behavior, zero out arguments that are beyond
     
    898935         */
    899936        IPC_SET_ARG5(call->data, 0);
    900         rc = answer_preprocess(call, saveddata ? &saved_data : NULL);
    901 
     937        int rc = answer_preprocess(call, saved ? &saved_data : NULL);
     938       
    902939        ipc_answer(&TASK->answerbox, call);
    903940        return rc;
     
    906943/** Answer an IPC call.
    907944 *
    908  * @param callid        Hash of the call to be answered.
    909  * @param data          Userspace address of call data with the answer.
    910  *
    911  * @return              Return 0 on success, otherwise return an error code.
    912  */
    913 unative_t sys_ipc_answer_slow(unative_t callid, ipc_data_t *data)
    914 {
    915         call_t *call;
    916         ipc_data_t saved_data;
    917         int saveddata = 0;
    918         int rc;
    919 
     945 * @param callid Hash of the call to be answered.
     946 * @param data   Userspace address of call data with the answer.
     947 *
     948 * @return 0 on success, otherwise an error code.
     949 *
     950 */
     951sysarg_t sys_ipc_answer_slow(sysarg_t callid, ipc_data_t *data)
     952{
    920953        /* Do not answer notification callids */
    921954        if (callid & IPC_CALLID_NOTIFICATION)
    922955                return 0;
    923 
    924         call = get_call(callid);
     956       
     957        call_t *call = get_call(callid);
    925958        if (!call)
    926959                return ENOENT;
    927 
     960       
     961        ipc_data_t saved_data;
     962        bool saved;
     963       
    928964        if (answer_need_old(call)) {
    929965                memcpy(&saved_data, &call->data, sizeof(call->data));
    930                 saveddata = 1;
    931         }
    932         rc = copy_from_uspace(&call->data.args, &data->args,
     966                saved = true;
     967        } else
     968                saved = false;
     969       
     970        int rc = copy_from_uspace(&call->data.args, &data->args,
    933971            sizeof(call->data.args));
    934972        if (rc != 0)
    935973                return rc;
    936 
    937         rc = answer_preprocess(call, saveddata ? &saved_data : NULL);
     974       
     975        rc = answer_preprocess(call, saved ? &saved_data : NULL);
    938976       
    939977        ipc_answer(&TASK->answerbox, call);
    940 
    941978        return rc;
    942979}
     
    944981/** Hang up a phone.
    945982 *
    946  * @param               Phone handle of the phone to be hung up.
    947  *
    948  * @return              Return 0 on success or an error code.
    949  */
    950 unative_t sys_ipc_hangup(int phoneid)
     983 * @param Phone handle of the phone to be hung up.
     984 *
     985 * @return 0 on success or an error code.
     986 *
     987 */
     988sysarg_t sys_ipc_hangup(sysarg_t phoneid)
    951989{
    952990        phone_t *phone;
    953 
    954         GET_CHECK_PHONE(phone, phoneid, return ENOENT);
    955 
     991       
     992        if (phone_get(phoneid, &phone) != EOK)
     993                return ENOENT;
     994       
    956995        if (ipc_phone_hangup(phone))
    957996                return -1;
    958 
     997       
    959998        return 0;
    960999}
     
    9621001/** Wait for an incoming IPC call or an answer.
    9631002 *
    964  * @param calldata      Pointer to buffer where the call/answer data is stored.
    965  * @param usec          Timeout. See waitq_sleep_timeout() for explanation.
    966  * @param flags         Select mode of sleep operation. See waitq_sleep_timeout()
    967  *                      for explanation.
    968  *
    969  * @return              Hash of the call.
    970  *                      If IPC_CALLID_NOTIFICATION bit is set in the hash, the
    971  *                      call is a notification. IPC_CALLID_ANSWERED denotes an
    972  *                      answer.
    973  */
    974 unative_t sys_ipc_wait_for_call(ipc_data_t *calldata, uint32_t usec, int flags)
     1003 * @param calldata Pointer to buffer where the call/answer data is stored.
     1004 * @param usec     Timeout. See waitq_sleep_timeout() for explanation.
     1005 * @param flags    Select mode of sleep operation. See waitq_sleep_timeout()
     1006 *                 for explanation.
     1007 *
     1008 * @return Hash of the call.
     1009 *         If IPC_CALLID_NOTIFICATION bit is set in the hash, the
     1010 *         call is a notification. IPC_CALLID_ANSWERED denotes an
     1011 *         answer.
     1012 *
     1013 */
     1014sysarg_t sys_ipc_wait_for_call(ipc_data_t *calldata, uint32_t usec,
     1015    unsigned int flags)
    9751016{
    9761017        call_t *call;
    977 
     1018       
    9781019restart:
    979 
     1020       
    9801021#ifdef CONFIG_UDEBUG
    9811022        udebug_stoppable_begin();
    982 #endif 
     1023#endif
     1024       
    9831025        call = ipc_wait_for_call(&TASK->answerbox, usec,
    9841026            flags | SYNCH_FLAGS_INTERRUPTIBLE);
    985 
     1027       
    9861028#ifdef CONFIG_UDEBUG
    9871029        udebug_stoppable_end();
    9881030#endif
     1031       
    9891032        if (!call)
    9901033                return 0;
    991 
     1034       
    9921035        if (call->flags & IPC_CALL_NOTIF) {
    993                 ASSERT(! (call->flags & IPC_CALL_STATIC_ALLOC));
    994 
    9951036                /* Set in_phone_hash to the interrupt counter */
    9961037                call->data.phone = (void *) call->priv;
    9971038               
    9981039                STRUCT_TO_USPACE(calldata, &call->data);
    999 
     1040               
    10001041                ipc_call_free(call);
    10011042               
    1002                 return ((unative_t) call) | IPC_CALLID_NOTIFICATION;
    1003         }
    1004 
     1043                return ((sysarg_t) call) | IPC_CALLID_NOTIFICATION;
     1044        }
     1045       
    10051046        if (call->flags & IPC_CALL_ANSWERED) {
    10061047                process_answer(call);
    1007 
    1008                 ASSERT(! (call->flags & IPC_CALL_STATIC_ALLOC));
    1009 
     1048               
    10101049                if (call->flags & IPC_CALL_DISCARD_ANSWER) {
    10111050                        ipc_call_free(call);
    10121051                        goto restart;
    1013                 } else {
    1014                         /*
    1015                          * Decrement the counter of active calls only if the
    1016                          * call is not an answer to IPC_M_PHONE_HUNGUP,
    1017                          * which doesn't contribute to the counter.
    1018                          */
    1019                         atomic_dec(&TASK->active_calls);
    1020                 }
    1021 
     1052                }
     1053               
    10221054                STRUCT_TO_USPACE(&calldata->args, &call->data.args);
    10231055                ipc_call_free(call);
    1024 
    1025                 return ((unative_t) call) | IPC_CALLID_ANSWERED;
    1026         }
    1027 
     1056               
     1057                return ((sysarg_t) call) | IPC_CALLID_ANSWERED;
     1058        }
     1059       
    10281060        if (process_request(&TASK->answerbox, call))
    10291061                goto restart;
    1030 
     1062       
    10311063        /* Include phone address('id') of the caller in the request,
    10321064         * copy whole call->data, not only call->data.args */
     
    10371069                 */
    10381070                ipc_data_t saved_data;
    1039                 int saveddata = 0;
    1040 
     1071                bool saved;
     1072               
    10411073                if (answer_need_old(call)) {
    10421074                        memcpy(&saved_data, &call->data, sizeof(call->data));
    1043                         saveddata = 1;
    1044                 }
     1075                        saved = true;
     1076                } else
     1077                        saved = false;
    10451078               
    10461079                IPC_SET_RETVAL(call->data, EPARTY);
    1047                 (void) answer_preprocess(call, saveddata ? &saved_data : NULL);
     1080                (void) answer_preprocess(call, saved ? &saved_data : NULL);
    10481081                ipc_answer(&TASK->answerbox, call);
    10491082                return 0;
    10501083        }
    1051         return (unative_t)call;
    1052 }
    1053 
    1054 /** Interrupt one thread from sys_ipc_wait_for_call(). */
    1055 unative_t sys_ipc_poke(void)
    1056 {
    1057         waitq_unsleep(&TASK->answerbox.wq);     
     1084       
     1085        return (sysarg_t) call;
     1086}
     1087
     1088/** Interrupt one thread from sys_ipc_wait_for_call().
     1089 *
     1090 */
     1091sysarg_t sys_ipc_poke(void)
     1092{
     1093        waitq_unsleep(&TASK->answerbox.wq);
    10581094        return EOK;
    10591095}
     
    10611097/** Connect an IRQ handler to a task.
    10621098 *
    1063  * @param inr           IRQ number.
    1064  * @param devno         Device number.
    1065  * @param method        Method to be associated with the notification.
    1066  * @param ucode         Uspace pointer to the top-half pseudocode.
    1067  *
    1068  * @return              EPERM or a return code returned by ipc_irq_register().
    1069  */
    1070 unative_t sys_ipc_register_irq(inr_t inr, devno_t devno, unative_t method,
     1099 * @param inr     IRQ number.
     1100 * @param devno   Device number.
     1101 * @param imethod Interface and method to be associated with the notification.
     1102 * @param ucode   Uspace pointer to the top-half pseudocode.
     1103 *
     1104 * @return EPERM or a return code returned by ipc_irq_register().
     1105 *
     1106 */
     1107sysarg_t sys_register_irq(inr_t inr, devno_t devno, sysarg_t imethod,
    10711108    irq_code_t *ucode)
    10721109{
    10731110        if (!(cap_get(TASK) & CAP_IRQ_REG))
    10741111                return EPERM;
    1075 
    1076         return ipc_irq_register(&TASK->answerbox, inr, devno, method, ucode);
     1112       
     1113        return ipc_irq_register(&TASK->answerbox, inr, devno, imethod, ucode);
    10771114}
    10781115
    10791116/** Disconnect an IRQ handler from a task.
    10801117 *
    1081  * @param inr           IRQ number.
    1082  * @param devno         Device number.
    1083  *
    1084  * @return              Zero on success or EPERM on error..
    1085  */
    1086 unative_t sys_ipc_unregister_irq(inr_t inr, devno_t devno)
     1118 * @param inr   IRQ number.
     1119 * @param devno Device number.
     1120 *
     1121 * @return Zero on success or EPERM on error.
     1122 *
     1123 */
     1124sysarg_t sys_unregister_irq(inr_t inr, devno_t devno)
    10871125{
    10881126        if (!(cap_get(TASK) & CAP_IRQ_REG))
    10891127                return EPERM;
    1090 
     1128       
    10911129        ipc_irq_unregister(&TASK->answerbox, inr, devno);
    1092 
     1130       
    10931131        return 0;
    10941132}
    10951133
    1096 #include <console/console.h>
    1097 
    1098 /**
    1099  * Syscall connect to a task by id.
    1100  *
    1101  * @return              Phone id on success, or negative error code.
    1102  */
    1103 unative_t sys_ipc_connect_kbox(sysarg64_t *uspace_taskid_arg)
     1134#ifdef __32_BITS__
     1135
     1136/** Syscall connect to a task by ID (32 bits)
     1137 *
     1138 * @return Phone id on success, or negative error code.
     1139 *
     1140 */
     1141sysarg_t sys_ipc_connect_kbox(sysarg64_t *uspace_taskid)
    11041142{
    11051143#ifdef CONFIG_UDEBUG
    1106         sysarg64_t taskid_arg;
    1107         int rc;
    1108        
    1109         rc = copy_from_uspace(&taskid_arg, uspace_taskid_arg, sizeof(sysarg64_t));
     1144        sysarg64_t taskid;
     1145        int rc = copy_from_uspace(&taskid, uspace_taskid, sizeof(sysarg64_t));
    11101146        if (rc != 0)
    1111                 return (unative_t) rc;
    1112 
    1113         LOG("sys_ipc_connect_kbox(%" PRIu64 ")\n", taskid_arg.value);
    1114 
    1115         return ipc_connect_kbox(taskid_arg.value);
     1147                return (sysarg_t) rc;
     1148       
     1149        return ipc_connect_kbox((task_id_t) taskid);
    11161150#else
    1117         return (unative_t) ENOTSUP;
     1151        return (sysarg_t) ENOTSUP;
    11181152#endif
    11191153}
    11201154
     1155#endif  /* __32_BITS__ */
     1156
     1157#ifdef __64_BITS__
     1158
     1159/** Syscall connect to a task by ID (64 bits)
     1160 *
     1161 * @return Phone id on success, or negative error code.
     1162 *
     1163 */
     1164sysarg_t sys_ipc_connect_kbox(sysarg_t taskid)
     1165{
     1166#ifdef CONFIG_UDEBUG
     1167        return ipc_connect_kbox((task_id_t) taskid);
     1168#else
     1169        return (sysarg_t) ENOTSUP;
     1170#endif
     1171}
     1172
     1173#endif  /* __64_BITS__ */
     1174
    11211175/** @}
    11221176 */
Note: See TracChangeset for help on using the changeset viewer.