00001
00002
00003
00004 #include "types.h"
00005 #include "defs.h"
00006 #include "traps.h"
00007 #include "mmu.h"
00008 #include "x86.h"
00009
00010
00011 #define ID (0x0020/4) // ID
00012 #define VER (0x0030/4) // Version
00013 #define TPR (0x0080/4) // Task Priority
00014 #define EOI (0x00B0/4) // EOI
00015 #define SVR (0x00F0/4) // Spurious Interrupt Vector
00016 #define ENABLE 0x00000100 // Unit Enable
00017 #define ESR (0x0280/4) // Error Status
00018 #define ICRLO (0x0300/4) // Interrupt Command
00019 #define INIT 0x00000500 // INIT/RESET
00020 #define STARTUP 0x00000600 // Startup IPI
00021 #define DELIVS 0x00001000 // Delivery status
00022 #define ASSERT 0x00004000 // Assert interrupt (vs deassert)
00023 #define LEVEL 0x00008000 // Level triggered
00024 #define BCAST 0x00080000 // Send to all APICs, including self.
00025 #define ICRHI (0x0310/4) // Interrupt Command [63:32]
00026 #define TIMER (0x0320/4) // Local Vector Table 0 (TIMER)
00027 #define X1 0x0000000B // divide counts by 1
00028 #define PERIODIC 0x00020000 // Periodic
00029 #define PCINT (0x0340/4) // Performance Counter LVT
00030 #define LINT0 (0x0350/4) // Local Vector Table 1 (LINT0)
00031 #define LINT1 (0x0360/4) // Local Vector Table 2 (LINT1)
00032 #define ERROR (0x0370/4) // Local Vector Table 3 (ERROR)
00033 #define MASKED 0x00010000 // Interrupt masked
00034 #define TICR (0x0380/4) // Timer Initial Count
00035 #define TCCR (0x0390/4) // Timer Current Count
00036 #define TDCR (0x03E0/4) // Timer Divide Configuration
00037
00038 volatile uint *lapic;
00039
00040 static void
00041 lapicw(int index, int value)
00042 {
00043 lapic[index] = value;
00044 lapic[ID];
00045 }
00046
00047 void
00048 lapicinit(int c)
00049 {
00050 if(!lapic)
00051 return;
00052
00053
00054 lapicw(SVR, ENABLE | (T_IRQ0 + IRQ_SPURIOUS));
00055
00056
00057
00058
00059
00060 lapicw(TDCR, X1);
00061 lapicw(TIMER, PERIODIC | (T_IRQ0 + IRQ_TIMER));
00062 lapicw(TICR, 10000000);
00063
00064
00065 lapicw(LINT0, MASKED);
00066 lapicw(LINT1, MASKED);
00067
00068
00069
00070 if(((lapic[VER]>>16) & 0xFF) >= 4)
00071 lapicw(PCINT, MASKED);
00072
00073
00074 lapicw(ERROR, T_IRQ0 + IRQ_ERROR);
00075
00076
00077 lapicw(ESR, 0);
00078 lapicw(ESR, 0);
00079
00080
00081 lapicw(EOI, 0);
00082
00083
00084 lapicw(ICRHI, 0);
00085 lapicw(ICRLO, BCAST | INIT | LEVEL);
00086 while(lapic[ICRLO] & DELIVS)
00087 ;
00088
00089
00090 lapicw(TPR, 0);
00091 }
00092
00093 int
00094 cpunum(void)
00095 {
00096
00097
00098
00099
00100
00101 if(readeflags()&FL_IF){
00102 static int n;
00103 if(n++ == 0)
00104 cprintf("cpu called from %x with interrupts enabled\n",
00105 __builtin_return_address(0));
00106 }
00107
00108 if(lapic)
00109 return lapic[ID]>>24;
00110 return 0;
00111 }
00112
00113
00114 void
00115 lapiceoi(void)
00116 {
00117 if(lapic)
00118 lapicw(EOI, 0);
00119 }
00120
00121
00122
00123 void
00124 microdelay(int us)
00125 {
00126 }
00127
00128
00129 #define IO_RTC 0x70
00130
00131
00132
00133 void
00134 lapicstartap(uchar apicid, uint addr)
00135 {
00136 int i;
00137 ushort *wrv;
00138
00139
00140
00141
00142 outb(IO_RTC, 0xF);
00143 outb(IO_RTC+1, 0x0A);
00144 wrv = (ushort*)(0x40<<4 | 0x67);
00145 wrv[0] = 0;
00146 wrv[1] = addr >> 4;
00147
00148
00149
00150 lapicw(ICRHI, apicid<<24);
00151 lapicw(ICRLO, INIT | LEVEL | ASSERT);
00152 microdelay(200);
00153 lapicw(ICRLO, INIT | LEVEL);
00154 microdelay(100);
00155
00156
00157
00158
00159
00160
00161 for(i = 0; i < 2; i++){
00162 lapicw(ICRHI, apicid<<24);
00163 lapicw(ICRLO, STARTUP | (addr>>12));
00164 microdelay(200);
00165 }
00166 }