Kernel - Fix user handles not being cleared by Threads_Delete
[tpg/acess2.git] / KernelLand / Modules / armv7 / GIC / gic.c
index 8dbab3a..1de851d 100644 (file)
@@ -16,6 +16,8 @@
 
 // === IMPORTS ===
 extern void    *gpIRQHandler;
+extern tPAddr  gGIC_DistributorAddr;
+extern tPAddr  gGIC_InterfaceAddr;
 
 // === TYPES ===
 typedef void (*tIRQ_Handler)(int, void*);
@@ -26,27 +28,23 @@ void        GIC_IRQHandler(void);
 
 // === GLOBALS ===
 MODULE_DEFINE(0, 0x100, armv7_GIC, GIC_Install, NULL, NULL);
-Uint32 *gpGIC_DistributorBase;
-Uint32 *gpGIC_InterfaceBase;
-tPAddr gGIC_DistributorAddr;
-tPAddr gGIC_InterfaceAddr;
+volatile Uint32        *gpGIC_DistributorBase;
+volatile Uint32        *gpGIC_InterfaceBase;
 tIRQ_Handler   gaIRQ_Handlers[N_IRQS];
 void   *gaIRQ_HandlerData[N_IRQS];
 
 // === CODE ===
 int GIC_Install(char **Arguments)
 {
-       // Realview PB
-       gGIC_InterfaceAddr   = 0x1e000000;
-       gGIC_DistributorAddr = 0x1e001000;
-
        // Initialise
-       gpGIC_InterfaceBase = (void*)MM_MapHWPages(gGIC_InterfaceAddr, 1);
-       LOG("gpGIC_InterfaceBase = %p", gpGIC_InterfaceBase);
+       Log_Debug("GIC", "Dist: %P, Interface: %P",
+               gGIC_DistributorAddr, gGIC_InterfaceAddr);
+       gpGIC_InterfaceBase = (Uint32*)MM_MapHWPages(gGIC_InterfaceAddr, 1)
+               + (gGIC_InterfaceAddr & (PAGE_SIZE-1))/4;
        gpGIC_DistributorBase = (void*)MM_MapHWPages(gGIC_DistributorAddr, 1);
-       LOG("gpGIC_DistributorBase = %p", gpGIC_DistributorBase);
 
-       gpGIC_InterfaceBase[GICC_PMR] = 0xFF;   
+       gpGIC_InterfaceBase[GICC_CTLR] = 0;     // Disable CPU interaface
+       gpGIC_InterfaceBase[GICC_PMR] = 0xFF;   // Effectively disable prioritories
        gpGIC_InterfaceBase[GICC_CTLR] = 1;     // Enable CPU
        gpGIC_DistributorBase[GICD_CTLR] = 1;   // Enable Distributor
 
@@ -54,14 +52,37 @@ int GIC_Install(char **Arguments)
 
        __asm__ __volatile__ ("cpsie if");      // Enable IRQs and FIQs
 
+#if 0
+       for( int i = 0; i < N_IRQS/32; i ++ ) {
+               Log_Debug("GIC", "GICD_ISENABLER%i %x = %08x",
+                       i, GICD_ISENABLER0 + i,
+                       gpGIC_DistributorBase[GICD_ISENABLER0+i]);
+               gpGIC_DistributorBase[GICD_ISENABLER0+i] = 0;
+       }
+#endif
+
+       #if 0
+       // Testing - First 32 actual interrupts enabled
+       gpGIC_DistributorBase[GICD_ISENABLER0+1] = 0xFFFFFFFF;
+       for( int i = 0; i < 32/4; i ++ )
+               gpGIC_DistributorBase[GICD_ITARGETSR0+8+i] = 0x01010101;
+       #endif
+
+       // Clear out pending IRQs.
+       gpGIC_InterfaceBase[GICC_EOIR] = gpGIC_InterfaceBase[GICC_IAR];
+
        return MODULE_ERR_OK;
 }
 
 void GIC_IRQHandler(void)
 {
        Uint32  num = gpGIC_InterfaceBase[GICC_IAR];
-//     Log_Debug("GIC", "IRQ 0x%x", num);
-       gaIRQ_Handlers[num]( num, gaIRQ_HandlerData[num] );
+       if( gaIRQ_Handlers[num] ) {
+               gaIRQ_Handlers[num]( num, gaIRQ_HandlerData[num] );
+       }
+       else {
+               Log_Debug("GIC", "IRQ 0x%x unhandled", num);
+       }
        gpGIC_InterfaceBase[GICC_EOIR] = num;
 }
 
@@ -71,21 +92,24 @@ int IRQ_AddHandler(int IRQ, tIRQ_Handler Handler, void *Ptr)
                return 1;
        }
        
-       LOG("IRQ = %i", IRQ);
        IRQ += 32;      // 32 internal IRQs
-       LOG("IRQ = %i (after adjust)", IRQ);
-       LOG("mask = 0x%x", 1 << (IRQ & (31-1)));
+       // - Enable IRQ, clear pending and send to CPU 1 only
        gpGIC_DistributorBase[GICD_ISENABLER0+IRQ/32] = 1 << (IRQ & (32-1));
        ((Uint8*)&gpGIC_DistributorBase[GICD_ITARGETSR0])[IRQ] = 1;
+       gpGIC_DistributorBase[GICD_ICPENDR0+IRQ/32] = 1 << (IRQ & (32-1));
+       gpGIC_DistributorBase[GICD_ICFGR0+IRQ/16] |= 2 << ((IRQ & 15)*2);
        
-//     Log_Warning("GIC", "TODO: Implement IRQ_AddHandler");
-       
-       if( gaIRQ_Handlers[IRQ] )
+       // TODO: Does the GIC need to handle IRQ sharing?
+       if( gaIRQ_Handlers[IRQ] ) {
+               Log_Warning("GIC", "IRQ %i already handled by %p, %p ignored",
+                       IRQ, gaIRQ_Handlers[IRQ], Handler);
                return 2;
+       }
        
        gaIRQ_Handlers[IRQ] = Handler;
        gaIRQ_HandlerData[IRQ] = Ptr;
        
+       Log_Debug("GIC", "IRQ %i handled by %p(%p)", IRQ, Handler, Ptr);
        return 0;
 }
 

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