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