Changeset a996ae31 in mainline for kernel/generic/src/ipc/irq.c
- Timestamp:
- 2012-02-12T14:26:04Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- d57122c
- Parents:
- ec12ab8
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/ipc/irq.c
rec12ab8 ra996ae31 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 if ((void *) ranges[i].base >= IO_SPACE_BOUNDARY) 93 km_unmap(ranges[i].base, ranges[i].size); 94 } 95 } 96 97 static int ranges_map_and_apply(irq_pio_range_t *ranges, size_t rangecount, 98 irq_cmd_t *cmds, size_t cmdcount) 99 { 100 uintptr_t *pbase; 101 size_t i, j; 102 103 /* Copy the physical base addresses aside. */ 104 pbase = malloc(rangecount * sizeof(uintptr_t), 0); 105 for (i = 0; i < rangecount; i++) 106 pbase[i] = ranges[i].base; 107 108 /* Map the PIO ranges into the kernel virtual address space. */ 109 for (i = 0; i < rangecount; i++) { 110 if ((void *) ranges[i].base < IO_SPACE_BOUNDARY) 111 continue; 112 ranges[i].base = km_map(pbase[i], ranges[i].size, 113 PAGE_READ | PAGE_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE); 114 if (!ranges[i].base) { 115 ranges_unmap(ranges, i); 116 free(pbase); 117 return ENOMEM; 118 } 119 } 120 121 /* Rewrite the pseudocode addresses from physical to kernel virtual. */ 122 for (i = 0; i < cmdcount; i++) { 123 uintptr_t addr; 124 125 /* Process only commands that use an address. */ 126 switch (cmds[i].cmd) { 127 case CMD_PIO_READ_8: 128 case CMD_PIO_READ_16: 129 case CMD_PIO_READ_32: 130 case CMD_PIO_WRITE_8: 131 case CMD_PIO_WRITE_16: 132 case CMD_PIO_WRITE_32: 133 case CMD_PIO_WRITE_A_8: 134 case CMD_PIO_WRITE_A_16: 135 case CMD_PIO_WRITE_A_32: 136 break; 137 default: 138 /* Move onto the next command. */ 139 continue; 140 } 141 142 addr = (uintptr_t) cmds[i].addr; 143 144 /* Process only memory mapped PIO addresses. */ 145 if ((void *) addr < IO_SPACE_BOUNDARY) 146 continue; 147 148 for (j = 0; j < rangecount; j++) { 149 150 /* Find the matching range. */ 151 if (!iswithin(pbase[j], ranges[j].size, addr, 1)) 152 continue; 153 154 /* Switch the command to a kernel virtual address. */ 155 addr -= pbase[j]; 156 addr += ranges[j].base; 157 158 cmds[i].addr = (void *) addr; 159 break; 160 } 161 } 162 163 free(pbase); 164 return EOK; 165 } 83 166 84 167 /** Free the top-half pseudocode. … … 90 173 { 91 174 if (code) { 175 ranges_unmap(code->ranges, code->rangecount); 176 free(code->ranges); 92 177 free(code->cmds); 93 178 free(code); … … 104 189 static irq_code_t *code_from_uspace(irq_code_t *ucode) 105 190 { 191 irq_pio_range_t *ranges = NULL; 192 irq_cmd_t *cmds = NULL; 193 106 194 irq_code_t *code = malloc(sizeof(*code), 0); 107 195 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, 196 if (rc != EOK) 197 goto error; 198 199 if ((code->rangecount > IRQ_MAX_RANGE_COUNT) || 200 (code->cmdcount > IRQ_MAX_PROG_SIZE)) 201 goto error; 202 203 ranges = malloc(sizeof(code->ranges[0]) * code->rangecount, 0); 204 rc = copy_from_uspace(ranges, code->ranges, 205 sizeof(code->ranges[0]) * code->rangecount); 206 if (rc != EOK) 207 goto error; 208 209 cmds = malloc(sizeof(code->cmds[0]) * code->cmdcount, 0); 210 rc = copy_from_uspace(cmds, code->cmds, 121 211 sizeof(code->cmds[0]) * code->cmdcount); 122 if (rc != 0) { 123 free(code->cmds); 124 free(code); 125 return NULL; 126 } 127 212 if (rc != EOK) 213 goto error; 214 215 rc = ranges_map_and_apply(ranges, code->rangecount, cmds, 216 code->cmdcount); 217 if (rc != EOK) 218 goto error; 219 220 code->ranges = ranges; 221 code->cmds = cmds; 222 128 223 return code; 224 225 error: 226 if (cmds) 227 free(cmds); 228 if (ranges) 229 free(ranges); 230 free(code); 231 return NULL; 129 232 } 130 233 … … 366 469 for (size_t i = 0; i < code->cmdcount; i++) { 367 470 uint32_t dstval; 368 void *va;369 uint8_t val8;370 uint16_t val16;371 uint32_t val32;372 471 373 472 uintptr_t srcarg = code->cmds[i].srcarg;
Note:
See TracChangeset
for help on using the changeset viewer.