Rev 501 | Rev 513 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 501 | Rev 512 | ||
---|---|---|---|
Line 38... | Line 38... | ||
38 | #include <arch.h> |
38 | #include <arch.h> |
39 | 39 | ||
40 | #ifdef CONFIG_SMP |
40 | #ifdef CONFIG_SMP |
41 | 41 | ||
42 | /* |
42 | /* |
43 | * This is functional, far-from-general-enough interface to the APIC. |
- | |
44 | * Advanced Programmable Interrupt Controller for MP systems. |
43 | * Advanced Programmable Interrupt Controller for SMP systems. |
45 | * Tested on: |
44 | * Tested on: |
46 | * Bochs 2.0.2 - Bochs 2.2 with 2-8 CPUs |
45 | * Bochs 2.0.2 - Bochs 2.2 with 2-8 CPUs |
47 | * Simics 2.0.28 - Simics 2.2.14 2-4 CPUs |
46 | * Simics 2.0.28 - Simics 2.2.14 2-4 CPUs |
48 | * ASUS P/I-P65UP5 + ASUS C-P55T2D REV. 1.41 with 2x 200Mhz Pentium CPUs |
47 | * ASUS P/I-P65UP5 + ASUS C-P55T2D REV. 1.41 with 2x 200Mhz Pentium CPUs |
49 | * ASUS PCH-DL with 2x 3000Mhz Pentium 4 Xeon (HT) CPUs |
48 | * ASUS PCH-DL with 2x 3000Mhz Pentium 4 Xeon (HT) CPUs |
Line 80... | Line 79... | ||
80 | * IRQ 0 remains masked as the time signal is generated by l_apic's themselves. |
79 | * IRQ 0 remains masked as the time signal is generated by l_apic's themselves. |
81 | * Other interrupts will be forwarded to the lowest priority CPU. |
80 | * Other interrupts will be forwarded to the lowest priority CPU. |
82 | */ |
81 | */ |
83 | io_apic_disable_irqs(0xffff); |
82 | io_apic_disable_irqs(0xffff); |
84 | trap_register(VECTOR_CLK, l_apic_timer_interrupt); |
83 | trap_register(VECTOR_CLK, l_apic_timer_interrupt); |
85 | for (i=1; i<16; i++) { |
84 | for (i=0; i<16; i++) { |
86 | int pin; |
85 | int pin; |
87 | 86 | ||
88 | if ((pin = mps_irq_to_pin(i)) != -1) |
87 | if ((pin = smp_irq_to_pin(i)) != -1) { |
89 | io_apic_change_ioredtbl(pin,0xf,IVT_IRQBASE+i,LOPRI); |
88 | io_apic_change_ioredtbl(pin,0xff,IVT_IRQBASE+i,LOPRI); |
- | 89 | } |
|
90 | } |
90 | } |
91 | 91 | ||
92 | 92 | ||
93 | /* |
93 | /* |
94 | * Ensure that io_apic has unique ID. |
94 | * Ensure that io_apic has unique ID. |
Line 350... | Line 350... | ||
350 | io_apic[IOWIN] = x; |
350 | io_apic[IOWIN] = x; |
351 | } |
351 | } |
352 | 352 | ||
353 | void io_apic_change_ioredtbl(int signal, int dest, __u8 v, int flags) |
353 | void io_apic_change_ioredtbl(int signal, int dest, __u8 v, int flags) |
354 | { |
354 | { |
355 | __u32 reglo, reghi; |
355 | io_redirection_reg_t reg; |
356 | int dlvr = 0; |
356 | int dlvr = 0; |
357 | 357 | ||
358 | if (flags & LOPRI) |
358 | if (flags & LOPRI) |
359 | dlvr = 1; |
359 | dlvr = DELMOD_LOWPRI; |
- | 360 | ||
360 | 361 | ||
361 | reglo = io_apic_read(IOREDTBL + signal*2); |
362 | reg.lo = io_apic_read(IOREDTBL + signal*2); |
362 | reghi = io_apic_read(IOREDTBL + signal*2 + 1); |
363 | reg.hi = io_apic_read(IOREDTBL + signal*2 + 1); |
363 | 364 | ||
364 | reghi &= ~0x0f000000; |
365 | reg.dest = dest; |
365 | reghi |= (dest<<24); |
366 | reg.destmod = DESTMOD_LOGIC; |
366 | - | ||
367 | reglo &= (~0x1ffff) | (1<<16); /* don't touch the mask */ |
367 | reg.trigger_mode = TRIGMOD_EDGE; |
368 | reglo |= (0<<15) | (0<<13) | (0<<11) | (dlvr<<8) | v; |
368 | reg.intpol = POLARITY_HIGH; |
- | 369 | reg.delmod = dlvr; |
|
- | 370 | reg.intvec = v; |
|
369 | 371 | ||
370 | io_apic_write(IOREDTBL + signal*2, reglo); |
372 | io_apic_write(IOREDTBL + signal*2, reg.lo); |
371 | io_apic_write(IOREDTBL + signal*2 + 1, reghi); |
373 | io_apic_write(IOREDTBL + signal*2 + 1, reg.hi); |
372 | } |
374 | } |
373 | 375 | ||
374 | void io_apic_disable_irqs(__u16 irqmask) |
376 | void io_apic_disable_irqs(__u16 irqmask) |
375 | { |
377 | { |
- | 378 | io_redirection_reg_t reg; |
|
376 | int i,pin; |
379 | int i, pin; |
377 | __u32 reglo; |
- | |
378 | 380 | ||
379 | for (i=0;i<16;i++) { |
381 | for (i=0;i<16;i++) { |
380 | if ((irqmask>>i) & 1) { |
382 | if ((irqmask>>i) & 1) { |
381 | /* |
383 | /* |
382 | * Mask the signal input in IO APIC if there is a |
384 | * Mask the signal input in IO APIC if there is a |
383 | * mapping for the respective IRQ number. |
385 | * mapping for the respective IRQ number. |
384 | */ |
386 | */ |
385 | pin = mps_irq_to_pin(i); |
387 | pin = smp_irq_to_pin(i); |
386 | if (pin != -1) { |
388 | if (pin != -1) { |
387 | reglo = io_apic_read(IOREDTBL + pin*2); |
389 | reg.lo = io_apic_read(IOREDTBL + pin*2); |
388 | reglo |= (1<<16); |
390 | reg.masked = true; |
389 | io_apic_write(IOREDTBL + pin*2,reglo); |
391 | io_apic_write(IOREDTBL + pin*2, reg.lo); |
390 | } |
392 | } |
391 | 393 | ||
392 | } |
394 | } |
393 | } |
395 | } |
394 | } |
396 | } |
395 | 397 | ||
396 | void io_apic_enable_irqs(__u16 irqmask) |
398 | void io_apic_enable_irqs(__u16 irqmask) |
397 | { |
399 | { |
398 | int i,pin; |
400 | int i, pin; |
399 | __u32 reglo; |
401 | io_redirection_reg_t reg; |
400 | 402 | ||
401 | for (i=0;i<16;i++) { |
403 | for (i=0;i<16;i++) { |
402 | if ((irqmask>>i) & 1) { |
404 | if ((irqmask>>i) & 1) { |
403 | /* |
405 | /* |
404 | * Unmask the signal input in IO APIC if there is a |
406 | * Unmask the signal input in IO APIC if there is a |
405 | * mapping for the respective IRQ number. |
407 | * mapping for the respective IRQ number. |
406 | */ |
408 | */ |
407 | pin = mps_irq_to_pin(i); |
409 | pin = smp_irq_to_pin(i); |
408 | if (pin != -1) { |
410 | if (pin != -1) { |
409 | reglo = io_apic_read(IOREDTBL + pin*2); |
411 | reg.lo = io_apic_read(IOREDTBL + pin*2); |
410 | reglo &= ~(1<<16); |
412 | reg.masked = false; |
411 | io_apic_write(IOREDTBL + pin*2,reglo); |
413 | io_apic_write(IOREDTBL + pin*2, reg.lo); |
412 | } |
414 | } |
413 | 415 | ||
414 | } |
416 | } |
415 | } |
417 | } |
416 | 418 |