Rev 1888 | Rev 2101 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1888 | Rev 1970 | ||
---|---|---|---|
Line 42... | Line 42... | ||
42 | #include <interrupt.h> |
42 | #include <interrupt.h> |
43 | #include <arch/interrupt.h> |
43 | #include <arch/interrupt.h> |
44 | #include <print.h> |
44 | #include <print.h> |
45 | #include <arch/asm.h> |
45 | #include <arch/asm.h> |
46 | #include <arch.h> |
46 | #include <arch.h> |
- | 47 | #include <ddi/irq.h> |
|
- | 48 | #include <ddi/device.h> |
|
47 | 49 | ||
48 | #ifdef CONFIG_SMP |
50 | #ifdef CONFIG_SMP |
49 | 51 | ||
50 | /* |
52 | /* |
51 | * Advanced Programmable Interrupt Controller for SMP systems. |
53 | * Advanced Programmable Interrupt Controller for SMP systems. |
Line 69... | Line 71... | ||
69 | */ |
71 | */ |
70 | volatile uint32_t *l_apic = (uint32_t *) 0xfee00000; |
72 | volatile uint32_t *l_apic = (uint32_t *) 0xfee00000; |
71 | volatile uint32_t *io_apic = (uint32_t *) 0xfec00000; |
73 | volatile uint32_t *io_apic = (uint32_t *) 0xfec00000; |
72 | 74 | ||
73 | uint32_t apic_id_mask = 0; |
75 | uint32_t apic_id_mask = 0; |
- | 76 | static irq_t l_apic_timer_irq; |
|
74 | 77 | ||
75 | static int apic_poll_errors(void); |
78 | static int apic_poll_errors(void); |
76 | 79 | ||
77 | #ifdef LAPIC_VERBOSE |
80 | #ifdef LAPIC_VERBOSE |
78 | static char *delmod_str[] = { |
81 | static char *delmod_str[] = { |
Line 115... | Line 118... | ||
115 | "Polarity High", |
118 | "Polarity High", |
116 | "Polarity Low" |
119 | "Polarity Low" |
117 | }; |
120 | }; |
118 | #endif /* LAPIC_VERBOSE */ |
121 | #endif /* LAPIC_VERBOSE */ |
119 | 122 | ||
- | 123 | /** APIC spurious interrupt handler. |
|
- | 124 | * |
|
- | 125 | * @param n Interrupt vector. |
|
- | 126 | * @param istate Interrupted state. |
|
- | 127 | */ |
|
- | 128 | static void apic_spurious(int n, istate_t *istate) |
|
- | 129 | { |
|
- | 130 | #ifdef CONFIG_DEBUG |
|
- | 131 | printf("cpu%d: APIC spurious interrupt\n", CPU->id); |
|
- | 132 | #endif |
|
- | 133 | } |
|
120 | 134 | ||
121 | static void apic_spurious(int n, istate_t *istate); |
135 | static irq_ownership_t l_apic_timer_claim(void) |
- | 136 | { |
|
- | 137 | return IRQ_ACCEPT; |
|
- | 138 | } |
|
- | 139 | ||
122 | static void l_apic_timer_interrupt(int n, istate_t *istate); |
140 | static void l_apic_timer_irq_handler(irq_t *irq, void *arg, ...) |
- | 141 | { |
|
- | 142 | clock(); |
|
- | 143 | } |
|
123 | 144 | ||
124 | /** Initialize APIC on BSP. */ |
145 | /** Initialize APIC on BSP. */ |
125 | void apic_init(void) |
146 | void apic_init(void) |
126 | { |
147 | { |
127 | io_apic_id_t idreg; |
148 | io_apic_id_t idreg; |
Line 137... | Line 158... | ||
137 | * Configure interrupt routing. |
158 | * Configure interrupt routing. |
138 | * IRQ 0 remains masked as the time signal is generated by l_apic's themselves. |
159 | * IRQ 0 remains masked as the time signal is generated by l_apic's themselves. |
139 | * Other interrupts will be forwarded to the lowest priority CPU. |
160 | * Other interrupts will be forwarded to the lowest priority CPU. |
140 | */ |
161 | */ |
141 | io_apic_disable_irqs(0xffff); |
162 | io_apic_disable_irqs(0xffff); |
- | 163 | ||
- | 164 | irq_initialize(&l_apic_timer_irq); |
|
- | 165 | l_apic_timer_irq.devno = device_assign_devno(); |
|
- | 166 | l_apic_timer_irq.inr = IRQ_CLK; |
|
- | 167 | l_apic_timer_irq.claim = l_apic_timer_claim; |
|
142 | exc_register(VECTOR_CLK, "l_apic_timer", (iroutine) l_apic_timer_interrupt); |
168 | l_apic_timer_irq.handler = l_apic_timer_irq_handler; |
- | 169 | irq_register(&l_apic_timer_irq); |
|
- | 170 | ||
143 | for (i = 0; i < IRQ_COUNT; i++) { |
171 | for (i = 0; i < IRQ_COUNT; i++) { |
144 | int pin; |
172 | int pin; |
145 | 173 | ||
146 | if ((pin = smp_irq_to_pin(i)) != -1) { |
174 | if ((pin = smp_irq_to_pin(i)) != -1) |
147 | io_apic_change_ioredtbl(pin, DEST_ALL, IVT_IRQBASE+i, LOPRI); |
175 | io_apic_change_ioredtbl(pin, DEST_ALL, IVT_IRQBASE+i, LOPRI); |
148 | } |
- | |
149 | } |
176 | } |
150 | 177 | ||
151 | /* |
178 | /* |
152 | * Ensure that io_apic has unique ID. |
179 | * Ensure that io_apic has unique ID. |
153 | */ |
180 | */ |
154 | idreg.value = io_apic_read(IOAPICID); |
181 | idreg.value = io_apic_read(IOAPICID); |
155 | if ((1<<idreg.apic_id) & apic_id_mask) { /* see if IO APIC ID is used already */ |
182 | if ((1 << idreg.apic_id) & apic_id_mask) { /* see if IO APIC ID is used already */ |
156 | for (i = 0; i < APIC_ID_COUNT; i++) { |
183 | for (i = 0; i < APIC_ID_COUNT; i++) { |
157 | if (!((1<<i) & apic_id_mask)) { |
184 | if (!((1 << i) & apic_id_mask)) { |
158 | idreg.apic_id = i; |
185 | idreg.apic_id = i; |
159 | io_apic_write(IOAPICID, idreg.value); |
186 | io_apic_write(IOAPICID, idreg.value); |
160 | break; |
187 | break; |
161 | } |
188 | } |
162 | } |
189 | } |
Line 168... | Line 195... | ||
168 | l_apic_init(); |
195 | l_apic_init(); |
169 | 196 | ||
170 | l_apic_debug(); |
197 | l_apic_debug(); |
171 | } |
198 | } |
172 | 199 | ||
173 | /** APIC spurious interrupt handler. |
- | |
174 | * |
- | |
175 | * @param n Interrupt vector. |
- | |
176 | * @param istate Interrupted state. |
- | |
177 | */ |
- | |
178 | void apic_spurious(int n, istate_t *istate) |
- | |
179 | { |
- | |
180 | #ifdef CONFIG_DEBUG |
- | |
181 | printf("cpu%d: APIC spurious interrupt\n", CPU->id); |
- | |
182 | #endif |
- | |
183 | } |
- | |
184 | - | ||
185 | /** Poll for APIC errors. |
200 | /** Poll for APIC errors. |
186 | * |
201 | * |
187 | * Examine Error Status Register and report all errors found. |
202 | * Examine Error Status Register and report all errors found. |
188 | * |
203 | * |
189 | * @return 0 on error, 1 on success. |
204 | * @return 0 on error, 1 on success. |
Line 438... | Line 453... | ||
438 | error.value = l_apic[LVT_Err]; |
453 | error.value = l_apic[LVT_Err]; |
439 | printf("LVT Err: vector=%hhd, %s, %s\n", error.vector, delivs_str[error.delivs], mask_str[error.masked]); |
454 | printf("LVT Err: vector=%hhd, %s, %s\n", error.vector, delivs_str[error.delivs], mask_str[error.masked]); |
440 | #endif |
455 | #endif |
441 | } |
456 | } |
442 | 457 | ||
443 | /** Local APIC Timer Interrupt. |
- | |
444 | * |
- | |
445 | * @param n Interrupt vector number. |
- | |
446 | * @param istate Interrupted state. |
- | |
447 | */ |
- | |
448 | void l_apic_timer_interrupt(int n, istate_t *istate) |
- | |
449 | { |
- | |
450 | l_apic_eoi(); |
- | |
451 | clock(); |
- | |
452 | } |
- | |
453 | - | ||
454 | /** Get Local APIC ID. |
458 | /** Get Local APIC ID. |
455 | * |
459 | * |
456 | * @return Local APIC ID. |
460 | * @return Local APIC ID. |
457 | */ |
461 | */ |
458 | uint8_t l_apic_id(void) |
462 | uint8_t l_apic_id(void) |