1845a180fSFrançois Revol /* 2845a180fSFrançois Revol * Copyright 2003-2006, Haiku Inc. All rights reserved. 3845a180fSFrançois Revol * Distributed under the terms of the MIT License. 4845a180fSFrançois Revol * 5845a180fSFrançois Revol * Authors: 6845a180fSFrançois Revol * Axel Dörfler <axeld@pinc-software.de> 7845a180fSFrançois Revol * Ingo Weinhold <bonefish@cs.tu-berlin.de> 84e44040dSFrançois Revol * François Revol <revol@free.fr> 94e44040dSFrançois Revol * Distributed under the terms of the MIT License. 104e44040dSFrançois Revol * 11845a180fSFrançois Revol * 12845a180fSFrançois Revol * Copyright 2001, Travis Geiselbrecht. All rights reserved. 13845a180fSFrançois Revol * Distributed under the terms of the NewOS License. 14845a180fSFrançois Revol */ 15845a180fSFrançois Revol 16845a180fSFrançois Revol #include <int.h> 17845a180fSFrançois Revol 1860b11851SFrançois Revol #include <arch_platform.h> 19845a180fSFrançois Revol #include <arch/smp.h> 20845a180fSFrançois Revol #include <boot/kernel_args.h> 21845a180fSFrançois Revol #include <device_manager.h> 22845a180fSFrançois Revol #include <kscheduler.h> 23845a180fSFrançois Revol #include <interrupt_controller.h> 24845a180fSFrançois Revol #include <smp.h> 25845a180fSFrançois Revol #include <thread.h> 26845a180fSFrançois Revol #include <timer.h> 27845a180fSFrançois Revol #include <util/DoublyLinkedList.h> 28845a180fSFrançois Revol #include <util/kernel_cpp.h> 29845a180fSFrançois Revol #include <vm.h> 30845a180fSFrançois Revol #include <vm_address_space.h> 31845a180fSFrançois Revol #include <vm_priv.h> 32845a180fSFrançois Revol #include <string.h> 3335471ac5SFrançois Revol 344e44040dSFrançois Revol #warning M68K: writeme! 35845a180fSFrançois Revol 3635471ac5SFrançois Revol 3735471ac5SFrançois Revol //#define TRACE_ARCH_INT 3835471ac5SFrançois Revol #ifdef TRACE_ARCH_INT 3935471ac5SFrançois Revol # define TRACE(x) dprintf x 4035471ac5SFrançois Revol #else 4135471ac5SFrançois Revol # define TRACE(x) ; 4235471ac5SFrançois Revol #endif 4335471ac5SFrançois Revol 4435471ac5SFrançois Revol typedef void (*m68k_exception_handler)(void); 4535471ac5SFrançois Revol #define M68K_EXCEPTION_VECTOR_COUNT 256 4630629f41SFrançois Revol #warning M68K: align on 4 ? 4736ee9f5cSFrançois Revol //m68k_exception_handler gExceptionVectors[M68K_EXCEPTION_VECTOR_COUNT]; 4836ee9f5cSFrançois Revol m68k_exception_handler *gExceptionVectors; 4935471ac5SFrançois Revol 50845a180fSFrançois Revol // defined in arch_exceptions.S 5135471ac5SFrançois Revol extern "C" void __m68k_exception_noop(void); 5235471ac5SFrançois Revol extern "C" void __m68k_exception_common(void); 5335471ac5SFrançois Revol 54845a180fSFrançois Revol extern int __irqvec_start; 55845a180fSFrançois Revol extern int __irqvec_end; 56845a180fSFrançois Revol 57845a180fSFrançois Revol extern"C" void m68k_exception_tail(void); 58845a180fSFrançois Revol 5930629f41SFrançois Revol // current fault handler 6030629f41SFrançois Revol addr_t gFaultHandler; 61845a180fSFrançois Revol 62845a180fSFrançois Revol // An iframe stack used in the early boot process when we don't have 63845a180fSFrançois Revol // threads yet. 64845a180fSFrançois Revol struct iframe_stack gBootFrameStack; 65845a180fSFrançois Revol 66845a180fSFrançois Revol // interrupt controller interface (initialized 67845a180fSFrançois Revol // in arch_int_init_post_device_manager()) 6860b11851SFrançois Revol //static struct interrupt_controller_module_info *sPIC; 6960b11851SFrançois Revol //static void *sPICCookie; 70845a180fSFrançois Revol 71845a180fSFrançois Revol 72845a180fSFrançois Revol void 73845a180fSFrançois Revol arch_int_enable_io_interrupt(int irq) 74845a180fSFrançois Revol { 7560b11851SFrançois Revol //if (!sPIC) 7660b11851SFrançois Revol // return; 77845a180fSFrançois Revol 78845a180fSFrançois Revol // TODO: I have no idea, what IRQ type is appropriate. 7960b11851SFrançois Revol //sPIC->enable_io_interrupt(sPICCookie, irq, IRQ_TYPE_LEVEL); 8060b11851SFrançois Revol M68KPlatform::Default()->EnableIOInterrupt(irq); 81845a180fSFrançois Revol } 82845a180fSFrançois Revol 83845a180fSFrançois Revol 84845a180fSFrançois Revol void 85845a180fSFrançois Revol arch_int_disable_io_interrupt(int irq) 86845a180fSFrançois Revol { 8760b11851SFrançois Revol //if (!sPIC) 8860b11851SFrançois Revol // return; 89845a180fSFrançois Revol 9060b11851SFrançois Revol //sPIC->disable_io_interrupt(sPICCookie, irq); 9160b11851SFrançois Revol M68KPlatform::Default()->DisableIOInterrupt(irq); 92845a180fSFrançois Revol } 93845a180fSFrançois Revol 94845a180fSFrançois Revol 95845a180fSFrançois Revol /* arch_int_*_interrupts() and friends are in arch_asm.S */ 96845a180fSFrançois Revol 97845a180fSFrançois Revol 98845a180fSFrançois Revol static void 99845a180fSFrançois Revol print_iframe(struct iframe *frame) 100845a180fSFrançois Revol { 101845a180fSFrançois Revol dprintf("iframe at %p:\n", frame); 1024e44040dSFrançois Revol dprintf(" d0 0x%08lx d1 0x%08lx d2 0x%08lx d3 0x%08lx\n", 10382610ec8SFrançois Revol frame->d[0], frame->d[1], frame->d[2], frame->d[3]); 1044e44040dSFrançois Revol kprintf(" d4 0x%08lx d5 0x%08lx d6 0x%08lx d7 0x%08lx\n", 10582610ec8SFrançois Revol frame->d[4], frame->d[5], frame->d[6], frame->d[7]); 1064e44040dSFrançois Revol kprintf(" a0 0x%08lx a1 0x%08lx a2 0x%08lx a3 0x%08lx\n", 10782610ec8SFrançois Revol frame->a[0], frame->a[1], frame->a[2], frame->a[3]); 10882610ec8SFrançois Revol kprintf(" a4 0x%08lx a5 0x%08lx a6 0x%08lx "/*"a7 0x%08lx (sp)"*/"\n", 10982610ec8SFrançois Revol frame->a[4], frame->a[5], frame->a[6]/*, frame->a[7]*/); 1104e44040dSFrançois Revol 1114e44040dSFrançois Revol /*kprintf(" pc 0x%08lx ccr 0x%02x\n", 1124e44040dSFrançois Revol frame->pc, frame->ccr);*/ 1134e44040dSFrançois Revol kprintf(" pc 0x%08lx sr 0x%04x\n", 11430629f41SFrançois Revol frame->cpu.pc, frame->cpu.sr); 1159a507b45SFrançois Revol #if 0 1164e44040dSFrançois Revol dprintf("r0-r3: 0x%08lx 0x%08lx 0x%08lx 0x%08lx\n", frame->d0, frame->d1, frame->d2, frame->d3); 1174e44040dSFrançois Revol dprintf("r4-r7: 0x%08lx 0x%08lx 0x%08lx 0x%08lx\n", frame->d4, frame->d5, frame->d6, frame->d7); 1184e44040dSFrançois Revol dprintf("r8-r11: 0x%08lx 0x%08lx 0x%08lx 0x%08lx\n", frame->a0, frame->a1, frame->a2, frame->a3); 1194e44040dSFrançois Revol dprintf("r12-r15: 0x%08lx 0x%08lx 0x%08lx 0x%08lx\n", frame->a4, frame->a5, frame->a6, frame->a7); 1204e44040dSFrançois Revol dprintf(" pc 0x%08lx sr 0x%08lx\n", frame->pc, frame->sr); 1219a507b45SFrançois Revol #endif 122845a180fSFrançois Revol } 123845a180fSFrançois Revol 12430629f41SFrançois Revol static addr_t 12530629f41SFrançois Revol fault_address(struct iframe *iframe) 12630629f41SFrançois Revol { 12730629f41SFrançois Revol switch (iframe->cpu.type) { 12830629f41SFrançois Revol case 0x0: 12930629f41SFrançois Revol case 0x1: 13030629f41SFrançois Revol return 0; 13130629f41SFrançois Revol case 0x2: 13230629f41SFrançois Revol return iframe->cpu.type_2.instruction_address; 13330629f41SFrançois Revol case 0x3: 13430629f41SFrançois Revol return iframe->cpu.type_3.effective_address; 13530629f41SFrançois Revol case 0x7: 13630629f41SFrançois Revol return iframe->cpu.type_7.effective_address; 13730629f41SFrançois Revol case 0x9: 13830629f41SFrançois Revol return iframe->cpu.type_9.instruction_address; 13930629f41SFrançois Revol case 0xa: 14030629f41SFrançois Revol return iframe->cpu.type_a.fault_address; 14130629f41SFrançois Revol case 0xb: 14230629f41SFrançois Revol return iframe->cpu.type_b.fault_address; 14330629f41SFrançois Revol default: 14430629f41SFrançois Revol return 0; 14530629f41SFrançois Revol } 14630629f41SFrançois Revol } 14730629f41SFrançois Revol 14830629f41SFrançois Revol static bool 14930629f41SFrançois Revol fault_was_write(struct iframe *iframe) 15030629f41SFrançois Revol { 15130629f41SFrançois Revol switch (iframe->cpu.type) { 15230629f41SFrançois Revol case 0x7: 15330629f41SFrançois Revol return !iframe->cpu.type_7.ssw.rw; 15430629f41SFrançois Revol case 0xa: 15530629f41SFrançois Revol return !iframe->cpu.type_a.ssw.rw; 15630629f41SFrançois Revol case 0xb: 15730629f41SFrançois Revol return !iframe->cpu.type_b.ssw.rw; 15830629f41SFrançois Revol default: 15930629f41SFrançois Revol panic("can't determine r/w from iframe type %d\n", 16030629f41SFrançois Revol iframe->cpu.type); 16130629f41SFrançois Revol return false; 16230629f41SFrançois Revol } 16330629f41SFrançois Revol } 164845a180fSFrançois Revol 16535471ac5SFrançois Revol extern "C" void m68k_exception_entry(struct iframe *iframe); 166845a180fSFrançois Revol void 16735471ac5SFrançois Revol m68k_exception_entry(struct iframe *iframe) 168845a180fSFrançois Revol { 16935471ac5SFrançois Revol int vector = iframe->cpu.vector >> 2; 170845a180fSFrançois Revol int ret = B_HANDLED_INTERRUPT; 1715222f12aSFrançois Revol bool hardwareInterrupt = false; 172845a180fSFrançois Revol 17335471ac5SFrançois Revol if (vector != -1) { 174845a180fSFrançois Revol dprintf("m68k_exception_entry: time %lld vector 0x%x, iframe %p, " 17535471ac5SFrançois Revol "pc: %p\n", system_time(), vector, iframe, (void*)iframe->cpu.pc); 176845a180fSFrançois Revol } 177845a180fSFrançois Revol 178845a180fSFrançois Revol struct thread *thread = thread_get_current_thread(); 179845a180fSFrançois Revol 180845a180fSFrançois Revol // push iframe 181845a180fSFrançois Revol if (thread) 182845a180fSFrançois Revol m68k_push_iframe(&thread->arch_info.iframes, iframe); 183845a180fSFrançois Revol else 184845a180fSFrançois Revol m68k_push_iframe(&gBootFrameStack, iframe); 185845a180fSFrançois Revol 186845a180fSFrançois Revol switch (vector) { 18735471ac5SFrançois Revol case 0: // system reset 188845a180fSFrançois Revol panic("system reset exception\n"); 189845a180fSFrançois Revol break; 19035471ac5SFrançois Revol case 2: // bus error 19135471ac5SFrançois Revol case 3: // address error 192845a180fSFrançois Revol { 193845a180fSFrançois Revol bool kernelDebugger = debug_debugger_running(); 194845a180fSFrançois Revol 195845a180fSFrançois Revol if (kernelDebugger) { 196845a180fSFrançois Revol // if this thread has a fault handler, we're allowed to be here 19730629f41SFrançois Revol if (thread && thread->fault_handler != 0) { 19830629f41SFrançois Revol iframe->cpu.pc = thread->fault_handler; 199845a180fSFrançois Revol break; 200845a180fSFrançois Revol } 201845a180fSFrançois Revol 20230629f41SFrançois Revol 203845a180fSFrançois Revol // otherwise, not really 204845a180fSFrançois Revol panic("page fault in debugger without fault handler! Touching " 20530629f41SFrançois Revol "address %p from ip %p\n", (void *)fault_address(iframe), 20630629f41SFrançois Revol (void *)iframe->cpu.pc); 207845a180fSFrançois Revol break; 20830629f41SFrançois Revol } else if ((iframe->cpu.sr & SR_IP_MASK) != 0) { 2095222f12aSFrançois Revol // interrupts disabled 2105222f12aSFrançois Revol 2115222f12aSFrançois Revol // If a page fault handler is installed, we're allowed to be here. 2125222f12aSFrançois Revol // TODO: Now we are generally allowing user_memcpy() with interrupts 2135222f12aSFrançois Revol // disabled, which in most cases is a bug. We should add some thread 2145222f12aSFrançois Revol // flag allowing to explicitly indicate that this handling is desired. 2155222f12aSFrançois Revol if (thread && thread->fault_handler != 0) { 2165222f12aSFrançois Revol iframe->cpu.pc = thread->fault_handler; 2175222f12aSFrançois Revol return; 2185222f12aSFrançois Revol } 2195222f12aSFrançois Revol 220845a180fSFrançois Revol // if the interrupts were disabled, and we are not running the 221845a180fSFrançois Revol // kernel startup the page fault was not allowed to happen and 222845a180fSFrançois Revol // we must panic 223845a180fSFrançois Revol panic("page fault, but interrupts were disabled. Touching " 22430629f41SFrançois Revol "address %p from ip %p\n", (void *)fault_address(iframe), 22530629f41SFrançois Revol (void *)iframe->cpu.pc); 226845a180fSFrançois Revol break; 227845a180fSFrançois Revol } else if (thread != NULL && thread->page_faults_allowed < 1) { 228845a180fSFrançois Revol panic("page fault not allowed at this place. Touching address " 22930629f41SFrançois Revol "%p from ip %p\n", (void *)fault_address(iframe), 23030629f41SFrançois Revol (void *)iframe->cpu.pc); 231845a180fSFrançois Revol } 232845a180fSFrançois Revol 233845a180fSFrançois Revol enable_interrupts(); 234845a180fSFrançois Revol 235845a180fSFrançois Revol addr_t newip; 236845a180fSFrançois Revol 23730629f41SFrançois Revol ret = vm_page_fault(fault_address(iframe), iframe->cpu.pc, 23830629f41SFrançois Revol fault_was_write(iframe), // store or load 23930629f41SFrançois Revol iframe->cpu.sr & SR_S, // was the system in user or supervisor 240845a180fSFrançois Revol &newip); 241845a180fSFrançois Revol if (newip != 0) { 242845a180fSFrançois Revol // the page fault handler wants us to modify the iframe to set the 243845a180fSFrançois Revol // IP the cpu will return to to be this ip 24430629f41SFrançois Revol iframe->cpu.pc = newip; 245845a180fSFrançois Revol } 246845a180fSFrançois Revol break; 247845a180fSFrançois Revol } 248845a180fSFrançois Revol 24935471ac5SFrançois Revol case 24: // spurious interrupt 25035471ac5SFrançois Revol dprintf("spurious interrupt\n"); 25135471ac5SFrançois Revol break; 25235471ac5SFrançois Revol case 25: // autovector interrupt 25335471ac5SFrançois Revol case 26: // autovector interrupt 25435471ac5SFrançois Revol case 27: // autovector interrupt 25535471ac5SFrançois Revol case 28: // autovector interrupt 25635471ac5SFrançois Revol case 29: // autovector interrupt 25735471ac5SFrançois Revol case 30: // autovector interrupt 25835471ac5SFrançois Revol case 31: // autovector interrupt 259845a180fSFrançois Revol { 26060b11851SFrançois Revol #if 0 261845a180fSFrançois Revol if (!sPIC) { 262845a180fSFrançois Revol panic("m68k_exception_entry(): external interrupt although we " 263845a180fSFrançois Revol "don't have a PIC driver!"); 264845a180fSFrançois Revol ret = B_HANDLED_INTERRUPT; 265845a180fSFrançois Revol break; 266845a180fSFrançois Revol } 26760b11851SFrançois Revol #endif 26860b11851SFrançois Revol M68KPlatform::Default()->AcknowledgeIOInterrupt(vector); 269845a180fSFrançois Revol 270845a180fSFrançois Revol dprintf("handling I/O interrupts...\n"); 27160b11851SFrançois Revol ret = int_io_interrupt_handler(vector, true); 27260b11851SFrançois Revol #if 0 273845a180fSFrançois Revol while ((irq = sPIC->acknowledge_io_interrupt(sPICCookie)) >= 0) { 274845a180fSFrançois Revol // TODO: correctly pass level-triggered vs. edge-triggered to the handler! 275845a180fSFrançois Revol ret = int_io_interrupt_handler(irq, true); 276845a180fSFrançois Revol } 27760b11851SFrançois Revol #endif 278845a180fSFrançois Revol dprintf("handling I/O interrupts done\n"); 2795222f12aSFrançois Revol hardwareInterrupt = true; 280845a180fSFrançois Revol break; 281845a180fSFrançois Revol } 282845a180fSFrançois Revol 28335471ac5SFrançois Revol case 9: // trace 284845a180fSFrançois Revol default: 28560b11851SFrançois Revol // vectors >= 64 are user defined vectors, used for IRQ 28660b11851SFrançois Revol if (vector >= 64) { 2872fc21d4fSFrançois Revol if (M68KPlatform::Default()->AcknowledgeIOInterrupt(vector)) { 28860b11851SFrançois Revol ret = int_io_interrupt_handler(vector, true); 28960b11851SFrançois Revol break; 29060b11851SFrançois Revol } 2912fc21d4fSFrançois Revol } 292845a180fSFrançois Revol dprintf("unhandled exception type 0x%x\n", vector); 293845a180fSFrançois Revol print_iframe(iframe); 294845a180fSFrançois Revol panic("unhandled exception type\n"); 295845a180fSFrançois Revol } 296845a180fSFrançois Revol 297845a180fSFrançois Revol if (ret == B_INVOKE_SCHEDULER) { 298845a180fSFrançois Revol int state = disable_interrupts(); 299845a180fSFrançois Revol GRAB_THREAD_LOCK(); 300845a180fSFrançois Revol scheduler_reschedule(); 301845a180fSFrançois Revol RELEASE_THREAD_LOCK(); 302845a180fSFrançois Revol restore_interrupts(state); 3035222f12aSFrançois Revol } else if (hardwareInterrupt && thread->post_interrupt_callback != NULL) { 3045222f12aSFrançois Revol void (*callback)(void*) = thread->post_interrupt_callback; 3055222f12aSFrançois Revol void* data = thread->post_interrupt_data; 3065222f12aSFrançois Revol 3075222f12aSFrançois Revol thread->post_interrupt_callback = NULL; 3085222f12aSFrançois Revol thread->post_interrupt_data = NULL; 3095222f12aSFrançois Revol 3105222f12aSFrançois Revol callback(data); 311845a180fSFrançois Revol } 312845a180fSFrançois Revol 313845a180fSFrançois Revol // pop iframe 314845a180fSFrançois Revol if (thread) 315845a180fSFrançois Revol m68k_pop_iframe(&thread->arch_info.iframes); 316845a180fSFrançois Revol else 317845a180fSFrançois Revol m68k_pop_iframe(&gBootFrameStack); 318845a180fSFrançois Revol } 319845a180fSFrançois Revol 320845a180fSFrançois Revol 321845a180fSFrançois Revol status_t 322845a180fSFrançois Revol arch_int_init(kernel_args *args) 323845a180fSFrançois Revol { 32430629f41SFrançois Revol status_t err; 32530629f41SFrançois Revol addr_t vbr; 32630629f41SFrançois Revol int i; 32730629f41SFrançois Revol 32836ee9f5cSFrançois Revol gExceptionVectors = (m68k_exception_handler *)args->arch_args.vir_vbr; 32936ee9f5cSFrançois Revol 33030629f41SFrançois Revol /* fill in the vector table */ 33130629f41SFrançois Revol for (i = 0; i < M68K_EXCEPTION_VECTOR_COUNT; i++) 33230629f41SFrançois Revol gExceptionVectors[i] = &__m68k_exception_common; 33360b11851SFrançois Revol 33436ee9f5cSFrançois Revol vbr = args->arch_args.phys_vbr; 33530629f41SFrançois Revol /* point VBR to the new table */ 33636ee9f5cSFrançois Revol asm volatile ("movec %0,%%vbr" : : "r"(vbr):); 33794b1f001SFrançois Revol 338845a180fSFrançois Revol return B_OK; 339845a180fSFrançois Revol } 340845a180fSFrançois Revol 341845a180fSFrançois Revol 342845a180fSFrançois Revol status_t 343845a180fSFrançois Revol arch_int_init_post_vm(kernel_args *args) 344845a180fSFrançois Revol { 34594b1f001SFrançois Revol status_t err; 34694b1f001SFrançois Revol err = M68KPlatform::Default()->InitPIC(args); 34794b1f001SFrançois Revol return err; 348845a180fSFrançois Revol } 349845a180fSFrançois Revol 350845a180fSFrançois Revol 35130629f41SFrançois Revol #if 0 /* PIC modules */ 352845a180fSFrançois Revol template<typename ModuleInfo> 353845a180fSFrançois Revol struct Module : DoublyLinkedListLinkImpl<Module<ModuleInfo> > { 354845a180fSFrançois Revol Module(ModuleInfo *module) 355845a180fSFrançois Revol : module(module) 356845a180fSFrançois Revol { 357845a180fSFrançois Revol } 358845a180fSFrançois Revol 359845a180fSFrançois Revol ~Module() 360845a180fSFrançois Revol { 361845a180fSFrançois Revol if (module) 362845a180fSFrançois Revol put_module(((module_info*)module)->name); 363845a180fSFrançois Revol } 364845a180fSFrançois Revol 365845a180fSFrançois Revol ModuleInfo *module; 366845a180fSFrançois Revol }; 367845a180fSFrançois Revol 368845a180fSFrançois Revol typedef Module<interrupt_controller_module_info> PICModule; 369845a180fSFrançois Revol 370845a180fSFrançois Revol struct PICModuleList : DoublyLinkedList<PICModule> { 371845a180fSFrançois Revol ~PICModuleList() 372845a180fSFrançois Revol { 373845a180fSFrançois Revol while (PICModule *module = First()) { 374845a180fSFrançois Revol Remove(module); 375845a180fSFrançois Revol delete module; 376845a180fSFrançois Revol } 377845a180fSFrançois Revol } 378845a180fSFrançois Revol }; 379845a180fSFrançois Revol 380845a180fSFrançois Revol 381845a180fSFrançois Revol class DeviceTreeIterator { 382845a180fSFrançois Revol public: 383845a180fSFrançois Revol DeviceTreeIterator(device_manager_info *deviceManager) 384845a180fSFrançois Revol : fDeviceManager(deviceManager), 385845a180fSFrançois Revol fNode(NULL), 386845a180fSFrançois Revol fParent(NULL) 387845a180fSFrançois Revol { 388845a180fSFrançois Revol Rewind(); 389845a180fSFrançois Revol } 390845a180fSFrançois Revol 391845a180fSFrançois Revol ~DeviceTreeIterator() 392845a180fSFrançois Revol { 393845a180fSFrançois Revol if (fParent != NULL) 394845a180fSFrançois Revol fDeviceManager->put_device_node(fParent); 395845a180fSFrançois Revol if (fNode != NULL) 396845a180fSFrançois Revol fDeviceManager->put_device_node(fNode); 397845a180fSFrançois Revol } 398845a180fSFrançois Revol 399845a180fSFrançois Revol void Rewind() 400845a180fSFrançois Revol { 401845a180fSFrançois Revol fNode = fDeviceManager->get_root(); 402845a180fSFrançois Revol } 403845a180fSFrançois Revol 404845a180fSFrançois Revol bool HasNext() const 405845a180fSFrançois Revol { 406845a180fSFrançois Revol return (fNode != NULL); 407845a180fSFrançois Revol } 408845a180fSFrançois Revol 409845a180fSFrançois Revol device_node_handle Next() 410845a180fSFrançois Revol { 411845a180fSFrançois Revol if (fNode == NULL) 412845a180fSFrançois Revol return NULL; 413845a180fSFrançois Revol 414845a180fSFrançois Revol device_node_handle foundNode = fNode; 415845a180fSFrançois Revol 416845a180fSFrançois Revol // get first child 417845a180fSFrançois Revol device_node_handle child = NULL; 418845a180fSFrançois Revol if (fDeviceManager->get_next_child_device(fNode, &child, NULL) 419845a180fSFrançois Revol == B_OK) { 420845a180fSFrançois Revol // move to the child node 421845a180fSFrançois Revol if (fParent != NULL) 422845a180fSFrançois Revol fDeviceManager->put_device_node(fParent); 423845a180fSFrançois Revol fParent = fNode; 424845a180fSFrançois Revol fNode = child; 425845a180fSFrançois Revol 426845a180fSFrançois Revol // no more children; backtrack to find the next sibling 427845a180fSFrançois Revol } else { 428845a180fSFrançois Revol while (fParent != NULL) { 429845a180fSFrançois Revol if (fDeviceManager->get_next_child_device(fParent, &fNode, NULL) 430845a180fSFrançois Revol == B_OK) { 431845a180fSFrançois Revol // get_next_child_device() always puts the node 432845a180fSFrançois Revol break; 433845a180fSFrançois Revol } 434845a180fSFrançois Revol fNode = fParent; 435845a180fSFrançois Revol fParent = fDeviceManager->get_parent(fNode); 436845a180fSFrançois Revol } 437845a180fSFrançois Revol 438845a180fSFrançois Revol // if we hit the root node again, we're done 439845a180fSFrançois Revol if (fParent == NULL) { 440845a180fSFrançois Revol fDeviceManager->put_device_node(fNode); 441845a180fSFrançois Revol fNode = NULL; 442845a180fSFrançois Revol } 443845a180fSFrançois Revol } 444845a180fSFrançois Revol 445845a180fSFrançois Revol return foundNode; 446845a180fSFrançois Revol } 447845a180fSFrançois Revol 448845a180fSFrançois Revol private: 449845a180fSFrançois Revol device_manager_info *fDeviceManager; 450845a180fSFrançois Revol device_node_handle fNode; 451845a180fSFrançois Revol device_node_handle fParent; 452845a180fSFrançois Revol }; 453845a180fSFrançois Revol 454845a180fSFrançois Revol 455845a180fSFrançois Revol static void 456845a180fSFrançois Revol get_interrupt_controller_modules(PICModuleList &list) 457845a180fSFrançois Revol { 458845a180fSFrançois Revol const char *namePrefix = "interrupt_controllers/"; 459845a180fSFrançois Revol size_t namePrefixLen = strlen(namePrefix); 460845a180fSFrançois Revol 461845a180fSFrançois Revol char name[B_PATH_NAME_LENGTH]; 462845a180fSFrançois Revol size_t length; 463845a180fSFrançois Revol uint32 cookie = 0; 464845a180fSFrançois Revol while (get_next_loaded_module_name(&cookie, name, &(length = sizeof(name))) 465845a180fSFrançois Revol == B_OK) { 466845a180fSFrançois Revol // an interrupt controller module? 467845a180fSFrançois Revol if (length <= namePrefixLen 468845a180fSFrançois Revol || strncmp(name, namePrefix, namePrefixLen) != 0) { 469845a180fSFrançois Revol continue; 470845a180fSFrançois Revol } 471845a180fSFrançois Revol 472845a180fSFrançois Revol // get the module 473845a180fSFrançois Revol interrupt_controller_module_info *moduleInfo; 474845a180fSFrançois Revol if (get_module(name, (module_info**)&moduleInfo) != B_OK) 475845a180fSFrançois Revol continue; 476845a180fSFrançois Revol 477845a180fSFrançois Revol // add it to the list 478845a180fSFrançois Revol PICModule *module = new(nothrow) PICModule(moduleInfo); 479845a180fSFrançois Revol if (!module) { 480845a180fSFrançois Revol put_module(((module_info*)moduleInfo)->name); 481845a180fSFrançois Revol continue; 482845a180fSFrançois Revol } 483845a180fSFrançois Revol list.Add(module); 484845a180fSFrançois Revol } 485845a180fSFrançois Revol } 486845a180fSFrançois Revol 487845a180fSFrançois Revol 488845a180fSFrançois Revol static bool 489845a180fSFrançois Revol probe_pic_device(device_node_handle node, PICModuleList &picModules) 490845a180fSFrançois Revol { 491845a180fSFrançois Revol for (PICModule *module = picModules.Head(); 492845a180fSFrançois Revol module; 493845a180fSFrançois Revol module = picModules.GetNext(module)) { 494845a180fSFrançois Revol bool noConnection; 495845a180fSFrançois Revol if (module->module->info.supports_device(node, &noConnection) > 0) { 496845a180fSFrançois Revol if (module->module->info.register_device(node) == B_OK) 497845a180fSFrançois Revol return true; 498845a180fSFrançois Revol } 499845a180fSFrançois Revol } 500845a180fSFrançois Revol 501845a180fSFrançois Revol return false; 502845a180fSFrançois Revol } 50330629f41SFrançois Revol #endif /* PIC modules */ 504845a180fSFrançois Revol 505845a180fSFrançois Revol status_t 506845a180fSFrançois Revol arch_int_init_post_device_manager(struct kernel_args *args) 507845a180fSFrançois Revol { 50830629f41SFrançois Revol #if 0 /* PIC modules */ 509845a180fSFrançois Revol // get the interrupt controller driver modules 510845a180fSFrançois Revol PICModuleList picModules; 511845a180fSFrançois Revol get_interrupt_controller_modules(picModules); 512845a180fSFrançois Revol if (picModules.IsEmpty()) { 513845a180fSFrançois Revol panic("arch_int_init_post_device_manager(): Found no PIC modules!"); 514845a180fSFrançois Revol return B_ENTRY_NOT_FOUND; 515845a180fSFrançois Revol } 516845a180fSFrançois Revol 517845a180fSFrançois Revol // get the device manager module 518845a180fSFrançois Revol device_manager_info *deviceManager; 519845a180fSFrançois Revol status_t error = get_module(B_DEVICE_MANAGER_MODULE_NAME, 520845a180fSFrançois Revol (module_info**)&deviceManager); 521845a180fSFrançois Revol if (error != B_OK) { 522845a180fSFrançois Revol panic("arch_int_init_post_device_manager(): Failed to get device " 523845a180fSFrançois Revol "manager: %s", strerror(error)); 524845a180fSFrançois Revol return error; 525845a180fSFrançois Revol } 526845a180fSFrançois Revol Module<device_manager_info> _deviceManager(deviceManager); // auto put 527845a180fSFrançois Revol 528845a180fSFrançois Revol // iterate through the device tree and probe the interrupt controllers 529845a180fSFrançois Revol DeviceTreeIterator iterator(deviceManager); 530845a180fSFrançois Revol while (device_node_handle node = iterator.Next()) 531845a180fSFrançois Revol probe_pic_device(node, picModules); 532845a180fSFrançois Revol 533845a180fSFrançois Revol // iterate through the tree again and get an interrupt controller node 534845a180fSFrançois Revol iterator.Rewind(); 535845a180fSFrançois Revol while (device_node_handle node = iterator.Next()) { 536845a180fSFrançois Revol char *deviceType; 537845a180fSFrançois Revol if (deviceManager->get_attr_string(node, B_DRIVER_DEVICE_TYPE, 538845a180fSFrançois Revol &deviceType, false) == B_OK) { 539845a180fSFrançois Revol bool isPIC 540845a180fSFrançois Revol = (strcmp(deviceType, B_INTERRUPT_CONTROLLER_DRIVER_TYPE) == 0); 541845a180fSFrançois Revol free(deviceType); 542845a180fSFrançois Revol 543845a180fSFrançois Revol if (isPIC) { 544845a180fSFrançois Revol driver_module_info *driver; 545845a180fSFrançois Revol void *driverCookie; 546845a180fSFrançois Revol error = deviceManager->init_driver(node, NULL, &driver, 547845a180fSFrançois Revol &driverCookie); 548845a180fSFrançois Revol if (error == B_OK) { 549845a180fSFrançois Revol sPIC = (interrupt_controller_module_info *)driver; 550845a180fSFrançois Revol sPICCookie = driverCookie; 551845a180fSFrançois Revol return B_OK; 552845a180fSFrançois Revol } 553845a180fSFrançois Revol } 554845a180fSFrançois Revol } 555845a180fSFrançois Revol } 556845a180fSFrançois Revol 55730629f41SFrançois Revol #endif /* PIC modules */ 55830629f41SFrançois Revol 559845a180fSFrançois Revol // no PIC found 560845a180fSFrançois Revol panic("arch_int_init_post_device_manager(): Found no supported PIC!"); 561845a180fSFrançois Revol 562845a180fSFrançois Revol return B_ENTRY_NOT_FOUND; 563845a180fSFrançois Revol } 564845a180fSFrançois Revol 565845a180fSFrançois Revol 56660b11851SFrançois Revol #if 0//PPC 567845a180fSFrançois Revol // #pragma mark - 568845a180fSFrançois Revol 569845a180fSFrançois Revol struct m68k_cpu_exception_context * 570845a180fSFrançois Revol m68k_get_cpu_exception_context(int cpu) 571845a180fSFrançois Revol { 572845a180fSFrançois Revol return sCPUExceptionContexts + cpu; 573845a180fSFrançois Revol } 574845a180fSFrançois Revol 575845a180fSFrançois Revol 576845a180fSFrançois Revol void 577845a180fSFrançois Revol m68k_set_current_cpu_exception_context(struct m68k_cpu_exception_context *context) 578845a180fSFrançois Revol { 579845a180fSFrançois Revol // translate to physical address 580845a180fSFrançois Revol addr_t physicalPage; 581845a180fSFrançois Revol addr_t inPageOffset = (addr_t)context & (B_PAGE_SIZE - 1); 582*90d870c1SIngo Weinhold status_t error = vm_get_page_mapping(VMAddressSpace::KernelID(), 583845a180fSFrançois Revol (addr_t)context - inPageOffset, &physicalPage); 584845a180fSFrançois Revol if (error != B_OK) { 585845a180fSFrançois Revol panic("m68k_set_current_cpu_exception_context(): Failed to get physical " 586845a180fSFrançois Revol "address!"); 587845a180fSFrançois Revol return; 588845a180fSFrançois Revol } 589845a180fSFrançois Revol 590845a180fSFrançois Revol asm volatile("mtsprg0 %0" : : "r"(physicalPage + inPageOffset)); 591845a180fSFrançois Revol } 592845a180fSFrançois Revol 59330629f41SFrançois Revol #endif 594