1
0
mirror of git://projects.qi-hardware.com/iris.git synced 2024-07-01 02:32:00 +03:00
iris/init.ccp
2009-05-18 09:30:27 +02:00

146 lines
4.1 KiB
COBOL

#pypp 0
// Also declare things which only work during kernel init.
#define INIT
#include "kernel.hh"
#define cp0_get(reg, sel, target) do { __asm__ volatile ("mfc0 %0, $" #reg ", " #sel : "=r (target)); } while (0)
#define cp0_set(reg, value) do { __asm__ volatile ("mtc0 %0, $" #reg :: "r (value)); } while (0)
#define cp0_set0(reg) do { __asm__ volatile ("mtc0 $zero, $" #reg); } while (0)
// cp0 registers.
#define INDEX 0
#define ENTRY_LO0 2
#define ENTRY_LO1 3
#define PAGE_MASK 5
#define WIRED 6
#define COUNT 9
#define ENTRY_HI 10
#define COMPARE 11
#define STATUS 12
#define CAUSE 13
#define EPC 14
#define CONFIG 16
static void init_idle ():
// initialize idle task as if it is currently running.
idle.size = sizeof (Thread)
idle.prev = NULL
idle.next = NULL
idle.thread_prev = NULL
idle.thread_next = NULL
idle.schedule_prev = NULL
idle.schedule_next = NULL
idle.address_space = &idle_memory
// initialize idle_memory.
idle_memory.size = sizeof (Memory)
idle_memory.prev = NULL
idle_memory.next = NULL
idle_memory.memory_prev = NULL
idle_memory.memory_next = NULL
idle_memory.pages = &idle_page
idle_memory.threads = &idle
idle_memory.memories = NULL
idle_memory.limit = 0
idle_memory.used = 0
idle_memory.cpu.directory = (Page ***)0x80000000
idle_memory.cpu.asid = 0
// initialize idle_page
idle_page.size = sizeof (Page)
idle_page.prev = NULL
idle_page.next = NULL
idle_page.page_prev = NULL
idle_page.page_next = NULL
// Not an error, this is really physical page 0.
idle_page.physical = 0
static void init_cp0 ():
// Set timer to a defined value
cp0_set (COMPARE, 1000000)
// Reset timer
cp0_set0 (COUNT)
// Use the interrupt vector for interrupts
cp0_set (CAUSE, 1 << 23)
// clear the tlb, hardwire page 0 to 0xffffffff
// and soft-wire it to (0x294 << 20) + (0x290 << 10)
// (for the idle task).
cp0_set (WIRED, 1)
cp0_set0 (PAGE_MASK)
cp0_set0 (ENTRY_LO0)
cp0_set0 (ENTRY_LO1)
// Get number of tlb entries (is 31).
unsigned num;
cp0_get (CONFIG, 1, num)
num >>= 25
num &= 0x3f
// Clear the tlb.
#if 0
for unsigned i = 1; i < num; ++i:
// this address doesn't reach the tlb, so it can't trigger exceptions.
cp0_set (ENTRY_HI, 0x70000000 + 0x1000 * i)
cp0_set (INDEX, i)
// write the data.
__asm__ volatile ("tlbwi")
#endif
// Fill the upper page in kseg3.
cp0_set (ENTRY_HI, 0xfffff000)
cp0_set (ENTRY_LO0, 0x1d)
cp0_set (ENTRY_LO1, 0x1f)
cp0_set0 (INDEX)
__asm__ volatile ("tlbwi")
// Fill the idle task's page in useg. Set it to non-cachable.
cp0_set (ENTRY_HI, 0x284a0000)
cp0_set (ENTRY_LO0, 0x16)
cp0_set (ENTRY_LO1, 0x14)
__asm__ volatile ("tlbwr")
// Allow eret to be used to jump to the idle task.
cp0_set (EPC, 0x284a0288)
// Enable all interrupts and say we're handling an exception.
// Since we're going to enter the idle task, allow access to cp0.
cp0_set (STATUS, 0x1000ff13)
static void init_threads ():
for unsigned i = 0; i < NUM_THREADS; ++i:
Memory *mem = top_memory.alloc_memory ()
Thread *thread = mem->alloc_thread ()
// TODO
/// Initialize the kernel, finish by falling into the idle task.
extern unsigned _end
void init ():
// Initialize kernel variables to empty.
sleepers = NULL
runners = NULL
zero_pages = NULL
// Fill junk pages with all memory not currently used.
junk_pages = (FreePage *)(((unsigned)&_end + (1 << 12) - 1) & ~((1 << 12) - 1))
FreePage *p, *next
unsigned count = 1
for p = junk_pages, next = p; (unsigned)next - 0x80000000 < (1 << 27); p = next, next = (FreePage *)((unsigned)p + (1 << 12)):
p->next = next
++count
p->next = NULL
// initialize system control coprocessor.
init_cp0 ()
// initialize everything about the idle task.
init_idle ()
// initialize top_memory.
top_memory.size = sizeof (Memory)
top_memory.prev = NULL
top_memory.next = NULL
top_memory.memory_prev = NULL
top_memory.memory_next = NULL
top_memory.pages = NULL
top_memory.threads = NULL
top_memory.memories = NULL
top_memory.limit = count
top_memory.used = 0
top_memory.cpu.directory = NULL
top_memory.cpu.asid = 0
init_threads ()
// Done; return to user space (the idle task).
__asm__ volatile ("eret")