Rev 2218 | Rev 3906 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 2218 | Rev 2441 | ||
|---|---|---|---|
| Line 123... | Line 123... | ||
| 123 | /** APIC spurious interrupt handler. |
123 | /** APIC spurious interrupt handler. |
| 124 | * |
124 | * |
| 125 | * @param n Interrupt vector. |
125 | * @param n Interrupt vector. |
| 126 | * @param istate Interrupted state. |
126 | * @param istate Interrupted state. |
| 127 | */ |
127 | */ |
| 128 | static void apic_spurious(int n, istate_t *istate) |
128 | static void apic_spurious(int n __attribute__((unused)), istate_t *istate __attribute__((unused))) |
| 129 | { |
129 | { |
| 130 | #ifdef CONFIG_DEBUG |
130 | #ifdef CONFIG_DEBUG |
| 131 | printf("cpu%d: APIC spurious interrupt\n", CPU->id); |
131 | printf("cpu%u: APIC spurious interrupt\n", CPU->id); |
| 132 | #endif |
132 | #endif |
| 133 | } |
133 | } |
| 134 | 134 | ||
| 135 | static irq_ownership_t l_apic_timer_claim(void) |
135 | static irq_ownership_t l_apic_timer_claim(void) |
| 136 | { |
136 | { |
| 137 | return IRQ_ACCEPT; |
137 | return IRQ_ACCEPT; |
| 138 | } |
138 | } |
| 139 | 139 | ||
| 140 | static void l_apic_timer_irq_handler(irq_t *irq, void *arg, ...) |
140 | static void l_apic_timer_irq_handler(irq_t *irq, void *arg __attribute__((unused)), ...) |
| 141 | { |
141 | { |
| 142 | /* |
142 | /* |
| 143 | * Holding a spinlock could prevent clock() from preempting |
143 | * Holding a spinlock could prevent clock() from preempting |
| 144 | * the current thread. In this case, we don't need to hold the |
144 | * the current thread. In this case, we don't need to hold the |
| 145 | * irq->lock so we just unlock it and then lock it again. |
145 | * irq->lock so we just unlock it and then lock it again. |
| Line 151... | Line 151... | ||
| 151 | 151 | ||
| 152 | /** Initialize APIC on BSP. */ |
152 | /** Initialize APIC on BSP. */ |
| 153 | void apic_init(void) |
153 | void apic_init(void) |
| 154 | { |
154 | { |
| 155 | io_apic_id_t idreg; |
155 | io_apic_id_t idreg; |
| 156 | unsigned int i; |
- | |
| 157 | 156 | ||
| 158 | exc_register(VECTOR_APIC_SPUR, "apic_spurious", (iroutine) apic_spurious); |
157 | exc_register(VECTOR_APIC_SPUR, "apic_spurious", (iroutine) apic_spurious); |
| 159 | 158 | ||
| 160 | enable_irqs_function = io_apic_enable_irqs; |
159 | enable_irqs_function = io_apic_enable_irqs; |
| 161 | disable_irqs_function = io_apic_disable_irqs; |
160 | disable_irqs_function = io_apic_disable_irqs; |
| 162 | eoi_function = l_apic_eoi; |
161 | eoi_function = l_apic_eoi; |
| Line 174... | Line 173... | ||
| 174 | l_apic_timer_irq.inr = IRQ_CLK; |
173 | l_apic_timer_irq.inr = IRQ_CLK; |
| 175 | l_apic_timer_irq.claim = l_apic_timer_claim; |
174 | l_apic_timer_irq.claim = l_apic_timer_claim; |
| 176 | l_apic_timer_irq.handler = l_apic_timer_irq_handler; |
175 | l_apic_timer_irq.handler = l_apic_timer_irq_handler; |
| 177 | irq_register(&l_apic_timer_irq); |
176 | irq_register(&l_apic_timer_irq); |
| 178 | 177 | ||
| - | 178 | uint8_t i; |
|
| 179 | for (i = 0; i < IRQ_COUNT; i++) { |
179 | for (i = 0; i < IRQ_COUNT; i++) { |
| 180 | int pin; |
180 | int pin; |
| 181 | 181 | ||
| 182 | if ((pin = smp_irq_to_pin(i)) != -1) |
182 | if ((pin = smp_irq_to_pin(i)) != -1) |
| 183 | io_apic_change_ioredtbl(pin, DEST_ALL, IVT_IRQBASE + i, LOPRI); |
183 | io_apic_change_ioredtbl((uint8_t) pin, DEST_ALL, (uint8_t) (IVT_IRQBASE + i), LOPRI); |
| 184 | } |
184 | } |
| 185 | 185 | ||
| 186 | /* |
186 | /* |
| 187 | * Ensure that io_apic has unique ID. |
187 | * Ensure that io_apic has unique ID. |
| 188 | */ |
188 | */ |
| Line 326... | Line 326... | ||
| 326 | /* |
326 | /* |
| 327 | * If this is not 82489DX-based l_apic we must send two STARTUP IPI's. |
327 | * If this is not 82489DX-based l_apic we must send two STARTUP IPI's. |
| 328 | */ |
328 | */ |
| 329 | for (i = 0; i<2; i++) { |
329 | for (i = 0; i<2; i++) { |
| 330 | icr.lo = l_apic[ICRlo]; |
330 | icr.lo = l_apic[ICRlo]; |
| 331 | icr.vector = ((uintptr_t) ap_boot) / 4096; /* calculate the reset vector */ |
331 | icr.vector = (uint8_t) (((uintptr_t) ap_boot) >> 12); /* calculate the reset vector */ |
| 332 | icr.delmod = DELMOD_STARTUP; |
332 | icr.delmod = DELMOD_STARTUP; |
| 333 | icr.destmod = DESTMOD_PHYS; |
333 | icr.destmod = DESTMOD_PHYS; |
| 334 | icr.level = LEVEL_ASSERT; |
334 | icr.level = LEVEL_ASSERT; |
| 335 | icr.shorthand = SHORTHAND_NONE; |
335 | icr.shorthand = SHORTHAND_NONE; |
| 336 | icr.trigger_mode = TRIGMOD_LEVEL; |
336 | icr.trigger_mode = TRIGMOD_LEVEL; |
| Line 423... | Line 423... | ||
| 423 | t2 = l_apic[CCRT]; |
423 | t2 = l_apic[CCRT]; |
| 424 | 424 | ||
| 425 | l_apic[ICRT] = t1-t2; |
425 | l_apic[ICRT] = t1-t2; |
| 426 | 426 | ||
| 427 | /* Program Logical Destination Register. */ |
427 | /* Program Logical Destination Register. */ |
| - | 428 | ASSERT(CPU->id < 8) |
|
| 428 | ldr.value = l_apic[LDR]; |
429 | ldr.value = l_apic[LDR]; |
| 429 | if (CPU->id < sizeof(CPU->id)*8) /* size in bits */ |
- | |
| 430 | ldr.id = (1<<CPU->id); |
430 | ldr.id = (uint8_t) (1 << CPU->id); |
| 431 | l_apic[LDR] = ldr.value; |
431 | l_apic[LDR] = ldr.value; |
| 432 | 432 | ||
| 433 | /* Program Destination Format Register for Flat mode. */ |
433 | /* Program Destination Format Register for Flat mode. */ |
| 434 | dfr.value = l_apic[DFR]; |
434 | dfr.value = l_apic[DFR]; |
| 435 | dfr.model = MODEL_FLAT; |
435 | dfr.model = MODEL_FLAT; |
| Line 511... | Line 511... | ||
| 511 | * @param pin IO APIC pin number. |
511 | * @param pin IO APIC pin number. |
| 512 | * @param dest Interrupt destination address. |
512 | * @param dest Interrupt destination address. |
| 513 | * @param v Interrupt vector to trigger. |
513 | * @param v Interrupt vector to trigger. |
| 514 | * @param flags Flags. |
514 | * @param flags Flags. |
| 515 | */ |
515 | */ |
| 516 | void io_apic_change_ioredtbl(int pin, int dest, uint8_t v, int flags) |
516 | void io_apic_change_ioredtbl(uint8_t pin, uint8_t dest, uint8_t v, int flags) |
| 517 | { |
517 | { |
| 518 | io_redirection_reg_t reg; |
518 | io_redirection_reg_t reg; |
| 519 | int dlvr = DELMOD_FIXED; |
519 | int dlvr = DELMOD_FIXED; |
| 520 | 520 | ||
| 521 | if (flags & LOPRI) |
521 | if (flags & LOPRI) |
| 522 | dlvr = DELMOD_LOWPRI; |
522 | dlvr = DELMOD_LOWPRI; |
| 523 | 523 | ||
| 524 | reg.lo = io_apic_read(IOREDTBL + pin*2); |
524 | reg.lo = io_apic_read((uint8_t) (IOREDTBL + pin * 2)); |
| 525 | reg.hi = io_apic_read(IOREDTBL + pin*2 + 1); |
525 | reg.hi = io_apic_read((uint8_t) (IOREDTBL + pin * 2 + 1)); |
| 526 | 526 | ||
| 527 | reg.dest = dest; |
527 | reg.dest = dest; |
| 528 | reg.destmod = DESTMOD_LOGIC; |
528 | reg.destmod = DESTMOD_LOGIC; |
| 529 | reg.trigger_mode = TRIGMOD_EDGE; |
529 | reg.trigger_mode = TRIGMOD_EDGE; |
| 530 | reg.intpol = POLARITY_HIGH; |
530 | reg.intpol = POLARITY_HIGH; |
| 531 | reg.delmod = dlvr; |
531 | reg.delmod = dlvr; |
| 532 | reg.intvec = v; |
532 | reg.intvec = v; |
| 533 | 533 | ||
| 534 | io_apic_write(IOREDTBL + pin*2, reg.lo); |
534 | io_apic_write((uint8_t) (IOREDTBL + pin * 2), reg.lo); |
| 535 | io_apic_write(IOREDTBL + pin*2 + 1, reg.hi); |
535 | io_apic_write((uint8_t) (IOREDTBL + pin * 2 + 1), reg.hi); |
| 536 | } |
536 | } |
| 537 | 537 | ||
| 538 | /** Mask IRQs in IO APIC. |
538 | /** Mask IRQs in IO APIC. |
| 539 | * |
539 | * |
| 540 | * @param irqmask Bitmask of IRQs to be masked (0 = do not mask, 1 = mask). |
540 | * @param irqmask Bitmask of IRQs to be masked (0 = do not mask, 1 = mask). |
| Line 551... | Line 551... | ||
| 551 | * Mask the signal input in IO APIC if there is a |
551 | * Mask the signal input in IO APIC if there is a |
| 552 | * mapping for the respective IRQ number. |
552 | * mapping for the respective IRQ number. |
| 553 | */ |
553 | */ |
| 554 | pin = smp_irq_to_pin(i); |
554 | pin = smp_irq_to_pin(i); |
| 555 | if (pin != -1) { |
555 | if (pin != -1) { |
| 556 | reg.lo = io_apic_read(IOREDTBL + pin * 2); |
556 | reg.lo = io_apic_read((uint8_t) (IOREDTBL + pin * 2)); |
| 557 | reg.masked = true; |
557 | reg.masked = true; |
| 558 | io_apic_write(IOREDTBL + pin * 2, reg.lo); |
558 | io_apic_write((uint8_t) (IOREDTBL + pin * 2), reg.lo); |
| 559 | } |
559 | } |
| 560 | 560 | ||
| 561 | } |
561 | } |
| 562 | } |
562 | } |
| 563 | } |
563 | } |
| Line 570... | Line 570... | ||
| 570 | { |
570 | { |
| 571 | unsigned int i; |
571 | unsigned int i; |
| 572 | int pin; |
572 | int pin; |
| 573 | io_redirection_reg_t reg; |
573 | io_redirection_reg_t reg; |
| 574 | 574 | ||
| 575 | for (i = 0;i < 16; i++) { |
575 | for (i = 0; i < 16; i++) { |
| 576 | if (irqmask & (1 << i)) { |
576 | if (irqmask & (1 << i)) { |
| 577 | /* |
577 | /* |
| 578 | * Unmask the signal input in IO APIC if there is a |
578 | * Unmask the signal input in IO APIC if there is a |
| 579 | * mapping for the respective IRQ number. |
579 | * mapping for the respective IRQ number. |
| 580 | */ |
580 | */ |
| 581 | pin = smp_irq_to_pin(i); |
581 | pin = smp_irq_to_pin(i); |
| 582 | if (pin != -1) { |
582 | if (pin != -1) { |
| 583 | reg.lo = io_apic_read(IOREDTBL + pin * 2); |
583 | reg.lo = io_apic_read((uint8_t) (IOREDTBL + pin * 2)); |
| 584 | reg.masked = false; |
584 | reg.masked = false; |
| 585 | io_apic_write(IOREDTBL + pin * 2, reg.lo); |
585 | io_apic_write((uint8_t) (IOREDTBL + pin * 2), reg.lo); |
| 586 | } |
586 | } |
| 587 | 587 | ||
| 588 | } |
588 | } |
| 589 | } |
589 | } |
| 590 | } |
590 | } |