Rev 1888 | Rev 2071 | 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) |