/* * Copyright (C) 2014 René Kijewski * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /** * The IRQ handler of x86 boards. * * @ingroup x86-irq * @{ * @file * @author René Kijewski */ #ifndef X86_PIC_H #define X86_PIC_H #include #ifdef __cplusplus extern "C" { #endif /** * @brief Initialize the Programmable Interrupt Controller. * * This function is called during initialization by x86_startup(). * You must not call this function on your own accord. */ void x86_init_pic(void); #define X86_IRQ_COUNT (0x10) /**< Number of IRQ lines */ /** * @brief Offset of the IRQ master in the interrupt numbers. * * x86_interrupts.c expects this value to be `0x20`. Do not change. */ #define PIC_MASTER_INTERRUPT_BASE (0x20) /** * @brief Offset of the IRQ slave in the interrupt numbers. * * The whole IRQ subsystem expects the IRQ slave numbers to come immediately after the master. */ #define PIC_SLAVE_INTERRUPT_BASE (PIC_MASTER_INTERRUPT_BASE + 8) #define PIC_MASTER (0x20) #define PIC_SLAVE (0xA0) #define PIC_COMMAND (0x00) #define PIC_DATA (0x01) #define PIC_IMR (0x01) #define PIC_EOI 0x20 /**< End-of-interrupt command code */ #define PIC_READ_IRR 0x0a /**< OCW3 irq ready next CMD read */ #define PIC_READ_ISR 0x0b /**< OCW3 irq service next CMD read */ #define PIC_ICW1_ICW4 (0x01) /**< ICW4 (not) needed */ #define PIC_ICW1_SINGLE (0x02) /**< Single (cascade) mode */ #define PIC_ICW1_INTERVAL4 (0x04) /**< Call address interval 4 (8) */ #define PIC_ICW1_LEVEL (0x08) /**< Level triggered (edge) mode */ #define PIC_ICW1_INIT (0x10) /**< Initialization - required! */ #define PIC_ICW4_8086 (0x01) /**< 8086/88 (MCS-80/85) mode */ #define PIC_ICW4_AUTO (0x02) /**< Auto (normal) EOI */ #define PIC_ICW4_BUF_SLAVE (0x08) /**< Buffered mode/slave */ #define PIC_ICW4_BUF_MASTER (0x0C) /**< Buffered mode/master */ #define PIC_ICW4_SFNM (0x10) /**< Special fully nested (not) */ #define PIC_NUM_PIT (0x0) /**< IRQ line of the Programmable Interrupt Controller **/ #define PIC_NUM_KEYBOARD_CONTROLLER_1 (0x1) /**< IRQ line of the first PS/2 port **/ #define PIC_NUM_SLAVE (0x2) /**< not a valid IRQ line! */ #define PIC_NUM_RS232_2_4 (0x3) /**< IRQ line of COM 2+4 **/ #define PIC_NUM_RS232_1_3 (0x4) /**< IRQ line of COM 1+2 **/ #define PIC_NUM_LPT2 (0x5) /**< IRQ line of the secondary printer or soundcard (available for PCI) **/ #define PIC_NUM_FLOPPY (0x6) /**< IRQ line of the floppy drive. **/ #define PIC_NUM_LPT1 (0x7) /**< IRQ line of the parallel port (available for PCI) **/ #define PIC_NUM_RTC (0x8) /**< IRQ line of the Real Time Clock **/ #define PIC_NUM_9 (0x9) /**< Free to use IRQ line (available for PCI) **/ #define PIC_NUM_ATA_4 (0xa) /**< Free to use IRQ line (available for PCI) **/ #define PIC_NUM_ATA_3 (0xb) /**< Free to use IRQ line (available for PCI) **/ #define PIC_NUM_KEYBOARD_CONTROLLER_2 (0xc) /**< IRQ line of the second PS/2 port **/ #define PIC_NUM_FPU (0xd) /**< not a valid IRQ line! */ #define PIC_NUM_ATA_1 (0xe) /**< IRQ line of the primary IDE controller **/ #define PIC_NUM_ATA_2 (0xf) /**< IRQ line of the secondary IDQ controller **/ #define PIC_MASK_PIT (1 << PIC_NUM_PIT) #define PIC_MASK_KEYBOARD_CONTROLLER_1 (1 << PIC_NUM_KEYBOARD_CONTROLLER_1) #define PIC_MASK_SLAVE (1 << PIC_NUM_SLAVE) #define PIC_MASK_RS232_2_4 (1 << PIC_NUM_RS232_2_4) #define PIC_MASK_RS232_1_3 (1 << PIC_NUM_RS232_1_3) #define PIC_MASK_LPT2 (1 << PIC_NUM_LPT2) #define PIC_MASK_FLOPPY (1 << PIC_NUM_FLOPPY) #define PIC_MASK_LPT1 (1 << PIC_NUM_LPT1) #define PIC_MASK_RTC (1 << PIC_NUM_RTC) #define PIC_MASK_9 (1 << PIC_NUM_9) #define PIC_MASK_ATA_4 (1 << PIC_NUM_ATA_4) #define PIC_MASK_ATA_3 (1 << PIC_NUM_ATA_3) #define PIC_MASK_KEYBOARD_CONTROLLER_2 (1 << PIC_NUM_KEYBOARD_CONTROLLER_2) #define PIC_MASK_FPU (1 << PIC_NUM_FPU) #define PIC_MASK_ATA_1 (1 << PIC_NUM_ATA_1) #define PIC_MASK_ATA_2 (1 << PIC_NUM_ATA_2) /** * @brief Callback handler if there was an interrupt on this IRQ line. * @param irq_num IRQ line in question. * * This callback is called out of the interrupt handler (irq_is_in() == true). * Lengthy operations should be handled in a dedicated thread; use msg_send_int(). * You must no enable interrupt inside the handler. */ typedef void (*x86_irq_handler_t)(uint8_t irq_num); /** * @brief Set callback function for an IRQ line. * @param handler The callback function, or NULL to do nothing. * * Setting a handler does not enable the interrupt. * Use x86_pic_enable_irq() or x86_pic_disable_irq() accordingly. * * This function must only be called with interrupts disabled. * * Beware on unsetting interrupt handlers: * The PIC default handler will still send an EOI. * Especially the keyboard controller does not like it, * if it is told that everything was done but it wasn't. * A raised #X86_INT_GP might be the least of your problems. */ void x86_pic_set_handler(unsigned irq, x86_irq_handler_t handler); /** * @brief Set the enabled IRQs * * Beware: this is the exact opposite of masking IRQs. * * This function should only be called by other subsystems like the PCI subsystem. */ void x86_pic_set_enabled_irqs(uint16_t mask); /** * @brief Enable (unmask) an IRQ * * This function should only be called by other subsystems like the PCI subsystem. */ void x86_pic_enable_irq(unsigned num); /** * @brief Disable (mask) an IRQ * * This function should only be called by other subsystems like the PCI subsystem. */ void x86_pic_disable_irq(unsigned num); #ifdef __cplusplus } #endif #endif /* X86_PIC_H */ /** @} */