Ignore:
File:
1 edited

Legend:

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

    r8add9ca5 r057d21a  
    4949#include <syscall/copy.h>
    5050#include <security/cap.h>
    51 #include <console/console.h>
    5251#include <mm/as.h>
    5352#include <print.h>
     
    5756 * requests.
    5857 */
    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  */
    71 static 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  */
    88 static 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  */
    106 static inline bool method_is_forwardable(sysarg_t imethod)
    107 {
    108         switch (imethod) {
     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 */
     77static 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 */
     94static inline int method_is_forwardable(unative_t method)
     95{
     96        switch (method) {
    10997        case IPC_M_CONNECTION_CLONE:
    11098        case IPC_M_CONNECT_ME:
    11199        case IPC_M_PHONE_HUNGUP:
    112100                /* This message is meant only for the original recipient. */
    113                 return false;
     101                return 0;
    114102        default:
    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  */
    128 static inline bool method_is_immutable(sysarg_t imethod)
    129 {
    130         switch (imethod) {
     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 */
     116static inline int method_is_immutable(unative_t method)
     117{
     118        switch (method) {
    131119        case IPC_M_SHARE_OUT:
    132120        case IPC_M_SHARE_IN:
    133121        case IPC_M_DATA_WRITE:
    134122        case IPC_M_DATA_READ:
    135                 return true;
     123                return 1;
     124                break;
    136125        default:
    137                 return false;
     126                return 0;
    138127        }
    139128}
     
    147136 * for answer_preprocess().
    148137 *
    149  * @param call Call structure to be decided.
    150  *
    151  * @return true if the old call contents should be saved.
    152  *
    153  */
    154 static inline bool answer_need_old(call_t *call)
    155 {
    156         switch (IPC_GET_IMETHOD(call->data)) {
     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 */
     143static inline int answer_need_old(call_t *call)
     144{
     145        switch (IPC_GET_METHOD(call->data)) {
    157146        case IPC_M_CONNECTION_CLONE:
    158147        case IPC_M_CONNECT_ME:
     
    163152        case IPC_M_DATA_WRITE:
    164153        case IPC_M_DATA_READ:
    165                 return true;
     154                return 1;
    166155        default:
    167                 return false;
     156                return 0;
    168157        }
    169158}
     
    173162 * This function is called directly after sys_ipc_answer().
    174163 *
    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  *
     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.
    180168 */
    181169static inline int answer_preprocess(call_t *answer, ipc_data_t *olddata)
    182170{
     171        int phoneid;
     172
    183173        if ((native_t) IPC_GET_RETVAL(answer->data) == EHANGUP) {
    184174                /* In case of forward, hangup the forwared phone,
     
    186176                 */
    187177                mutex_lock(&answer->data.phone->lock);
    188                 irq_spinlock_lock(&TASK->answerbox.lock, true);
     178                spinlock_lock(&TASK->answerbox.lock);
    189179                if (answer->data.phone->state == IPC_PHONE_CONNECTED) {
    190180                        list_remove(&answer->data.phone->link);
    191181                        answer->data.phone->state = IPC_PHONE_SLAMMED;
    192182                }
    193                 irq_spinlock_unlock(&TASK->answerbox.lock, true);
     183                spinlock_unlock(&TASK->answerbox.lock);
    194184                mutex_unlock(&answer->data.phone->lock);
    195185        }
    196        
     186
    197187        if (!olddata)
    198188                return 0;
    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                
     189
     190        if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECTION_CLONE) {
     191                phoneid = IPC_GET_ARG1(*olddata);
     192                phone_t *phone = &TASK->phones[phoneid];
    204193                if (IPC_GET_RETVAL(answer->data) != EOK) {
    205194                        /*
     
    213202                        mutex_lock(&phone->lock);
    214203                        if (phone->state == IPC_PHONE_CONNECTED) {
    215                                 irq_spinlock_lock(&phone->callee->lock, true);
     204                                spinlock_lock(&phone->callee->lock);
    216205                                list_remove(&phone->link);
    217206                                phone->state = IPC_PHONE_SLAMMED;
    218                                 irq_spinlock_unlock(&phone->callee->lock, true);
     207                                spinlock_unlock(&phone->callee->lock);
    219208                        }
    220209                        mutex_unlock(&phone->lock);
    221210                }
    222         } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_CONNECT_ME) {
    223                 phone_t *phone = (phone_t *) IPC_GET_ARG5(*olddata);
    224                
     211        } else if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_ME) {
     212                phone_t *phone = (phone_t *)IPC_GET_ARG5(*olddata);
    225213                if (IPC_GET_RETVAL(answer->data) != EOK) {
    226214                        /*
     
    232220                        mutex_lock(&phone->lock);
    233221                        if (phone->state == IPC_PHONE_CONNECTED) {
    234                                 irq_spinlock_lock(&phone->callee->lock, true);
     222                                spinlock_lock(&phone->callee->lock);
    235223                                list_remove(&phone->link);
    236224                                phone->state = IPC_PHONE_SLAMMED;
    237                                 irq_spinlock_unlock(&phone->callee->lock, true);
     225                                spinlock_unlock(&phone->callee->lock);
    238226                        }
    239227                        mutex_unlock(&phone->lock);
    240228                }
    241         } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_CONNECT_TO_ME) {
    242                 int phoneid = IPC_GET_ARG5(*olddata);
    243                
     229        } else if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_TO_ME) {
     230                phoneid = IPC_GET_ARG5(*olddata);
    244231                if (IPC_GET_RETVAL(answer->data) != EOK) {
    245232                        /* The connection was not accepted */
     
    248235                        /* The connection was accepted */
    249236                        phone_connect(phoneid, &answer->sender->answerbox);
    250                         /* Set 'task hash' as arg4 of response */
    251                         IPC_SET_ARG4(answer->data, (sysarg_t) TASK);
    252237                        /* Set 'phone hash' as arg5 of response */
    253238                        IPC_SET_ARG5(answer->data,
    254                             (sysarg_t) &TASK->phones[phoneid]);
    255                 }
    256         } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_CONNECT_ME_TO) {
     239                            (unative_t) &TASK->phones[phoneid]);
     240                }
     241        } else if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_ME_TO) {
    257242                /* If the users accepted call, connect */
    258243                if (IPC_GET_RETVAL(answer->data) == EOK) {
     
    260245                            &TASK->answerbox);
    261246                }
    262         } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_SHARE_OUT) {
     247        } else if (IPC_GET_METHOD(*olddata) == IPC_M_SHARE_OUT) {
    263248                if (!IPC_GET_RETVAL(answer->data)) {
    264249                        /* Accepted, handle as_area receipt */
     250                        ipl_t ipl;
     251                        int rc;
     252                        as_t *as;
    265253                       
    266                         irq_spinlock_lock(&answer->sender->lock, true);
    267                         as_t *as = answer->sender->as;
    268                         irq_spinlock_unlock(&answer->sender->lock, true);
     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);
    269259                       
    270                         int rc = as_area_share(as, IPC_GET_ARG1(*olddata),
     260                        rc = as_area_share(as, IPC_GET_ARG1(*olddata),
    271261                            IPC_GET_ARG2(*olddata), AS,
    272262                            IPC_GET_ARG1(answer->data), IPC_GET_ARG3(*olddata));
     
    274264                        return rc;
    275265                }
    276         } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_SHARE_IN) {
     266        } else if (IPC_GET_METHOD(*olddata) == IPC_M_SHARE_IN) {
    277267                if (!IPC_GET_RETVAL(answer->data)) {
    278                         irq_spinlock_lock(&answer->sender->lock, true);
    279                         as_t *as = answer->sender->as;
    280                         irq_spinlock_unlock(&answer->sender->lock, true);
     268                        ipl_t ipl;
     269                        as_t *as;
     270                        int rc;
    281271                       
    282                         int rc = as_area_share(AS, IPC_GET_ARG1(answer->data),
     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),
    283279                            IPC_GET_ARG2(*olddata), as, IPC_GET_ARG1(*olddata),
    284280                            IPC_GET_ARG2(answer->data));
    285281                        IPC_SET_RETVAL(answer->data, rc);
    286282                }
    287         } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_DATA_READ) {
     283        } else if (IPC_GET_METHOD(*olddata) == IPC_M_DATA_READ) {
    288284                ASSERT(!answer->buffer);
    289285                if (!IPC_GET_RETVAL(answer->data)) {
     
    299295                                 */
    300296                                IPC_SET_ARG1(answer->data, dst);
    301                                
     297
    302298                                answer->buffer = malloc(size, 0);
    303299                                int rc = copy_from_uspace(answer->buffer,
     
    314310                        }
    315311                }
    316         } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_DATA_WRITE) {
     312        } else if (IPC_GET_METHOD(*olddata) == IPC_M_DATA_WRITE) {
    317313                ASSERT(answer->buffer);
    318314                if (!IPC_GET_RETVAL(answer->data)) {
    319315                        /* The recipient agreed to receive data. */
    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                        
     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
    324325                        if (size <= max_size) {
    325                                 int rc = copy_to_uspace((void *) dst,
     326                                rc = copy_to_uspace((void *) dst,
    326327                                    answer->buffer, size);
    327328                                if (rc)
     
    334335                answer->buffer = NULL;
    335336        }
    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        }
    350351}
    351352
     
    359360/** Called before the request is sent.
    360361 *
    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  *
     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.
    366366 */
    367367static int request_preprocess(call_t *call, phone_t *phone)
    368368{
    369         switch (IPC_GET_IMETHOD(call->data)) {
     369        int newphid;
     370        size_t size;
     371        uintptr_t src;
     372        int rc;
     373
     374        switch (IPC_GET_METHOD(call->data)) {
    370375        case IPC_M_CONNECTION_CLONE: {
    371376                phone_t *cloned_phone;
    372                 if (phone_get(IPC_GET_ARG1(call->data), &cloned_phone) != EOK)
    373                         return ENOENT;
    374                
     377                GET_CHECK_PHONE(cloned_phone, IPC_GET_ARG1(call->data),
     378                    return ENOENT);
    375379                phones_lock(cloned_phone, phone);
    376                
    377380                if ((cloned_phone->state != IPC_PHONE_CONNECTED) ||
    378381                    phone->state != IPC_PHONE_CONNECTED) {
     
    380383                        return EINVAL;
    381384                }
    382                
    383385                /*
    384386                 * We can be pretty sure now that both tasks exist and we are
     
    386388                 * we are effectively preventing them from finishing their
    387389                 * potential cleanup.
    388                  *
    389390                 */
    390                 int newphid = phone_alloc(phone->callee->task);
     391                newphid = phone_alloc(phone->callee->task);
    391392                if (newphid < 0) {
    392393                        phones_unlock(cloned_phone, phone);
    393394                        return ELIMIT;
    394395                }
    395                
    396396                ipc_phone_connect(&phone->callee->task->phones[newphid],
    397397                    cloned_phone->callee);
    398398                phones_unlock(cloned_phone, phone);
    399                
    400399                /* Set the new phone for the callee. */
    401400                IPC_SET_ARG1(call->data, newphid);
     
    403402        }
    404403        case IPC_M_CONNECT_ME:
    405                 IPC_SET_ARG5(call->data, (sysarg_t) phone);
     404                IPC_SET_ARG5(call->data, (unative_t) phone);
    406405                break;
    407         case IPC_M_CONNECT_ME_TO: {
    408                 int newphid = phone_alloc(TASK);
     406        case IPC_M_CONNECT_ME_TO:
     407                newphid = phone_alloc(TASK);
    409408                if (newphid < 0)
    410409                        return ELIMIT;
    411                
    412410                /* Set arg5 for server */
    413                 IPC_SET_ARG5(call->data, (sysarg_t) &TASK->phones[newphid]);
     411                IPC_SET_ARG5(call->data, (unative_t) &TASK->phones[newphid]);
    414412                call->flags |= IPC_CALL_CONN_ME_TO;
    415413                call->priv = newphid;
    416414                break;
    417         }
    418         case IPC_M_SHARE_OUT: {
    419                 size_t size = as_area_get_size(IPC_GET_ARG1(call->data));
     415        case IPC_M_SHARE_OUT:
     416                size = as_area_get_size(IPC_GET_ARG1(call->data));
    420417                if (!size)
    421418                        return EPERM;
    422                
    423419                IPC_SET_ARG2(call->data, size);
    424420                break;
    425         }
    426         case IPC_M_DATA_READ: {
    427                 size_t size = IPC_GET_ARG2(call->data);
     421        case IPC_M_DATA_READ:
     422                size = IPC_GET_ARG2(call->data);
    428423                if ((size <= 0 || (size > DATA_XFER_LIMIT)))
    429424                        return ELIMIT;
    430                
    431425                break;
    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);
     426        case IPC_M_DATA_WRITE:
     427                src = IPC_GET_ARG1(call->data);
     428                size = IPC_GET_ARG2(call->data);
    436429               
    437430                if (size > DATA_XFER_LIMIT)
     
    439432               
    440433                call->buffer = (uint8_t *) malloc(size, 0);
    441                 int rc = copy_from_uspace(call->buffer, (void *) src, size);
     434                rc = copy_from_uspace(call->buffer, (void *) src, size);
    442435                if (rc != 0) {
    443436                        free(call->buffer);
    444437                        return rc;
    445438                }
    446                
    447439                break;
    448         }
    449440#ifdef CONFIG_UDEBUG
    450441        case IPC_M_DEBUG_ALL:
     
    454445                break;
    455446        }
    456        
    457447        return 0;
    458448}
     
    464454/** Do basic kernel processing of received call answer.
    465455 *
    466  * @param call Call structure with the answer.
    467  *
     456 * @param call          Call structure with the answer.
    468457 */
    469458static void process_answer(call_t *call)
     
    472461            (call->flags & IPC_CALL_FORWARDED))
    473462                IPC_SET_RETVAL(call->data, EFORWARD);
    474        
     463
    475464        if (call->flags & IPC_CALL_CONN_ME_TO) {
    476465                if (IPC_GET_RETVAL(call->data))
     
    479468                        IPC_SET_ARG5(call->data, call->priv);
    480469        }
    481        
     470
    482471        if (call->buffer) {
    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                  */
     472                /* This must be an affirmative answer to IPC_M_DATA_READ. */
     473                /* or IPC_M_DEBUG_ALL/UDEBUG_M_MEM_READ... */
    488474                uintptr_t dst = IPC_GET_ARG1(call->data);
    489475                size_t size = IPC_GET_ARG2(call->data);
     
    498484/** Do basic kernel processing of received call request.
    499485 *
    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  *
     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.
    506491 */
    507492static int process_request(answerbox_t *box, call_t *call)
    508493{
    509         if (IPC_GET_IMETHOD(call->data) == IPC_M_CONNECT_TO_ME) {
    510                 int phoneid = phone_alloc(TASK);
     494        int phoneid;
     495
     496        if (IPC_GET_METHOD(call->data) == IPC_M_CONNECT_TO_ME) {
     497                phoneid = phone_alloc(TASK);
    511498                if (phoneid < 0) { /* Failed to allocate phone */
    512499                        IPC_SET_RETVAL(call->data, ELIMIT);
     
    514501                        return -1;
    515502                }
    516                
    517503                IPC_SET_ARG5(call->data, phoneid);
    518504        }
    519        
    520         switch (IPC_GET_IMETHOD(call->data)) {
     505        switch (IPC_GET_METHOD(call->data)) {
    521506        case IPC_M_DEBUG_ALL:
    522507                return -1;
     
    524509                break;
    525510        }
    526        
    527511        return 0;
    528512}
     
    533517 * the generic function (i.e. sys_ipc_call_sync_slow()).
    534518 *
    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  */
    547 sysarg_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 {
     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 */
     530unative_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;
    550534        phone_t *phone;
    551         if (phone_get(phoneid, &phone) != EOK)
    552                 return ENOENT;
     535        int res;
     536        int rc;
    553537       
    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        
     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);
    560545        /*
    561546         * To achieve deterministic behavior, zero out arguments that are beyond
    562547         * the limits of the fast version.
    563548         */
    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) {
     549        IPC_SET_ARG4(call.data, 0);
     550        IPC_SET_ARG5(call.data, 0);
     551
     552        if (!(res = request_preprocess(&call, phone))) {
    571553#ifdef CONFIG_UDEBUG
    572554                udebug_stoppable_begin();
    573555#endif
    574                 rc = ipc_call_sync(phone, call);
     556                rc = ipc_call_sync(phone, &call);
    575557#ifdef CONFIG_UDEBUG
    576558                udebug_stoppable_end();
    577559#endif
    578                
    579                 if (rc != EOK) {
    580                         /* The call will be freed by ipc_cleanup(). */
     560                if (rc != EOK)
    581561                        return rc;
    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);
     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);
    590568        if (rc != 0)
    591569                return rc;
    592        
     570
    593571        return 0;
    594572}
     
    596574/** Make a synchronous IPC call allowing to transmit the entire payload.
    597575 *
    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  */
    606 sysarg_t sys_ipc_call_sync_slow(sysarg_t phoneid, ipc_data_t *request,
     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 */
     583unative_t sys_ipc_call_sync_slow(unative_t phoneid, ipc_data_t *question,
    607584    ipc_data_t *reply)
    608585{
     586        call_t call;
    609587        phone_t *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) {
     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))) {
    624600#ifdef CONFIG_UDEBUG
    625601                udebug_stoppable_begin();
    626602#endif
    627                 rc = ipc_call_sync(phone, call);
     603                rc = ipc_call_sync(phone, &call);
    628604#ifdef CONFIG_UDEBUG
    629605                udebug_stoppable_end();
    630606#endif
    631                
    632                 if (rc != EOK) {
    633                         /* The call will be freed by ipc_cleanup(). */
     607                if (rc != EOK)
    634608                        return rc;
    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);
     609                process_answer(&call);
     610        } else
     611                IPC_SET_RETVAL(call.data, res);
     612
     613        rc = STRUCT_TO_USPACE(&reply->args, &call.data.args);
    643614        if (rc != 0)
    644615                return rc;
    645        
     616
    646617        return 0;
    647618}
    648619
    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  */
    657 static int check_call_limit(phone_t *phone)
    658 {
    659         if (atomic_get(&phone->active_calls) >= IPC_MAX_ASYNC_CALLS)
     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 */
     624static int check_call_limit(void)
     625{
     626        if (atomic_preinc(&TASK->active_calls) > IPC_MAX_ASYNC_CALLS) {
     627                atomic_dec(&TASK->active_calls);
    660628                return -1;
    661        
     629        }
    662630        return 0;
    663631}
     
    668636 * the generic function sys_ipc_call_async_slow().
    669637 *
    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  */
    683 sysarg_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 {
     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 */
     650unative_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;
    686654        phone_t *phone;
    687         if (phone_get(phoneid, &phone) != EOK)
    688                 return IPC_CALLRET_FATAL;
    689        
    690         if (check_call_limit(phone))
     655        int res;
     656
     657        if (check_call_limit())
    691658                return IPC_CALLRET_TEMPORARY;
    692        
    693         call_t *call = ipc_call_alloc(0);
    694         IPC_SET_IMETHOD(call->data, imethod);
     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);
    695664        IPC_SET_ARG1(call->data, arg1);
    696665        IPC_SET_ARG2(call->data, arg2);
    697666        IPC_SET_ARG3(call->data, arg3);
    698667        IPC_SET_ARG4(call->data, arg4);
    699        
    700668        /*
    701669         * To achieve deterministic behavior, zero out arguments that are beyond
     
    703671         */
    704672        IPC_SET_ARG5(call->data, 0);
    705        
    706         int res = request_preprocess(call, phone);
    707        
    708         if (!res)
     673
     674        if (!(res = request_preprocess(call, phone)))
    709675                ipc_call(phone, call);
    710676        else
    711677                ipc_backsend_err(phone, call, res);
    712        
    713         return (sysarg_t) call;
     678
     679        return (unative_t) call;
    714680}
    715681
    716682/** Make an asynchronous IPC call allowing to transmit the entire payload.
    717683 *
    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  */
    724 sysarg_t sys_ipc_call_async_slow(sysarg_t phoneid, ipc_data_t *data)
    725 {
     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 */
     689unative_t sys_ipc_call_async_slow(unative_t phoneid, ipc_data_t *data)
     690{
     691        call_t *call;
    726692        phone_t *phone;
    727         if (phone_get(phoneid, &phone) != EOK)
    728                 return IPC_CALLRET_FATAL;
    729 
    730         if (check_call_limit(phone))
     693        int res;
     694        int rc;
     695
     696        if (check_call_limit())
    731697                return IPC_CALLRET_TEMPORARY;
    732698
    733         call_t *call = ipc_call_alloc(0);
    734         int rc = copy_from_uspace(&call->data.args, &data->args,
     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,
    735703            sizeof(call->data.args));
    736704        if (rc != 0) {
    737705                ipc_call_free(call);
    738                 return (sysarg_t) rc;
    739         }
    740        
    741         int res = request_preprocess(call, phone);
    742        
    743         if (!res)
     706                return (unative_t) rc;
     707        }
     708        if (!(res = request_preprocess(call, phone)))
    744709                ipc_call(phone, call);
    745710        else
    746711                ipc_backsend_err(phone, call, res);
    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  */
    773 static 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);
     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 */
     736static 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);
    778744        if (!call)
    779745                return ENOENT;
    780746       
    781747        call->flags |= IPC_CALL_FORWARDED;
    782        
    783         phone_t *phone;
    784         if (phone_get(phoneid, &phone) != EOK) {
     748
     749        GET_CHECK_PHONE(phone, phoneid, {
    785750                IPC_SET_RETVAL(call->data, EFORWARD);
    786751                ipc_answer(&TASK->answerbox, call);
    787752                return ENOENT;
    788         }
    789        
    790         if (!method_is_forwardable(IPC_GET_IMETHOD(call->data))) {
     753        });
     754
     755        if (!method_is_forwardable(IPC_GET_METHOD(call->data))) {
    791756                IPC_SET_RETVAL(call->data, EFORWARD);
    792757                ipc_answer(&TASK->answerbox, call);
    793758                return EPERM;
    794759        }
    795        
     760
    796761        /*
    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.
     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.
    801766         */
    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)
     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)
    805770                                phone_dealloc(IPC_GET_ARG5(call->data));
    806                        
    807                         IPC_SET_ARG1(call->data, imethod);
     771
     772                        IPC_SET_ARG1(call->data, method);
    808773                        IPC_SET_ARG2(call->data, arg1);
    809774                        IPC_SET_ARG3(call->data, arg2);
    810                        
    811775                        if (slow) {
    812776                                IPC_SET_ARG4(call->data, arg3);
     
    817781                        }
    818782                } else {
    819                         IPC_SET_IMETHOD(call->data, imethod);
     783                        IPC_SET_METHOD(call->data, method);
    820784                        IPC_SET_ARG1(call->data, arg1);
    821785                        IPC_SET_ARG2(call->data, arg2);
     
    827791                }
    828792        }
    829        
     793
    830794        return ipc_forward(call, phone, &TASK->answerbox, mode);
    831795}
     
    833797/** Forward a received call to another destination - fast version.
    834798 *
    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  */
    852 sysarg_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,
     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 */
     815unative_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,
    856819            0, mode, false);
    857820}
     
    859822/** Forward a received call to another destination - slow version.
    860823 *
     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 *
    861831 * This function is the slow verision of the sys_ipc_forward_fast interface.
    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  */
    876 sysarg_t sys_ipc_forward_slow(sysarg_t callid, sysarg_t phoneid,
    877     ipc_data_t *data, unsigned int mode)
     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 */
     838unative_t sys_ipc_forward_slow(unative_t callid, unative_t phoneid,
     839    ipc_data_t *data, int mode)
    878840{
    879841        ipc_data_t newdata;
    880         int rc = copy_from_uspace(&newdata.args, &data->args,
     842        int rc;
     843
     844        rc = copy_from_uspace(&newdata.args, &data->args,
    881845            sizeof(newdata.args));
    882         if (rc != 0)
    883                 return (sysarg_t) rc;
    884        
     846        if (rc != 0) 
     847                return (unative_t) rc;
     848
    885849        return sys_ipc_forward_common(callid, phoneid,
    886             IPC_GET_IMETHOD(newdata), IPC_GET_ARG1(newdata),
     850            IPC_GET_METHOD(newdata), IPC_GET_ARG1(newdata),
    887851            IPC_GET_ARG2(newdata), IPC_GET_ARG3(newdata),
    888852            IPC_GET_ARG4(newdata), IPC_GET_ARG5(newdata), mode, true);
     
    894858 * than the generic sys_ipc_answer().
    895859 *
    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  */
    906 sysarg_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 {
     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 */
     869unative_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
    909877        /* Do not answer notification callids */
    910878        if (callid & IPC_CALLID_NOTIFICATION)
    911879                return 0;
    912        
    913         call_t *call = get_call(callid);
     880
     881        call = get_call(callid);
    914882        if (!call)
    915883                return ENOENT;
    916        
    917         ipc_data_t saved_data;
    918         bool saved;
    919        
     884
    920885        if (answer_need_old(call)) {
    921886                memcpy(&saved_data, &call->data, sizeof(call->data));
    922                 saved = true;
    923         } else
    924                 saved = false;
    925        
     887                saveddata = 1;
     888        }
     889
    926890        IPC_SET_RETVAL(call->data, retval);
    927891        IPC_SET_ARG1(call->data, arg1);
     
    929893        IPC_SET_ARG3(call->data, arg3);
    930894        IPC_SET_ARG4(call->data, arg4);
    931        
    932895        /*
    933896         * To achieve deterministic behavior, zero out arguments that are beyond
     
    935898         */
    936899        IPC_SET_ARG5(call->data, 0);
    937         int rc = answer_preprocess(call, saved ? &saved_data : NULL);
    938        
     900        rc = answer_preprocess(call, saveddata ? &saved_data : NULL);
     901
    939902        ipc_answer(&TASK->answerbox, call);
    940903        return rc;
     
    943906/** Answer an IPC call.
    944907 *
    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  */
    951 sysarg_t sys_ipc_answer_slow(sysarg_t callid, ipc_data_t *data)
    952 {
     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 */
     913unative_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
    953920        /* Do not answer notification callids */
    954921        if (callid & IPC_CALLID_NOTIFICATION)
    955922                return 0;
    956        
    957         call_t *call = get_call(callid);
     923
     924        call = get_call(callid);
    958925        if (!call)
    959926                return ENOENT;
    960        
    961         ipc_data_t saved_data;
    962         bool saved;
    963        
     927
    964928        if (answer_need_old(call)) {
    965929                memcpy(&saved_data, &call->data, sizeof(call->data));
    966                 saved = true;
    967         } else
    968                 saved = false;
    969        
    970         int rc = copy_from_uspace(&call->data.args, &data->args,
     930                saveddata = 1;
     931        }
     932        rc = copy_from_uspace(&call->data.args, &data->args,
    971933            sizeof(call->data.args));
    972934        if (rc != 0)
    973935                return rc;
    974        
    975         rc = answer_preprocess(call, saved ? &saved_data : NULL);
     936
     937        rc = answer_preprocess(call, saveddata ? &saved_data : NULL);
    976938       
    977939        ipc_answer(&TASK->answerbox, call);
     940
    978941        return rc;
    979942}
     
    981944/** Hang up a phone.
    982945 *
    983  * @param Phone handle of the phone to be hung up.
    984  *
    985  * @return 0 on success or an error code.
    986  *
    987  */
    988 sysarg_t sys_ipc_hangup(sysarg_t phoneid)
     946 * @param               Phone handle of the phone to be hung up.
     947 *
     948 * @return              Return 0 on success or an error code.
     949 */
     950unative_t sys_ipc_hangup(int phoneid)
    989951{
    990952        phone_t *phone;
    991        
    992         if (phone_get(phoneid, &phone) != EOK)
    993                 return ENOENT;
    994        
     953
     954        GET_CHECK_PHONE(phone, phoneid, return ENOENT);
     955
    995956        if (ipc_phone_hangup(phone))
    996957                return -1;
    997        
     958
    998959        return 0;
    999960}
     
    1001962/** Wait for an incoming IPC call or an answer.
    1002963 *
    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  */
    1014 sysarg_t sys_ipc_wait_for_call(ipc_data_t *calldata, uint32_t usec,
    1015     unsigned int flags)
     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 */
     974unative_t sys_ipc_wait_for_call(ipc_data_t *calldata, uint32_t usec, int flags)
    1016975{
    1017976        call_t *call;
    1018        
     977
    1019978restart:
    1020        
     979
    1021980#ifdef CONFIG_UDEBUG
    1022981        udebug_stoppable_begin();
    1023 #endif
    1024        
     982#endif 
    1025983        call = ipc_wait_for_call(&TASK->answerbox, usec,
    1026984            flags | SYNCH_FLAGS_INTERRUPTIBLE);
    1027        
     985
    1028986#ifdef CONFIG_UDEBUG
    1029987        udebug_stoppable_end();
    1030988#endif
    1031        
    1032989        if (!call)
    1033990                return 0;
    1034        
     991
    1035992        if (call->flags & IPC_CALL_NOTIF) {
     993                ASSERT(! (call->flags & IPC_CALL_STATIC_ALLOC));
     994
    1036995                /* Set in_phone_hash to the interrupt counter */
    1037996                call->data.phone = (void *) call->priv;
    1038997               
    1039998                STRUCT_TO_USPACE(calldata, &call->data);
    1040                
     999
    10411000                ipc_call_free(call);
    10421001               
    1043                 return ((sysarg_t) call) | IPC_CALLID_NOTIFICATION;
    1044         }
    1045        
     1002                return ((unative_t) call) | IPC_CALLID_NOTIFICATION;
     1003        }
     1004
    10461005        if (call->flags & IPC_CALL_ANSWERED) {
    10471006                process_answer(call);
    1048                
     1007
     1008                ASSERT(! (call->flags & IPC_CALL_STATIC_ALLOC));
     1009
    10491010                if (call->flags & IPC_CALL_DISCARD_ANSWER) {
    10501011                        ipc_call_free(call);
    10511012                        goto restart;
    1052                 }
    1053                
     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
    10541022                STRUCT_TO_USPACE(&calldata->args, &call->data.args);
    10551023                ipc_call_free(call);
    1056                
    1057                 return ((sysarg_t) call) | IPC_CALLID_ANSWERED;
    1058         }
    1059        
     1024
     1025                return ((unative_t) call) | IPC_CALLID_ANSWERED;
     1026        }
     1027
    10601028        if (process_request(&TASK->answerbox, call))
    10611029                goto restart;
    1062        
     1030
    10631031        /* Include phone address('id') of the caller in the request,
    10641032         * copy whole call->data, not only call->data.args */
     
    10691037                 */
    10701038                ipc_data_t saved_data;
    1071                 bool saved;
    1072                
     1039                int saveddata = 0;
     1040
    10731041                if (answer_need_old(call)) {
    10741042                        memcpy(&saved_data, &call->data, sizeof(call->data));
    1075                         saved = true;
    1076                 } else
    1077                         saved = false;
     1043                        saveddata = 1;
     1044                }
    10781045               
    10791046                IPC_SET_RETVAL(call->data, EPARTY);
    1080                 (void) answer_preprocess(call, saved ? &saved_data : NULL);
     1047                (void) answer_preprocess(call, saveddata ? &saved_data : NULL);
    10811048                ipc_answer(&TASK->answerbox, call);
    10821049                return 0;
    10831050        }
    1084        
    1085         return (sysarg_t) call;
    1086 }
    1087 
    1088 /** Interrupt one thread from sys_ipc_wait_for_call().
    1089  *
    1090  */
    1091 sysarg_t sys_ipc_poke(void)
    1092 {
    1093         waitq_unsleep(&TASK->answerbox.wq);
     1051        return (unative_t)call;
     1052}
     1053
     1054/** Interrupt one thread from sys_ipc_wait_for_call(). */
     1055unative_t sys_ipc_poke(void)
     1056{
     1057        waitq_unsleep(&TASK->answerbox.wq);     
    10941058        return EOK;
    10951059}
     
    10971061/** Connect an IRQ handler to a task.
    10981062 *
    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  */
    1107 sysarg_t sys_register_irq(inr_t inr, devno_t devno, sysarg_t imethod,
     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 */
     1070unative_t sys_ipc_register_irq(inr_t inr, devno_t devno, unative_t method,
    11081071    irq_code_t *ucode)
    11091072{
    11101073        if (!(cap_get(TASK) & CAP_IRQ_REG))
    11111074                return EPERM;
    1112        
    1113         return ipc_irq_register(&TASK->answerbox, inr, devno, imethod, ucode);
     1075
     1076        return ipc_irq_register(&TASK->answerbox, inr, devno, method, ucode);
    11141077}
    11151078
    11161079/** Disconnect an IRQ handler from a task.
    11171080 *
    1118  * @param inr   IRQ number.
    1119  * @param devno Device number.
    1120  *
    1121  * @return Zero on success or EPERM on error.
    1122  *
    1123  */
    1124 sysarg_t sys_unregister_irq(inr_t inr, devno_t devno)
     1081 * @param inr           IRQ number.
     1082 * @param devno         Device number.
     1083 *
     1084 * @return              Zero on success or EPERM on error..
     1085 */
     1086unative_t sys_ipc_unregister_irq(inr_t inr, devno_t devno)
    11251087{
    11261088        if (!(cap_get(TASK) & CAP_IRQ_REG))
    11271089                return EPERM;
     1090
     1091        ipc_irq_unregister(&TASK->answerbox, inr, devno);
     1092
     1093        return 0;
     1094}
     1095
     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 */
     1103unative_t sys_ipc_connect_kbox(sysarg64_t *uspace_taskid_arg)
     1104{
     1105#ifdef CONFIG_UDEBUG
     1106        sysarg64_t taskid_arg;
     1107        int rc;
    11281108       
    1129         ipc_irq_unregister(&TASK->answerbox, inr, devno);
    1130        
    1131         return 0;
    1132 }
    1133 
    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  */
    1141 sysarg_t sys_ipc_connect_kbox(sysarg64_t *uspace_taskid)
    1142 {
    1143 #ifdef CONFIG_UDEBUG
    1144         sysarg64_t taskid;
    1145         int rc = copy_from_uspace(&taskid, uspace_taskid, sizeof(sysarg64_t));
     1109        rc = copy_from_uspace(&taskid_arg, uspace_taskid_arg, sizeof(sysarg64_t));
    11461110        if (rc != 0)
    1147                 return (sysarg_t) rc;
    1148        
    1149         return ipc_connect_kbox((task_id_t) taskid);
     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);
    11501116#else
    1151         return (sysarg_t) ENOTSUP;
     1117        return (unative_t) ENOTSUP;
    11521118#endif
    11531119}
    11541120
    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  */
    1164 sysarg_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 
    11751121/** @}
    11761122 */
Note: See TracChangeset for help on using the changeset viewer.