Streamlined avr_irq subsystem
[simavr] / simavr / sim / sim_irq.h
1 /*
2         sim_irq.h
3
4         Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
5
6         This file is part of simavr.
7
8         simavr is free software: you can redistribute it and/or modify
9         it under the terms of the GNU General Public License as published by
10         the Free Software Foundation, either version 3 of the License, or
11         (at your option) any later version.
12
13         simavr is distributed in the hope that it will be useful,
14         but WITHOUT ANY WARRANTY; without even the implied warranty of
15         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16         GNU General Public License for more details.
17
18         You should have received a copy of the GNU General Public License
19         along with simavr.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #ifndef __SIM_IRQ_H__
23 #define __SIM_IRQ_H__
24
25 #include <stdint.h>
26
27 /*
28  * Internal IRQ system
29  * 
30  * This subsystem allow any piece of code to "register" a hook to be called when an IRQ is
31  * raised. The IRQ definition is up to the module defining it, for example a IOPORT pin change
32  * might be an IRQ in wich case any oiece of code can be notified when a pin has changed state
33  * 
34  * The notify hooks are chained, and duplicates are filtered out so you can't register a
35  * notify hook twice on one particylar IRQ
36  * 
37  * IRQ calling order is not defined, so don't rely on it.
38  * 
39  * IRQ hook needs to be registered in reset() handlers, ie after all modules init() bits
40  * have been called, to prevent race condition of the initialization order.
41  */
42 struct avr_irq_t;
43
44 typedef void (*avr_irq_notify_t)(struct avr_irq_t * irq, uint32_t value, void * param);
45
46 // internal structure for a hook, never seen by the notify procs
47 typedef struct avr_irq_hook_t {
48         struct avr_irq_hook_t * next;
49         int busy;       // prevent reentrance of callbacks
50         
51         struct avr_irq_t * chain;       // raise the IRQ on this too - optional if "notify" is on
52         avr_irq_notify_t notify;        // called when IRQ is raised - optional if "chain" is on
53         void * param;                           // "notify" parameter
54 } avr_irq_hook_t;
55
56 enum {
57         IRQ_FLAG_NOT            = (1 << 0),     // change polarity of the IRQ
58         IRQ_FLAG_FILTERED       = (1 << 1),     // do not "notify" if "value" is the same as previous raise
59         IRQ_FLAG_ALLOC          = (1 << 2), // this irq structure was malloced via avr_alloc_irq
60 };
61
62 /*
63  * Public IRQ structure
64  */
65 typedef struct avr_irq_t {
66         uint32_t                        irq;
67         uint32_t                        value;
68         uint8_t                         flags;  // IRQ_*
69         avr_irq_hook_t *        hook;
70 } avr_irq_t;
71
72 avr_irq_t * avr_alloc_irq(uint32_t base, uint32_t count);
73 void avr_free_irq(avr_irq_t * irq, uint32_t count);
74
75 void avr_init_irq(avr_irq_t * irq, uint32_t base, uint32_t count);
76 void avr_raise_irq(avr_irq_t * irq, uint32_t value);
77 // this connects a "source" IRQ to a "destination" IRQ
78 void avr_connect_irq(avr_irq_t * src, avr_irq_t * dst);
79 void avr_irq_register_notify(avr_irq_t * irq, avr_irq_notify_t notify, void * param);
80
81 #endif /* __SIM_IRQ_H__ */