Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 1955 → Rev 1956

/trunk/kernel/genarch/include/kbd/i8042.h
37,7 → 37,7
 
#include <typedefs.h>
 
extern void i8042_init(void);
extern void i8042_init(devno_t devno, inr_t inr);
extern void i8042_poll(void);
extern void i8042_grab(void);
extern void i8042_release(void);
/trunk/kernel/genarch/src/kbd/i8042.c
41,7 → 41,6
#include <genarch/kbd/scanc.h>
#include <genarch/kbd/scanc_pc.h>
#include <arch/drivers/i8042.h>
#include <arch/interrupt.h>
#include <cpu.h>
#include <arch/asm.h>
#include <arch.h>
49,6 → 48,8
#include <console/chardev.h>
#include <console/console.h>
#include <interrupt.h>
#include <sysinfo/sysinfo.h>
#include <ddi/irq.h>
 
/* Keyboard commands. */
#define KBD_ENABLE 0xf4
86,82 → 87,100
.read = i8042_key_read
};
 
static void i8042_interrupt(int n, istate_t *istate);
static void i8042_wait(void);
/** Structure for i8042's IRQ. */
static irq_t i8042_irq;
 
static iroutine oldvector;
/** Initialize keyboard and service interrupts using kernel routine */
/** Wait until the controller reads its data. */
static void i8042_wait(void) {
while (i8042_status_read() & i8042_WAIT_MASK) {
/* wait */
}
}
 
void i8042_grab(void)
{
oldvector = exc_register(VECTOR_KBD, "i8042_interrupt", (iroutine) i8042_interrupt);
ipl_t ipl = interrupts_disable();
i8042_wait();
i8042_command_write(i8042_SET_COMMAND);
i8042_wait();
i8042_data_write(i8042_COMMAND);
i8042_wait();
 
spinlock_lock(&i8042_irq.lock);
i8042_irq.notif_cfg.notify = false;
spinlock_unlock(&i8042_irq.lock);
interrupts_restore(ipl);
}
/** Resume the former interrupt vector */
 
void i8042_release(void)
{
if (oldvector)
exc_register(VECTOR_KBD, "user_interrupt", oldvector);
ipl_t ipl = interrupts_disable();
spinlock_lock(&i8042_irq.lock);
if (i8042_irq.notif_cfg.answerbox)
i8042_irq.notif_cfg.notify = true;
spinlock_unlock(&i8042_irq.lock);
interrupts_restore(ipl);
}
 
/** Initialize i8042. */
void i8042_init(void)
static irq_ownership_t i8042_claim(void)
{
int i;
return IRQ_ACCEPT;
}
 
i8042_grab();
/* Prevent user from accidentaly releasing calling i8042_resume
* and disabling keyboard
*/
oldvector = NULL;
static void i8042_irq_handler(irq_t *irq, void *arg, ...)
{
if (irq->notif_cfg.notify && irq->notif_cfg.answerbox)
ipc_irq_send_notif(irq);
else {
uint8_t x;
uint8_t status;
while (((status = i8042_status_read()) & i8042_BUFFER_FULL_MASK)) {
x = i8042_data_read();
if ((status & i8042_MOUSE_DATA))
continue;
if (x & KEY_RELEASE)
key_released(x ^ KEY_RELEASE);
else
key_pressed(x);
}
}
}
 
trap_virtual_enable_irqs(1<<IRQ_KBD);
/** Initialize i8042. */
void i8042_init(devno_t devno, inr_t inr)
{
chardev_initialize("i8042_kbd", &kbrd, &ops);
stdin = &kbrd;
 
irq_initialize(&i8042_irq);
i8042_irq.devno = devno;
i8042_irq.inr = inr;
i8042_irq.claim = i8042_claim;
i8042_irq.handler = i8042_irq_handler;
irq_register(&i8042_irq);
trap_virtual_enable_irqs(1 << inr);
/*
* Clear input buffer.
* Number of iterations is limited to prevent infinite looping.
*/
int i;
for (i = 0; (i8042_status_read() & i8042_BUFFER_FULL_MASK) && i < 100; i++) {
i8042_data_read();
}
}
 
/** Process i8042 interrupt.
*
* @param n Interrupt vector.
* @param istate Interrupted state.
*/
void i8042_interrupt(int n, istate_t *istate)
{
uint8_t x;
uint8_t status;
 
while (((status=i8042_status_read()) & i8042_BUFFER_FULL_MASK)) {
x = i8042_data_read();
 
if ((status & i8042_MOUSE_DATA))
continue;
 
if (x & KEY_RELEASE)
key_released(x ^ KEY_RELEASE);
else
key_pressed(x);
}
trap_virtual_eoi();
sysinfo_set_item_val("kbd", NULL, true);
sysinfo_set_item_val("kbd.devno", NULL, devno);
sysinfo_set_item_val("kbd.inr", NULL, inr);
i8042_grab();
}
 
/** Wait until the controller reads its data. */
void i8042_wait(void) {
while (i8042_status_read() & i8042_WAIT_MASK) {
/* wait */
}
}
 
/* Called from getc(). */
void i8042_resume(chardev_t *d)
{
/trunk/kernel/arch/ia32/include/interrupt.h
45,30 → 45,28
#define IRQ_COUNT 16
 
#define IVT_EXCBASE 0
#define IVT_IRQBASE (IVT_EXCBASE+EXC_COUNT)
#define IVT_FREEBASE (IVT_IRQBASE+IRQ_COUNT)
#define IVT_IRQBASE (IVT_EXCBASE + EXC_COUNT)
#define IVT_FREEBASE (IVT_IRQBASE + IRQ_COUNT)
 
#define IRQ_CLK 0
#define IRQ_KBD 1
#define IRQ_PIC1 2
#define IRQ_CLK 0
#define IRQ_KBD 1
#define IRQ_PIC1 2
#define IRQ_PIC_SPUR 7
 
/* this one must have four least significant bits set to ones */
#define VECTOR_APIC_SPUR (IVT_ITEMS-1)
#define VECTOR_APIC_SPUR (IVT_ITEMS - 1)
 
#if (((VECTOR_APIC_SPUR + 1)%16) || VECTOR_APIC_SPUR >= IVT_ITEMS)
#if (((VECTOR_APIC_SPUR + 1) % 16) || VECTOR_APIC_SPUR >= IVT_ITEMS)
#error Wrong definition of VECTOR_APIC_SPUR
#endif
 
#define VECTOR_DEBUG 1
#define VECTOR_PIC_SPUR (IVT_IRQBASE+IRQ_PIC_SPUR)
#define VECTOR_CLK (IVT_IRQBASE+IRQ_CLK)
#define VECTOR_KBD (IVT_IRQBASE+IRQ_KBD)
#define VECTOR_DEBUG 1
#define VECTOR_CLK (IVT_IRQBASE + IRQ_CLK)
#define VECTOR_PIC_SPUR (IVT_IRQBASE + IRQ_PIC_SPUR)
#define VECTOR_SYSCALL IVT_FREEBASE
#define VECTOR_TLB_SHOOTDOWN_IPI (IVT_FREEBASE + 1)
#define VECTOR_DEBUG_IPI (IVT_FREEBASE + 2)
 
#define VECTOR_SYSCALL (IVT_FREEBASE+0)
#define VECTOR_TLB_SHOOTDOWN_IPI (IVT_FREEBASE+1)
#define VECTOR_DEBUG_IPI (IVT_FREEBASE+2)
 
struct istate {
uint32_t eax;
uint32_t ecx;
110,18 → 108,10
extern void (* enable_irqs_function)(uint16_t irqmask);
extern void (* eoi_function)(void);
 
extern void PRINT_INFO_ERRCODE(istate_t *istate);
extern void null_interrupt(int n, istate_t *istate);
extern void gp_fault(int n, istate_t *istate);
extern void nm_fault(int n, istate_t *istate);
extern void ss_fault(int n, istate_t *istate);
extern void simd_fp_exception(int n, istate_t *istate);
extern void syscall(int n, istate_t *istate);
extern void tlb_shootdown_ipi(int n, istate_t *istate);
 
extern void decode_istate(istate_t *istate);
extern void interrupt_init(void);
extern void trap_virtual_enable_irqs(uint16_t irqmask);
extern void trap_virtual_disable_irqs(uint16_t irqmask);
extern void trap_virtual_eoi(void);
 
#endif
 
/trunk/kernel/arch/ia32/src/ia32.c
57,10 → 57,12
 
#include <arch/mm/memory_init.h>
#include <interrupt.h>
#include <ddi/irq.h>
#include <arch/debugger.h>
#include <proc/thread.h>
#include <syscall/syscall.h>
#include <console/console.h>
#include <ddi/device.h>
 
#ifdef CONFIG_SMP
#include <arch/smp/apic.h>
71,16 → 73,11
pm_init();
 
if (config.cpu_active == 1) {
interrupt_init();
bios_init();
i8259_init(); /* PIC */
i8254_init(); /* hard clock */
exc_register(VECTOR_SYSCALL, "syscall", (iroutine) syscall);
#ifdef CONFIG_SMP
exc_register(VECTOR_TLB_SHOOTDOWN_IPI, "tlb_shootdown",
(iroutine) tlb_shootdown_ipi);
#endif /* CONFIG_SMP */
/* PIC */
i8259_init();
}
}
 
87,6 → 84,11
void arch_post_mm_init(void)
{
if (config.cpu_active == 1) {
/* Initialize IRQ routing */
irq_init(IRQ_COUNT, IRQ_COUNT);
/* hard clock */
i8254_init();
 
#ifdef CONFIG_FB
if (vesa_present())
95,7 → 97,6
#endif
ega_init(); /* video */
/* Enable debugger */
debugger_init();
/* Merge all memory zones to 1 big zone */
126,7 → 127,8
 
void arch_post_smp_init(void)
{
i8042_init(); /* keyboard controller */
/* keyboard controller */
i8042_init(device_assign_devno(), IRQ_KBD);
}
 
void calibrate_delay_loop(void)
/trunk/kernel/arch/ia32/src/pm.c
139,13 → 139,8
d->access |= DPL_USER;
}
idt_setoffset(d, ((uintptr_t) interrupt_handlers) + i*interrupt_handler_size);
exc_register(i, "undef", (iroutine) null_interrupt);
idt_setoffset(d, ((uintptr_t) interrupt_handlers) + i * interrupt_handler_size);
}
exc_register(13, "gp_fault", (iroutine) gp_fault);
exc_register( 7, "nm_fault", (iroutine) nm_fault);
exc_register(12, "ss_fault", (iroutine) ss_fault);
exc_register(19, "simd_fp", (iroutine) simd_fp_exception);
}
 
 
/trunk/kernel/arch/ia32/src/mm/page.c
111,7 → 111,7
if (as_page_fault(page, access, istate) == AS_PF_FAULT) {
fault_if_from_uspace(istate, "Page fault: %#x", page);
 
PRINT_INFO_ERRCODE(istate);
decode_istate(istate);
printf("page fault address: %#x\n", page);
panic("page fault\n");
}
/trunk/kernel/arch/ia32/src/interrupt.c
51,6 → 51,7
#include <arch/ddi/ddi.h>
#include <ipc/sysipc.h>
#include <interrupt.h>
#include <ddi/irq.h>
 
/*
* Interrupt and exception dispatching.
60,7 → 61,7
void (* enable_irqs_function)(uint16_t irqmask) = NULL;
void (* eoi_function)(void) = NULL;
 
void PRINT_INFO_ERRCODE(istate_t *istate)
void decode_istate(istate_t *istate)
{
char *symbol = get_symtab_entry(istate->eip);
 
83,16 → 84,25
printf(" %#x, %#x, %#x, %#x\n", istate->stack[4], istate->stack[5], istate->stack[6], istate->stack[7]);
}
 
void null_interrupt(int n, istate_t *istate)
static void trap_virtual_eoi(void)
{
if (eoi_function)
eoi_function();
else
panic("no eoi_function\n");
 
}
 
static void null_interrupt(int n, istate_t *istate)
{
fault_if_from_uspace(istate, "unserviced interrupt: %d", n);
 
PRINT_INFO_ERRCODE(istate);
decode_istate(istate);
panic("unserviced interrupt: %d\n", n);
}
 
/** General Protection Fault. */
void gp_fault(int n, istate_t *istate)
static void gp_fault(int n, istate_t *istate)
{
if (TASK) {
count_t ver;
115,19 → 125,19
fault_if_from_uspace(istate, "general protection fault");
}
 
PRINT_INFO_ERRCODE(istate);
decode_istate(istate);
panic("general protection fault\n");
}
 
void ss_fault(int n, istate_t *istate)
static void ss_fault(int n, istate_t *istate)
{
fault_if_from_uspace(istate, "stack fault");
 
PRINT_INFO_ERRCODE(istate);
decode_istate(istate);
panic("stack fault\n");
}
 
void simd_fp_exception(int n, istate_t *istate)
static void simd_fp_exception(int n, istate_t *istate)
{
uint32_t mxcsr;
asm
138,12 → 148,12
fault_if_from_uspace(istate, "SIMD FP exception(19), MXCSR: %#zx",
(unative_t)mxcsr);
 
PRINT_INFO_ERRCODE(istate);
decode_istate(istate);
printf("MXCSR: %#zx\n",(unative_t)(mxcsr));
panic("SIMD FP exception(19)\n");
}
 
void nm_fault(int n, istate_t *istate)
static void nm_fault(int n, istate_t *istate)
{
#ifdef CONFIG_FPU_LAZY
scheduler_fpu_lazy_request();
153,17 → 163,63
#endif
}
 
void syscall(int n, istate_t *istate)
#ifdef CONFIG_SMP
static void tlb_shootdown_ipi(int n, istate_t *istate)
{
panic("Obsolete syscall handler.");
trap_virtual_eoi();
tlb_shootdown_ipi_recv();
}
#endif
 
void tlb_shootdown_ipi(int n, istate_t *istate)
/** Handler of IRQ exceptions */
static void irq_interrupt(int n, istate_t *istate)
{
ASSERT(n >= IVT_IRQBASE);
int inum = n - IVT_IRQBASE;
ASSERT(inum < IRQ_COUNT);
ASSERT((inum != IRQ_PIC_SPUR) && (inum != IRQ_PIC1));
 
irq_t *irq = irq_dispatch_and_lock(inum);
if (irq) {
/*
* The IRQ handler was found.
*/
irq->handler(irq, irq->arg);
spinlock_unlock(&irq->lock);
} else {
/*
* Spurious interrupt.
*/
#ifdef CONFIG_DEBUG
printf("cpu%d: spurious interrupt (inum=%d)\n", CPU->id, inum);
#endif
}
trap_virtual_eoi();
tlb_shootdown_ipi_recv();
}
 
void interrupt_init(void)
{
int i;
for (i = 0; i < IVT_ITEMS; i++)
exc_register(i, "null", (iroutine) null_interrupt);
for (i = 0; i < IRQ_COUNT; i++) {
if ((i != IRQ_PIC_SPUR) && (i != IRQ_PIC1))
exc_register(IVT_IRQBASE + i, "irq", (iroutine) irq_interrupt);
}
exc_register(7, "nm_fault", (iroutine) nm_fault);
exc_register(12, "ss_fault", (iroutine) ss_fault);
exc_register(13, "gp_fault", (iroutine) gp_fault);
exc_register(19, "simd_fp", (iroutine) simd_fp_exception);
#ifdef CONFIG_SMP
exc_register(VECTOR_TLB_SHOOTDOWN_IPI, "tlb_shootdown", (iroutine) tlb_shootdown_ipi);
#endif
}
 
void trap_virtual_enable_irqs(uint16_t irqmask)
{
if (enable_irqs_function)
180,14 → 236,5
panic("no disable_irqs_function\n");
}
 
void trap_virtual_eoi(void)
{
if (eoi_function)
eoi_function();
else
panic("no eoi_function\n");
 
}
 
/** @}
*/
/trunk/kernel/arch/ia32/src/drivers/i8254.c
49,7 → 49,8
#include <arch/cpuid.h>
#include <arch.h>
#include <time/delay.h>
#include <interrupt.h>
#include <ddi/irq.h>
#include <ddi/device.h>
 
#define CLK_PORT1 0x40
#define CLK_PORT4 0x43
57,10 → 58,27
#define CLK_CONST 1193180
#define MAGIC_NUMBER 1194
 
static void i8254_interrupt(int n, istate_t *istate);
static irq_t i8254_irq;
 
static irq_ownership_t i8254_claim(void)
{
return IRQ_ACCEPT;
}
 
static void i8254_irq_handler(irq_t *irq, void *arg, ...)
{
clock();
}
 
void i8254_init(void)
{
irq_initialize(&i8254_irq);
i8254_irq.devno = device_assign_devno();
i8254_irq.inr = IRQ_CLK;
i8254_irq.claim = i8254_claim;
i8254_irq.handler = i8254_irq_handler;
irq_register(&i8254_irq);
i8254_normal_operation();
}
 
67,11 → 85,10
void i8254_normal_operation(void)
{
outb(CLK_PORT4, 0x36);
pic_disable_irqs(1<<IRQ_CLK);
outb(CLK_PORT1, (CLK_CONST/HZ) & 0xf);
outb(CLK_PORT1, (CLK_CONST/HZ) >> 8);
pic_enable_irqs(1<<IRQ_CLK);
exc_register(VECTOR_CLK, "i8254_clock", (iroutine) i8254_interrupt);
pic_disable_irqs(1 << IRQ_CLK);
outb(CLK_PORT1, (CLK_CONST / HZ) & 0xf);
outb(CLK_PORT1, (CLK_CONST / HZ) >> 8);
pic_enable_irqs(1 << IRQ_CLK);
}
 
#define LOOPS 150000
129,11 → 146,5
return;
}
 
void i8254_interrupt(int n, istate_t *istate)
{
trap_virtual_eoi();
clock();
}
 
/** @}
*/