OFFSET(BREGS_edi, bregs, edi);
OFFSET(BREGS_flags, bregs, flags);
OFFSET(BREGS_code, bregs, code);
+ DEFINE(BREGS_size, sizeof(struct bregs));
}
// INT 08h System Timer ISR Entry Point
void VISIBLE16
-handle_08(void)
+handle_08(struct bregs *regs)
{
- debug_isr(DEBUG_ISR_08);
+ debug_enter(regs, DEBUG_ISR_08);
floppy_tick();
usb_check_event();
// chain to user timer tick INT #0x1c
- u32 eax=0, flags;
- call16_simpint(0x1c, &eax, &flags);
+ struct bregs br;
+ memset(&br, 0, sizeof(br));
+ br.flags = F_IF;
+ call16_int(0x1c, &br);
eoi_pic1();
}
// int70h: IRQ8 - CMOS RTC
void VISIBLE16
-handle_70(void)
+handle_70(struct bregs *regs)
{
- debug_isr(DEBUG_ISR_70);
+ debug_enter(regs, DEBUG_ISR_70);
// Check which modes are enabled and have occurred.
u8 registerB = inb_cmos(CMOS_STATUS_B);
goto done;
if (registerC & RTC_B_AIE) {
// Handle Alarm Interrupt.
- u32 eax=0, flags;
- call16_simpint(0x4a, &eax, &flags);
+ struct bregs br;
+ memset(&br, 0, sizeof(br));
+ br.flags = F_IF;
+ call16_int(0x4a, &br);
}
if (!(registerC & RTC_B_PIE))
goto done;
// record completion in BIOS task complete flag
void VISIBLE16
-handle_76(void)
+handle_76(struct bregs *regs)
{
- debug_isr(DEBUG_ISR_76);
+ debug_enter(regs, DEBUG_ISR_76);
SET_BDA(disk_interrupt_flag, 0xff);
eoi_pic2();
}
// INT 0Eh Diskette Hardware ISR Entry Point
void VISIBLE16
-handle_0e(void)
+handle_0e(struct bregs *regs)
{
- debug_isr(DEBUG_ISR_0e);
+ debug_enter(regs, DEBUG_ISR_0e);
if (! CONFIG_FLOPPY)
goto done;
};
// Handle a scancode read from the ps2 port. Note that "noinline" is
-// used to make sure the call to call16_simpint in process_key doesn't
+// used to make sure the call to call16_int in process_key doesn't
// have the overhead of this function's stack.
static void noinline
__process_key(u8 scancode)
if (CONFIG_KBD_CALL_INT15_4F) {
// allow for keyboard intercept
- u32 eax = (0x4f << 8) | key;
- u32 flags;
- call16_simpint(0x15, &eax, &flags);
- if (!(flags & F_CF))
+ struct bregs br;
+ memset(&br, 0, sizeof(br));
+ br.eax = (0x4f << 8) | key;
+ br.flags = F_IF|F_CF;
+ call16_int(0x15, &br);
+ if (!(br.flags & F_CF))
return;
- key = eax;
+ key = br.eax;
}
__process_key(key);
}
// NMI handler
void VISIBLE16
-handle_02(void)
+handle_02(struct bregs *regs)
{
- debug_isr(DEBUG_ISR_02);
+ debug_enter(regs, DEBUG_ISR_02);
}
void
// INT 75 - IRQ13 - MATH COPROCESSOR EXCEPTION
void VISIBLE16
-handle_75(void)
+handle_75(struct bregs *regs)
{
- debug_isr(DEBUG_ISR_75);
+ debug_enter(regs, DEBUG_ISR_75);
// clear irq13
outb(0, PORT_MATH_CLEAR);
// clear interrupt
eoi_pic2();
// legacy nmi call
- u32 eax=0, flags;
- call16_simpint(0x02, &eax, &flags);
+ struct bregs br;
+ memset(&br, 0, sizeof(br));
+ br.flags = F_IF;
+ call16_int(0x02, &br);
}
// This file may be distributed under the terms of the GNU LGPLv3 license.
#include "biosvar.h" // GET_EBDA
-#include "util.h" // debug_isr
-#include "pic.h" // eoi_pic2
+#include "util.h" // dprintf
#include "bregs.h" // struct bregs
#include "ps2port.h" // ps2_mouse_command
#include "usb-hid.h" // usb_mouse_command
}
}
-void noinline
-process_mouse(u8 data)
+static void
+invoke_mouse_handler(u16 ebda_seg)
{
- if (!CONFIG_MOUSE)
- return;
-
- u16 ebda_seg = get_ebda_seg();
- u8 mouse_flags_1 = GET_EBDA(ebda_seg, mouse_flag1);
- u8 mouse_flags_2 = GET_EBDA(ebda_seg, mouse_flag2);
-
- if (! (mouse_flags_2 & 0x80))
- // far call handler not installed
- return;
-
- u8 package_count = mouse_flags_2 & 0x07;
- u8 index = mouse_flags_1 & 0x07;
- SET_EBDA(ebda_seg, mouse_data[index], data);
-
- if ((index+1) < package_count) {
- mouse_flags_1++;
- SET_EBDA(ebda_seg, mouse_flag1, mouse_flags_1);
- return;
- }
-
u16 status = GET_EBDA(ebda_seg, mouse_data[0]);
u16 X = GET_EBDA(ebda_seg, mouse_data[1]);
u16 Y = GET_EBDA(ebda_seg, mouse_data[2]);
- SET_EBDA(ebda_seg, mouse_flag1, 0);
struct segoff_s func = GET_EBDA(ebda_seg, far_call_pointer);
dprintf(16, "mouse farcall s=%04x x=%04x y=%04x func=%04x:%04x\n"
:
: "edi", "esi", "cc", "memory");
}
+
+void noinline
+process_mouse(u8 data)
+{
+ if (!CONFIG_MOUSE)
+ return;
+
+ u16 ebda_seg = get_ebda_seg();
+ u8 mouse_flags_1 = GET_EBDA(ebda_seg, mouse_flag1);
+ u8 mouse_flags_2 = GET_EBDA(ebda_seg, mouse_flag2);
+
+ if (! (mouse_flags_2 & 0x80))
+ // far call handler not installed
+ return;
+
+ u8 package_count = mouse_flags_2 & 0x07;
+ u8 index = mouse_flags_1 & 0x07;
+ SET_EBDA(ebda_seg, mouse_data[index], data);
+
+ if ((index+1) < package_count) {
+ mouse_flags_1++;
+ SET_EBDA(ebda_seg, mouse_flag1, mouse_flags_1);
+ return;
+ }
+
+ SET_EBDA(ebda_seg, mouse_flag1, 0);
+ stack_hop_back(ebda_seg, 0, invoke_mouse_handler);
+}
, regs->code.seg, regs->code.offset, regs->flags);
}
-// Report entry to an Interrupt Service Routine (ISR).
-void
-__debug_isr(const char *fname)
-{
- puts_cs(&debuginfo, fname);
- putc(&debuginfo, '\n');
- debug_serial_flush();
-}
-
// Function called on handler startup.
void
__debug_enter(struct bregs *regs, const char *fname)
// INT74h : PS/2 mouse hardware interrupt
void VISIBLE16
-handle_74(void)
+handle_74(struct bregs *regs)
{
if (! CONFIG_PS2PORT)
return;
- debug_isr(DEBUG_ISR_74);
+ debug_enter(regs, DEBUG_ISR_74);
u8 v = inb(PORT_PS2_STATUS);
if ((v & (I8042_STR_OBF|I8042_STR_AUXDATA))
// INT09h : Keyboard Hardware Service Entry Point
void VISIBLE16
-handle_09(void)
+handle_09(struct bregs *regs)
{
if (! CONFIG_PS2PORT)
return;
- debug_isr(DEBUG_ISR_09);
+ debug_enter(regs, DEBUG_ISR_09);
// read key from keyboard controller
u8 v = inb(PORT_PS2_STATUS);
lretw
.endm
+ IRQ_TRAMPOLINE 02
IRQ_TRAMPOLINE 10
IRQ_TRAMPOLINE 13
IRQ_TRAMPOLINE 15
IRQ_TRAMPOLINE 16
IRQ_TRAMPOLINE 18
IRQ_TRAMPOLINE 19
+ IRQ_TRAMPOLINE 1c
+ IRQ_TRAMPOLINE 4a
/****************************************************************
* Interrupt entry points
****************************************************************/
- // Main entry point for interrupts without args
- DECLFUNC irqentry
-irqentry:
- ENTRY_ST
+ // Main entry point for interrupts handled on extra stack
+ DECLFUNC irqentry_extrastack
+irqentry_extrastack:
+ cli
+ cld
+ pushw %ds
+ pushl %eax
+ movl $_datalow_seg, %eax
+ movl %eax, %ds
+ movl StackPos, %eax
+ subl $BREGS_size+12, %eax
+ popl BREGS_eax(%eax)
+ popw BREGS_ds(%eax)
+ movl %edi, BREGS_edi(%eax)
+ movl %esi, BREGS_esi(%eax)
+ movl %ebp, BREGS_ebp(%eax)
+ movl %ebx, BREGS_ebx(%eax)
+ movl %edx, BREGS_edx(%eax)
+ movl %ecx, BREGS_ecx(%eax)
+ movw %es, BREGS_es(%eax)
+ popl %ecx
+ popl BREGS_code(%eax)
+ popw BREGS_flags(%eax)
+
+ movw %ss, BREGS_size+8(%eax)
+ movzwl %sp, %edx
+ movl %edx, BREGS_size+4(%eax)
+ movl %esp, BREGS_size+0(%eax)
+ movw %ds, %dx
+ movw %dx, %ss
+ movl %eax, %esp
+ calll *%ecx
+
+ movl %esp, %eax
+ movw BREGS_size+8(%eax), %ss
+ movl BREGS_size+0(%eax), %esp
+ movl BREGS_edi(%eax), %edi
+ movl BREGS_esi(%eax), %esi
+ movl BREGS_ebp(%eax), %ebp
+ movl BREGS_ebx(%eax), %ebx
+ movl BREGS_edx(%eax), %edx
+ movl BREGS_ecx(%eax), %ecx
+ movw BREGS_es(%eax), %es
+ pushw BREGS_flags(%eax)
+ pushl BREGS_code(%eax)
+ pushw BREGS_ds(%eax)
+ pushl BREGS_eax(%eax)
+ popl %eax
+ popw %ds
iretw
// Main entry point for interrupts with args
ENTRY_ARG_ST
iretw
- // Define an entry point for an interrupt (no args passed).
+ // Define an entry point for hardware interrupts.
.macro IRQ_ENTRY num
.global entry_\num
entry_\num :
pushl $ handle_\num
- jmp irqentry
+ jmp irqentry_extrastack
.endm
.macro DECL_IRQ_ENTRY num
}
// Switch to the extra stack and call a function.
-inline u32
+u32
stack_hop(u32 eax, u32 edx, void *func)
{
if (on_extra_stack())
}
// Switch back to original caller's stack and call a function.
-static u32
+u32
stack_hop_back(u32 eax, u32 edx, void *func)
{
if (!on_extra_stack())
return *(volatile const u8 *)addr;
}
-#define call16_simpint(nr, peax, pflags) do { \
- ASSERT16(); \
- asm volatile( \
- "pushl %%ebp\n" \
- "sti\n" \
- "stc\n" \
- "int %2\n" \
- "pushfl\n" \
- "popl %1\n" \
- "cli\n" \
- "cld\n" \
- "popl %%ebp" \
- : "+a"(*peax), "=c"(*pflags) \
- : "i"(nr) \
- : "ebx", "edx", "esi", "edi", "cc", "memory"); \
- } while (0)
-
// GDT bits
#define GDT_CODE (0x9bULL << 40) // Code segment - P,R,A bits also set
#define GDT_DATA (0x93ULL << 40) // Data segment - W,A bits also set
// stacks.c
extern u8 ExtraStack[], *StackPos;
-inline u32 stack_hop(u32 eax, u32 edx, void *func);
+u32 stack_hop(u32 eax, u32 edx, void *func);
+u32 stack_hop_back(u32 eax, u32 edx, void *func);
u32 call32(void *func, u32 eax, u32 errret);
struct bregs;
inline void farcall16(struct bregs *callregs);
void __dprintf(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2)));
void __debug_enter(struct bregs *regs, const char *fname);
-void __debug_isr(const char *fname);
void __debug_stub(struct bregs *regs, int lineno, const char *fname);
void __warn_invalid(struct bregs *regs, int lineno, const char *fname);
void __warn_unimplemented(struct bregs *regs, int lineno, const char *fname);
if ((lvl) && (lvl) <= CONFIG_DEBUG_LEVEL) \
__debug_enter((regs), __func__); \
} while (0)
-#define debug_isr(lvl) do { \
- if ((lvl) && (lvl) <= CONFIG_DEBUG_LEVEL) \
- __debug_isr(__func__); \
- } while (0)
#define debug_stub(regs) \
__debug_stub((regs), __LINE__, __func__)
#define warn_invalid(regs) \
import re
# Functions that change stacks
-STACKHOP = ['__send_disk_op']
+STACKHOP = ['stack_hop', 'stack_hop_back']
# List of functions we can assume are never called.
#IGNORE = ['panic', '__dprintf']
IGNORE = ['panic']