Xv6 with picoc & Linkage editor
v1.0
The project delineate mutual cohesion between c library, linkage editor ( linker), interpreter and operating system by porting the same on xv6 kernel
|
00001 // The I/O APIC manages hardware interrupts for an SMP system. 00002 // http://www.intel.com/design/chipsets/datashts/29056601.pdf 00003 // See also picirq.c. 00004 00005 #include "types.h" 00006 #include "defs.h" 00007 #include "traps.h" 00008 00009 #define IOAPIC 0xFEC00000 // Default physical address of IO APIC 00010 00011 #define REG_ID 0x00 // Register index: ID 00012 #define REG_VER 0x01 // Register index: version 00013 #define REG_TABLE 0x10 // Redirection table base 00014 00015 // The redirection table starts at REG_TABLE and uses 00016 // two registers to configure each interrupt. 00017 // The first (low) register in a pair contains configuration bits. 00018 // The second (high) register contains a bitmask telling which 00019 // CPUs can serve that interrupt. 00020 #define INT_DISABLED 0x00010000 // Interrupt disabled 00021 #define INT_LEVEL 0x00008000 // Level-triggered (vs edge-) 00022 #define INT_ACTIVELOW 0x00002000 // Active low (vs high) 00023 #define INT_LOGICAL 0x00000800 // Destination is CPU id (vs APIC ID) 00024 00025 volatile struct ioapic *ioapic; 00026 00027 // IO APIC MMIO structure: write reg, then read or write data. 00028 struct ioapic { 00029 uint reg; 00030 uint pad[3]; 00031 uint data; 00032 }; 00033 00034 static uint 00035 ioapicread(int reg) 00036 { 00037 ioapic->reg = reg; 00038 return ioapic->data; 00039 } 00040 00041 static void 00042 ioapicwrite(int reg, uint data) 00043 { 00044 ioapic->reg = reg; 00045 ioapic->data = data; 00046 } 00047 00048 void 00049 ioapicinit(void) 00050 { 00051 int i, id, maxintr; 00052 00053 if(!ismp) 00054 return; 00055 00056 ioapic = (volatile struct ioapic*)IOAPIC; 00057 maxintr = (ioapicread(REG_VER) >> 16) & 0xFF; 00058 id = ioapicread(REG_ID) >> 24; 00059 if(id != ioapicid) 00060 cprintf("ioapicinit: id isn't equal to ioapicid; not a MP\n"); 00061 00062 // Mark all interrupts edge-triggered, active high, disabled, 00063 // and not routed to any CPUs. 00064 for(i = 0; i <= maxintr; i++){ 00065 ioapicwrite(REG_TABLE+2*i, INT_DISABLED | (T_IRQ0 + i)); 00066 ioapicwrite(REG_TABLE+2*i+1, 0); 00067 } 00068 } 00069 00070 void 00071 ioapicenable(int irq, int cpunum) 00072 { 00073 if(!ismp) 00074 return; 00075 00076 // Mark interrupt edge-triggered, active high, 00077 // enabled, and routed to the given cpunum, 00078 // which happens to be that cpu's APIC ID. 00079 ioapicwrite(REG_TABLE+2*irq, T_IRQ0 + irq); 00080 ioapicwrite(REG_TABLE+2*irq+1, cpunum << 24); 00081 }