Usermode/libc - Fix strchr and strrchr behavior
[tpg/acess2.git] / KernelLand / Modules / armv7 / GIC / gic.c
1 /*
2  * ARMv7 GIC Support
3  * - By John Hodge (thePowersGang)
4  * 
5  * gic.c
6  * - GIC Core
7  */
8 #define DEBUG   1
9
10 #include <acess.h>
11 #include <modules.h>
12 #include "gic.h"
13 #include <options.h>
14
15 #define N_IRQS  1024
16
17 // === IMPORTS ===
18 extern void     *gpIRQHandler;
19 extern tPAddr   gGIC_DistributorAddr;
20 extern tPAddr   gGIC_InterfaceAddr;
21
22 // === TYPES ===
23 typedef void (*tIRQ_Handler)(int, void*);
24
25 // === PROTOTYPES ===
26  int    GIC_Install(char **Arguments);
27 void    GIC_IRQHandler(void);
28
29 // === GLOBALS ===
30 MODULE_DEFINE(0, 0x100, armv7_GIC, GIC_Install, NULL, NULL);
31 volatile Uint32 *gpGIC_DistributorBase;
32 volatile Uint32 *gpGIC_InterfaceBase;
33 tIRQ_Handler    gaIRQ_Handlers[N_IRQS];
34 void    *gaIRQ_HandlerData[N_IRQS];
35
36 // === CODE ===
37 int GIC_Install(char **Arguments)
38 {
39         // Initialise
40         Log_Debug("GIC", "Dist: %P, Interface: %P",
41                 gGIC_DistributorAddr, gGIC_InterfaceAddr);
42         gpGIC_InterfaceBase = (Uint32*)MM_MapHWPages(gGIC_InterfaceAddr, 1)
43                 + (gGIC_InterfaceAddr & (PAGE_SIZE-1))/4;
44         gpGIC_DistributorBase = (void*)MM_MapHWPages(gGIC_DistributorAddr, 1);
45
46         gpGIC_InterfaceBase[GICC_CTLR] = 0;     // Disable CPU interaface
47         gpGIC_InterfaceBase[GICC_PMR] = 0xFF;   // Effectively disable prioritories
48         gpGIC_InterfaceBase[GICC_CTLR] = 1;     // Enable CPU
49         gpGIC_DistributorBase[GICD_CTLR] = 1;   // Enable Distributor
50
51         gpIRQHandler = GIC_IRQHandler;
52
53         __asm__ __volatile__ ("cpsie if");      // Enable IRQs and FIQs
54
55 #if 0
56         for( int i = 0; i < N_IRQS/32; i ++ ) {
57                 Log_Debug("GIC", "GICD_ISENABLER%i %x = %08x",
58                         i, GICD_ISENABLER0 + i,
59                         gpGIC_DistributorBase[GICD_ISENABLER0+i]);
60                 gpGIC_DistributorBase[GICD_ISENABLER0+i] = 0;
61         }
62 #endif
63
64         #if 0
65         // Testing - First 32 actual interrupts enabled
66         gpGIC_DistributorBase[GICD_ISENABLER0+1] = 0xFFFFFFFF;
67         for( int i = 0; i < 32/4; i ++ )
68                 gpGIC_DistributorBase[GICD_ITARGETSR0+8+i] = 0x01010101;
69         #endif
70
71         // Clear out pending IRQs.
72         gpGIC_InterfaceBase[GICC_EOIR] = gpGIC_InterfaceBase[GICC_IAR];
73
74         return MODULE_ERR_OK;
75 }
76
77 void GIC_IRQHandler(void)
78 {
79         Uint32  num = gpGIC_InterfaceBase[GICC_IAR];
80         if( gaIRQ_Handlers[num] ) {
81                 gaIRQ_Handlers[num]( num, gaIRQ_HandlerData[num] );
82         }
83         else {
84                 Log_Debug("GIC", "IRQ 0x%x unhandled", num);
85         }
86         gpGIC_InterfaceBase[GICC_EOIR] = num;
87 }
88
89 int IRQ_AddHandler(int IRQ, tIRQ_Handler Handler, void *Ptr)
90 {
91         if( IRQ < 0 || IRQ >= N_IRQS-32 ) {
92                 return 1;
93         }
94         
95         IRQ += 32;      // 32 internal IRQs
96         // - Enable IRQ, clear pending and send to CPU 1 only
97         gpGIC_DistributorBase[GICD_ISENABLER0+IRQ/32] = 1 << (IRQ & (32-1));
98         ((Uint8*)&gpGIC_DistributorBase[GICD_ITARGETSR0])[IRQ] = 1;
99         gpGIC_DistributorBase[GICD_ICPENDR0+IRQ/32] = 1 << (IRQ & (32-1));
100         gpGIC_DistributorBase[GICD_ICFGR0+IRQ/16] |= 2 << ((IRQ & 15)*2);
101         
102         // TODO: Does the GIC need to handle IRQ sharing?
103         if( gaIRQ_Handlers[IRQ] ) {
104                 Log_Warning("GIC", "IRQ %i already handled by %p, %p ignored",
105                         IRQ, gaIRQ_Handlers[IRQ], Handler);
106                 return 2;
107         }
108         
109         gaIRQ_Handlers[IRQ] = Handler;
110         gaIRQ_HandlerData[IRQ] = Ptr;
111         
112         Log_Debug("GIC", "IRQ %i handled by %p(%p)", IRQ, Handler, Ptr);
113         return 0;
114 }
115

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