static void kb_handle_interrupt(uint8_t irq, struct irq_regs* regs) { uint8_t scan_code = INB(0x60); if(scan_code == 0xFA && !g_initial_ack_received) { // Currently, we seem to be getting an interrupt // right after enabling the keyboard and interrupts. // The scan code is 0xFA, and the current set is 1. // This is not a valid scan code, and we currently do not // know why this is being sent. We have only ever seen it // get "sent" once, in this instance. So we simply ignore it. g_initial_ack_received = true; pic_send_eoi(pic_irq_keyboard); return; } //terminal_write_string("KB IRQ Scan code: "); //terminal_write_hex(scan_code); //terminal_write_string("\n"); // Translate scancode int sc_index = sc_get_entry_index(g_current_map, scan_code); if (sc_index < 0) { // Unknown scan-code terminal_write_string("Unknown scan code value: "); terminal_write_uint32_x(scan_code); terminal_write_string("\n"); // Reset to the first map in the set reset_map(); } else { struct sc_map_entry* sc_entry = &g_current_map->entries[sc_index]; switch (sc_entry->type) { case sc_map_entry_type_press: reset_map(); if(g_current_subscriber->down != NULL) { g_current_subscriber->down(sc_entry->data); } break; case sc_map_entry_type_release: reset_map(); if(g_current_subscriber->up != NULL) { g_current_subscriber->up(sc_entry->data); } break; case sc_map_entry_type_map: g_current_map = &g_current_set->maps[sc_entry->data]; break; } } pic_send_eoi(pic_irq_keyboard); }
void keyboard_isr(void) { uint8_t scancode; bool make; scancode = _read_buf(); // is this keystroke a make or a break? make = !(0x80 & scancode); // clear the break bit scancode &= 0x7f; switch (scancode) { case LCTRL: _.ctrl = make; goto keyboard_isr_end; case LSHIFT: _.lshift = make; goto keyboard_isr_end; case RSHIFT: _.rshift = make; goto keyboard_isr_end; } if (!make) goto keyboard_isr_end; { char c; // map control characters switch (c = _keymap[scancode][!!_.shift]) { case 'u': if (_.ctrl) c = '\r'; // line kill break; case 'l': if (_.ctrl) c = 127; break; case 127: // DEL -> backspace c = '\b'; // erase break; } if (c) console_put_ibuf(c); } keyboard_isr_end: _.shift = _.lshift || _.rshift; pic_send_eoi(KEYBOARD_IRQ_NUM); return; }
/* When an IRQ interrupt is sent, this will get called */ void irq_handler(registers_t *regs) { if (isr_handlers[regs->int_no]) { isr_handlers[regs->int_no](regs); } pic_send_eoi(regs->int_no-32); }
static void sched_timer() { /* * Send EOI first, because sched * will run into the user space of a process */ pic_send_eoi(IRQ0); sched(); }
/* Takes a raw vector/trap number (32-47) */ int pic_check_spurious(int trap_nr) { if (trap_nr == PIC1_SPURIOUS && !(pic_get_isr() & (1 << 7))) { ++ pic1_spurious_irqs; return 1; } if (trap_nr == PIC2_SPURIOUS && !(pic_get_isr() & (1 << 15))) { ++ pic2_spurious_irqs; pic_send_eoi(PIC1_OFFSET + 2); return 1; } return 0; }
extern "C" void intr_common_handler(interrupt_registers_t regs){ //if we have such handler, call it if(_intrHandlers[regs.intr_num] != 0){ _intrHandlers[regs.intr_num](regs); }else{ //no such handler //if this is one of the reserved ISRs if(regs.intr_num <= interrupt::MaxReservedIsrs){ //TODO call fault handle } } //if interrupt was generated by PIC if(IS_PIC_INTERRUPT(regs.intr_num)){ //send eoi to pic pic_send_eoi(regs.intr_num); } }
/* Takes a raw vector/trap number (32-47), not a device IRQ (0-15) */ bool pic_check_spurious(int trap_nr) { /* the PIC may send spurious irqs via one of the chips irq 7. if the isr * doesn't show that irq, then it was spurious, and we don't send an eoi. * Check out http://wiki.osdev.org/8259_PIC#Spurious_IRQs */ if ((trap_nr == PIC1_SPURIOUS) && !(pic_get_isr() & (1 << 7))) { printd("Spurious PIC1 irq!\n"); /* want to know if this happens */ return TRUE; } if ((trap_nr == PIC2_SPURIOUS) && !(pic_get_isr() & (1 << 15))) { printd("Spurious PIC2 irq!\n"); /* want to know if this happens */ /* for the cascaded PIC, we *do* need to send an EOI to the master's * cascade irq (2). */ pic_send_eoi(2 + PIC1_OFFSET); return TRUE; } return FALSE; }
int keyboard_init(void) { extern void _keyboard_isr(void); bool intr_flag; _.shift = _.rshift = _.lshift = false; _.ctrl = false; // save IF intr_flag = eflags_get_intr_flag(); intr_disable(); // TODO perform a controller reset intr_register_irq(KEYBOARD_IRQ_NUM, _keyboard_isr); pic_send_eoi(KEYBOARD_IRQ_NUM); keyboard_enable_irq(); // restore previous IF eflags_set_intr_flag(intr_flag); return 0; }
// ===================================================================================================================== int sched_irq(int irq, void* data, struct irq_context* ctx) { // We need to send EOI on the PIC here because this function will not return to the common IRQ handler path ... pic_send_eoi(0); struct cpu* curr_cpu = cpu_get_current(); struct thread* curr = curr_cpu->thread_current; struct amd64_thread* t_arch; // Save the kernel stack pointer of the previous thread. if (curr) { t_arch = (struct amd64_thread*)curr->arch_data; t_arch->rsp = (uint64_t)ctx; } // Select the next thread to run. struct thread* next = sched_next(curr_cpu, curr); // upadte the TSS structure of the current CPU for the new thread struct amd64_cpu* arch_cpu = (struct amd64_cpu*)curr_cpu->arch_data; arch_cpu->tss.rsp0 = (ptr_t)next->kernel_stack + next->kernel_stack_size; // switch to the address space of the new process if (next->proc) { struct amd64_process* proc_arch = (struct amd64_process*)next->proc->arch_data; cpu_set_cr3(proc_arch->cr3); } // Switch to the next thread. t_arch = (struct amd64_thread*)next->arch_data; sched_arch_switch_to(t_arch->rsp); return 0; }
// ===================================================================================================================== void irq_arch_finished(int irq) { pic_send_eoi(irq); }