Changeset 8b243f2 in mainline for kernel/generic/src
- Timestamp:
- 2007-06-17T19:34:36Z (18 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- bd72c3e9
- Parents:
- 4680ef5
- Location:
- kernel/generic/src/ipc
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/ipc/ipc.c
r4680ef5 r8b243f2 35 35 /* Lock ordering 36 36 * 37 * First the answerbox, then the phone 37 * First the answerbox, then the phone. 38 38 */ 39 39 … … 54 54 #include <ipc/irq.h> 55 55 56 /* Open channel that is assigned automatically to new tasks */56 /** Open channel that is assigned automatically to new tasks */ 57 57 answerbox_t *ipc_phone_0 = NULL; 58 58 59 59 static slab_cache_t *ipc_call_slab; 60 60 61 /* Initialize new call */ 61 /** Initialize a call structure. 62 * 63 * @param call Call structure to be initialized. 64 */ 62 65 static void _ipc_call_init(call_t *call) 63 66 { 64 memsetb((uintptr_t) call, sizeof(*call), 0);67 memsetb((uintptr_t) call, sizeof(*call), 0); 65 68 call->callerbox = &TASK->answerbox; 66 69 call->sender = TASK; 67 70 } 68 71 69 /** Allocate & initialize call structure72 /** Allocate and initialize a call structure. 70 73 * 71 * The call is initialized, so that the reply will be directed 72 * to TASK->answerbox 73 * 74 * @param flags Parameters for slab_alloc (ATOMIC, etc.) 75 */ 76 call_t * ipc_call_alloc(int flags) 74 * The call is initialized, so that the reply will be directed to 75 * TASK->answerbox. 76 * 77 * @param flags Parameters for slab_alloc (e.g FRAME_ATOMIC). 78 * 79 * @return If flags permit it, return NULL, or initialized kernel 80 * call structure. 81 */ 82 call_t *ipc_call_alloc(int flags) 77 83 { 78 84 call_t *call; … … 84 90 } 85 91 86 /** Initialize allocated call */ 92 /** Initialize a statically allocated call structure. 93 * 94 * @param call Statically allocated kernel call structure to be 95 * initialized. 96 */ 87 97 void ipc_call_static_init(call_t *call) 88 98 { … … 91 101 } 92 102 93 /** Deallocate call stracuture */ 103 /** Deallocate a call stracuture. 104 * 105 * @param call Call structure to be freed. 106 */ 94 107 void ipc_call_free(call_t *call) 95 108 { 109 ASSERT(!(call->flags & IPC_CALL_STATIC_ALLOC)); 96 110 slab_free(ipc_call_slab, call); 97 111 } 98 112 99 /** Initialize answerbox structure 113 /** Initialize an answerbox structure. 114 * 115 * @param box Answerbox structure to be initialized. 100 116 */ 101 117 void ipc_answerbox_init(answerbox_t *box) … … 113 129 } 114 130 115 /** Connect phone to answerbox */ 131 /** Connect a phone to an answerbox. 132 * 133 * @param phone Initialized phone structure. 134 * @param box Initialized answerbox structure. 135 */ 116 136 void ipc_phone_connect(phone_t *phone, answerbox_t *box) 117 137 { … … 128 148 } 129 149 130 /** Initialize phone structure and connect phone to answerbox 150 /** Initialize a phone structure. 151 * 152 * @param phone Phone structure to be initialized. 131 153 */ 132 154 void ipc_phone_init(phone_t *phone) … … 138 160 } 139 161 140 /** Helper function to facilitate synchronous calls */ 162 /** Helper function to facilitate synchronous calls. 163 * 164 * @param phone Destination kernel phone structure. 165 * @param request Call structure with request. 166 */ 141 167 void ipc_call_sync(phone_t *phone, call_t *request) 142 168 { … … 145 171 ipc_answerbox_init(&sync_box); 146 172 147 /* We will receive data on special box*/173 /* We will receive data in a special box. */ 148 174 request->callerbox = &sync_box; 149 175 … … 152 178 } 153 179 154 /** Answer message that was not dispatched and is not entered in 155 * any queue 180 /** Answer a message which was not dispatched and is not listed in any queue. 181 * 182 * @param call Call structure to be answered. 156 183 */ 157 184 static void _ipc_answer_free_call(call_t *call) … … 167 194 } 168 195 169 /** Answer message, that is in callee queue170 * 171 * @param box Answerbox that is answering the message172 * @param call Modified request that is being sent back196 /** Answer a message which is in a callee queue. 197 * 198 * @param box Answerbox that is answering the message. 199 * @param call Modified request that is being sent back. 173 200 */ 174 201 void ipc_answer(answerbox_t *box, call_t *call) … … 182 209 } 183 210 184 /** Simulate sending back a message 211 /** Simulate sending back a message. 185 212 * 186 213 * Most errors are better handled by forming a normal backward 187 214 * message and sending it as a normal answer. 215 * 216 * @param phone Phone structure the call should appear to come from. 217 * @param call Call structure to be answered. 218 * @param err Return value to be used for the answer. 188 219 */ 189 220 void ipc_backsend_err(phone_t *phone, call_t *call, unative_t err) … … 195 226 } 196 227 197 /* Unsafe unchecking ipc_call */ 228 /** Unsafe unchecking version of ipc_call. 229 * 230 * @param phone Phone structure the call comes from. 231 * @param box Destination answerbox structure. 232 */ 198 233 static void _ipc_call(phone_t *phone, answerbox_t *box, call_t *call) 199 234 { 200 if (! 235 if (!(call->flags & IPC_CALL_FORWARDED)) { 201 236 atomic_inc(&phone->active_calls); 202 237 call->data.phone = phone; … … 209 244 } 210 245 211 /** Send a asynchronous request using phone to answerbox 212 * 213 * @param phone Phone connected to answerbox. 214 * @param call Structure representing the call. 246 /** Send an asynchronous request using a phone to an answerbox. 247 * 248 * @param phone Phone structure the call comes from and which is 249 * connected to the destination answerbox. 250 * @param call Call structure with request. 251 * 252 * @return Return 0 on success, ENOENT on error. 215 253 */ 216 254 int ipc_call(phone_t *phone, call_t *call) … … 239 277 } 240 278 241 /** Disconnect phone from answerbox 242 * 243 * This call leaves the phone in HUNGUP state. The change to 'free' is done279 /** Disconnect phone from answerbox. 280 * 281 * This call leaves the phone in the HUNGUP state. The change to 'free' is done 244 282 * lazily later. 245 283 * 246 * @param phone Phone to be hung up284 * @param phone Phone structure to be hung up. 247 285 * 248 * @return 0 - phone disconnected, -1 - the phone was already disconnected 286 * @return Return 0 if the phone is disconnected. 287 * Return -1 if the phone was already disconnected. 249 288 */ 250 289 int ipc_phone_hangup(phone_t *phone) … … 254 293 255 294 spinlock_lock(&phone->lock); 256 if (phone->state == IPC_PHONE_FREE || phone->state == IPC_PHONE_HUNGUP \257 ||phone->state == IPC_PHONE_CONNECTING) {295 if (phone->state == IPC_PHONE_FREE || phone->state == IPC_PHONE_HUNGUP || 296 phone->state == IPC_PHONE_CONNECTING) { 258 297 spinlock_unlock(&phone->lock); 259 298 return -1; … … 280 319 } 281 320 282 /** Forwards call from one answerbox to a new one 283 * 284 * @param call Call to be redirected. 285 * @param newphone Phone to target answerbox. 286 * @param oldbox Old answerbox 287 * @return 0 on forward ok, error code, if there was error 321 /** Forwards call from one answerbox to another one. 322 * 323 * @param call Call structure to be redirected. 324 * @param newphone Phone structure to target answerbox. 325 * @param oldbox Old answerbox structure. 326 * 327 * @return Return 0 if forwarding succeeded or an error code if 328 * there was error. 288 329 * 289 * - the return value serves only as an information for the forwarder,290 * the original caller is notified automatically with EFORWARD330 * The return value serves only as an information for the forwarder, 331 * the original caller is notified automatically with EFORWARD. 291 332 */ 292 333 int ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox) … … 300 341 301 342 302 /** Wait for phone call 303 * 304 * @param box Answerbox expecting the call. 305 * @param usec Timeout in microseconds. See documentation for waitq_sleep_timeout() for 306 * decription of its special meaning. 307 * @param flags Select mode of sleep operation. See documentation for waitq_sleep_timeout()i 308 * for description of its special meaning. 309 * @return Recived message address 310 * - to distinguish between call and answer, look at call->flags 311 */ 312 call_t * ipc_wait_for_call(answerbox_t *box, uint32_t usec, int flags) 343 /** Wait for a phone call. 344 * 345 * @param box Answerbox expecting the call. 346 * @param usec Timeout in microseconds. See documentation for 347 * waitq_sleep_timeout() for decription of its special 348 * meaning. 349 * @param flags Select mode of sleep operation. See documentation for 350 * waitq_sleep_timeout() for description of its special 351 * meaning. 352 * @return Recived call structure or NULL. 353 * 354 * To distinguish between a call and an answer, have a look at call->flags. 355 */ 356 call_t *ipc_wait_for_call(answerbox_t *box, uint32_t usec, int flags) 313 357 { 314 358 call_t *request; … … 351 395 } 352 396 353 /** Answer all calls from list with EHANGUP msg */ 397 /** Answer all calls from list with EHANGUP answer. 398 * 399 * @param lst Head of the list to be cleaned up. 400 */ 354 401 static void ipc_cleanup_call_list(link_t *lst) 355 402 { … … 365 412 } 366 413 367 /** Cleans up all IPC communication of the current task 414 /** Cleans up all IPC communication of the current task. 368 415 * 369 416 * Note: ipc_hangup sets returning answerbox to TASK->answerbox, you 370 * have to change it as well if you want to cleanup other current then current.417 * have to change it as well if you want to cleanup other tasks than TASK. 371 418 */ 372 419 void ipc_cleanup(void) … … 378 425 379 426 /* Disconnect all our phones ('ipc_phone_hangup') */ 380 for (i =0;i < IPC_MAX_PHONES; i++)427 for (i = 0; i < IPC_MAX_PHONES; i++) 381 428 ipc_phone_hangup(&TASK->phones[i]); 382 429 … … 414 461 /* Locking not needed, no one else should modify 415 462 * it, when we are in cleanup */ 416 for (i =0;i < IPC_MAX_PHONES; i++) {417 if (TASK->phones[i].state == IPC_PHONE_HUNGUP && \463 for (i = 0; i < IPC_MAX_PHONES; i++) { 464 if (TASK->phones[i].state == IPC_PHONE_HUNGUP && 418 465 atomic_get(&TASK->phones[i].active_calls) == 0) 419 466 TASK->phones[i].state = IPC_PHONE_FREE; … … 434 481 break; 435 482 436 call = ipc_wait_for_call(&TASK->answerbox, SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NONE); 437 ASSERT((call->flags & IPC_CALL_ANSWERED) || (call->flags & IPC_CALL_NOTIF)); 438 ASSERT(! (call->flags & IPC_CALL_STATIC_ALLOC)); 483 call = ipc_wait_for_call(&TASK->answerbox, SYNCH_NO_TIMEOUT, 484 SYNCH_FLAGS_NONE); 485 ASSERT((call->flags & IPC_CALL_ANSWERED) || 486 (call->flags & IPC_CALL_NOTIF)); 487 ASSERT(!(call->flags & IPC_CALL_STATIC_ALLOC)); 439 488 440 489 atomic_dec(&TASK->active_calls); … … 447 496 void ipc_init(void) 448 497 { 449 ipc_call_slab = slab_cache_create("ipc_call", sizeof(call_t), 0, NULL, NULL, 0); 450 } 451 452 453 /** Kconsole - list answerbox contents */ 498 ipc_call_slab = slab_cache_create("ipc_call", sizeof(call_t), 0, NULL, 499 NULL, 0); 500 } 501 502 503 /** List answerbox contents. 504 * 505 * @param taskid Task ID. 506 */ 454 507 void ipc_print_task(task_id_t taskid) 455 508 { … … 469 522 /* Print opened phones & details */ 470 523 printf("PHONE:\n"); 471 for (i =0; i < IPC_MAX_PHONES;i++) {524 for (i = 0; i < IPC_MAX_PHONES; i++) { 472 525 spinlock_lock(&task->phones[i].lock); 473 526 if (task->phones[i].state != IPC_PHONE_FREE) { 474 printf("%d: ", i);527 printf("%d: ", i); 475 528 switch (task->phones[i].state) { 476 529 case IPC_PHONE_CONNECTING: -
kernel/generic/src/ipc/ipcrsc.c
r4680ef5 r8b243f2 133 133 #include <debug.h> 134 134 135 /** Find call_t * in call table according to callid 136 * 137 * TODO: Some speedup (hash table?) 138 * @return NULL on not found, otherwise pointer to call structure 139 */ 140 call_t * get_call(unative_t callid) 135 /** Find call_t * in call table according to callid. 136 * 137 * @todo Some speedup (hash table?) 138 * 139 * @param callid Userspace hash of the call. Currently it is the call 140 * structure kernel address. 141 * 142 * @return NULL on not found, otherwise pointer to the call 143 * structure. 144 */ 145 call_t *get_call(unative_t callid) 141 146 { 142 147 link_t *lst; … … 145 150 spinlock_lock(&TASK->answerbox.lock); 146 151 for (lst = TASK->answerbox.dispatched_calls.next; 147 152 lst != &TASK->answerbox.dispatched_calls; lst = lst->next) { 148 153 call = list_get_instance(lst, call_t, link); 149 if ((unative_t) call == callid) {154 if ((unative_t) call == callid) { 150 155 result = call; 151 156 break; … … 156 161 } 157 162 158 /** Allocate new phone slot in current TASK structure */ 163 /** Allocate new phone slot in the current TASK structure. 164 * 165 * @return New phone handle or -1 if the phone handle limit is 166 * exceeded. 167 */ 159 168 int phone_alloc(void) 160 169 { … … 163 172 spinlock_lock(&TASK->lock); 164 173 165 for (i =0; i < IPC_MAX_PHONES; i++) {166 if (TASK->phones[i].state == IPC_PHONE_HUNGUP && \174 for (i = 0; i < IPC_MAX_PHONES; i++) { 175 if (TASK->phones[i].state == IPC_PHONE_HUNGUP && 167 176 atomic_get(&TASK->phones[i].active_calls) == 0) 168 177 TASK->phones[i].state = IPC_PHONE_FREE; … … 180 189 } 181 190 191 /** Mark a phone structure free. 192 * 193 * @param phone Phone structure to be marked free. 194 */ 182 195 static void phone_deallocp(phone_t *phone) 183 196 { … … 188 201 } 189 202 190 /** Free slot from a disconnected phone 191 * 192 * All already sent messages will be correctly processed 203 /** Free slot from a disconnected phone. 204 * 205 * All already sent messages will be correctly processed. 206 * 207 * @param phoneid Phone handle of the phone to be freed. 193 208 */ 194 209 void phone_dealloc(int phoneid) … … 197 212 } 198 213 199 /** Connect phone to a given answerbox 200 * 201 * @param phoneid The slot that will be connected 214 /** Connect phone to a given answerbox. 215 * 216 * @param phoneid Phone handle to be connected. 217 * @param box Answerbox to which to connect the phone handle. 202 218 * 203 219 * The procedure _enforces_ that the user first marks the phone -
kernel/generic/src/ipc/irq.c
r4680ef5 r8b243f2 61 61 /** Execute code associated with IRQ notification. 62 62 * 63 * @param call 64 * @param code 63 * @param call Notification call. 64 * @param code Top-half pseudocode. 65 65 */ 66 66 static void code_execute(call_t *call, irq_code_t *code) … … 72 72 return; 73 73 74 for (i =0; i < code->cmdcount;i++) {74 for (i = 0; i < code->cmdcount; i++) { 75 75 switch (code->cmds[i].cmd) { 76 76 case CMD_MEM_READ_1: 77 dstval = *((uint8_t *) code->cmds[i].addr);77 dstval = *((uint8_t *) code->cmds[i].addr); 78 78 break; 79 79 case CMD_MEM_READ_2: 80 dstval = *((uint16_t *) code->cmds[i].addr);80 dstval = *((uint16_t *) code->cmds[i].addr); 81 81 break; 82 82 case CMD_MEM_READ_4: 83 dstval = *((uint32_t *) code->cmds[i].addr);83 dstval = *((uint32_t *) code->cmds[i].addr); 84 84 break; 85 85 case CMD_MEM_READ_8: 86 dstval = *((uint64_t *) code->cmds[i].addr);86 dstval = *((uint64_t *) code->cmds[i].addr); 87 87 break; 88 88 case CMD_MEM_WRITE_1: 89 *((uint8_t *) code->cmds[i].addr) = code->cmds[i].value;89 *((uint8_t *) code->cmds[i].addr) = code->cmds[i].value; 90 90 break; 91 91 case CMD_MEM_WRITE_2: 92 *((uint16_t *) code->cmds[i].addr) = code->cmds[i].value;92 *((uint16_t *) code->cmds[i].addr) = code->cmds[i].value; 93 93 break; 94 94 case CMD_MEM_WRITE_4: 95 *((uint32_t *) code->cmds[i].addr) = code->cmds[i].value;95 *((uint32_t *) code->cmds[i].addr) = code->cmds[i].value; 96 96 break; 97 97 case CMD_MEM_WRITE_8: 98 *((uint64_t *) code->cmds[i].addr) = code->cmds[i].value;98 *((uint64_t *) code->cmds[i].addr) = code->cmds[i].value; 99 99 break; 100 100 #if defined(ia32) || defined(amd64) 101 101 case CMD_PORT_READ_1: 102 dstval = inb((long) code->cmds[i].addr);102 dstval = inb((long) code->cmds[i].addr); 103 103 break; 104 104 case CMD_PORT_WRITE_1: 105 outb((long) code->cmds[i].addr, code->cmds[i].value);105 outb((long) code->cmds[i].addr, code->cmds[i].value); 106 106 break; 107 107 #endif … … 125 125 } 126 126 127 /** Free top-half pseudocode. 128 * 129 * @param code Pointer to the top-half pseudocode. 130 */ 127 131 static void code_free(irq_code_t *code) 128 132 { … … 133 137 } 134 138 135 static irq_code_t * code_from_uspace(irq_code_t *ucode) 139 /** Copy top-half pseudocode from userspace into the kernel. 140 * 141 * @param ucode Userspace address of the top-half pseudocode. 142 * 143 * @return Kernel address of the copied pseudocode. 144 */ 145 static irq_code_t *code_from_uspace(irq_code_t *ucode) 136 146 { 137 147 irq_code_t *code; … … 151 161 } 152 162 ucmds = code->cmds; 153 code->cmds = malloc(sizeof(code->cmds[0]) * (code->cmdcount), 0); 154 rc = copy_from_uspace(code->cmds, ucmds, sizeof(code->cmds[0]) * (code->cmdcount)); 163 code->cmds = malloc(sizeof(code->cmds[0]) * code->cmdcount, 0); 164 rc = copy_from_uspace(code->cmds, ucmds, 165 sizeof(code->cmds[0]) * code->cmdcount); 155 166 if (rc != 0) { 156 167 free(code->cmds); … … 164 175 /** Unregister task from IRQ notification. 165 176 * 166 * @param box 167 * @param inr IRQ numbe.168 * @param devno 177 * @param box Answerbox associated with the notification. 178 * @param inr IRQ number. 179 * @param devno Device number. 169 180 */ 170 181 void ipc_irq_unregister(answerbox_t *box, inr_t inr, devno_t devno) … … 196 207 /** Register an answerbox as a receiving end for IRQ notifications. 197 208 * 198 * @param box Receiving answerbox. 199 * @param inr IRQ number. 200 * @param devno Device number. 201 * @param method Method to be associated with the notification. 202 * @param ucode Uspace pointer to top-half pseudocode. 203 * 204 * @return EBADMEM, ENOENT or EEXISTS on failure or 0 on success. 205 */ 206 int ipc_irq_register(answerbox_t *box, inr_t inr, devno_t devno, unative_t method, irq_code_t *ucode) 209 * @param box Receiving answerbox. 210 * @param inr IRQ number. 211 * @param devno Device number. 212 * @param method Method to be associated with the notification. 213 * @param ucode Uspace pointer to top-half pseudocode. 214 * 215 * @return EBADMEM, ENOENT or EEXISTS on failure or 0 on success. 216 */ 217 int ipc_irq_register(answerbox_t *box, inr_t inr, devno_t devno, 218 unative_t method, irq_code_t *ucode) 207 219 { 208 220 ipl_t ipl; … … 214 226 if (!code) 215 227 return EBADMEM; 216 } else 228 } else { 217 229 code = NULL; 230 } 218 231 219 232 ipl = interrupts_disable(); … … 248 261 } 249 262 250 /** Add call toproper answerbox queue.263 /** Add a call to the proper answerbox queue. 251 264 * 252 265 * Assume irq->lock is locked. 253 266 * 267 * @param irq IRQ structure referencing the target answerbox. 268 * @param call IRQ notification call. 254 269 */ 255 270 static void send_call(irq_t *irq, call_t *call) … … 262 277 } 263 278 264 /** Send notification message 265 * 279 /** Send notification message. 280 * 281 * @param irq IRQ structure. 282 * @param a1 Driver-specific payload argument. 283 * @param a2 Driver-specific payload argument. 284 * @param a3 Driver-specific payload argument. 266 285 */ 267 286 void ipc_irq_send_msg(irq_t *irq, unative_t a1, unative_t a2, unative_t a3) … … 290 309 } 291 310 292 /** Notify task that an irqhad occurred.311 /** Notify a task that an IRQ had occurred. 293 312 * 294 313 * We expect interrupts to be disabled and the irq->lock already held. 314 * 315 * @param irq IRQ structure. 295 316 */ 296 317 void ipc_irq_send_notif(irq_t *irq) … … 324 345 * send notifications to it. 325 346 * 326 * @param box 347 * @param box Answerbox for which we want to carry out the cleanup. 327 348 */ 328 349 void ipc_irq_cleanup(answerbox_t *box) -
kernel/generic/src/ipc/sysipc.c
r4680ef5 r8b243f2 50 50 #include <print.h> 51 51 52 #define GET_CHECK_PHONE(phone, phoneid, err) { \ 53 if (phoneid > IPC_MAX_PHONES) { err; } \ 54 phone = &TASK->phones[phoneid]; \ 55 } 56 57 #define STRUCT_TO_USPACE(dst, src) copy_to_uspace(dst, src, sizeof(*(src))) 58 59 /** Return true if the method is a system method */ 52 #define GET_CHECK_PHONE(phone, phoneid, err) \ 53 { \ 54 if (phoneid > IPC_MAX_PHONES) { \ 55 err; \ 56 } \ 57 phone = &TASK->phones[phoneid]; \ 58 } 59 60 #define STRUCT_TO_USPACE(dst, src) copy_to_uspace(dst, src, sizeof(*(src))) 61 62 /** Decide if the method is a system method. 63 * 64 * @param method Method to be decided. 65 * 66 * @return Return 1 if the method is a system method. 67 * Otherwise return 0. 68 */ 60 69 static inline int is_system_method(unative_t method) 61 70 { … … 65 74 } 66 75 67 /** Return true if the message with this method is forwardable76 /** Decide if the message with this method is forwardable. 68 77 * 69 78 * - some system messages may be forwarded, for some of them 70 79 * it is useless 80 * 81 * @param method Method to be decided. 82 * 83 * @return Return 1 if the method is forwardable. 84 * Otherwise return 0. 71 85 */ 72 86 static inline int is_forwardable(unative_t method) … … 78 92 } 79 93 80 /****************************************************/ 81 /* Functions that preprocess answer before sending 82 * it to the recepient 83 */ 84 85 /** Return true if the caller (ipc_answer) should save 86 * the old call contents for answer_preprocess 94 95 /*********************************************************************** 96 * Functions that preprocess answer before sending it to the recepient. 97 ***********************************************************************/ 98 99 /** Decide if the caller (e.g. ipc_answer()) should save the old call contents 100 * for answer_preprocess(). 101 * 102 * @param call Call structure to be decided. 103 * 104 * @return Return 1 if the old call contents should be saved. 105 * Return 0 otherwise. 87 106 */ 88 107 static inline int answer_need_old(call_t *call) … … 99 118 } 100 119 101 /** Interpret process answer as control information 102 * 103 * This function is called directly after sys_ipc_answer 120 /** Interpret process answer as control information. 121 * 122 * This function is called directly after sys_ipc_answer(). 123 * 124 * @param answer Call structure with the answer. 125 * @param olddata Saved data of the request. 126 * 127 * @return Return 0 on success or an error code. 104 128 */ 105 129 static inline int answer_preprocess(call_t *answer, ipc_data_t *olddata) … … 132 156 /* The connection was accepted */ 133 157 phone_connect(phoneid, &answer->sender->answerbox); 134 /* Set 'phone identification' as arg3 of response */158 /* Set 'phone hash' as arg3 of response */ 135 159 IPC_SET_ARG3(answer->data, 136 160 (unative_t) &TASK->phones[phoneid]); … … 182 206 } 183 207 184 /** Called before the request is sent 185 * 186 * @return 0 - no error, -1 - report error to user 208 /** Called before the request is sent. 209 * 210 * @param call Call structure with the request. 211 * 212 * @return Return 0 on success, ELIMIT or EPERM on error. 187 213 */ 188 214 static int request_preprocess(call_t *call) … … 203 229 case IPC_M_AS_AREA_SEND: 204 230 size = as_get_size(IPC_GET_ARG1(call->data)); 205 if (!size) {231 if (!size) 206 232 return EPERM; 207 }208 233 IPC_SET_ARG2(call->data, size); 209 234 break; … … 214 239 } 215 240 216 /****************************************************/ 217 /* Functions called to process received call/answer 218 * before passing to uspace 219 */ 220 221 /** Do basic kernel processing of received call answer */ 241 /******************************************************************************* 242 * Functions called to process received call/answer before passing it to uspace. 243 *******************************************************************************/ 244 245 /** Do basic kernel processing of received call answer. 246 * 247 * @param call Call structure with the answer. 248 */ 222 249 static void process_answer(call_t *call) 223 250 { … … 234 261 } 235 262 236 /** Do basic kernel processing of received call request 237 * 238 * @return 0 - the call should be passed to userspace, 1 - ignore call 263 /** Do basic kernel processing of received call request. 264 * 265 * @param box Destination answerbox structure. 266 * @param call Call structure with the request. 267 * 268 * @return Return 0 if the call should be passed to userspace. 269 * Return -1 if the call should be ignored. 239 270 */ 240 271 static int process_request(answerbox_t *box, call_t *call) … … 246 277 if (phoneid < 0) { /* Failed to allocate phone */ 247 278 IPC_SET_RETVAL(call->data, ELIMIT); 248 ipc_answer(box, call);279 ipc_answer(box, call); 249 280 return -1; 250 281 } … … 254 285 } 255 286 256 /** Send a call over IPC, wait for reply, return to user 257 * 258 * @return Call identification, returns -1 on fatal error, 259 -2 on 'Too many async request, handle answers first 287 /** Make a fast call over IPC, wait for reply and return to user. 288 * 289 * This function can handle only one argument of payload, but is faster than 290 * the generic function (i.e. sys_ipc_call_sync()). 291 * 292 * @param phoneid Phone handle for the call. 293 * @param method Method of the call. 294 * @param arg1 Service-defined payload argument. 295 * @param data Address of userspace structure where the reply call will 296 * be stored. 297 * 298 * @return Returns 0 on success. 299 * Return ENOENT if there is no such phone handle. 260 300 */ 261 301 unative_t sys_ipc_call_sync_fast(unative_t phoneid, unative_t method, … … 272 312 IPC_SET_ARG1(call.data, arg1); 273 313 274 if (!(res =request_preprocess(&call))) {314 if (!(res = request_preprocess(&call))) { 275 315 ipc_call_sync(phone, &call); 276 316 process_answer(&call); 277 } else 317 } else { 278 318 IPC_SET_RETVAL(call.data, res); 319 } 279 320 STRUCT_TO_USPACE(&data->args, &call.data.args); 280 321 … … 282 323 } 283 324 284 /** Synchronous IPC call allowing to send whole message */ 325 /** Make a synchronous IPC call allowing to transmit the entire payload. 326 * 327 * @param phoneid Phone handle for the call. 328 * @param question Userspace address of call data with the request. 329 * @param reply Userspace address of call data where to store the answer. 330 * 331 * @return Zero on success or an error code. 332 */ 285 333 unative_t sys_ipc_call_sync(unative_t phoneid, ipc_data_t *question, 286 334 ipc_data_t *reply) … … 299 347 GET_CHECK_PHONE(phone, phoneid, return ENOENT); 300 348 301 if (!(res =request_preprocess(&call))) {349 if (!(res = request_preprocess(&call))) { 302 350 ipc_call_sync(phone, &call); 303 351 process_answer(&call); … … 312 360 } 313 361 314 /** Check that the task did not exceed allowed limit315 * 316 * @return 0 - Limit OK, -1 - limit exceeded362 /** Check that the task did not exceed the allowed limit of asynchronous calls. 363 * 364 * @return Return 0 if limit not reached or -1 if limit exceeded. 317 365 */ 318 366 static int check_call_limit(void) … … 325 373 } 326 374 327 /** Send an asynchronous call over ipc 328 * 329 * @return Call identification, returns -1 on fatal error, 330 -2 on 'Too many async request, handle answers first 375 /** Make a fast asynchronous call over IPC. 376 * 377 * This function can only handle two arguments of payload, but is faster than 378 * the generic function sys_ipc_call_async(). 379 * 380 * @param phoneid Phone handle for the call. 381 * @param method Method of the call. 382 * @param arg1 Service-defined payload argument. 383 * @param arg2 Service-defined payload argument. 384 * 385 * @return Return call hash on success. 386 * Return IPC_CALLRET_FATAL in case of a fatal error and 387 * IPC_CALLRET_TEMPORARY if there are too many pending 388 * asynchronous requests; answers should be handled first. 331 389 */ 332 390 unative_t sys_ipc_call_async_fast(unative_t phoneid, unative_t method, … … 356 414 } 357 415 358 /** Synchronous IPC call allowing to send whole message 359 * 360 * @return The same as sys_ipc_call_async 416 /** Make an asynchronous IPC call allowing to transmit the entire payload. 417 * 418 * @param phoneid Phone handle for the call. 419 * @param data Userspace address of call data with the request. 420 * 421 * @return See sys_ipc_call_async_fast(). 361 422 */ 362 423 unative_t sys_ipc_call_async(unative_t phoneid, ipc_data_t *data) … … 387 448 } 388 449 389 /** Forward received call to another destination 390 * 391 * The arg1 and arg2 are changed in the forwarded message 450 /** Forward a received call to another destination. 451 * 452 * @param callid Hash of the call to forward. 453 * @param phoneid Phone handle to use for forwarding. 454 * @param method New method to use for the forwarded call. 455 * @param arg1 New value of the first argument for the forwarded call. 456 * 457 * @return Return 0 on succes, otherwise return an error code. 458 * 459 * In case the original method is a system method, ARG1 and ARG2 are overwritten 460 * in the forwarded message with the new method and the new arg1, respectively. 461 * Otherwise the METHOD and ARG1 are rewritten with the new method and arg1, 462 * respectively. 392 463 * 393 464 * Warning: If implementing non-fast version, make sure that 394 * arg3 is not rewritten for certain system IPC465 * ARG3 is not rewritten for certain system IPC 395 466 */ 396 467 unative_t sys_ipc_forward_fast(unative_t callid, unative_t phoneid, … … 435 506 } 436 507 437 /** Send IPC answer */ 508 /** Answer an IPC call - fast version. 509 * 510 * This function can handle only two return arguments of payload, but is faster 511 * than the generic sys_ipc_answer(). 512 * 513 * @param callid Hash of the call to be answered. 514 * @param retval Return value of the answer. 515 * @param arg1 Service-defined return value. 516 * @param arg2 Service-defined return value. 517 * 518 * @return Return 0 on success, otherwise return an error code. 519 */ 438 520 unative_t sys_ipc_answer_fast(unative_t callid, unative_t retval, 439 521 unative_t arg1, unative_t arg2) … … 466 548 } 467 549 468 /** Send IPC answer */ 550 /** Answer an IPC call. 551 * 552 * @param callid Hash of the call to be answered. 553 * @param data Userspace address of call data with the answer. 554 * 555 * @return Return 0 on success, otherwise return an error code. 556 */ 469 557 unative_t sys_ipc_answer(unative_t callid, ipc_data_t *data) 470 558 { … … 498 586 } 499 587 500 /** Hang up the phone 501 * 588 /** Hang up a phone. 589 * 590 * @param Phone handle of the phone to be hung up. 591 * 592 * @return Return 0 on success or an error code. 502 593 */ 503 594 unative_t sys_ipc_hangup(int phoneid) … … 513 604 } 514 605 515 /** Wait for incoming ipc call or answer606 /** Wait for an incoming IPC call or an answer. 516 607 * 517 608 * @param calldata Pointer to buffer where the call/answer data is stored. … … 520 611 * for explanation. 521 612 * 522 * @return Callid, if callid & 1, then the call is answer 613 * @return Hash of the call. 614 * If IPC_CALLID_NOTIFICATION bit is set in the hash, the 615 * call is a notification. IPC_CALLID_ANSWERED denotes an 616 * answer. 523 617 */ 524 618 unative_t sys_ipc_wait_for_call(ipc_data_t *calldata, uint32_t usec, int flags) … … 542 636 ipc_call_free(call); 543 637 544 return ((unative_t) call) | IPC_CALLID_NOTIFICATION;638 return ((unative_t) call) | IPC_CALLID_NOTIFICATION; 545 639 } 546 640 … … 560 654 ipc_call_free(call); 561 655 562 return ((unative_t) call) | IPC_CALLID_ANSWERED;656 return ((unative_t) call) | IPC_CALLID_ANSWERED; 563 657 } 564 658 … … 574 668 } 575 669 576 /** Connect irq handler totask.577 * 578 * @param inr 579 * @param devno 580 * @param method 581 * @param ucode 582 * 583 * @return 670 /** Connect an IRQ handler to a task. 671 * 672 * @param inr IRQ number. 673 * @param devno Device number. 674 * @param method Method to be associated with the notification. 675 * @param ucode Uspace pointer to the top-half pseudocode. 676 * 677 * @return EPERM or a return code returned by ipc_irq_register(). 584 678 */ 585 679 unative_t sys_ipc_register_irq(inr_t inr, devno_t devno, unative_t method, … … 592 686 } 593 687 594 /** Disconnect irq handler from task. 595 * 596 * @param inr IRQ number. 597 * @param devno Device number. 688 /** Disconnect an IRQ handler from a task. 689 * 690 * @param inr IRQ number. 691 * @param devno Device number. 692 * 693 * @return Zero on success or EPERM on error.. 598 694 */ 599 695 unative_t sys_ipc_unregister_irq(inr_t inr, devno_t devno)
Note:
See TracChangeset
for help on using the changeset viewer.