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); |