/* * pic_apic.c - APIC PIC driver implementation * * Copyright (c) 2017 Maxime Villard * * This file is part of ALMOS-MKH. * * ALMOS-MKH is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2.0 of the License. * * ALMOS-MKH 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 * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ALMOS-MKH; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include extern iopic_input_t iopic_input; static void idt_set_seg(struct idt_seg *seg, void *func, int ist, int type, int dpl, int sel) { seg->gd_looffset = (uint64_t)func & 0xffff; seg->gd_selector = sel; seg->gd_ist = ist; seg->gd_type = type; seg->gd_dpl = dpl; seg->gd_p = 1; seg->gd_hioffset = (uint64_t)func >> 16; seg->gd_zero = 0; seg->gd_xx1 = 0; seg->gd_xx2 = 0; seg->gd_xx3 = 0; } /* -------------------------------------------------------------------------- */ extern uint8_t *idtstore; void pic_apic_init(chdev_t *pic) { /* XXX APIC already initialized earlier */ } void pic_apic_extend_init(uint32_t *xcu_base) { x86_panic((char *)__func__); } void pic_apic_bind_irq(lid_t lid, chdev_t *src_chdev) { struct idt_seg seg, *idt; void *isr; int slot; /* get the source chdev functional type, channel, and direction */ uint32_t func = src_chdev->func; uint32_t channel = src_chdev->channel; /* get external IRQ index */ uint32_t irq_id; if (func == DEV_FUNC_IOC) irq_id = iopic_input.ioc[channel]; else if (func == DEV_FUNC_TXT) irq_id = iopic_input.txt[channel]; else assert(false, __FUNCTION__, "unsupported device\n"); /* get the ISR pointer */ isr = src_chdev->isr; /* create the IDT entry, and register it */ idt_set_seg(&seg, isr, 0, SDT_SYS386IGT, SEL_KPL, GDT_FIXED_SEL(GDT_KCODE_SEL, SEL_KPL)); slot = idt_slot_alloc(); idt = (struct idt_seg *)&idtstore; memcpy(&idt[slot], &seg, sizeof(struct idt_seg)); /* Bind the IRQ line in IOAPIC */ hal_ioapic_bind_irq(irq_id, slot, lid); x86_printf("-> allocated %z\n", (uint64_t)slot); } void pic_apic_enable_irq(lid_t lid, xptr_t src_chdev_xp) { chdev_t *src_chdev = (chdev_t *)src_chdev_xp; uint32_t func = src_chdev->func; uint32_t channel = src_chdev->channel; uint32_t irq_id; /* get external IRQ index */ if (func == DEV_FUNC_IOC) irq_id = iopic_input.ioc[channel]; else if (func == DEV_FUNC_TXT) irq_id = iopic_input.txt[channel]; else assert(false, __FUNCTION__, "unsupported device\n"); /* enable the line */ hal_ioapic_enable_irq(irq_id); } void pic_apic_disable_irq(lid_t lid, xptr_t src_chdev_xp) { chdev_t *src_chdev = (chdev_t *)src_chdev_xp; uint32_t func = src_chdev->func; uint32_t channel = src_chdev->channel; uint32_t irq_id; /* get external IRQ index */ if (func == DEV_FUNC_IOC) irq_id = iopic_input.ioc[channel]; else if (func == DEV_FUNC_TXT) irq_id = iopic_input.txt[channel]; else assert(false, __FUNCTION__, "unsupported device\n"); /* disable the line */ hal_ioapic_disable_irq(irq_id); } void pic_apic_enable_timer(uint32_t period) { x86_panic((char *)__func__); } void pic_apic_enable_ipi() { x86_panic((char *)__func__); } void pic_apic_send_ipi(cxy_t cxy, lid_t lid) { x86_panic((char *)__func__); }