Changeset 56c167c in mainline
- Timestamp:
- 2012-07-21T13:47:22Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 8486c07
- Parents:
- fb7e545e
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/ipc/irq.c
rfb7e545e r56c167c 39 39 * when interrupt is detected. The application may provide a simple 'top-half' 40 40 * handler as part of its registration, which can perform simple operations 41 * (read/write port/memory, add information to notification ipcmessage).41 * (read/write port/memory, add information to notification IPC message). 42 42 * 43 43 * The structure of a notification message is as follows: 44 44 * - IMETHOD: interface and method as registered by 45 45 * the SYS_IRQ_REGISTER syscall 46 * - ARG1: payload modified by a 'top-half' handler 47 * - ARG2: payload modified by a 'top-half' handler 48 * - ARG3: payload modified by a 'top-half' handler 49 * - ARG4: payload modified by a 'top-half' handler 50 * - ARG5: payload modified by a 'top-half' handler 46 * - ARG1: payload modified by a 'top-half' handler (scratch[1]) 47 * - ARG2: payload modified by a 'top-half' handler (scratch[2]) 48 * - ARG3: payload modified by a 'top-half' handler (scratch[3]) 49 * - ARG4: payload modified by a 'top-half' handler (scratch[4]) 50 * - ARG5: payload modified by a 'top-half' handler (scratch[5]) 51 51 * - in_phone_hash: interrupt counter (may be needed to assure correct order 52 52 * in multithreaded drivers) … … 87 87 static void ranges_unmap(irq_pio_range_t *ranges, size_t rangecount) 88 88 { 89 size_t i; 90 91 for (i = 0; i < rangecount; i++) { 89 for (size_t i = 0; i < rangecount; i++) { 92 90 #ifdef IO_SPACE_BOUNDARY 93 91 if ((void *) ranges[i].base >= IO_SPACE_BOUNDARY) … … 100 98 irq_cmd_t *cmds, size_t cmdcount) 101 99 { 102 uintptr_t *pbase;103 size_t i, j;104 105 100 /* Copy the physical base addresses aside. */ 106 pbase = malloc(rangecount * sizeof(uintptr_t), 0);107 for ( i = 0; i < rangecount; i++)101 uintptr_t *pbase = malloc(rangecount * sizeof(uintptr_t), 0); 102 for (size_t i = 0; i < rangecount; i++) 108 103 pbase[i] = ranges[i].base; 109 104 110 105 /* Map the PIO ranges into the kernel virtual address space. */ 111 for ( i = 0; i < rangecount; i++) {106 for (size_t i = 0; i < rangecount; i++) { 112 107 #ifdef IO_SPACE_BOUNDARY 113 108 if ((void *) ranges[i].base < IO_SPACE_BOUNDARY) … … 122 117 } 123 118 } 124 119 125 120 /* Rewrite the pseudocode addresses from physical to kernel virtual. */ 126 for ( i = 0; i < cmdcount; i++) {121 for (size_t i = 0; i < cmdcount; i++) { 127 122 uintptr_t addr; 128 123 size_t size; 129 124 130 125 /* Process only commands that use an address. */ 131 126 switch (cmds[i].cmd) { 132 127 case CMD_PIO_READ_8: 133 134 128 case CMD_PIO_WRITE_8: 129 case CMD_PIO_WRITE_A_8: 135 130 size = 1; 136 131 break; 137 138 139 132 case CMD_PIO_READ_16: 133 case CMD_PIO_WRITE_16: 134 case CMD_PIO_WRITE_A_16: 140 135 size = 2; 141 136 break; 142 143 144 137 case CMD_PIO_READ_32: 138 case CMD_PIO_WRITE_32: 139 case CMD_PIO_WRITE_A_32: 145 140 size = 4; 146 141 break; … … 149 144 continue; 150 145 } 151 146 152 147 addr = (uintptr_t) cmds[i].addr; 153 148 149 size_t j; 154 150 for (j = 0; j < rangecount; j++) { 155 156 151 /* Find the matching range. */ 157 152 if (!iswithin(pbase[j], ranges[j].size, addr, size)) 158 153 continue; 159 154 160 155 /* Switch the command to a kernel virtual address. */ 161 156 addr -= pbase[j]; 162 157 addr += ranges[j].base; 163 158 164 159 cmds[i].addr = (void *) addr; 165 160 break; 166 161 } 167 162 168 163 if (j == rangecount) { 169 164 /* … … 176 171 } 177 172 } 178 173 179 174 free(pbase); 180 175 return EOK; … … 207 202 irq_pio_range_t *ranges = NULL; 208 203 irq_cmd_t *cmds = NULL; 209 204 210 205 irq_code_t *code = malloc(sizeof(*code), 0); 211 206 int rc = copy_from_uspace(code, ucode, sizeof(*code)); … … 222 217 if (rc != EOK) 223 218 goto error; 224 219 225 220 cmds = malloc(sizeof(code->cmds[0]) * code->cmdcount, 0); 226 221 rc = copy_from_uspace(cmds, code->cmds, … … 233 228 if (rc != EOK) 234 229 goto error; 235 230 236 231 code->ranges = ranges; 237 232 code->cmds = cmds; 238 233 239 234 return code; 240 235 241 236 error: 242 237 if (cmds) 243 238 free(cmds); 239 244 240 if (ranges) 245 241 free(ranges); 242 246 243 free(code); 247 244 return NULL; … … 250 247 /** Register an answerbox as a receiving end for IRQ notifications. 251 248 * 252 * @param box Receiving answerbox. 253 * @param inr IRQ number. 254 * @param devno Device number. 255 * @param imethod Interface and method to be associated with the 256 * notification. 257 * @param ucode Uspace pointer to top-half pseudocode. 258 * @return EOK on success or a negative error code. 249 * @param box Receiving answerbox. 250 * @param inr IRQ number. 251 * @param devno Device number. 252 * @param imethod Interface and method to be associated with the 253 * notification. 254 * @param ucode Uspace pointer to top-half pseudocode. 255 * 256 * @return EOK on success or a negative error code. 259 257 * 260 258 */ … … 266 264 (sysarg_t) devno 267 265 }; 268 266 269 267 if ((inr < 0) || (inr > last_inr)) 270 268 return ELIMIT; … … 329 327 /** Unregister task from IRQ notification. 330 328 * 331 * @param box Answerbox associated with the notification. 332 * @param inr IRQ number. 333 * @param devno Device number. 334 * @return EOK on success or a negative error code. 329 * @param box Answerbox associated with the notification. 330 * @param inr IRQ number. 331 * @param devno Device number. 332 * 333 * @return EOK on success or a negative error code. 334 * 335 335 */ 336 336 int ipc_irq_unregister(answerbox_t *box, inr_t inr, devno_t devno) … … 340 340 (sysarg_t) devno 341 341 }; 342 342 343 343 if ((inr < 0) || (inr > last_inr)) 344 344 return ELIMIT; … … 436 436 /* Remove from the hash table. */ 437 437 hash_table_remove(&irq_uspace_hash_table, key, 2); 438 438 439 439 /* 440 440 * Release both locks so that we can free the pseudo code. … … 442 442 irq_spinlock_unlock(&box->irq_lock, false); 443 443 irq_spinlock_unlock(&irq_uspace_hash_table_lock, true); 444 444 445 445 code_free(irq->notif_cfg.code); 446 446 free(irq); … … 582 582 { 583 583 ASSERT(irq); 584 584 585 585 ASSERT(interrupts_disabled()); 586 586 ASSERT(irq_spinlock_locked(&irq->lock));
Note:
See TracChangeset
for help on using the changeset viewer.