Subversion Repositories HelenOS

Rev

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