X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FModules%2Farmv7%2FGIC%2Fgic.c;h=1de851dc5ee15fade2e499150ce858d2212d3ed6;hb=2015e19b71476d1fee2480aef4de60d22ed5438d;hp=654417912eb75852db4bbd3db9e8707263255e24;hpb=be5123fe1f4aa66b76ce8ef589362ad21b6bbf72;p=tpg%2Facess2.git diff --git a/KernelLand/Modules/armv7/GIC/gic.c b/KernelLand/Modules/armv7/GIC/gic.c index 65441791..1de851dc 100644 --- a/KernelLand/Modules/armv7/GIC/gic.c +++ b/KernelLand/Modules/armv7/GIC/gic.c @@ -28,8 +28,8 @@ void GIC_IRQHandler(void); // === GLOBALS === MODULE_DEFINE(0, 0x100, armv7_GIC, GIC_Install, NULL, NULL); -Uint32 *gpGIC_DistributorBase; -Uint32 *gpGIC_InterfaceBase; +volatile Uint32 *gpGIC_DistributorBase; +volatile Uint32 *gpGIC_InterfaceBase; tIRQ_Handler gaIRQ_Handlers[N_IRQS]; void *gaIRQ_HandlerData[N_IRQS]; @@ -37,12 +37,14 @@ void *gaIRQ_HandlerData[N_IRQS]; int GIC_Install(char **Arguments) { // 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 @@ -50,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; } @@ -67,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; }