Subversion Repositories HelenOS

Rev

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