NanoPayload

stage2/irq.c

149:e4db1ec10bca
2016-02-29 Paul Boddie Switched to mapped stack regions, keeping stack pointers within their regions.
     1 /*     2  * Interrupt handling.     3  *     4  * Copyright (C) 2015, 2016 Paul Boddie <paul@boddie.org.uk>     5  *     6  * This program is free software: you can redistribute it and/or modify     7  * it under the terms of the GNU General Public License as published by     8  * the Free Software Foundation, either version 3 of the License, or     9  * (at your option) any later version.    10  *    11  * This program is distributed in the hope that it will be useful,    12  * but WITHOUT ANY WARRANTY; without even the implied warranty of    13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    14  * GNU General Public License for more details.    15  *    16  * You should have received a copy of the GNU General Public License    17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.    18  */    19     20 #ifdef CONFIG_CPU_JZ4730_MINIPC    21 #include "minipc.h"    22 #else    23 #include "nanonote.h"    24 #endif    25     26 #include "board-specific.h"    27 #include "board.h"    28 #include "lcd.h"    29 #include "jzlcd.h"    30 #include "cpu.h"    31 #include "irq.h"    32     33 extern vidinfo_t panel_info;    34     35 void next_pixel(unsigned short *x, unsigned short *y)    36 {    37 	(*x)++;    38 	if (*x >= panel_info.vl_col) {    39 		*x = 0;    40 		(*y)++;    41 		if (*y >= panel_info.vl_row)    42 			*y = 0;    43 	}    44 }    45     46 /* Task management. */    47     48 enum { max_tasks = 3 };    49 static u32 stack_pointers[max_tasks];    50 static u32 registers[max_tasks][32];    51     52 u8 current_task;    53 u32 *current_stack_pointer;    54 u32 *current_registers;    55     56 extern u32 _got_copy_start;    57     58 const u32 stack_start = 0x00080000;    59 const u32 stack_size = 0x00002000;    60 const u32 pagesize = 4 * 1024;    61     62 /* Tasks. */    63     64 void plot_pattern(unsigned short pixel_type, unsigned short x, unsigned short y)    65 {    66 	while (1) {    67 		if (pixel_type)    68 			test_pixel(x, y, pixel_type);    69 		else    70 			clear_pixel(x, y);    71 		next_pixel(&x, &y);    72 		udelay(100);    73 	}    74 }    75     76 /* Initialisation and handling. */    77     78 void irq_init()    79 {    80 	handle_error_level();    81 	timer_init_irq();    82 	init_interrupts();    83 }    84     85 void irq_handle()    86 {    87 	unsigned short i;    88     89 	/* Check interrupt identity. */    90     91 	if (REG_INTC_IPR & (1 << TIMER_CHAN_IRQ)) {    92     93 		/* Switch task. */    94     95 		switch_task();    96     97 		/* Clear interrupt status. */    98     99 		__intc_ack_irq(TIMER_CHAN_IRQ);   100 		__tcu_clear_full_match_flag(TIMER_CHAN);   101    102 	/* Handle other interrupts, anyway. */   103    104 	} else {   105 		for (i = 0; i < 32; i++) {   106 			if (REG_INTC_IPR & (1 << i))   107 				__intc_ack_irq(i);   108 		}   109 	}   110 }   111    112 void init_tasks()   113 {   114 	current_task = 0;   115 	current_stack_pointer = &stack_pointers[current_task];   116 	current_registers = registers[current_task];   117 }   118    119 void start_task(unsigned short task)   120 {   121 	u32 args[] = {task, 0, (task - 1) * 60};   122 	u32 virtual, physical;   123    124 	/*   125 	Each task employs a stack at a multiple of the given start address in   126 	physical memory, but at the same address in virtual memory.   127 	*/   128    129 	physical = stack_start - stack_size * task;   130 	virtual = physical;   131    132 	init_page_table(page_table_start, virtual - pagesize * 2, physical - pagesize * 2, pagesize, 0x1e, task);   133    134 	stack_pointers[task] = virtual - 12;   135    136 	/*   137 	Set the registers for the new task, initialising the global pointer and   138 	return address.   139 	*/   140    141 	init_registers(registers[task], _got_copy_start, (void (*)()) plot_pattern, args, 3);   142 }   143    144 void switch_task()   145 {   146 	/* Switch the current task. */   147    148 	current_task++;   149 	if (current_task == max_tasks) current_task = 1;   150    151 	/* Indicate the current stack pointer and task registers. */   152    153 	current_stack_pointer = &stack_pointers[current_task];   154 	current_registers = registers[current_task];   155 }