1/* 2 * Copyright 2014, General Dynamics C4 Systems 3 * 4 * This software may be distributed and modified according to the terms of 5 * the GNU General Public License version 2. Note that NO WARRANTY is provided. 6 * See "LICENSE_GPLv2.txt" for details. 7 * 8 * @TAG(GD_GPL) 9 */ 10 11#include <linker.h> 12#include <machine/io.h> 13#include <plat/machine/hardware.h> 14#include <plat/machine/pic.h> 15 16/* PIC (i8259) base registers */ 17#define PIC1_BASE 0x20 18#define PIC2_BASE 0xa0 19 20/* Program PIC (i8259) to remap IRQs 0-15 to interrupt vectors starting at 'interrupt' */ 21BOOT_CODE void 22pic_remap_irqs(interrupt_t interrupt) 23{ 24 out8(PIC1_BASE, 0x11); 25 out8(PIC2_BASE, 0x11); 26 out8(PIC1_BASE + 1, interrupt); 27 out8(PIC2_BASE + 1, interrupt + 8); 28 out8(PIC1_BASE + 1, 0x04); 29 out8(PIC2_BASE + 1, 0x02); 30 out8(PIC1_BASE + 1, 0x01); 31 out8(PIC2_BASE + 1, 0x01); 32 out8(PIC1_BASE + 1, 0x0); 33 out8(PIC2_BASE + 1, 0x0); 34} 35 36BOOT_CODE void pic_disable(void) 37{ 38 /* We assume that pic_remap_irqs has already been called and 39 * just mask all the irqs */ 40 out8(PIC1_BASE + 1, 0xff); 41 out8(PIC2_BASE + 1, 0xff); 42} 43 44void pic_mask_irq(bool_t mask, irq_t irq) 45{ 46 uint8_t bit_mask; 47 uint16_t pic_port; 48 49 assert(irq >= irq_isa_min); 50 assert(irq <= irq_isa_max); 51 52 if (irq < 8) { 53 bit_mask = BIT(irq); 54 pic_port = PIC1_BASE + 1; 55 } else { 56 bit_mask = BIT(irq - 8); 57 pic_port = PIC2_BASE + 1; 58 } 59 60 if (mask) { 61 /* Disables the interrupt */ 62 out8(pic_port, (in8(pic_port) | bit_mask)); 63 } else { 64 /* Enables the interrupt */ 65 out8(pic_port, (in8(pic_port) & ~bit_mask)); 66 } 67} 68 69bool_t pic_is_irq_pending(void) 70{ 71 /* Interrupt Request Register (IRR) - holds pending IRQs */ 72 uint8_t irr; 73 74 /* Send to PIC1's OCW3, in order to read IRR from next inb instruction */ 75 out8(PIC1_BASE, 0x0a); 76 77 /* Read IRR */ 78 irr = in8(PIC1_BASE); 79 80 /* Since slave PIC is connected to IRQ2 of master PIC, 81 * there is no need to check IRR of slave PIC. 82 */ 83 return irr != 0; 84} 85 86static uint16_t pic_get_isr(void) 87{ 88 out8(PIC1_BASE, 0x0b); 89 out8(PIC2_BASE, 0x0b); 90 return (((uint16_t)in8(PIC2_BASE)) << 8) | in8(PIC1_BASE); 91} 92 93void pic_ack_active_irq(void) 94{ 95 irq_t irq = getActiveIRQ(); 96 if (irq >= irq_isa_min + 8) { 97 /* ack slave PIC, unless we got a spurious irq 15 98 * It is spurious if the bit is not set in the ISR 99 * Even if it was spurious we will still need to 100 * acknowledge the master PIC */ 101 if (irq != irq_isa_min + 15 || (pic_get_isr() & BIT(15))) { 102 out8(PIC2_BASE, 0x20); 103 } 104 } 105 /* ack master PIC, unless we got a spurious IRQ 7 106 * It is spurious if the bit is not set in the ISR */ 107 if (irq != irq_isa_min + 7 || (pic_get_isr() & BIT(7))) { 108 out8(PIC1_BASE, 0x20); 109 } 110} 111