Kernel - Fixing bugs exposed with `qemu -nographic`
[tpg/acess2.git] / KernelLand / Modules / Interfaces / EDI / edi_int.inc.c
1 /*
2  * AcessOS EDI Interface
3  * - IRQ Class
4  * 
5  * By John Hodge (thePowersGang)
6  * 
7  * This file has been released into the public domain.
8  * You are free to use it as you wish.
9  */
10 #include "edi/edi.h"
11
12 // === TYPES ===
13 typedef struct {
14         uint16_t        State;  // 0: Unallocated, 1: Allocated, 2: Initialised, (Bit 0x8000 set if in heap)
15         uint16_t        Num;
16         interrupt_handler_t     Handler;
17 } tEdiIRQ;
18
19 // === PROTOTYPES ===
20 void EDI_Int_IRQ_Handler(tRegs *Regs);
21
22 // === GLOBALS ===
23 tEdiIRQ gEdi_IRQObjects[16];
24
25 // === FUNCTIONS ===
26 /**
27  * \fn object_pointer Edi_Int_IRQ_Construct(void)
28  * \brief Creates a new IRQ Object
29  * \return      Pointer to object
30  */
31 object_pointer Edi_Int_IRQ_Construct(void)
32 {
33          int    i;
34         // Search for a free irq
35         for( i = 0; i < 16; i ++ )
36         {
37                 if(gEdi_IRQObjects[i].State)    continue;
38                 gEdi_IRQObjects[i].State = 1;
39                 gEdi_IRQObjects[i].Num = 0;
40                 gEdi_IRQObjects[i].Handler = NULL;
41                 return &gEdi_IRQObjects[i];
42         }
43         return NULL;
44 }
45
46 /**
47  * \fn void Edi_Int_IRQ_Destruct(object_pointer Object)
48  * \brief Destruct an IRQ Object
49  * \param Object        Object to destroy
50  */
51 void Edi_Int_IRQ_Destruct(object_pointer Object)
52 {
53         tEdiIRQ *obj;
54         
55         VALIDATE_PTR(Object,);
56         obj = GET_DATA(Object);
57         
58         if( !obj->State )       return;
59         
60         if( obj->Handler )
61                 irq_uninstall_handler( obj->Num );
62         
63         if( obj->State & 0x8000 ) {     // If in heap, free
64                 free(Object);
65         } else {        // Otherwise, mark as unallocated
66                 obj->State = 0;
67         }
68 }
69
70 /**
71  * \fn int32_t  Edi_Int_IRQ_InitInt(object_pointer Object, uint16_t Num, interrupt_handler_t Handler)
72  * \brief Initialises an IRQ
73  * \param Object        Object Pointer (this)
74  * \param Num   IRQ Number to use
75  * \param Handler       Callback for IRQ
76  */
77 int32_t Edi_Int_IRQ_InitInt(object_pointer Object, uint16_t Num, interrupt_handler_t Handler)
78 {
79         tEdiIRQ *obj;
80         
81         //LogF("Edi_Int_IRQ_InitInt: (Object=0x%x, Num=%i, Handler=0x%x)\n", Object, Num, Handler);
82         
83         VALIDATE_PTR(Object,0);
84         obj = GET_DATA(Object);
85         
86         if( !obj->State )       return 0;
87         
88         if(Num > 15)    return 0;
89         
90         // Install the IRQ if a handler is passed
91         if(Handler) {
92                 if( !irq_install_handler(Num, Edi_Int_IRQ_Handler) )
93                         return 0;
94                 obj->Handler = Handler;
95         }
96         
97         obj->Num = Num;
98         obj->State &= ~0x3FFF;
99         obj->State |= 2;        // Set initialised flag
100         return 1;
101 }
102
103 /**
104  * \fn uint16_t Edi_Int_IRQ_GetInt(object_pointer Object)
105  * \brief Returns the irq number associated with the object
106  * \param Object        IRQ Object to get number from
107  * \return IRQ Number
108  */
109 uint16_t Edi_Int_IRQ_GetInt(object_pointer Object)
110 {
111         tEdiIRQ *obj;
112         
113         VALIDATE_PTR(Object,0);
114         obj = GET_DATA(Object);
115         
116         if( !obj->State )       return 0;
117         return obj->Num;
118 }
119
120 /**
121  * \fn void EDI_Int_IRQ_SetHandler(object_pointer Object, interrupt_handler_t Handler)
122  * \brief Set the IRQ handler for an IRQ object
123  * \param Object        IRQ Object to alter
124  * \param Handler       Function to use as handler
125  */
126 void EDI_Int_IRQ_SetHandler(object_pointer Object, interrupt_handler_t Handler)
127 {
128         tEdiIRQ *obj;
129         
130         // Get Data Pointer
131         VALIDATE_PTR(Object,);
132         obj = GET_DATA(Object);
133         
134         // Sanity Check arguments
135         if( !obj->State )       return ;
136         
137         // Only register the mediator if it is not already
138         if( Handler && !obj->Handler )
139                 if( !irq_install_handler(obj->Num, Edi_Int_IRQ_Handler) )
140                         return ;
141         obj->Handler = Handler;
142 }
143
144 /**
145  * \fn void EDI_Int_IRQ_Return(object_pointer Object)
146  * \brief Return from interrupt
147  * \param Object        IRQ Object
148  * \note Due to the structure of acess interrupts, this is a dummy
149  */
150 void EDI_Int_IRQ_Return(object_pointer Object)
151 {
152 }
153
154 /**
155  * \fn void Edi_Int_IRQ_Handler(struct regs *Regs)
156  * \brief EDI IRQ Handler - Calls the handler 
157  * \param Regs  Register state at IRQ call
158  */
159 void Edi_Int_IRQ_Handler(struct regs *Regs)
160 {
161          int    i;
162         for( i = 0; i < 16; i ++ )
163         {
164                 if(!gEdi_IRQObjects[i].State)   continue;       // Unused, Skip
165                 if(gEdi_IRQObjects[i].Num != Regs->int_no)      continue;       // Another IRQ, Skip
166                 if(!gEdi_IRQObjects[i].Handler) continue;       // No Handler, Skip
167                 gEdi_IRQObjects[i].Handler( Regs->int_no );     // Call Handler
168                 return;
169         }
170 }
171
172
173 // === CLASS DECLARATION ===
174 static edi_function_declaration_t       scEdi_Int_Functions_IRQ[] = {
175                 {"int32_t", "init_interrupt", 1, 3, NULL, //scEdi_Int_Variables_IO[0],
176                         (function_pointer)Edi_Int_IRQ_InitInt
177                         },
178                 {"uint32_t", "interrupt_get_irq", 1, 1, NULL, //scEdi_Int_Variables_IO[1],
179                         (function_pointer)Edi_Int_IRQ_GetInt
180                         },
181                 {"void", "interrupt_set_handler", 1, 2, NULL, //scEdi_Int_Variables_IO[2],
182                         (function_pointer)Edi_Int_IRQ_GetInt
183                         },
184                 {"void", "interrupt_return", 1, 1, NULL, //scEdi_Int_Variables_IO[3],
185                         (function_pointer)Edi_Int_IRQ_GetInt
186                         }
187         };
188 static edi_class_declaration_t  scEdi_Int_Class_IRQ = 
189         {
190                 INTERRUPTS_CLASS, 1, 12,
191                 scEdi_Int_Functions_IRQ,
192                 Edi_Int_IRQ_Construct,
193                 Edi_Int_IRQ_Destruct,
194                 NULL
195         };

UCC git Repository :: git.ucc.asn.au