Changes in kernel/generic/src/ipc/irq.c [17b3cc6:3cc070d] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/ipc/irq.c
r17b3cc6 r3cc070d 74 74 #include <arch.h> 75 75 #include <mm/slab.h> 76 #include <mm/page.h> 77 #include <mm/km.h> 76 78 #include <errno.h> 77 79 #include <ddi/irq.h> … … 81 83 #include <console/console.h> 82 84 #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_BOUNDARY 93 if ((void *) ranges[i].base >= IO_SPACE_BOUNDARY) 94 #endif 95 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_BOUNDARY 113 if ((void *) ranges[i].base < IO_SPACE_BOUNDARY) 114 continue; 115 #endif 116 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 all 171 * defined ranges. 172 */ 173 ranges_unmap(ranges, rangecount); 174 free(pbase); 175 return EINVAL; 176 } 177 } 178 179 free(pbase); 180 return EOK; 181 } 83 182 84 183 /** Free the top-half pseudocode. … … 90 189 { 91 190 if (code) { 191 ranges_unmap(code->ranges, code->rangecount); 192 free(code->ranges); 92 193 free(code->cmds); 93 194 free(code); … … 104 205 static irq_code_t *code_from_uspace(irq_code_t *ucode) 105 206 { 207 irq_pio_range_t *ranges = NULL; 208 irq_cmd_t *cmds = NULL; 209 106 210 irq_code_t *code = malloc(sizeof(*code), 0); 107 211 int rc = copy_from_uspace(code, ucode, sizeof(*code)); 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, 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, 121 227 sizeof(code->cmds[0]) * code->cmdcount); 122 if (rc != 0) { 123 free(code->cmds); 124 free(code); 125 return NULL; 126 } 127 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 128 239 return code; 240 241 error: 242 if (cmds) 243 free(cmds); 244 if (ranges) 245 free(ranges); 246 free(code); 247 return NULL; 129 248 } 130 249 … … 174 293 irq->notif_cfg.code = code; 175 294 irq->notif_cfg.counter = 0; 176 irq->driver_as = AS;177 295 178 296 /* … … 239 357 240 358 ASSERT(irq->notif_cfg.answerbox == box); 241 242 /* Free up the pseudo code and associated structures. */243 code_free(irq->notif_cfg.code);244 359 245 360 /* Remove the IRQ from the answerbox's list. */ … … 260 375 irq_spinlock_unlock(&box->irq_lock, false); 261 376 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); 262 380 263 381 /* Free up the IRQ structure. */ … … 307 425 list_remove(&irq->notif_cfg.link); 308 426 309 /* Free up the pseudo code and associated structures. */310 code_free(irq->notif_cfg.code);311 312 427 /* 313 428 * We need to drop the IRQ lock now because hash_table_remove() … … 321 436 /* Remove from the hash table. */ 322 437 hash_table_remove(&irq_uspace_hash_table, key, 2); 323 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); 324 446 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); 325 451 } 326 452 … … 365 491 return IRQ_DECLINE; 366 492 367 as_t *current_as = AS;368 if (current_as != irq->driver_as)369 as_switch(AS, irq->driver_as);370 371 493 for (size_t i = 0; i < code->cmdcount; i++) { 372 494 uint32_t dstval; 373 void *va;374 uint8_t val8;375 uint16_t val16;376 uint32_t val32;377 495 378 496 uintptr_t srcarg = code->cmds[i].srcarg; … … 431 549 } 432 550 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;487 551 case CMD_BTEST: 488 552 if ((srcarg) && (dstarg)) { … … 498 562 break; 499 563 case CMD_ACCEPT: 500 if (AS != current_as)501 as_switch(AS, current_as);502 564 return IRQ_ACCEPT; 503 565 case CMD_DECLINE: 504 566 default: 505 if (AS != current_as)506 as_switch(AS, current_as);507 567 return IRQ_DECLINE; 508 568 } 509 569 } 510 511 if (AS != current_as)512 as_switch(AS, current_as);513 570 514 571 return IRQ_DECLINE;
Note:
See TracChangeset
for help on using the changeset viewer.