#include #include namespace GIC { /* This code (correctly) assumes that initial registers' values are 0x0, * thus does not work (read: correctly overwrite) with subsequent changes, * but since GIC is prepared at system startup and then never touched again, * this should not be a problem */ void enableInterrupt(const uint16_t m, const TargetCPU target, const Sensitivity sensitivity) { /* register offset (used in an uint32_t array, so no need to multiply by 4) */ uint16_t n; /* Enable interrupt m */ n = m / 32; distributor[GICD_ISENABLER + n] = distributor[GICD_ISENABLER + n] | (1 << (m % 32)); /* Set target CPU */ n = m / 4; distributor[GICD_ITARGETSR + n] = distributor[GICD_ITARGETSR + n] | (target << ((m % 4) * 8)); /* Edge or level triggered? */ n = m / 16; distributor[GICD_ICFGR + n] = distributor[GICD_ICFGR + n] | (sensitivity << (2 * (m % 16) + 1)); /* Enable all priorities */ cpuInterface[1] = 0xff; } void printDistributorStatus(void) { for (short i = 0; i < 1024; ++i) { printk("Distributor "); printk(itoa(i * 4)); printk(" : "); printkl(itoa(distributor[i])); } } void printCPUInterfaceStatus(void) { for (short i = 0; i < 64; ++i) { printk("CPUInterface "); printk(itoa(i * 4)); printk(" : "); printkl(itoa(cpuInterface[i])); } } void enable(void) { enableInterrupt(54, CPU0T, EDGE); /* Timer0 */ /* Enable distributor and CPU interfaces * Do this always at the end, * since writing on GIC registers is not allowed when it is enabled */ distributor[0] = distributor[GICD_CTLR] | 0x1; cpuInterface[0] = cpuInterface[GICC_CTLR] | 0x1; } }