Changes in kernel/generic/src/ipc/irq.c [3cc070d:17b3cc6] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/ipc/irq.c
r3cc070d r17b3cc6 74 74 #include <arch.h> 75 75 #include <mm/slab.h> 76 #include <mm/page.h>77 #include <mm/km.h>78 76 #include <errno.h> 79 77 #include <ddi/irq.h> … … 83 81 #include <console/console.h> 84 82 #include <print.h> 85 #include <macros.h>86 87 static void ranges_unmap(irq_pio_range_t *ranges, size_t rangecount)88 {89 size_t i;90 91 for (i = 0; i < rangecount; i++) {92 #ifdef IO_SPACE_BOUNDARY93 if ((void *) ranges[i].base >= IO_SPACE_BOUNDARY)94 #endif95 km_unmap(ranges[i].base, ranges[i].size);96 }97 }98 99 static int ranges_map_and_apply(irq_pio_range_t *ranges, size_t rangecount,100 irq_cmd_t *cmds, size_t cmdcount)101 {102 uintptr_t *pbase;103 size_t i, j;104 105 /* Copy the physical base addresses aside. */106 pbase = malloc(rangecount * sizeof(uintptr_t), 0);107 for (i = 0; i < rangecount; i++)108 pbase[i] = ranges[i].base;109 110 /* Map the PIO ranges into the kernel virtual address space. */111 for (i = 0; i < rangecount; i++) {112 #ifdef IO_SPACE_BOUNDARY113 if ((void *) ranges[i].base < IO_SPACE_BOUNDARY)114 continue;115 #endif116 ranges[i].base = km_map(pbase[i], ranges[i].size,117 PAGE_READ | PAGE_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);118 if (!ranges[i].base) {119 ranges_unmap(ranges, i);120 free(pbase);121 return ENOMEM;122 }123 }124 125 /* Rewrite the pseudocode addresses from physical to kernel virtual. */126 for (i = 0; i < cmdcount; i++) {127 uintptr_t addr;128 size_t size;129 130 /* Process only commands that use an address. */131 switch (cmds[i].cmd) {132 case CMD_PIO_READ_8:133 case CMD_PIO_WRITE_8:134 case CMD_PIO_WRITE_A_8:135 size = 1;136 break;137 case CMD_PIO_READ_16:138 case CMD_PIO_WRITE_16:139 case CMD_PIO_WRITE_A_16:140 size = 2;141 break;142 case CMD_PIO_READ_32:143 case CMD_PIO_WRITE_32:144 case CMD_PIO_WRITE_A_32:145 size = 4;146 break;147 default:148 /* Move onto the next command. */149 continue;150 }151 152 addr = (uintptr_t) cmds[i].addr;153 154 for (j = 0; j < rangecount; j++) {155 156 /* Find the matching range. */157 if (!iswithin(pbase[j], ranges[j].size, addr, size))158 continue;159 160 /* Switch the command to a kernel virtual address. */161 addr -= pbase[j];162 addr += ranges[j].base;163 164 cmds[i].addr = (void *) addr;165 break;166 }167 168 if (j == rangecount) {169 /*170 * The address used in this command is outside of all171 * defined ranges.172 */173 ranges_unmap(ranges, rangecount);174 free(pbase);175 return EINVAL;176 }177 }178 179 free(pbase);180 return EOK;181 }182 83 183 84 /** Free the top-half pseudocode. … … 189 90 { 190 91 if (code) { 191 ranges_unmap(code->ranges, code->rangecount);192 free(code->ranges);193 92 free(code->cmds); 194 93 free(code); … … 205 104 static irq_code_t *code_from_uspace(irq_code_t *ucode) 206 105 { 207 irq_pio_range_t *ranges = NULL;208 irq_cmd_t *cmds = NULL;209 210 106 irq_code_t *code = malloc(sizeof(*code), 0); 211 107 int rc = copy_from_uspace(code, ucode, sizeof(*code)); 212 if (rc != EOK) 213 goto error; 214 215 if ((code->rangecount > IRQ_MAX_RANGE_COUNT) || 216 (code->cmdcount > IRQ_MAX_PROG_SIZE)) 217 goto error; 218 219 ranges = malloc(sizeof(code->ranges[0]) * code->rangecount, 0); 220 rc = copy_from_uspace(ranges, code->ranges, 221 sizeof(code->ranges[0]) * code->rangecount); 222 if (rc != EOK) 223 goto error; 224 225 cmds = malloc(sizeof(code->cmds[0]) * code->cmdcount, 0); 226 rc = copy_from_uspace(cmds, code->cmds, 108 if (rc != 0) { 109 free(code); 110 return NULL; 111 } 112 113 if (code->cmdcount > IRQ_MAX_PROG_SIZE) { 114 free(code); 115 return NULL; 116 } 117 118 irq_cmd_t *ucmds = code->cmds; 119 code->cmds = malloc(sizeof(code->cmds[0]) * code->cmdcount, 0); 120 rc = copy_from_uspace(code->cmds, ucmds, 227 121 sizeof(code->cmds[0]) * code->cmdcount); 228 if (rc != EOK) 229 goto error; 230 231 rc = ranges_map_and_apply(ranges, code->rangecount, cmds, 232 code->cmdcount); 233 if (rc != EOK) 234 goto error; 235 236 code->ranges = ranges; 237 code->cmds = cmds; 238 122 if (rc != 0) { 123 free(code->cmds); 124 free(code); 125 return NULL; 126 } 127 239 128 return code; 240 241 error:242 if (cmds)243 free(cmds);244 if (ranges)245 free(ranges);246 free(code);247 return NULL;248 129 } 249 130 … … 293 174 irq->notif_cfg.code = code; 294 175 irq->notif_cfg.counter = 0; 176 irq->driver_as = AS; 295 177 296 178 /* … … 357 239 358 240 ASSERT(irq->notif_cfg.answerbox == box); 241 242 /* Free up the pseudo code and associated structures. */ 243 code_free(irq->notif_cfg.code); 359 244 360 245 /* Remove the IRQ from the answerbox's list. */ … … 375 260 irq_spinlock_unlock(&box->irq_lock, false); 376 261 irq_spinlock_unlock(&irq_uspace_hash_table_lock, true); 377 378 /* Free up the pseudo code and associated structures. */379 code_free(irq->notif_cfg.code);380 262 381 263 /* Free up the IRQ structure. */ … … 425 307 list_remove(&irq->notif_cfg.link); 426 308 309 /* Free up the pseudo code and associated structures. */ 310 code_free(irq->notif_cfg.code); 311 427 312 /* 428 313 * We need to drop the IRQ lock now because hash_table_remove() … … 436 321 /* Remove from the hash table. */ 437 322 hash_table_remove(&irq_uspace_hash_table, key, 2); 438 439 /* 440 * Release both locks so that we can free the pseudo code. 441 */ 442 irq_spinlock_unlock(&box->irq_lock, false); 443 irq_spinlock_unlock(&irq_uspace_hash_table_lock, true); 444 445 code_free(irq->notif_cfg.code); 323 446 324 free(irq); 447 448 /* Reacquire both locks before taking another round. */449 irq_spinlock_lock(&irq_uspace_hash_table_lock, true);450 irq_spinlock_lock(&box->irq_lock, false);451 325 } 452 326 … … 491 365 return IRQ_DECLINE; 492 366 367 as_t *current_as = AS; 368 if (current_as != irq->driver_as) 369 as_switch(AS, irq->driver_as); 370 493 371 for (size_t i = 0; i < code->cmdcount; i++) { 494 372 uint32_t dstval; 373 void *va; 374 uint8_t val8; 375 uint16_t val16; 376 uint32_t val32; 495 377 496 378 uintptr_t srcarg = code->cmds[i].srcarg; … … 549 431 } 550 432 break; 433 case CMD_MEM_READ_8: 434 va = code->cmds[i].addr; 435 memcpy_from_uspace(&val8, va, sizeof(val8)); 436 if (dstarg) 437 scratch[dstarg] = val8; 438 break; 439 case CMD_MEM_READ_16: 440 va = code->cmds[i].addr; 441 memcpy_from_uspace(&val16, va, sizeof(val16)); 442 if (dstarg) 443 scratch[dstarg] = val16; 444 break; 445 case CMD_MEM_READ_32: 446 va = code->cmds[i].addr; 447 memcpy_from_uspace(&val32, va, sizeof(val32)); 448 if (dstarg) 449 scratch[dstarg] = val32; 450 break; 451 case CMD_MEM_WRITE_8: 452 val8 = code->cmds[i].value; 453 va = code->cmds[i].addr; 454 memcpy_to_uspace(va, &val8, sizeof(val8)); 455 break; 456 case CMD_MEM_WRITE_16: 457 val16 = code->cmds[i].value; 458 va = code->cmds[i].addr; 459 memcpy_to_uspace(va, &val16, sizeof(val16)); 460 break; 461 case CMD_MEM_WRITE_32: 462 val32 = code->cmds[i].value; 463 va = code->cmds[i].addr; 464 memcpy_to_uspace(va, &val32, sizeof(val32)); 465 break; 466 case CMD_MEM_WRITE_A_8: 467 if (srcarg) { 468 val8 = scratch[srcarg]; 469 va = code->cmds[i].addr; 470 memcpy_to_uspace(va, &val8, sizeof(val8)); 471 } 472 break; 473 case CMD_MEM_WRITE_A_16: 474 if (srcarg) { 475 val16 = scratch[srcarg]; 476 va = code->cmds[i].addr; 477 memcpy_to_uspace(va, &val16, sizeof(val16)); 478 } 479 break; 480 case CMD_MEM_WRITE_A_32: 481 if (srcarg) { 482 val32 = scratch[srcarg]; 483 va = code->cmds[i].addr; 484 memcpy_to_uspace(va, &val32, sizeof(val32)); 485 } 486 break; 551 487 case CMD_BTEST: 552 488 if ((srcarg) && (dstarg)) { … … 562 498 break; 563 499 case CMD_ACCEPT: 500 if (AS != current_as) 501 as_switch(AS, current_as); 564 502 return IRQ_ACCEPT; 565 503 case CMD_DECLINE: 566 504 default: 505 if (AS != current_as) 506 as_switch(AS, current_as); 567 507 return IRQ_DECLINE; 568 508 } 569 509 } 510 511 if (AS != current_as) 512 as_switch(AS, current_as); 570 513 571 514 return IRQ_DECLINE;
Note:
See TracChangeset
for help on using the changeset viewer.