aboutsummaryrefslogtreecommitdiffstats
path: root/extras/mini-os/events.c
blob: 8ca49d284bf7ea04cada1c155e6e92b59b4a8ea3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/* -*-  Mode:C; c-basic-offset:4; tab-width:4 -*-
 ****************************************************************************
 * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
 * (C) 2005 - Grzegorz Milos - Intel Research Cambridge
 ****************************************************************************
 *
 *        File: events.c
 *      Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
 *     Changes: Grzegorz Milos (gm281@cam.ac.uk)
 *              
 *        Date: Jul 2003, changes Jun 2005
 * 
 * Environment: Xen Minimal OS
 * Description: Deals with events recieved on event channels
 *
 ****************************************************************************
 */

#include <os.h>
#include <hypervisor.h>
#include <events.h>
#include <lib.h>

#include <xen/event_channel.h>
static ev_action_t ev_actions[NR_EVS];
void default_handler(u32 port, struct pt_regs *regs);


/*
 * Demux events to different handlers.
 */
int do_event(u32 port, struct pt_regs *regs)
{
    ev_action_t  *action;

    if (port >= NR_EVS) {
        printk("Port number too large: %d\n", port);
        return 0;
    }

    action = &ev_actions[port];
    action->count++;

    if (!action->handler)
        goto out;
    
    if (action->status & EVS_DISABLED)
        goto out;
    
    /* call the handler */
    action->handler(port, regs);

	clear_evtchn(port);
    
 out:
    return 1;

}

int bind_virq( u32 virq, void (*handler)(int, struct pt_regs *) )
{
	evtchn_op_t op;
	int ret = 0;
	u32 port;

	/* Try to bind the virq to a port */
	op.cmd = EVTCHNOP_bind_virq;
	op.u.bind_virq.virq = virq;

	if ( HYPERVISOR_event_channel_op(&op) != 0 )
	{
		ret = 1;
		printk("Failed to bind virtual IRQ %d\n", virq);
		goto out;
    }

    port = op.u.bind_virq.port;
	
	if(ev_actions[port].handler)
        printk("WARN: Handler for port %d already registered, replacing\n",
				port);

	ev_actions[port].handler = handler;
	ev_actions[port].status &= ~EVS_DISABLED;
	
	/* Finally unmask the port */
	unmask_evtchn(port);
out:
	return ret;
}

/*
 * Initially all events are without a handler and disabled
 */
void init_events(void)
{
    int i;

    /* inintialise event handler */
    for ( i = 0; i < NR_EVS; i++ )
    {
        ev_actions[i].status  = EVS_DISABLED;
        ev_actions[i].handler = NULL;
    }
}

void default_handler(u32 port, struct pt_regs *regs) {
    printk("[Port %d] - event received\n", port);
}