/trunk/kernel/arch/mips32/include/interrupt.h |
---|
37,18 → 37,11 |
#include <arch/exception.h> |
#define IVT_ITEMS 40 |
#define INT_OFFSET 32 |
#define IRQ_COUNT 8 |
#define IVT_ITEMS 32 |
#define IVT_FIRST 0 |
#define int_register(it, name, handler) exc_register(((it)+INT_OFFSET),name,handler) |
extern function timer_fnc; |
#define IRQ2 2 |
#define IRQ3 3 |
#define IRQ7 7 |
#define TIMER_IRQ IRQ7 |
extern void interrupt_init(void); |
#endif |
/trunk/kernel/arch/mips32/include/console.h |
---|
35,7 → 35,7 |
#ifndef KERN_mips32_CONSOLE_H_ |
#define KERN_mips32_CONSOLE_H_ |
void console_init(void); |
extern void console_init(devno_t devno); |
#endif |
/trunk/kernel/arch/mips32/include/drivers/serial.h |
---|
62,8 → 62,8 |
int irq; |
}serial_t; |
void serial_console(void); |
int serial_init(void); |
extern void serial_console(devno_t devno); |
extern int serial_init(void); |
#endif |
/trunk/kernel/arch/mips32/include/drivers/msim.h |
---|
37,12 → 37,7 |
#include <console/chardev.h> |
#define MSIM_VIDEORAM 0xB0000000 |
/** Address of 'keyboard' device. */ |
#define MSIM_KBD_ADDRESS 0xB0000000 |
#define MSIM_KBD_IRQ 2 |
void msim_console(void); |
void msim_console(devno_t devno); |
void msim_kbd_release(void); |
void msim_kbd_grab(void); |
/trunk/kernel/arch/mips32/src/exception.c |
---|
45,6 → 45,7 |
#include <interrupt.h> |
#include <func.h> |
#include <console/kconsole.h> |
#include <ddi/irq.h> |
#include <arch/debugger.h> |
static char * exctable[] = { |
145,10 → 146,26 |
/* decode interrupt number and process the interrupt */ |
cause = (cp0_cause_read() >> 8) &0xff; |
for (i = 0; i < 8; i++) |
if (cause & (1 << i)) |
exc_dispatch(i+INT_OFFSET, istate); |
for (i = 0; i < 8; i++) { |
if (cause & (1 << i)) { |
irq_t *irq = irq_dispatch_and_lock(i); |
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, i); |
#endif |
} |
} |
} |
} |
/** Handle syscall userspace call */ |
static void syscall_exception(int n, istate_t *istate) |
163,6 → 180,7 |
/* Clear exception table */ |
for (i=0;i < IVT_ITEMS; i++) |
exc_register(i, "undef", (iroutine) unhandled_exception); |
exc_register(EXC_Bp, "bkpoint", (iroutine) breakpoint_exception); |
exc_register(EXC_RI, "resinstr", (iroutine) reserved_instr_exception); |
exc_register(EXC_Mod, "tlb_mod", (iroutine) tlbmod_exception); |
/trunk/kernel/arch/mips32/src/console.c |
---|
38,14 → 38,14 |
#include <arch/drivers/serial.h> |
#include <arch/drivers/msim.h> |
void console_init(void) |
void console_init(devno_t devno) |
{ |
if (arc_enabled()) { |
arc_console(); |
} else if (serial_init()) { |
serial_console(); |
serial_console(devno); |
} else { |
msim_console(); |
msim_console(devno); |
} |
} |
56,6 → 56,7 |
{ |
msim_kbd_grab(); |
} |
/** Return console to userspace |
* |
*/ |
/trunk/kernel/arch/mips32/src/mips32.c |
---|
54,6 → 54,7 |
#include <arch/debugger.h> |
#include <genarch/fb/fb.h> |
#include <macros.h> |
#include <ddi/device.h> |
#include <arch/asm/regname.h> |
102,7 → 103,6 |
memcpy(NORM_EXC, (char *)exception_entry, EXCEPTION_JUMP_SIZE); |
memcpy(CACHE_EXC, (char *)cache_error_entry, EXCEPTION_JUMP_SIZE); |
interrupt_init(); |
/* |
* Switch to BEV normal level so that exception vectors point to the kernel. |
* Clear the error level. |
114,17 → 114,13 |
*/ |
cp0_mask_all_int(); |
/* |
* Unmask hardware clock interrupt. |
*/ |
cp0_unmask_int(TIMER_IRQ); |
console_init(); |
debugger_init(); |
} |
void arch_post_mm_init(void) |
{ |
interrupt_init(); |
console_init(device_assign_devno()); |
#ifdef CONFIG_FB |
fb_init(0x12000000, 640, 480, 24, 1920, false); // gxemul framebuffer |
#endif |
/trunk/kernel/arch/mips32/src/interrupt.c |
---|
39,9 → 39,16 |
#include <arch/cp0.h> |
#include <time/clock.h> |
#include <arch/drivers/arc.h> |
#include <ipc/sysipc.h> |
#include <ddi/device.h> |
#include <ddi/irq.h> |
#define IRQ_COUNT 8 |
#define TIMER_IRQ 7 |
function timer_fnc = NULL; |
static irq_t timer_irq; |
/** Disable interrupts. |
* |
* @return Old interrupt priority level. |
91,8 → 98,13 |
cp0_compare_write(nextcount); |
} |
static void timer_exception(int n, istate_t *istate) |
static irq_ownership_t timer_claim(void) |
{ |
return IRQ_ACCEPT; |
} |
static void timer_irq_handler(irq_t *irq, void *arg, ...) |
{ |
unsigned long drift; |
drift = cp0_count_read() - nextcount; |
103,42 → 115,25 |
nextcount = cp0_count_read() + cp0_compare_value - drift; |
cp0_compare_write(nextcount); |
clock(); |
} |
static void swint0(int n, istate_t *istate) |
{ |
cp0_cause_write(cp0_cause_read() & ~(1 << 8)); /* clear SW0 interrupt */ |
ipc_irq_send_notif(0); |
if (timer_fnc != NULL) |
timer_fnc(); |
} |
static void swint1(int n, istate_t *istate) |
{ |
cp0_cause_write(cp0_cause_read() & ~(1 << 9)); /* clear SW1 interrupt */ |
ipc_irq_send_notif(1); |
} |
/* Initialize basic tables for exception dispatching */ |
void interrupt_init(void) |
{ |
int_register(TIMER_IRQ, "timer", timer_exception); |
int_register(0, "swint0", swint0); |
int_register(1, "swint1", swint1); |
timer_start(); |
} |
irq_init(IRQ_COUNT, IRQ_COUNT); |
static void ipc_int(int n, istate_t *istate) |
{ |
ipc_irq_send_notif(n-INT_OFFSET); |
} |
irq_initialize(&timer_irq); |
timer_irq.devno = device_assign_devno(); |
timer_irq.inr = TIMER_IRQ; |
timer_irq.claim = timer_claim; |
timer_irq.handler = timer_irq_handler; |
irq_register(&timer_irq); |
/* Reregister irq to be IPC-ready */ |
void irq_ipc_bind_arch(unative_t irq) |
{ |
/* Do not allow to redefine timer */ |
/* Swint0, Swint1 are already handled */ |
if (irq == TIMER_IRQ || irq < 2) |
return; |
int_register(irq, "ipc_int", ipc_int); |
timer_start(); |
cp0_unmask_int(TIMER_IRQ); |
} |
/** @} |
/trunk/kernel/arch/mips32/src/drivers/serial.c |
---|
37,7 → 37,11 |
#include <arch/drivers/serial.h> |
#include <console/chardev.h> |
#include <console/console.h> |
#include <ddi/irq.h> |
#define SERIAL_IRQ 2 |
static irq_t serial_irq; |
static chardev_t console; |
static serial_t sconf[SERIAL_MAX]; |
static bool kb_enabled; |
91,9 → 95,7 |
return ch; |
} |
/** Process keyboard interrupt. Does not work in simics? */ |
static void serial_interrupt(int n, void *stack) |
static void serial_handler(void) |
{ |
serial_t *sd = (serial_t *)console.data; |
char ch; |
107,7 → 109,19 |
chardev_push_character(&console, ch); |
} |
/** Process keyboard interrupt. Does not work in simics? */ |
static void serial_irq_handler(irq_t *irq, void *arg, ...) |
{ |
if ((irq->notif_cfg.notify) && (irq->notif_cfg.answerbox)) |
ipc_irq_send_notif(irq); |
else |
serial_handler(); |
} |
static irq_ownership_t serial_claim(void) |
{ |
return IRQ_ACCEPT; |
} |
static chardev_operations_t serial_ops = { |
.resume = serial_enable, |
116,16 → 130,8 |
.read = serial_do_read |
}; |
iroutine old_timer; |
/** Do polling on timer interrupt */ |
static void timer_replace(int n, istate_t *istate) |
void serial_console(devno_t devno) |
{ |
old_timer(n, istate); |
serial_interrupt(n, istate); |
} |
void serial_console(void) |
{ |
serial_t *sd = &sconf[0]; |
133,11 → 139,17 |
console.data = sd; |
kb_enabled = true; |
// int_register(2, "serial_drvr", serial_interrupt); |
irq_initialize(&serial_irq); |
serial_irq.devno = devno; |
serial_irq.inr = SERIAL_IRQ; |
serial_irq.claim = serial_claim; |
serial_irq.handler = serial_irq_handler; |
irq_register(&serial_irq); |
/* I don't know why, but the serial interrupts simply |
* don't work on simics |
*/ |
old_timer = int_register(TIMER_IRQ, "serial_drvr_poll", timer_replace); |
timer_fnc = &serial_handler; |
stdin = &console; |
stdout = &console; |
/trunk/kernel/arch/mips32/src/drivers/arc.c |
---|
353,21 → 353,12 |
.read = arc_read |
}; |
iroutine old_timer; |
/** Do polling on timer interrupt */ |
static void timer_replace(int n, istate_t *istate) |
{ |
arc_keyboard_poll(); |
old_timer(n, istate); |
arc_keyboard_poll(); |
} |
void arc_console(void) |
{ |
kbd_polling_enabled = true; |
chardev_initialize("arc_console", &console, &arc_ops); |
old_timer = int_register(TIMER_IRQ, "arc_kb_poll", timer_replace); |
timer_fnc = &arc_keyboard_poll; |
stdin = &console; |
stdout = &console; |
} |
/trunk/kernel/arch/mips32/src/drivers/msim.c |
---|
37,8 → 37,16 |
#include <arch/drivers/msim.h> |
#include <arch/cp0.h> |
#include <console/console.h> |
#include <ddi/irq.h> |
#include <sysinfo/sysinfo.h> |
/** Address of devices. */ |
#define MSIM_VIDEORAM 0xB0000000 |
#define MSIM_KBD_ADDRESS 0xB0000000 |
#define MSIM_KBD_IRQ 2 |
static chardev_t console; |
static irq_t msim_irq; |
static void msim_write(chardev_t *dev, const char ch); |
static void msim_enable(chardev_t *dev); |
89,8 → 97,11 |
} |
/** Process keyboard interrupt. */ |
static void msim_interrupt(int n, istate_t *istate) |
static void msim_irq_handler(irq_t *irq, void *arg, ...) |
{ |
if ((irq->notif_cfg.notify) && (irq->notif_cfg.answerbox)) |
ipc_irq_send_notif(irq); |
else { |
char ch = 0; |
ch = *((char *) MSIM_KBD_ADDRESS); |
100,31 → 111,46 |
ch = '\b'; |
chardev_push_character(&console, ch); |
} |
} |
static irq_ownership_t msim_claim(void) |
{ |
return IRQ_ACCEPT; |
} |
void msim_kbd_grab(void) |
{ |
msim_irq.notif_cfg.notify = false; |
} |
void msim_kbd_release(void) |
{ |
if (msim_irq.notif_cfg.answerbox) |
msim_irq.notif_cfg.notify = true; |
} |
/* Return console object representing msim console */ |
void msim_console(void) |
void msim_console(devno_t devno) |
{ |
chardev_initialize("msim_console", &console, &msim_ops); |
stdin = &console; |
stdout = &console; |
int_register(MSIM_KBD_IRQ, "msim_kbd", msim_interrupt); |
irq_initialize(&msim_irq); |
msim_irq.devno = devno; |
msim_irq.inr = MSIM_KBD_IRQ; |
msim_irq.claim = msim_claim; |
msim_irq.handler = msim_irq_handler; |
irq_register(&msim_irq); |
cp0_unmask_int(MSIM_KBD_IRQ); |
stdin = &console; |
stdout = &console; |
sysinfo_set_item_val("kbd", NULL, true); |
sysinfo_set_item_val("kbd.devno", NULL, devno); |
sysinfo_set_item_val("kbd.inr", NULL, MSIM_KBD_IRQ); |
sysinfo_set_item_val("kbd.address.virtual", NULL, MSIM_KBD_ADDRESS); |
} |
static iroutine oldvector; |
void msim_kbd_grab(void) |
{ |
oldvector = int_register(MSIM_KBD_IRQ, "msim_kbd", msim_interrupt); |
} |
void msim_kbd_release(void) |
{ |
if (oldvector) |
int_register(MSIM_KBD_IRQ, "user_interrupt", oldvector); |
} |
/** @} |
*/ |