# HG changeset patch # User Paul Boddie # Date 1496001722 -7200 # Node ID 647180a1278b44b2a5f0ce1cb000f49496db5521 # Parent 124757d0843fb23c8a93c30daa854238ed8aad2e Added register and display state saving and retrieval in the interrupt handler. diff -r 124757d0843f -r 647180a1278b display.c --- a/display.c Sun May 28 19:11:01 2017 +0200 +++ b/display.c Sun May 28 22:02:02 2017 +0200 @@ -23,7 +23,7 @@ void init_framebuffer(uint32_t *data) { - uint32_t *addr = (uint32_t *) KSEG0_BASE; + uint32_t *addr = (uint32_t *) SCREEN_BASE_KSEG0; uint16_t x, y; for (y = 0; y < LINE_COUNT; y++) @@ -39,7 +39,7 @@ void init_framebuffer_with_pattern() { - uint32_t *addr = (uint32_t *) KSEG0_BASE; + uint32_t *addr = (uint32_t *) SCREEN_BASE_KSEG0; uint32_t base, value; uint16_t x, y; uint8_t row, offset; diff -r 124757d0843f -r 647180a1278b vga.S --- a/vga.S Sun May 28 19:11:01 2017 +0200 +++ b/vga.S Sun May 28 22:02:02 2017 +0200 @@ -140,8 +140,16 @@ li $s0, 0 /* line counter */ la $s1, vbp_active /* current event */ - move $s2, $zero /* line address */ - move $s3, $zero /* screen address */ + li $s2, SCREEN_BASE /* line address */ + li $s3, SCREEN_BASE /* screen address */ + + /* Save the state for retrieval in the interrupt handler. */ + + li $k0, IRQ_STACK_LIMIT + sw $s0, -44($k0) + sw $s1, -48($k0) + sw $s2, -52($k0) + sw $s3, -56($k0) /* Enable interrupts and loop. */ @@ -482,7 +490,8 @@ */ la $v0, DCH0SSA - sw $zero, 0($v0) + li $v1, SCREEN_BASE + sw $v1, 0($v0) /* For the reset channel, a single byte of zero is transferred: @@ -631,6 +640,28 @@ interrupt_handler: + /* Store affected registers. */ + + li $k0, IRQ_STACK_LIMIT + sw $v0, -4($k0) + sw $v1, -8($k0) + sw $s0, -12($k0) + sw $s1, -16($k0) + sw $s2, -20($k0) + sw $s3, -24($k0) + sw $t8, -28($k0) + sw $ra, -32($k0) + sw $sp, -36($k0) + + /* Load state. */ + + lw $s0, -44($k0) + lw $s1, -48($k0) + lw $s2, -52($k0) + lw $s3, -56($k0) + + li $sp, IRQ_STACK_TOP + /* Check for a timer interrupt condition. */ la $v0, IFS0 @@ -695,14 +726,14 @@ /* Test for wraparound. */ - li $t8, SCREEN_SIZE + li $t8, (SCREEN_BASE + SCREEN_SIZE) sltu $t8, $s2, $t8 bnez $t8, irq_dma_update nop /* Reset the source address. */ - move $s2, $zero + li $s2, SCREEN_BASE irq_dma_update: @@ -718,6 +749,26 @@ sw $v1, CLR($v0) irq_exit: + /* Save state. */ + + li $k0, IRQ_STACK_LIMIT + sw $s0, -44($k0) + sw $s1, -48($k0) + sw $s2, -52($k0) + sw $s3, -56($k0) + + /* Restore affected registers. */ + + lw $v0, -4($k0) + lw $v1, -8($k0) + lw $s0, -12($k0) + lw $s1, -16($k0) + lw $s2, -20($k0) + lw $s3, -24($k0) + lw $t8, -28($k0) + lw $ra, -32($k0) + lw $sp, -36($k0) + eret nop diff -r 124757d0843f -r 647180a1278b vga.h --- a/vga.h Sun May 28 19:11:01 2017 +0200 +++ b/vga.h Sun May 28 22:02:02 2017 +0200 @@ -1,19 +1,25 @@ #ifndef __VGA_H__ #define __VGA_H__ -#define LINE_LENGTH 160 /* pixels */ -#define LINE_COUNT 256 /* distinct display lines */ +#define LINE_LENGTH 160 /* pixels */ +#define LINE_COUNT 256 /* distinct display lines */ -#define HFREQ_LIMIT 643 /* 24MHz cycles */ -#define HSYNC_START 460 /* 24MHz cycles */ -#define HSYNC_LIMIT 64 /* 24MHz cycles */ +#define HFREQ_LIMIT 643 /* 24MHz cycles */ +#define HSYNC_START 460 /* 24MHz cycles */ +#define HSYNC_LIMIT 64 /* 24MHz cycles */ #define HSYNC_END (HSYNC_START + HSYNC_LIMIT) -#define VISIBLE_START 70 /* horizontal lines, back porch end */ +#define VISIBLE_START 70 /* horizontal lines, back porch end */ #define VFP_START (VISIBLE_START + 2 * LINE_COUNT) -#define VSYNC_START 620 /* horizontal lines, front porch end */ -#define VSYNC_END 622 /* horizontal lines, back porch start */ +#define VSYNC_START 620 /* horizontal lines, front porch end */ +#define VSYNC_END 622 /* horizontal lines, back porch start */ +#define SCREEN_BASE 256 #define SCREEN_SIZE (40 * 1024) +#define SCREEN_BASE_KSEG0 (KSEG0_BASE + SCREEN_BASE) + +#define IRQ_STACK_LIMIT SCREEN_BASE_KSEG0 +#define IRQ_STACK_TOP (IRQ_STACK_LIMIT - 56) + #endif /* __VGA_H__ */