Rev 1628 | Rev 1698 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 1628 | Rev 1693 | ||
|---|---|---|---|
| Line 32... | Line 32... | ||
| 32 | * when interrupt is detected. The application may provide a simple 'top-half' |
32 | * when interrupt is detected. The application may provide a simple 'top-half' |
| 33 | * handler as part of its registration, which can perform simple operations |
33 | * handler as part of its registration, which can perform simple operations |
| 34 | * (read/write port/memory, add information to notification ipc message). |
34 | * (read/write port/memory, add information to notification ipc message). |
| 35 | * |
35 | * |
| 36 | * The structure of a notification message is as follows: |
36 | * The structure of a notification message is as follows: |
| 37 | * - METHOD: IPC_M_INTERRUPT |
- | |
| 38 | * - ARG1: interrupt number |
37 | * - METHOD: interrupt number |
| 39 | * - ARG2: payload modified by a 'top-half' handler |
38 | * - ARG1: payload modified by a 'top-half' handler |
| - | 39 | * - ARG2: payload |
|
| - | 40 | * - ARG3: payload |
|
| 40 | * - ARG3: interrupt counter (may be needed to assure correct order |
41 | * - in_phone_hash: interrupt counter (may be needed to assure correct order |
| 41 | * in multithreaded drivers) |
42 | * in multithreaded drivers) |
| 42 | */ |
43 | */ |
| 43 | 44 | ||
| 44 | #include <arch.h> |
45 | #include <arch.h> |
| 45 | #include <mm/slab.h> |
46 | #include <mm/slab.h> |
| Line 64... | Line 65... | ||
| 64 | #include <print.h> |
65 | #include <print.h> |
| 65 | /* Execute code associated with IRQ notification */ |
66 | /* Execute code associated with IRQ notification */ |
| 66 | static void code_execute(call_t *call, irq_code_t *code) |
67 | static void code_execute(call_t *call, irq_code_t *code) |
| 67 | { |
68 | { |
| 68 | int i; |
69 | int i; |
| - | 70 | __native dstval = 0; |
|
| 69 | 71 | ||
| 70 | if (!code) |
72 | if (!code) |
| 71 | return; |
73 | return; |
| 72 | 74 | ||
| 73 | for (i=0; i < code->cmdcount;i++) { |
75 | for (i=0; i < code->cmdcount;i++) { |
| 74 | switch (code->cmds[i].cmd) { |
76 | switch (code->cmds[i].cmd) { |
| 75 | case CMD_MEM_READ_1: |
77 | case CMD_MEM_READ_1: |
| 76 | IPC_SET_ARG2(call->data, *((__u8 *)code->cmds[i].addr)); |
78 | dstval = *((__u8 *)code->cmds[i].addr); |
| 77 | break; |
79 | break; |
| 78 | case CMD_MEM_READ_2: |
80 | case CMD_MEM_READ_2: |
| 79 | IPC_SET_ARG2(call->data, *((__u16 *)code->cmds[i].addr)); |
81 | dstval = *((__u16 *)code->cmds[i].addr); |
| 80 | break; |
82 | break; |
| 81 | case CMD_MEM_READ_4: |
83 | case CMD_MEM_READ_4: |
| 82 | IPC_SET_ARG2(call->data, *((__u32 *)code->cmds[i].addr)); |
84 | dstval = *((__u32 *)code->cmds[i].addr); |
| 83 | break; |
85 | break; |
| 84 | case CMD_MEM_READ_8: |
86 | case CMD_MEM_READ_8: |
| 85 | IPC_SET_ARG2(call->data, *((__u64 *)code->cmds[i].addr)); |
87 | dstval = *((__u64 *)code->cmds[i].addr); |
| 86 | break; |
88 | break; |
| 87 | case CMD_MEM_WRITE_1: |
89 | case CMD_MEM_WRITE_1: |
| 88 | *((__u8 *)code->cmds[i].addr) = code->cmds[i].value; |
90 | *((__u8 *)code->cmds[i].addr) = code->cmds[i].value; |
| 89 | break; |
91 | break; |
| 90 | case CMD_MEM_WRITE_2: |
92 | case CMD_MEM_WRITE_2: |
| Line 96... | Line 98... | ||
| 96 | case CMD_MEM_WRITE_8: |
98 | case CMD_MEM_WRITE_8: |
| 97 | *((__u64 *)code->cmds[i].addr) = code->cmds[i].value; |
99 | *((__u64 *)code->cmds[i].addr) = code->cmds[i].value; |
| 98 | break; |
100 | break; |
| 99 | #if defined(ia32) || defined(amd64) |
101 | #if defined(ia32) || defined(amd64) |
| 100 | case CMD_PORT_READ_1: |
102 | case CMD_PORT_READ_1: |
| 101 | IPC_SET_ARG2(call->data, inb((long)code->cmds[i].addr)); |
103 | dstval = inb((long)code->cmds[i].addr); |
| 102 | break; |
104 | break; |
| 103 | case CMD_PORT_WRITE_1: |
105 | case CMD_PORT_WRITE_1: |
| 104 | outb((long)code->cmds[i].addr, code->cmds[i].value); |
106 | outb((long)code->cmds[i].addr, code->cmds[i].value); |
| 105 | break; |
107 | break; |
| 106 | #endif |
108 | #endif |
| 107 | #if defined(ia64) |
109 | #if defined(ia64) |
| 108 | case CMD_IA64_GETCHAR: |
110 | case CMD_IA64_GETCHAR: |
| 109 | IPC_SET_ARG2(call->data, _getc(&ski_uconsole)); |
111 | dstval = _getc(&ski_uconsole); |
| 110 | break; |
112 | break; |
| 111 | #endif |
113 | #endif |
| 112 | #if defined(ppc32) |
114 | #if defined(ppc32) |
| 113 | case CMD_PPC32_GETCHAR: |
115 | case CMD_PPC32_GETCHAR: |
| 114 | IPC_SET_ARG2(call->data, cuda_get_scancode()); |
116 | dstval = cuda_get_scancode(); |
| 115 | break; |
117 | break; |
| 116 | #endif |
118 | #endif |
| 117 | default: |
119 | default: |
| 118 | break; |
120 | break; |
| 119 | } |
121 | } |
| - | 122 | if (code->cmds[i].dstarg && code->cmds[i].dstarg < 4) { |
|
| - | 123 | call->data.args[code->cmds[i].dstarg] = dstval; |
|
| - | 124 | } |
|
| 120 | } |
125 | } |
| 121 | } |
126 | } |
| 122 | 127 | ||
| 123 | static void code_free(irq_code_t *code) |
128 | static void code_free(irq_code_t *code) |
| 124 | { |
129 | { |
| Line 222... | Line 227... | ||
| 222 | } |
227 | } |
| 223 | 228 | ||
| 224 | /** Send notification message |
229 | /** Send notification message |
| 225 | * |
230 | * |
| 226 | */ |
231 | */ |
| 227 | void ipc_irq_send_msg(int irq, __native a2, __native a3) |
232 | void ipc_irq_send_msg(int irq, __native a1, __native a2, __native a3) |
| 228 | { |
233 | { |
| 229 | call_t *call; |
234 | call_t *call; |
| 230 | int mq = irq + IPC_IRQ_RESERVED_VIRTUAL; |
235 | int mq = irq + IPC_IRQ_RESERVED_VIRTUAL; |
| 231 | 236 | ||
| 232 | spinlock_lock(&irq_conns[mq].lock); |
237 | spinlock_lock(&irq_conns[mq].lock); |
| Line 236... | Line 241... | ||
| 236 | if (!call) { |
241 | if (!call) { |
| 237 | spinlock_unlock(&irq_conns[mq].lock); |
242 | spinlock_unlock(&irq_conns[mq].lock); |
| 238 | return; |
243 | return; |
| 239 | } |
244 | } |
| 240 | call->flags |= IPC_CALL_NOTIF; |
245 | call->flags |= IPC_CALL_NOTIF; |
| 241 | IPC_SET_METHOD(call->data, IPC_M_INTERRUPT); |
246 | IPC_SET_METHOD(call->data, irq); |
| 242 | IPC_SET_ARG1(call->data, irq); |
247 | IPC_SET_ARG1(call->data, a1); |
| 243 | IPC_SET_ARG2(call->data, a2); |
248 | IPC_SET_ARG2(call->data, a2); |
| 244 | IPC_SET_ARG3(call->data, a3); |
249 | IPC_SET_ARG3(call->data, a3); |
| - | 250 | /* Put a counter to the message */ |
|
| - | 251 | call->private = atomic_preinc(&irq_conns[mq].counter); |
|
| 245 | 252 | ||
| 246 | send_call(mq, call); |
253 | send_call(mq, call); |
| 247 | } |
254 | } |
| 248 | spinlock_unlock(&irq_conns[mq].lock); |
255 | spinlock_unlock(&irq_conns[mq].lock); |
| 249 | } |
256 | } |
| Line 265... | Line 272... | ||
| 265 | if (!call) { |
272 | if (!call) { |
| 266 | spinlock_unlock(&irq_conns[mq].lock); |
273 | spinlock_unlock(&irq_conns[mq].lock); |
| 267 | return; |
274 | return; |
| 268 | } |
275 | } |
| 269 | call->flags |= IPC_CALL_NOTIF; |
276 | call->flags |= IPC_CALL_NOTIF; |
| - | 277 | /* Put a counter to the message */ |
|
| 270 | IPC_SET_METHOD(call->data, IPC_M_INTERRUPT); |
278 | call->private = atomic_preinc(&irq_conns[mq].counter); |
| 271 | IPC_SET_ARG1(call->data, irq); |
279 | /* Set up args */ |
| 272 | IPC_SET_ARG3(call->data, atomic_preinc(&irq_conns[mq].counter)); |
280 | IPC_SET_METHOD(call->data, irq); |
| 273 | 281 | ||
| 274 | /* Execute code to handle irq */ |
282 | /* Execute code to handle irq */ |
| 275 | code_execute(call, irq_conns[mq].code); |
283 | code_execute(call, irq_conns[mq].code); |
| 276 | 284 | ||
| 277 | send_call(mq, call); |
285 | send_call(mq, call); |