1/** 2 * \file 3 * \brief I/O APIC driver. 4 * 5 * Barrelfish only supports edge triggered interrupts. 6 */ 7 8/* 9 * Copyright (c) 2007, 2008, 2009, ETH Zurich. 10 * All rights reserved. 11 * 12 * This file is distributed under the terms in the attached LICENSE file. 13 * If you do not find this file, copies can be found by writing to: 14 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group. 15 */ 16 17#include <stdio.h> 18#include <barrelfish/barrelfish.h> 19#include <mm/mm.h> 20 21#include "ioapic.h" 22 23#include "acpi_debug.h" 24 25/** 26 * \brief Initialize I/O APIC. 27 * 28 * Initializes the I/O APIC pointed to by 'a', with virtual base 29 * address 'base', ID 'id' and INTI base 'irqbase'. All interrupts are 30 * masked initially and have to be unmasked individually upon use. 31 * 32 * \param a Pointer to I/O APIC structure. 33 * \param base Virtual base address for I/O APIC registers. 34 * \param id ID of I/O APIC (from ACPI). 35 * \param irqbase INTI base (from ACPI). 36 * 37 * \return 0 on success. 38 */ 39errval_t ioapic_init(struct ioapic *a, lvaddr_t base, uint8_t id, 40 uint32_t irqbase) 41{ 42 lpc_ioapic_initialize(&a->dev, (void *)base); 43 44 a->irqbase = irqbase; 45 a->initialized = 1; 46 47 // Write I/O APIC ID 48 lpc_ioapic_id_wr(&a->dev, (lpc_ioapic_id_t) { .id = id }); 49 50 // Check number of supported IRQs 51 a->nintis = lpc_ioapic_ver_rd(&a->dev).mre + 1; 52 if (a->nintis == 1) { 53 ACPI_DEBUG("Warning: I/O APIC claims only to support a single interrupt!" 54 " This is probably going to break...\n"); 55 } else { 56 ACPI_DEBUG("I/O APIC supports %d interrupts\n", a->nintis); 57 } 58 59 // Mask out all interrupts 60 for(int i = 0; i < a->nintis; i++) { 61 ioapic_toggle_inti(a, i, false); 62 } 63 64 return SYS_ERR_OK; 65} 66 67void ioapic_toggle_inti(struct ioapic *a, int inti, bool enable) 68{ 69 assert(inti >= 0 && inti < a->nintis); 70 lpc_ioapic_redir_tbl_t tbl = lpc_ioapic_redirtbl_rd(&a->dev, inti); 71 tbl.mask = enable ? 0 : 1; 72 lpc_ioapic_redirtbl_wr(&a->dev, inti, tbl); 73} 74 75void ioapic_setup_inti(struct ioapic *a, int inti, lpc_ioapic_redir_tbl_t entry) 76{ 77 assert(inti >= 0 && inti < a->nintis); 78 lpc_ioapic_redirtbl_wr(&a->dev, inti, entry); 79} 80 81void ioapic_route_inti(struct ioapic *a, int inti, uint8_t vector, uint8_t dest) 82{ 83 assert(inti >= 0 && inti < a->nintis); 84 lpc_ioapic_redir_tbl_t tbl = lpc_ioapic_redirtbl_rd(&a->dev, inti); 85 tbl.vector = vector; 86 tbl.dest = dest; 87 lpc_ioapic_redirtbl_wr(&a->dev, inti, tbl); 88} 89