Rev 1281 | Rev 1288 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1281 | Rev 1284 | ||
---|---|---|---|
Line 24... | Line 24... | ||
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | */ |
27 | */ |
28 | 28 | ||
- | 29 | /** IRQ notification framework |
|
- | 30 | * |
|
- | 31 | * This framework allows applications to register to receive a notification |
|
- | 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 |
|
- | 34 | * (read/write port/memory, add information to notification ipc message). |
|
- | 35 | * |
|
- | 36 | * The structure of a notification message is as follows: |
|
- | 37 | * - METHOD: IPC_M_INTERRUPT |
|
- | 38 | * - ARG1: interrupt number |
|
- | 39 | * - ARG2: payload modified by a 'top-half' handler |
|
- | 40 | * - ARG3: interrupt counter (may be needed to assure correct order |
|
- | 41 | * in multithreaded drivers) |
|
- | 42 | */ |
|
- | 43 | ||
29 | #include <arch.h> |
44 | #include <arch.h> |
30 | #include <mm/slab.h> |
45 | #include <mm/slab.h> |
31 | #include <errno.h> |
46 | #include <errno.h> |
32 | #include <ipc/ipc.h> |
47 | #include <ipc/ipc.h> |
33 | #include <ipc/irq.h> |
48 | #include <ipc/irq.h> |
- | 49 | #include <atomic.h> |
|
34 | 50 | ||
35 | typedef struct { |
51 | typedef struct { |
36 | SPINLOCK_DECLARE(lock); |
52 | SPINLOCK_DECLARE(lock); |
37 | answerbox_t *box; |
53 | answerbox_t *box; |
38 | irq_code_t *code; |
54 | irq_code_t *code; |
- | 55 | atomic_t counter; |
|
39 | } ipc_irq_t; |
56 | } ipc_irq_t; |
40 | 57 | ||
41 | 58 | ||
42 | static ipc_irq_t *irq_conns = NULL; |
59 | static ipc_irq_t *irq_conns = NULL; |
43 | static int irq_conns_size; |
60 | static int irq_conns_size; |
Line 75... | Line 92... | ||
75 | *((__u32 *)code->cmds[i].addr) = code->cmds[i].value; |
92 | *((__u32 *)code->cmds[i].addr) = code->cmds[i].value; |
76 | break; |
93 | break; |
77 | case CMD_MEM_WRITE_8: |
94 | case CMD_MEM_WRITE_8: |
78 | *((__u64 *)code->cmds[i].addr) = code->cmds[i].value; |
95 | *((__u64 *)code->cmds[i].addr) = code->cmds[i].value; |
79 | break; |
96 | break; |
- | 97 | #if defined(ia32) || defined(amd64) |
|
- | 98 | case CMD_PORT_READ_1: |
|
- | 99 | IPC_SET_ARG2(call->data, inb((long)code->cmds[i].addr)); |
|
- | 100 | break; |
|
- | 101 | case CMD_PORT_WRITE_1: |
|
- | 102 | outb((long)code->cmds[i].addr, code->cmds[i].value); |
|
- | 103 | break; |
|
- | 104 | #endif |
|
80 | default: |
105 | default: |
81 | break; |
106 | break; |
82 | } |
107 | } |
83 | } |
108 | } |
84 | } |
109 | } |
Line 151... | Line 176... | ||
151 | code_free(code); |
176 | code_free(code); |
152 | return EEXISTS; |
177 | return EEXISTS; |
153 | } |
178 | } |
154 | irq_conns[irq].box = box; |
179 | irq_conns[irq].box = box; |
155 | irq_conns[irq].code = code; |
180 | irq_conns[irq].code = code; |
- | 181 | atomic_set(&irq_conns[irq].counter, 0); |
|
156 | spinlock_unlock(&irq_conns[irq].lock); |
182 | spinlock_unlock(&irq_conns[irq].lock); |
157 | interrupts_restore(ipl); |
183 | interrupts_restore(ipl); |
158 | 184 | ||
159 | return 0; |
185 | return 0; |
160 | } |
186 | } |
Line 173... | Line 199... | ||
173 | if (irq_conns[irq].box) { |
199 | if (irq_conns[irq].box) { |
174 | call = ipc_call_alloc(FRAME_ATOMIC); |
200 | call = ipc_call_alloc(FRAME_ATOMIC); |
175 | call->flags |= IPC_CALL_NOTIF; |
201 | call->flags |= IPC_CALL_NOTIF; |
176 | IPC_SET_METHOD(call->data, IPC_M_INTERRUPT); |
202 | IPC_SET_METHOD(call->data, IPC_M_INTERRUPT); |
177 | IPC_SET_ARG1(call->data, irq); |
203 | IPC_SET_ARG1(call->data, irq); |
- | 204 | IPC_SET_ARG3(call->data, atomic_preinc(&irq_conns[irq].counter)); |
|
178 | 205 | ||
179 | /* Execute code to handle irq */ |
206 | /* Execute code to handle irq */ |
180 | code_execute(call, irq_conns[irq].code); |
207 | code_execute(call, irq_conns[irq].code); |
181 | 208 | ||
182 | spinlock_lock(&irq_conns[irq].box->irq_lock); |
209 | spinlock_lock(&irq_conns[irq].box->irq_lock); |