mirror of
git://projects.qi-hardware.com/iris.git
synced 2025-04-21 12:27:27 +03:00
make things work with unfinished new startup procedure
This commit is contained in:
@@ -33,16 +33,16 @@ void ball (int x, int y, unsigned colour):
|
||||
continue
|
||||
framebuffer[ty * 320 + tx] = (colour)
|
||||
|
||||
Kernel::Num start ():
|
||||
Kernel::my_parent.init_done ()
|
||||
Iris::Num start ():
|
||||
Iris::my_parent.init_done ()
|
||||
int colour = 0x3f30ff
|
||||
framebuffer = (unsigned *)0x15000
|
||||
Display display = Kernel::my_parent.get_device <Display> (0x10000)
|
||||
Iris::Display display = Iris::my_parent.get_device <Iris::Display> (0x10000)
|
||||
int x = r, y = r, dx = 3, dy = 0
|
||||
Kernel::Cap eof = Kernel::my_receiver.create_capability (0)
|
||||
Iris::Cap eof = Iris::my_receiver.create_capability (0)
|
||||
while true:
|
||||
display.set_eof_cb (eof)
|
||||
Kernel::wait ()
|
||||
Iris::wait ()
|
||||
ball (x, y, 0)
|
||||
x += dx
|
||||
y += dy
|
||||
|
||||
@@ -32,16 +32,16 @@ void square (int x, int y, bool print):
|
||||
continue
|
||||
framebuffer[ty * 320 + tx] = (print ? colour : 0)
|
||||
|
||||
Kernel::Num start ():
|
||||
Kernel::my_parent.init_done ()
|
||||
Iris::Num start ():
|
||||
Iris::my_parent.init_done ()
|
||||
colour = 0xffff00
|
||||
framebuffer = (unsigned *)0x15000
|
||||
Display display = Kernel::my_parent.get_device <Display> (0x10001)
|
||||
Iris::Display display = Iris::my_parent.get_device <Iris::Display> (0x10001)
|
||||
int x = r, y = r, dx = 3, dy = 3
|
||||
Kernel::Cap eof = Kernel::my_receiver.create_capability (0)
|
||||
Iris::Cap eof = Iris::my_receiver.create_capability (0)
|
||||
while true:
|
||||
display.set_eof_cb (eof)
|
||||
Kernel::wait ()
|
||||
Iris::wait ()
|
||||
square (x, y, false)
|
||||
x += dx
|
||||
y += dy
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
class DevBuzzer:
|
||||
static unsigned const pwm = 4
|
||||
Kernel::Cap event
|
||||
Iris::Cap event
|
||||
bool is_beeping
|
||||
public:
|
||||
DevBuzzer ():
|
||||
@@ -36,9 +36,9 @@ class DevBuzzer:
|
||||
return
|
||||
tcu_stop_counter (pwm)
|
||||
event.invoke ()
|
||||
Kernel::free_cap (event)
|
||||
Iris::free_cap (event)
|
||||
is_beeping = false
|
||||
void beep (unsigned freq, unsigned ms, Kernel::Cap cb):
|
||||
void beep (unsigned freq, unsigned ms, Iris::Cap cb):
|
||||
stop ()
|
||||
event = cb
|
||||
unsigned full = JZ_EXTAL / 64 / freq
|
||||
@@ -46,37 +46,37 @@ class DevBuzzer:
|
||||
tcu_set_half_data (pwm, full / 2)
|
||||
tcu_set_count (pwm, 0)
|
||||
tcu_start_counter (pwm)
|
||||
Kernel::my_receiver.set_alarm (ms * HZ / 1000)
|
||||
Iris::my_receiver.set_alarm (ms * HZ / 1000)
|
||||
is_beeping = true
|
||||
|
||||
enum codes:
|
||||
BUZZER = 32
|
||||
|
||||
Kernel::Num start ():
|
||||
Iris::Num start ():
|
||||
map_tcu ()
|
||||
|
||||
DevBuzzer buzzer
|
||||
|
||||
Device dev = Kernel::my_receiver.create_capability (BUZZER)
|
||||
Kernel::my_parent.provide_device <Buzzer> (dev.copy ())
|
||||
Kernel::free_cap (dev)
|
||||
Kernel::my_parent.init_done ()
|
||||
Iris::Device dev = Iris::my_receiver.create_capability (BUZZER)
|
||||
Iris::my_parent.provide_device <Iris::Buzzer> (dev.copy ())
|
||||
Iris::free_cap (dev)
|
||||
Iris::my_parent.init_done ()
|
||||
unsigned user (~0)
|
||||
unsigned next_user (0)
|
||||
while true:
|
||||
Kernel::wait ()
|
||||
switch Kernel::recv.protected_data.h:
|
||||
Iris::wait ()
|
||||
switch Iris::recv.protected_data.h:
|
||||
case ~0:
|
||||
// Alarm.
|
||||
buzzer.stop ()
|
||||
break
|
||||
case 0:
|
||||
switch Kernel::recv.protected_data.l:
|
||||
switch Iris::recv.protected_data.l:
|
||||
case BUZZER:
|
||||
// Buzzer device control request.
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
Kernel::Cap arg = Kernel::get_arg ()
|
||||
Device::host (BUZZER, user, reply, arg)
|
||||
Iris::Cap reply = Iris::get_reply ()
|
||||
Iris::Cap arg = Iris::get_arg ()
|
||||
Iris::Device::host (BUZZER, user, reply, arg)
|
||||
break
|
||||
default:
|
||||
kdebug ("invalid buzzer request\n")
|
||||
@@ -84,22 +84,22 @@ Kernel::Num start ():
|
||||
break
|
||||
case BUZZER:
|
||||
// Buzzer device user request.
|
||||
if Kernel::recv.protected_data.l != user:
|
||||
if Iris::recv.protected_data.l != user:
|
||||
kdebug ("invalid user requesting buzzer\n")
|
||||
Kernel::recv.reply.invoke ()
|
||||
Iris::recv.reply.invoke ()
|
||||
break
|
||||
switch Kernel::recv.data[0].l:
|
||||
case Buzzer::BEEP:
|
||||
switch Iris::recv.data[0].l:
|
||||
case Iris::Buzzer::BEEP:
|
||||
// Volume is not used by this buzzer.
|
||||
Kernel::Cap arg = Kernel::get_arg ()
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
buzzer.beep (Kernel::recv.data[1].l, Kernel::recv.data[1].h, arg)
|
||||
Iris::Cap arg = Iris::get_arg ()
|
||||
Iris::Cap reply = Iris::get_reply ()
|
||||
buzzer.beep (Iris::recv.data[1].l, Iris::recv.data[1].h, arg)
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (reply)
|
||||
Iris::free_cap (reply)
|
||||
break
|
||||
case Buzzer::STOP:
|
||||
case Iris::Buzzer::STOP:
|
||||
buzzer.stop ()
|
||||
Kernel::recv.reply.invoke ()
|
||||
Iris::recv.reply.invoke ()
|
||||
break
|
||||
default:
|
||||
kdebug ("Buzzer: other\n")
|
||||
@@ -107,5 +107,5 @@ Kernel::Num start ():
|
||||
break
|
||||
default:
|
||||
kdebug ("Buzzer: unknown num: ")
|
||||
kdebug_num (Kernel::recv.protected_data.h)
|
||||
kdebug_num (Iris::recv.protected_data.h)
|
||||
kdebug ("\n")
|
||||
@@ -29,7 +29,9 @@ static unsigned __slots, __caps
|
||||
static list *__slot_admin, *__cap_admin
|
||||
static list *__first_free_slot, *__first_free_cap
|
||||
|
||||
namespace Kernel:
|
||||
namespace Iris:
|
||||
bool enable_debug
|
||||
Caps my_caps
|
||||
Receiver my_receiver
|
||||
Thread my_thread
|
||||
Memory my_memory
|
||||
@@ -44,6 +46,8 @@ namespace Kernel:
|
||||
used[i] = true
|
||||
unsigned num = 0
|
||||
for list *i = __first_free_cap; i; i = i->next:
|
||||
if used[i - __cap_admin] == false:
|
||||
panic (0, "inconsistent userspace cap db")
|
||||
used[i - __cap_admin] = false
|
||||
++num
|
||||
kdebug_num (num, 2)
|
||||
@@ -54,6 +58,9 @@ namespace Kernel:
|
||||
|
||||
void free_slot (unsigned slot):
|
||||
//kdebug ("free slot\n")
|
||||
for list *i = __first_free_slot; i; i = i->next:
|
||||
if slot == i - __slot_admin:
|
||||
panic (0, "double free of userspace slot")
|
||||
__slot_admin[slot].prev = NULL
|
||||
__slot_admin[slot].next = __first_free_slot
|
||||
if __slot_admin[slot].next:
|
||||
@@ -61,12 +68,16 @@ namespace Kernel:
|
||||
__first_free_slot = &__slot_admin[slot]
|
||||
|
||||
void free_cap (Cap cap):
|
||||
//kdebug ("free cap ")
|
||||
//kdebug_num (cap.idx (), 2)
|
||||
//kdebug ("\n")
|
||||
if enable_debug:
|
||||
kdebug ("free cap ")
|
||||
kdebug_num (cap.idx (), 2)
|
||||
kdebug ("\n")
|
||||
for list *i = __first_free_cap; i; i = i->next:
|
||||
if cap.idx () == i - __cap_admin:
|
||||
panic (0, "double free of userspace cap")
|
||||
if cap.slot () != 0:
|
||||
kdebug ("trying to free capability from non-0 slot\n")
|
||||
Kernel::panic (0)
|
||||
Iris::panic (0)
|
||||
return
|
||||
list *l = &__cap_admin[cap.idx ()]
|
||||
l->prev = NULL
|
||||
@@ -80,7 +91,7 @@ namespace Kernel:
|
||||
if !__first_free_slot:
|
||||
// Out of slots... Probably best to raise an exception. For now, just return NO_SLOT.
|
||||
kdebug ("out of slots!\n")
|
||||
Kernel::panic (0)
|
||||
Iris::panic (0)
|
||||
return ~0
|
||||
list *ret = __first_free_slot
|
||||
__first_free_slot = ret->next
|
||||
@@ -89,42 +100,45 @@ namespace Kernel:
|
||||
return ret - __slot_admin
|
||||
|
||||
Cap alloc_cap ():
|
||||
//kdebug ("alloc cap ")
|
||||
if !__first_free_cap:
|
||||
// Out of caps... Probably best to raise an exception. For now, just return CAP_NONE
|
||||
kdebug ("out of capabilities!\n")
|
||||
Kernel::panic (0)
|
||||
Iris::panic (0)
|
||||
return Cap (0, CAP_NONE)
|
||||
list *ret = __first_free_cap
|
||||
__first_free_cap = ret->next
|
||||
if ret->next:
|
||||
ret->next->prev = NULL
|
||||
//kdebug_num (ret - __cap_admin, 2)
|
||||
//kdebug ("\n")
|
||||
if enable_debug:
|
||||
kdebug ("alloc cap ")
|
||||
kdebug_num (ret - __cap_admin, 2)
|
||||
kdebug ("\n")
|
||||
return Cap (0, ret - __cap_admin)
|
||||
|
||||
extern "C":
|
||||
void run__main (unsigned slots, unsigned caps, list *slot_admin, list *cap_admin):
|
||||
Iris::enable_debug = false
|
||||
__slots = slots
|
||||
__caps = caps
|
||||
__slot_admin = slot_admin
|
||||
__cap_admin = cap_admin
|
||||
__first_free_slot = NULL
|
||||
for unsigned i = 1; i < __slots; ++i:
|
||||
Kernel::free_slot (i)
|
||||
Iris::free_slot (i)
|
||||
__first_free_cap = NULL
|
||||
for unsigned i = 7; i < __caps; ++i:
|
||||
Kernel::free_cap (Kernel::Cap (0, i))
|
||||
Kernel::my_receiver = Kernel::Cap (0, __receiver_num)
|
||||
Kernel::my_thread = Kernel::Cap (0, __thread_num)
|
||||
Kernel::my_memory = Kernel::Cap (0, __memory_num)
|
||||
Kernel::my_call = Kernel::Cap (0, __call_num)
|
||||
Kernel::my_parent = Kernel::Cap (0, __parent_num)
|
||||
Kernel::recv.reply = Kernel::alloc_cap ()
|
||||
Kernel::recv.arg = Kernel::alloc_cap ()
|
||||
Kernel::Num ret = start ()
|
||||
Kernel::my_parent.invoke (~0, ret)
|
||||
Kernel::my_memory.destroy (Kernel::my_thread)
|
||||
for unsigned i = 6; i < __caps; ++i:
|
||||
Iris::free_cap (Iris::Cap (0, i))
|
||||
Iris::my_caps = Iris::Cap (0, __caps_num)
|
||||
Iris::my_receiver = Iris::Cap (0, __receiver_num)
|
||||
Iris::my_thread = Iris::Cap (0, __thread_num)
|
||||
Iris::my_memory = Iris::Cap (0, __memory_num)
|
||||
Iris::my_call = Iris::Cap (0, __call_num)
|
||||
Iris::my_parent = Iris::Cap (0, __parent_num)
|
||||
Iris::recv.reply = Iris::alloc_cap ()
|
||||
Iris::recv.arg = Iris::alloc_cap ()
|
||||
Iris::Num ret = start ()
|
||||
Iris::my_parent.invoke (~0, ret)
|
||||
Iris::my_memory.destroy (Iris::my_thread)
|
||||
// The program no longer exists. If it somehow does, generate an address fault.
|
||||
while true:
|
||||
*(volatile unsigned *)~0
|
||||
|
||||
@@ -19,64 +19,64 @@
|
||||
#include <devices.hh>
|
||||
#include <iris.hh>
|
||||
|
||||
Kernel::Num start ():
|
||||
Device d = Kernel::my_receiver.create_capability (0)
|
||||
Kernel::my_parent.provide_device <Display> (d.copy (), 0x10000)
|
||||
Kernel::free_cap (d)
|
||||
Kernel::my_parent.init_done ()
|
||||
Display real = Kernel::my_parent.get_device <Display> (0)
|
||||
Iris::Num start ():
|
||||
Iris::Device d = Iris::my_receiver.create_capability (0)
|
||||
Iris::my_parent.provide_device <Iris::Display> (d.copy (), 0x10000)
|
||||
Iris::free_cap (d)
|
||||
Iris::my_parent.init_done ()
|
||||
Iris::Display real = Iris::my_parent.get_device <Iris::Display> (0)
|
||||
while true:
|
||||
Kernel::wait ()
|
||||
Kernel::Cap arg = Kernel::get_arg ()
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
switch Kernel::recv.protected_data.h:
|
||||
Iris::wait ()
|
||||
Iris::Cap arg = Iris::get_arg ()
|
||||
Iris::Cap reply = Iris::get_reply ()
|
||||
switch Iris::recv.protected_data.h:
|
||||
case 0:
|
||||
switch Kernel::recv.data[0].l:
|
||||
case Device::CREATE_USER:
|
||||
Kernel::Memory mem (arg)
|
||||
Kernel::Caps ret = mem.create_caps (3)
|
||||
Kernel::Cap target = Kernel::my_receiver.create_capability (Kernel::Num (0, 1))
|
||||
switch Iris::recv.data[0].l:
|
||||
case Iris::Device::CREATE_USER:
|
||||
Iris::Memory mem (arg)
|
||||
Iris::Caps ret = mem.create_caps (3)
|
||||
Iris::Cap target = Iris::my_receiver.create_capability (Iris::Num (0, 1))
|
||||
ret.set (0, target.copy ())
|
||||
ret.set (1, mem)
|
||||
Kernel::free_cap (target)
|
||||
Iris::free_cap (target)
|
||||
for unsigned i = 0; i < 320 * 240 * 4; i += PAGE_SIZE:
|
||||
Kernel::Page p = Kernel::my_memory.mapping ((void *)(0x15000 + i))
|
||||
Kernel::Page t = mem.create_page ()
|
||||
t.set_flags (Kernel::Page::PAYING, Kernel::Page::PAYING)
|
||||
p.share (t, Kernel::Page::FORGET)
|
||||
Iris::Page p = Iris::my_memory.mapping ((void *)(0x15000 + i))
|
||||
Iris::Page t = mem.create_page ()
|
||||
t.set_flags (Iris::Page::PAYING, Iris::Page::PAYING)
|
||||
p.share (t, Iris::Page::FORGET)
|
||||
mem.map (t, 0x15000 + i)
|
||||
Kernel::my_memory.destroy (t)
|
||||
Kernel::free_cap (t)
|
||||
Kernel::free_cap (p)
|
||||
Iris::my_memory.destroy (t)
|
||||
Iris::free_cap (t)
|
||||
Iris::free_cap (p)
|
||||
reply.invoke (0, 0, ret.copy ())
|
||||
Kernel::free_cap (ret)
|
||||
Iris::free_cap (ret)
|
||||
break
|
||||
case Device::DESTROY_USER:
|
||||
Kernel::panic (0, "destroying emulation user")
|
||||
case Device::USE:
|
||||
case Device::UNUSE:
|
||||
case Iris::Device::DESTROY_USER:
|
||||
Iris::panic (0, "destroying emulation user")
|
||||
case Iris::Device::USE:
|
||||
case Iris::Device::UNUSE:
|
||||
reply.invoke ()
|
||||
break
|
||||
default:
|
||||
kdebug_num (Kernel::recv.data[0].l)
|
||||
kdebug_num (Iris::recv.data[0].l)
|
||||
kdebug ("\n")
|
||||
Kernel::panic (0, "invalid emulation command")
|
||||
Iris::panic (0, "invalid emulation command")
|
||||
break
|
||||
case 1:
|
||||
switch Kernel::recv.data[0].l:
|
||||
case Display::SET_EOF_CB:
|
||||
switch Iris::recv.data[0].l:
|
||||
case Iris::Display::SET_EOF_CB:
|
||||
real.set_eof_cb (arg.copy ())
|
||||
while Kernel::recv.data[0].l != 0:
|
||||
Kernel::my_parent.wait <Display> (0)
|
||||
while Iris::recv.data[0].l != 0:
|
||||
Iris::my_parent.wait <Iris::Display> (0)
|
||||
real.set_eof_cb (arg.copy ())
|
||||
reply.invoke ()
|
||||
break
|
||||
default:
|
||||
kdebug_num (Kernel::recv.data[0].l)
|
||||
kdebug_num (Iris::recv.data[0].l)
|
||||
kdebug_char ('\n')
|
||||
Kernel::panic (Kernel::recv.data[0].l, "invalid operation on display emulation")
|
||||
Iris::panic (Iris::recv.data[0].l, "invalid operation on display emulation")
|
||||
break
|
||||
default:
|
||||
Kernel::panic (0, "bug in display emulation")
|
||||
Kernel::free_cap (arg)
|
||||
Kernel::free_cap (reply)
|
||||
Iris::panic (0, "bug in display emulation")
|
||||
Iris::free_cap (arg)
|
||||
Iris::free_cap (reply)
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
display-emu.ccp
|
||||
286
source/elfrun.ccp
Normal file
286
source/elfrun.ccp
Normal file
@@ -0,0 +1,286 @@
|
||||
#pypp 0
|
||||
// Iris: micro-kernel for a capability-based operating system.
|
||||
// source/elfrun.ccp: Process creation server.
|
||||
// Copyright 2009 Bas Wijnen <wijnen@debian.org>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "devices.hh"
|
||||
#include "iris.hh"
|
||||
#include <elf.h>
|
||||
|
||||
static unsigned _free
|
||||
extern unsigned _end
|
||||
|
||||
void init_alloc ():
|
||||
_free = ((unsigned)&_end + PAGE_SIZE - 1) & PAGE_MASK
|
||||
|
||||
char *alloc_space (unsigned pages):
|
||||
unsigned ret = (_free + PAGE_SIZE - 1) & PAGE_MASK
|
||||
_free = ret + (pages << PAGE_BITS)
|
||||
return (char *)ret
|
||||
|
||||
void *operator new[] (unsigned size):
|
||||
//kdebug ("new ")
|
||||
void *ret = (void *)_free
|
||||
size = (size + 3) & ~3
|
||||
unsigned rest = PAGE_SIZE - (((_free - 1) & ~PAGE_MASK) + 1)
|
||||
if rest < size:
|
||||
unsigned pages = ((size - rest) + PAGE_SIZE - 1) >> PAGE_BITS
|
||||
for unsigned p = 0; p < pages; ++p:
|
||||
Iris::Page page = Iris::my_memory.create_page ()
|
||||
page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME, Iris::Page::PAYING | Iris::Page::FRAME)
|
||||
Iris::my_memory.map (page, _free + rest + (p << PAGE_BITS))
|
||||
Iris::free_cap (page)
|
||||
_free += size
|
||||
//kdebug_num ((unsigned)ret)
|
||||
//kdebug ("+")
|
||||
//kdebug_num (size)
|
||||
//kdebug ("\n")
|
||||
return ret
|
||||
|
||||
void *operator new (unsigned size):
|
||||
return new char[size]
|
||||
|
||||
static Iris::Memory parent_memory
|
||||
static Iris::Cap parent
|
||||
static unsigned slot
|
||||
static char *mapping
|
||||
static unsigned pages
|
||||
static Iris::Caps pages_caps
|
||||
static Iris::Memory mem
|
||||
|
||||
static Iris::Caps map_string (Iris::String data):
|
||||
// Get the size.
|
||||
Iris::Num size = data.get_size ()
|
||||
if size.value () == 0:
|
||||
Iris::panic (0, "data string is empty")
|
||||
// Allocate a caps with all the pages.
|
||||
pages = (size.value () + PAGE_SIZE - 1) >> PAGE_BITS
|
||||
pages_caps = Iris::my_memory.create_caps (pages)
|
||||
slot = pages_caps.use ()
|
||||
// Map them into the address space as well.
|
||||
mapping = alloc_space (pages)
|
||||
// Create a memory for the program.
|
||||
mem = parent_memory.create_memory ()
|
||||
// Load the file into memory and map it.
|
||||
for unsigned p = 0; p < pages; ++p:
|
||||
//kdebug_num (p)
|
||||
//kdebug ("/")
|
||||
//kdebug_num (pages)
|
||||
//kdebug ("\n")
|
||||
Iris::set_recv_arg (Iris::Cap (slot, p))
|
||||
data.get_page (p << PAGE_BITS)
|
||||
Iris::my_memory.map (Iris::Cap (slot, p), (unsigned)&mapping[p << PAGE_BITS])
|
||||
|
||||
static Iris::Caps map_caps (Iris::Caps data, unsigned p):
|
||||
// Get the size.
|
||||
if p == 0:
|
||||
Iris::panic (0, "data caps is empty")
|
||||
// Allocate a new caps with all the pages for mapping locally.
|
||||
pages = p
|
||||
pages_caps = Iris::my_memory.create_caps (pages)
|
||||
slot = pages_caps.use ()
|
||||
unsigned src_slot = data.use ()
|
||||
// Map them into the address space as well.
|
||||
mapping = alloc_space (pages)
|
||||
// Create a memory for the program.
|
||||
mem = parent_memory.create_memory ()
|
||||
// Load the file into memory and map it.
|
||||
for unsigned p = 0; p < pages; ++p:
|
||||
//kdebug_num (p)
|
||||
//kdebug ("/")
|
||||
//kdebug_num (pages)
|
||||
//kdebug ("\n")
|
||||
Iris::Page page = Iris::Cap (slot, p)
|
||||
Iris::set_recv_arg (page)
|
||||
Iris::my_memory.create_page ()
|
||||
Iris::Page (Iris::Cap (src_slot, p)).share (page)
|
||||
Iris::my_memory.map (page, (unsigned)&mapping[p << PAGE_BITS])
|
||||
Iris::free_slot (src_slot)
|
||||
|
||||
static Iris::Caps run (Iris::Caps data, Iris::Memory parent_memory, Iris::Cap parent, unsigned num_slots, unsigned num_caps):
|
||||
Iris::Thread thread = mem.create_thread (num_slots)
|
||||
Elf32_Ehdr *header = (Elf32_Ehdr *)mapping
|
||||
for unsigned j = 0; j < SELFMAG; ++j:
|
||||
if header->e_ident[j] != ELFMAG[j]:
|
||||
Iris::panic (header->e_ident[j], "invalid ELF magic")
|
||||
return Iris::Caps ()
|
||||
if header->e_ident[EI_CLASS] != ELFCLASS32:
|
||||
kdebug ("invalid ELF class:")
|
||||
kdebug_num (header->e_ident[EI_CLASS])
|
||||
kdebug (" != ")
|
||||
kdebug_num (ELFCLASS32)
|
||||
kdebug ("\n")
|
||||
Iris::panic (0)
|
||||
return Iris::Caps ()
|
||||
if header->e_ident[EI_DATA] != ELFDATA2LSB:
|
||||
Iris::panic (header->e_ident[EI_DATA], "invalid ELF data")
|
||||
if header->e_ident[EI_VERSION] != EV_CURRENT:
|
||||
Iris::panic (header->e_ident[EI_VERSION], "invalid ELF version")
|
||||
if header->e_type != ET_EXEC:
|
||||
Iris::panic (header->e_type, "invalid ELF type")
|
||||
if header->e_machine != EM_MIPS_RS3_LE && header->e_machine != EM_MIPS:
|
||||
Iris::panic (header->e_machine, "invalid ELF machine")
|
||||
thread.set_pc (header->e_entry)
|
||||
thread.set_sp (0x80000000)
|
||||
for unsigned section = 0; section < header->e_shnum; ++section:
|
||||
Elf32_Shdr *shdr = (Elf32_Shdr *)((unsigned)mapping + header->e_shoff + section * header->e_shentsize)
|
||||
if ~shdr->sh_flags & SHF_ALLOC:
|
||||
continue
|
||||
bool readonly = !(shdr->sh_flags & SHF_WRITE)
|
||||
//bool executable = shdr->sh_flags & SHF_EXEC_INSTR
|
||||
if shdr->sh_type != SHT_NOBITS:
|
||||
unsigned file_offset = shdr->sh_offset >> PAGE_BITS
|
||||
if (file_offset + ((shdr->sh_size + PAGE_SIZE - 1) >> PAGE_BITS)) >= (PAGE_SIZE >> 2):
|
||||
kdebug ("thread size: ")
|
||||
kdebug_num (file_offset)
|
||||
kdebug (",")
|
||||
kdebug_num (shdr->sh_size)
|
||||
kdebug ("\n")
|
||||
Iris::panic (shdr->sh_size, "thread too large")
|
||||
return Iris::Caps ()
|
||||
for unsigned p = (shdr->sh_addr & PAGE_MASK); p < shdr->sh_addr + shdr->sh_size; p += PAGE_SIZE:
|
||||
unsigned section_offset = (p - (shdr->sh_addr & PAGE_MASK)) >> PAGE_BITS
|
||||
unsigned idx = file_offset + section_offset
|
||||
Iris::Page page = mem.mapping ((void *)p)
|
||||
if Iris::recv.data[0].l == Iris::NO_ERROR:
|
||||
// The address already has a mapping; assume that it is correct.
|
||||
Iris::free_cap (page)
|
||||
continue
|
||||
Iris::free_cap (page)
|
||||
page = mem.create_page ()
|
||||
unsigned f
|
||||
if readonly:
|
||||
f = Iris::Page::PAYING | Iris::Page::MAPPED_READONLY
|
||||
else:
|
||||
f = Iris::Page::PAYING
|
||||
page.set_flags (f, f)
|
||||
Iris::Page (slot, idx).share (page, 0)
|
||||
//kdebug ("mapping at ")
|
||||
//kdebug_num (p)
|
||||
//if readonly:
|
||||
// kdebug (" (readonly)")
|
||||
//kdebug ("\n")
|
||||
if !mem.map (page, p):
|
||||
Iris::panic (0, "unable to map page")
|
||||
return Iris::Caps ()
|
||||
Iris::free_cap (page)
|
||||
else:
|
||||
if readonly:
|
||||
Iris::panic (0, "unwritable bss section")
|
||||
return Iris::Caps ()
|
||||
for unsigned p = (shdr->sh_addr & PAGE_MASK); p < shdr->sh_addr + shdr->sh_size; p += PAGE_SIZE:
|
||||
Iris::Page page = mem.mapping ((void *)p)
|
||||
if Iris::recv.data[0].l == Iris::NO_ERROR:
|
||||
// No error means there is a mapping.
|
||||
Iris::free_cap (page)
|
||||
for unsigned a = p; a < ((p + PAGE_SIZE) & PAGE_MASK); a += 4:
|
||||
if a >= shdr->sh_addr + shdr->sh_size:
|
||||
break
|
||||
if a < shdr->sh_addr:
|
||||
continue
|
||||
((unsigned *)&mapping[p - shdr->sh_addr])[(a & ~PAGE_MASK) >> 2] = 0
|
||||
else:
|
||||
Iris::free_cap (page)
|
||||
page = mem.create_page ()
|
||||
if Iris::recv.data[0].l != Iris::NO_ERROR:
|
||||
Iris::panic (Iris::recv.data[0].l, "out of memory")
|
||||
if !page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME, Iris::Page::PAYING | Iris::Page::FRAME):
|
||||
Iris::panic (0, "out of memory")
|
||||
if !mem.map (page, p):
|
||||
Iris::panic (0, "unable to map bss page")
|
||||
Iris::free_cap (page)
|
||||
for unsigned p = 0; p < pages; ++p:
|
||||
Iris::my_memory.destroy (Iris::Page (slot, p))
|
||||
Iris::my_memory.destroy (pages_caps)
|
||||
Iris::free_slot (slot)
|
||||
Iris::free_cap (pages_caps)
|
||||
Iris::Page stackpage = mem.create_page ()
|
||||
stackpage.set_flags (Iris::Page::PAYING | Iris::Page::FRAME, Iris::Page::PAYING | Iris::Page::FRAME)
|
||||
if Iris::recv.data[0].l != Iris::NO_ERROR || !mem.map (stackpage, 0x7ffff000):
|
||||
Iris::panic (Iris::recv.data[0].l, "unable to map initial stack page")
|
||||
Iris::free_cap (stackpage)
|
||||
Iris::Caps caps = mem.create_caps (num_caps)
|
||||
thread.use (caps, 0)
|
||||
thread.set_info (Iris::Thread::A0, num_slots)
|
||||
thread.set_info (Iris::Thread::A1, num_caps)
|
||||
Iris::Receiver receiver = mem.create_receiver ()
|
||||
receiver.set_owner (thread.copy ())
|
||||
Iris::Cap call = receiver.create_call_capability ()
|
||||
caps.set (__caps_num, caps.copy ())
|
||||
caps.set (__receiver_num, receiver.copy ())
|
||||
caps.set (__thread_num, thread.copy ())
|
||||
caps.set (__memory_num, mem.copy ())
|
||||
caps.set (__call_num, call.copy ())
|
||||
caps.set (__parent_num, parent.copy ())
|
||||
Iris::free_cap (receiver)
|
||||
Iris::free_cap (thread)
|
||||
Iris::free_cap (mem)
|
||||
Iris::free_cap (call)
|
||||
return caps
|
||||
|
||||
Iris::Num start ():
|
||||
kdebug ("elfrun started.\n")
|
||||
init_alloc ()
|
||||
Iris::Device dev = Iris::my_receiver.create_capability (0)
|
||||
Iris::my_parent.provide_device <Iris::Elfrun> (dev.copy ())
|
||||
|
||||
unsigned user = ~0
|
||||
while true:
|
||||
Iris::wait ()
|
||||
Iris::Cap reply = Iris::get_reply ()
|
||||
Iris::Cap arg = Iris::get_arg ()
|
||||
Iris::print_caps ()
|
||||
switch Iris::recv.protected_data.h:
|
||||
case 0:
|
||||
Iris::Device::host (1, user, reply, arg)
|
||||
break
|
||||
case 1:
|
||||
switch Iris::recv.data[0].l:
|
||||
case Iris::Elfrun::RUN_STRING:
|
||||
unsigned num_slots = Iris::recv.data[1].l
|
||||
unsigned num_caps = Iris::recv.data[1].h
|
||||
parent_memory = Iris::Caps (arg).get (Iris::Elfrun::PARENT_MEMORY)
|
||||
parent = Iris::Caps (arg).get (Iris::Elfrun::PARENT)
|
||||
Iris::String data = Iris::Caps (arg).get (Iris::Elfrun::DATA)
|
||||
map_string (data)
|
||||
Iris::Caps ret = run (data, parent_memory, parent, num_slots, num_caps)
|
||||
reply.invoke (0, 0, ret.copy ())
|
||||
free_cap (ret)
|
||||
free_cap (parent_memory)
|
||||
free_cap (parent)
|
||||
free_cap (data)
|
||||
break
|
||||
case Iris::Elfrun::RUN_CAPS:
|
||||
unsigned num_slots = Iris::recv.data[1].l
|
||||
unsigned num_caps = Iris::recv.data[1].h
|
||||
unsigned p = Iris::recv.data[0].h
|
||||
parent_memory = Iris::Caps (arg).get (Iris::Elfrun::PARENT_MEMORY)
|
||||
parent = Iris::Caps (arg).get (Iris::Elfrun::PARENT)
|
||||
Iris::Caps data = Iris::Caps (arg).get (Iris::Elfrun::DATA)
|
||||
map_caps (data, p)
|
||||
Iris::Caps ret = run (data, parent_memory, parent, num_slots, num_caps)
|
||||
reply.invoke (0, 0, ret.copy ())
|
||||
free_cap (ret)
|
||||
free_cap (parent_memory)
|
||||
free_cap (parent)
|
||||
free_cap (data)
|
||||
break
|
||||
default:
|
||||
Iris::panic (0, "invalid operation for elfrun")
|
||||
reply.invoke (~0)
|
||||
break
|
||||
Iris::free_cap (arg)
|
||||
Iris::free_cap (reply)
|
||||
1
source/gpio.ccp
Symbolic link
1
source/gpio.ccp
Symbolic link
@@ -0,0 +1 @@
|
||||
nanonote-gpio.ccp
|
||||
412
source/init.ccp
Normal file
412
source/init.ccp
Normal file
@@ -0,0 +1,412 @@
|
||||
#pypp 0
|
||||
// Iris: micro-kernel for a capability-based operating system.
|
||||
// bootstrap/init.ccp: Bootstrapping code.
|
||||
// Copyright 2009 Bas Wijnen <wijnen@debian.org>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "devices.hh"
|
||||
#include "iris.hh"
|
||||
#include "keys.hh"
|
||||
|
||||
#define NUM_SLOTS 8
|
||||
#define NUM_CAPS 32
|
||||
|
||||
static unsigned _free
|
||||
extern unsigned _end
|
||||
|
||||
void init_alloc ():
|
||||
_free = ((unsigned)&_end + PAGE_SIZE - 1) & PAGE_MASK
|
||||
|
||||
char *alloc_space (unsigned pages):
|
||||
unsigned ret = (_free + PAGE_SIZE - 1) & PAGE_MASK
|
||||
_free = ret + (pages << PAGE_BITS)
|
||||
return (char *)ret
|
||||
|
||||
void *operator new[] (unsigned size):
|
||||
//kdebug ("new ")
|
||||
void *ret = (void *)_free
|
||||
size = (size + 3) & ~3
|
||||
unsigned rest = PAGE_SIZE - (((_free - 1) & ~PAGE_MASK) + 1)
|
||||
if rest < size:
|
||||
unsigned pages = ((size - rest) + PAGE_SIZE - 1) >> PAGE_BITS
|
||||
for unsigned p = 0; p < pages; ++p:
|
||||
Iris::Page page = Iris::my_memory.create_page ()
|
||||
page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME, Iris::Page::PAYING | Iris::Page::FRAME)
|
||||
Iris::my_memory.map (page, _free + rest + (p << PAGE_BITS))
|
||||
Iris::free_cap (page)
|
||||
_free += size
|
||||
//kdebug_num ((unsigned)ret)
|
||||
//kdebug ("+")
|
||||
//kdebug_num (size)
|
||||
//kdebug ("\n")
|
||||
return ret
|
||||
|
||||
void *operator new (unsigned size):
|
||||
return new char[size]
|
||||
|
||||
template <typename _T> //
|
||||
struct List:
|
||||
struct Item:
|
||||
Item *prev, *next
|
||||
_T value
|
||||
_T &operator* ():
|
||||
return value
|
||||
_T *operator-> ():
|
||||
return &value
|
||||
Item *first
|
||||
Item *begin ():
|
||||
return first
|
||||
void erase (Item *i):
|
||||
if i->prev:
|
||||
i->prev->next = i->next
|
||||
else:
|
||||
first = i->next
|
||||
if i->next:
|
||||
i->next->prev = i->prev
|
||||
delete i
|
||||
Item *insert (Item *after = NULL):
|
||||
Item *ret = new Item
|
||||
if after:
|
||||
ret->prev = after->prev
|
||||
ret->next = after
|
||||
if ret->prev:
|
||||
ret->prev->next = ret
|
||||
else:
|
||||
first = ret
|
||||
after->prev = ret
|
||||
else:
|
||||
ret->prev = NULL
|
||||
ret->next = first
|
||||
first = ret
|
||||
if ret->next:
|
||||
ret->next->prev = ret
|
||||
return ret
|
||||
void init ():
|
||||
first = NULL
|
||||
List () : first (NULL):
|
||||
|
||||
struct Program
|
||||
|
||||
struct Device:
|
||||
char *name
|
||||
unsigned name_len
|
||||
unsigned type, index
|
||||
Iris::Cap cap
|
||||
Program *server
|
||||
Program *client
|
||||
|
||||
struct Program:
|
||||
char *name
|
||||
unsigned name_len
|
||||
unsigned size
|
||||
Iris::Caps pages
|
||||
Iris::Memory memory
|
||||
Iris::Thread thread
|
||||
List <Device> devices
|
||||
|
||||
static Iris::Memory top_memory
|
||||
static Iris::Directory root
|
||||
static Iris::Elfrun elfrun
|
||||
static List <Program> programs
|
||||
|
||||
static bool name_match (char const *name, unsigned name_len, Iris::String n):
|
||||
char nm[16]
|
||||
n.get_chars (0, nm)
|
||||
for unsigned t = 0; t < 16 && t < name_len; ++t:
|
||||
if nm[t] != name[t]:
|
||||
return false
|
||||
return true
|
||||
|
||||
static Iris::Caps load (char const *name, unsigned name_len, unsigned &size, Iris::Caps target = Iris::alloc_cap ()):
|
||||
kdebug ("loading ")
|
||||
for unsigned i = 0; i < name_len; ++i:
|
||||
kdebug_char (name[i])
|
||||
kdebug ("\n")
|
||||
root.lock_ro ()
|
||||
Iris::Num sz = root.get_size ()
|
||||
if sz.h:
|
||||
Iris::panic (sz.h, "too many files")
|
||||
for unsigned i = 0; i < sz.l; ++i:
|
||||
Iris::String n = root.get_name (i)
|
||||
if !name_match (name, name_len, n):
|
||||
Iris::free_cap (n)
|
||||
continue
|
||||
Iris::free_cap (n)
|
||||
Iris::String file = root.get_file_ro (i)
|
||||
Iris::Num s = file.get_size ()
|
||||
if s.h:
|
||||
Iris::panic (s.h, "file is too large to load")
|
||||
size = s.l
|
||||
unsigned pages = (size + PAGE_SIZE - 1) >> PAGE_BITS
|
||||
if pages > 0:
|
||||
Iris::set_recv_arg (target)
|
||||
Iris::my_memory.create_caps (pages)
|
||||
unsigned slot = target.use ()
|
||||
for unsigned p = 0; p < pages; ++p:
|
||||
Iris::set_recv_arg (Iris::Cap (slot, p))
|
||||
file.get_page (p << PAGE_BITS)
|
||||
Iris::free_slot (slot)
|
||||
Iris::free_cap (file)
|
||||
root.unlock_ro ()
|
||||
return target
|
||||
Iris::panic (0, "file not found for init")
|
||||
return target
|
||||
|
||||
static void delspace (char *&line, unsigned &maxlen):
|
||||
while maxlen && (*line == ' ' || *line == '\t'):
|
||||
++line
|
||||
--maxlen
|
||||
if maxlen && *line == '#':
|
||||
line += maxlen
|
||||
maxlen = 0
|
||||
|
||||
static bool match (char *&line, unsigned &maxlen, char const *word):
|
||||
delspace (line, maxlen)
|
||||
char const *w = word
|
||||
char *l = line
|
||||
unsigned len = 0
|
||||
while *word:
|
||||
if *l++ != *word++:
|
||||
return false
|
||||
++len
|
||||
line = l
|
||||
maxlen -= len
|
||||
delspace (line, maxlen)
|
||||
//kdebug ("match: ")
|
||||
//kdebug (w)
|
||||
//kdebug ("\n")
|
||||
return true
|
||||
|
||||
static bool isnamechar (char c):
|
||||
if c >= 'a' && c <= 'z':
|
||||
return true
|
||||
if c >= 'A' && c <= 'Z':
|
||||
return true
|
||||
if c >= '0' && c <= '9':
|
||||
return true
|
||||
if c == '_':
|
||||
return true
|
||||
return false
|
||||
|
||||
static bool get_name (char *&line, unsigned &len, char *&name, unsigned &name_len):
|
||||
delspace (line, len)
|
||||
if !len:
|
||||
return false
|
||||
name_len = 0
|
||||
while name_len < len && isnamechar (line[name_len]):
|
||||
++name_len
|
||||
name = new char[name_len]
|
||||
for unsigned i = 0; i < name_len; ++i:
|
||||
name[i] = line[i]
|
||||
line += name_len
|
||||
len -= name_len
|
||||
delspace (line, len)
|
||||
return true
|
||||
|
||||
static bool string_match (char const *s1, unsigned l1, char const *s2, unsigned l2):
|
||||
if l1 != l2:
|
||||
return false
|
||||
for unsigned i = 0; i < l1; ++i:
|
||||
if s1[i] != s2[i]:
|
||||
return false
|
||||
return true
|
||||
|
||||
struct Type:
|
||||
char const *name
|
||||
unsigned len
|
||||
unsigned type
|
||||
|
||||
static unsigned read_num (char *&line, unsigned &len):
|
||||
delspace (line, len)
|
||||
unsigned num = 0
|
||||
while len && *line >= '0' && *line <= '9':
|
||||
num *= 10
|
||||
num += *line - '0'
|
||||
++line
|
||||
--len
|
||||
delspace (line, len)
|
||||
return num
|
||||
|
||||
static Type types[] = {
|
||||
{ "String", 6, Iris::String::ID },
|
||||
{ "WString", 7, Iris::WString::ID },
|
||||
{ "Device", 6, Iris::Device::ID },
|
||||
{ "Parent", 6, Iris::Parent::ID },
|
||||
{ "Keyboard", 8, Iris::Keyboard::ID },
|
||||
{ "Buzzer", 6, Iris::Buzzer::ID },
|
||||
{ "Display", 7, Iris::Display::ID },
|
||||
{ "Setting", 7, Iris::Setting::ID },
|
||||
{ "Directory", 9, Iris::Directory::ID },
|
||||
{ "WDirectory", 10, Iris::WDirectory::ID },
|
||||
{ "Filesystem", 10, Iris::Filesystem::ID },
|
||||
{ "Stream", 6, Iris::Stream::ID },
|
||||
{ NULL, 0, 0 }
|
||||
}
|
||||
|
||||
static void find_type (char *&line, unsigned &len, unsigned &type, unsigned &index):
|
||||
char *n
|
||||
unsigned l
|
||||
if !get_name (line, len, n, l) || !len:
|
||||
Iris::panic (0, "no name for type")
|
||||
for unsigned t = 0; types[t].len != 0; ++t:
|
||||
if string_match (types[t].name, types[t].len, n, l):
|
||||
type = types[t].type
|
||||
if len && *line == ',':
|
||||
++line
|
||||
--len
|
||||
index = read_num (line, len)
|
||||
else:
|
||||
index = 0
|
||||
return
|
||||
Iris::panic (0, "no valid type found")
|
||||
|
||||
static void parse_line (char *&line, unsigned maxlen):
|
||||
char *start = line
|
||||
while maxlen && *line != '\n':
|
||||
++line
|
||||
--maxlen
|
||||
// The line to execute is from start to line.
|
||||
maxlen = line - start
|
||||
if *line == '\n':
|
||||
++line
|
||||
delspace (start, maxlen)
|
||||
if !maxlen:
|
||||
return
|
||||
if match (start, maxlen, "load"):
|
||||
Program *p = &**programs.insert ()
|
||||
if !get_name (start, maxlen, p->name, p->name_len) || !match (start, maxlen, "=") || !maxlen:
|
||||
Iris::panic (0, "syntax error in init.config (load)")
|
||||
char q = *start++
|
||||
--maxlen
|
||||
unsigned len = 0
|
||||
while maxlen && *start != q:
|
||||
++start
|
||||
--maxlen
|
||||
++len
|
||||
if !maxlen:
|
||||
Iris::panic (0, "no closing quote in init.config")
|
||||
p->pages = load (start - len, len, p->size)
|
||||
++start
|
||||
--maxlen
|
||||
else if match (start, maxlen, "killbootthreads"):
|
||||
Iris::my_parent.init_done ()
|
||||
else if match (start, maxlen, "receive"):
|
||||
// receive <name> / <type> [, <index>] = <cap>
|
||||
char *n
|
||||
unsigned l
|
||||
if !get_name (start, maxlen, n, l) || !match (start, maxlen, "/") || !maxlen:
|
||||
Iris::panic (0, "syntax error in init.config (receive)")
|
||||
List <Program>::Item *p
|
||||
for p = programs.begin (); p; p = p->next:
|
||||
if string_match ((*p)->name, (*p)->name_len, n, l):
|
||||
break
|
||||
if !p:
|
||||
Iris::panic (0, "program not found for receive")
|
||||
List <Device>::Item *dev = (*p)->devices.insert ()
|
||||
find_type (start, maxlen, (*dev)->type, (*dev)->index)
|
||||
if !match (start, maxlen, "=") || !get_name (start, maxlen, (*dev)->name, (*dev)->name_len):
|
||||
Iris::panic (1, "syntax error in init.config (receive)")
|
||||
else if match (start, maxlen, "driver"):
|
||||
char *n
|
||||
unsigned l
|
||||
if !get_name (start, maxlen, n, l):
|
||||
Iris::panic (0, "syntax error in init.config (driver)")
|
||||
List <Program>::Item *p
|
||||
for p = programs.begin (); p; p = p->next:
|
||||
if string_match ((*p)->name, (*p)->name_len, n, l):
|
||||
break
|
||||
if !p:
|
||||
Iris::panic (0, "program not found for driver")
|
||||
Iris::Cap cap = Iris::my_receiver.create_capability ((unsigned)&**p)
|
||||
kdebug ("running ")
|
||||
for unsigned i = 0; i < (*p)->name_len; ++i:
|
||||
kdebug_char ((*p)->name[i])
|
||||
kdebug ("\n")
|
||||
Iris::Caps caps = elfrun.run_caps (top_memory, (*p)->pages, cap.copy (), ((*p)->size + PAGE_SIZE - 1) >> PAGE_BITS)
|
||||
Iris::free_cap (cap)
|
||||
(*p)->thread = caps.get (__thread_num)
|
||||
(*p)->memory = caps.get (__memory_num)
|
||||
(*p)->thread.make_priv ()
|
||||
(*p)->thread.run ()
|
||||
// TODO: pass arguments.
|
||||
start += maxlen
|
||||
maxlen = 0
|
||||
else if match (start, maxlen, "wait"):
|
||||
// TODO
|
||||
start += maxlen
|
||||
maxlen = 0
|
||||
else if match (start, maxlen, "sysreq"):
|
||||
// TODO
|
||||
start += maxlen
|
||||
maxlen = 0
|
||||
else if match (start, maxlen, "give"):
|
||||
// TODO
|
||||
start += maxlen
|
||||
maxlen = 0
|
||||
else if match (start, maxlen, "run"):
|
||||
// TODO
|
||||
start += maxlen
|
||||
maxlen = 0
|
||||
else if match (start, maxlen, "include"):
|
||||
// TODO
|
||||
start += maxlen
|
||||
maxlen = 0
|
||||
else:
|
||||
Iris::panic (0, "invalid line in init.config")
|
||||
delspace (start, maxlen)
|
||||
if maxlen:
|
||||
kdebug ("Junk: ")
|
||||
for unsigned i = 0; i < maxlen; ++i:
|
||||
kdebug_char (start[i])
|
||||
kdebug_char ('\n')
|
||||
Iris::panic (0, "junk at end of line in init.config")
|
||||
|
||||
Iris::Num start ():
|
||||
init_alloc ()
|
||||
programs.init ()
|
||||
root = Iris::my_parent.get_device <Iris::Directory> ()
|
||||
elfrun = Iris::my_parent.get_device <Iris::Elfrun> ()
|
||||
top_memory = Iris::get_top_memory ()
|
||||
unsigned config_size
|
||||
Iris::Caps config_pages = load ("init.config", 12, config_size)
|
||||
unsigned pages = (config_size + PAGE_SIZE - 1) >> PAGE_BITS
|
||||
char *config = alloc_space (pages)
|
||||
unsigned pages_slot = config_pages.use ()
|
||||
for unsigned p = 0; p < pages; ++p:
|
||||
Iris::Page page (pages_slot, p)
|
||||
Iris::my_memory.map (page, (unsigned)&config[p << PAGE_BITS])
|
||||
char *ptr = config
|
||||
kdebug ("parsing config\n")
|
||||
while ptr - config < config_size:
|
||||
parse_line (ptr, config + config_size - ptr)
|
||||
kdebug ("destroying pages\n")
|
||||
for unsigned p = 0; p < pages; ++p:
|
||||
Iris::my_memory.destroy (Iris::Cap (pages_slot, p))
|
||||
Iris::my_memory.destroy (config_pages)
|
||||
Iris::free_cap (config_pages)
|
||||
Iris::free_slot (pages_slot)
|
||||
kdebug ("waiting for events.\n")
|
||||
while true:
|
||||
Iris::wait ()
|
||||
Program *caller = (Program *)Iris::recv.protected_data.l
|
||||
if !caller:
|
||||
// System request.
|
||||
// TODO.
|
||||
kdebug ("system request\n")
|
||||
continue
|
||||
switch Iris::recv.data[0].l:
|
||||
default:
|
||||
// TODO.
|
||||
kdebug ("child request\n")
|
||||
@@ -225,7 +225,7 @@ static void log_str (char const *str):
|
||||
while *str:
|
||||
log_char (*str++)
|
||||
|
||||
static void log_num (Kernel::Num n):
|
||||
static void log_num (Iris::Num n):
|
||||
char const *encode = "0123456789abcdef"
|
||||
log_char ('[')
|
||||
for unsigned i = 0; i < 8; ++i:
|
||||
@@ -237,10 +237,10 @@ static void log_num (Kernel::Num n):
|
||||
|
||||
static void log_msg ():
|
||||
log_str ("prot:")
|
||||
log_num (Kernel::recv.protected_data)
|
||||
log_num (Iris::recv.protected_data)
|
||||
log_str ("data:")
|
||||
for unsigned i = 0; i < 2; ++i:
|
||||
log_num (Kernel::recv.data[i])
|
||||
log_num (Iris::recv.data[i])
|
||||
log_char ('\n')
|
||||
|
||||
enum captype:
|
||||
@@ -261,25 +261,25 @@ static unsigned pages
|
||||
static Descriptor descriptor __attribute__ ((aligned (16)))
|
||||
static bool is_on
|
||||
|
||||
static unsigned create (Kernel::Memory mem, Kernel::Caps caps):
|
||||
static unsigned create (Iris::Memory mem, Iris::Caps caps):
|
||||
unsigned physical = mem.alloc_range (pages)
|
||||
unsigned address = 0x15000
|
||||
if physical & ~PAGE_MASK:
|
||||
Kernel::panic (0, "can't allocate framebuffer")
|
||||
Iris::panic (0, "can't allocate framebuffer")
|
||||
assert (physical & PAGE_MASK && ~physical)
|
||||
for unsigned i = 0; i < pages; ++i:
|
||||
Kernel::Page p = mem.create_page ()
|
||||
Iris::Page p = mem.create_page ()
|
||||
p.alloc_physical (physical + (i << PAGE_BITS), false, true)
|
||||
if address != ~0:
|
||||
mem.map (p, address + (i << PAGE_BITS))
|
||||
Kernel::free_cap (p)
|
||||
Iris::free_cap (p)
|
||||
return physical
|
||||
|
||||
static void destroy (unsigned physical, Kernel::Caps caps):
|
||||
static void destroy (unsigned physical, Iris::Caps caps):
|
||||
unsigned address = 0x15000
|
||||
Kernel::Memory mem = caps.get (1)
|
||||
Iris::Memory mem = caps.get (1)
|
||||
if physical == ~0:
|
||||
Kernel::panic (0, "unable to destroy framebuffer with wrong cap0")
|
||||
Iris::panic (0, "unable to destroy framebuffer with wrong cap0")
|
||||
if descriptor.frame == physical && is_on:
|
||||
lcd_clr_ena ()
|
||||
#ifdef NANONOTE
|
||||
@@ -287,13 +287,13 @@ static void destroy (unsigned physical, Kernel::Caps caps):
|
||||
#endif
|
||||
if address != ~0:
|
||||
for unsigned i = 0; i < pages; ++i:
|
||||
Kernel::Page p = mem.mapping ((void *)(address + (i << PAGE_BITS)))
|
||||
Iris::Page p = mem.mapping ((void *)(address + (i << PAGE_BITS)))
|
||||
mem.destroy (p)
|
||||
Kernel::free_cap (p)
|
||||
Iris::free_cap (p)
|
||||
|
||||
static void use (unsigned physical, Kernel::Caps caps):
|
||||
static void use (unsigned physical, Iris::Caps caps):
|
||||
if physical == ~0:
|
||||
Kernel::panic (0, "unable to use framebuffer with wrong cap0")
|
||||
Iris::panic (0, "unable to use framebuffer with wrong cap0")
|
||||
bool was_unused = descriptor.frame == 0
|
||||
descriptor.frame = physical
|
||||
unsigned dptr = (unsigned)&descriptor
|
||||
@@ -304,9 +304,9 @@ static void use (unsigned physical, Kernel::Caps caps):
|
||||
write_reg (BACKLIGHT1, 0x5f)
|
||||
#endif
|
||||
|
||||
static void unuse (unsigned physical, Kernel::Caps caps):
|
||||
static void unuse (unsigned physical, Iris::Caps caps):
|
||||
if physical == ~0:
|
||||
Kernel::panic (0, "unable to unuse framebuffer with wrong cap0")
|
||||
Iris::panic (0, "unable to unuse framebuffer with wrong cap0")
|
||||
if descriptor.frame == physical:
|
||||
lcd_clr_ena ()
|
||||
#ifdef NANONOTE
|
||||
@@ -314,8 +314,8 @@ static void unuse (unsigned physical, Kernel::Caps caps):
|
||||
#endif
|
||||
descriptor.frame = 0
|
||||
|
||||
Kernel::Num start ():
|
||||
Kernel::schedule ()
|
||||
Iris::Num start ():
|
||||
Iris::schedule ()
|
||||
map_lcd ()
|
||||
map_cpm ()
|
||||
#ifdef NANONOTE
|
||||
@@ -324,13 +324,13 @@ Kernel::Num start ():
|
||||
|
||||
pages = (frame_size + ~PAGE_MASK) >> PAGE_BITS
|
||||
#if 0
|
||||
unsigned physical = Kernel::my_memory.alloc_range (pages)
|
||||
unsigned physical = Iris::my_memory.alloc_range (pages)
|
||||
assert (physical & PAGE_MASK && ~physical)
|
||||
for unsigned i = 0; i < pages; ++i:
|
||||
Kernel::Page p = Kernel::my_memory.create_page ()
|
||||
Iris::Page p = Iris::my_memory.create_page ()
|
||||
p.alloc_physical (physical + (i << PAGE_BITS), false, true)
|
||||
Kernel::my_memory.map (p, (unsigned)LCD_FRAMEBUFFER_BASE + (i << PAGE_BITS))
|
||||
Kernel::free_cap (p)
|
||||
Iris::my_memory.map (p, (unsigned)LCD_FRAMEBUFFER_BASE + (i << PAGE_BITS))
|
||||
Iris::free_cap (p)
|
||||
for unsigned y = 0; y < v; ++y:
|
||||
for unsigned x = 0; x < h; ++x:
|
||||
unsigned r = spot (x, y, 100, 160)
|
||||
@@ -346,10 +346,10 @@ Kernel::Num start ():
|
||||
#else
|
||||
unsigned physical = 0
|
||||
#endif
|
||||
Kernel::Page p = Kernel::my_memory.mapping (&descriptor)
|
||||
Iris::Page p = Iris::my_memory.mapping (&descriptor)
|
||||
unsigned paddr = p.physical_address ()
|
||||
physical_descriptor = paddr + ((unsigned)&descriptor & ~PAGE_MASK)
|
||||
Kernel::free_cap (p)
|
||||
Iris::free_cap (p)
|
||||
descriptor.next = physical_descriptor
|
||||
descriptor.frame = physical
|
||||
descriptor.id = 0xdeadbeef
|
||||
@@ -359,67 +359,67 @@ Kernel::Num start ():
|
||||
reset ()
|
||||
|
||||
#if defined (TRENDTAC)
|
||||
Kernel::Cap logcap = Kernel::my_receiver.create_capability (LOG)
|
||||
Iris::Cap logcap = Iris::my_receiver.create_capability (LOG)
|
||||
__asm__ volatile ("li $a0, 1\nlw $a1, %0\nbreak" :: "m"(logcap.code): "a0", "a1", "memory")
|
||||
#endif
|
||||
|
||||
// Register the backlight device.
|
||||
Kernel::Cap backlight = Kernel::my_receiver.create_capability (BACKLIGHT)
|
||||
Kernel::my_parent.provide_device <Setting> (backlight.copy ())
|
||||
Kernel::free_cap (backlight)
|
||||
Iris::Cap backlight = Iris::my_receiver.create_capability (BACKLIGHT)
|
||||
Iris::my_parent.provide_device <Iris::Setting> (backlight.copy ())
|
||||
Iris::free_cap (backlight)
|
||||
|
||||
// Register the display device.
|
||||
Kernel::Cap display = Kernel::my_receiver.create_capability (LCD)
|
||||
Kernel::my_parent.provide_device <Display> (display.copy ())
|
||||
Kernel::free_cap (display)
|
||||
Kernel::my_parent.init_done ()
|
||||
Iris::Cap display = Iris::my_receiver.create_capability (LCD)
|
||||
Iris::my_parent.provide_device <Iris::Display> (display.copy ())
|
||||
Iris::free_cap (display)
|
||||
Iris::my_parent.init_done ()
|
||||
|
||||
Kernel::Cap eof_cb
|
||||
Iris::Cap eof_cb
|
||||
bool have_eof = false
|
||||
is_on = true
|
||||
unsigned lcd_user = 0
|
||||
unsigned current_backlight = 0
|
||||
while true:
|
||||
Kernel::wait ()
|
||||
Iris::wait ()
|
||||
//log_msg ()
|
||||
switch Kernel::recv.protected_data.h:
|
||||
switch Iris::recv.protected_data.h:
|
||||
case 0:
|
||||
switch Kernel::recv.protected_data.l:
|
||||
switch Iris::recv.protected_data.l:
|
||||
case IRQ_LCD:
|
||||
have_eof = false
|
||||
eof_cb.invoke ()
|
||||
Kernel::free_cap (eof_cb)
|
||||
Iris::free_cap (eof_cb)
|
||||
break
|
||||
#if defined (TRENDTAC)
|
||||
case LOG:
|
||||
log_char (Kernel::recv.data[0].l)
|
||||
log_char (Iris::recv.data[0].l)
|
||||
break
|
||||
#endif
|
||||
case BACKLIGHT:
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
Kernel::Cap arg = Kernel::get_arg ()
|
||||
Device::host (BACKLIGHT, current_backlight, reply, arg)
|
||||
Iris::Cap reply = Iris::get_reply ()
|
||||
Iris::Cap arg = Iris::get_arg ()
|
||||
Iris::Device::host (BACKLIGHT, current_backlight, reply, arg)
|
||||
break
|
||||
case LCD:
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
Kernel::Cap arg = Kernel::get_arg ()
|
||||
Device::host (LCD, lcd_user, reply, arg, 3, create, destroy, use, unuse)
|
||||
Iris::Cap reply = Iris::get_reply ()
|
||||
Iris::Cap arg = Iris::get_arg ()
|
||||
Iris::Device::host (LCD, lcd_user, reply, arg, 3, create, destroy, use, unuse)
|
||||
break
|
||||
default:
|
||||
Kernel::panic (Kernel::recv.protected_data.l, "invalid operation for master lcd")
|
||||
Iris::panic (Iris::recv.protected_data.l, "invalid operation for master lcd")
|
||||
break
|
||||
break
|
||||
case BACKLIGHT:
|
||||
if current_backlight != Kernel::recv.protected_data.l:
|
||||
if current_backlight != Iris::recv.protected_data.l:
|
||||
log_char ('&')
|
||||
log_num (current_backlight)
|
||||
log_num (Kernel::recv.protected_data)
|
||||
log_num (Iris::recv.protected_data)
|
||||
log_char ('\n')
|
||||
break
|
||||
switch Kernel::recv.data[0].l:
|
||||
case Setting::SET:
|
||||
switch Iris::recv.data[0].l:
|
||||
case Iris::Setting::SET:
|
||||
// TODO
|
||||
unsigned state = Kernel::recv.data[1].l
|
||||
unsigned state = Iris::recv.data[1].l
|
||||
if !state:
|
||||
#if defined (NANONOTE)
|
||||
if is_on:
|
||||
@@ -434,40 +434,40 @@ Kernel::Num start ():
|
||||
is_on = true
|
||||
#else
|
||||
#endif
|
||||
Kernel::recv.reply.invoke ()
|
||||
Iris::recv.reply.invoke ()
|
||||
break
|
||||
case Setting::GET_RANGE:
|
||||
Kernel::recv.reply.invoke (~0)
|
||||
case Iris::Setting::GET_RANGE:
|
||||
Iris::recv.reply.invoke (~0)
|
||||
break
|
||||
default:
|
||||
Kernel::panic (0, "invalid operation for backlight")
|
||||
Iris::panic (0, "invalid operation for backlight")
|
||||
break
|
||||
break
|
||||
case LCD:
|
||||
if descriptor.frame != Kernel::recv.protected_data.l:
|
||||
//Kernel::panic (0, "invalid user requesting lcd")
|
||||
Kernel::recv.reply.invoke (~0)
|
||||
if descriptor.frame != Iris::recv.protected_data.l:
|
||||
//Iris::panic (0, "invalid user requesting lcd")
|
||||
Iris::recv.reply.invoke (~0)
|
||||
break
|
||||
switch Kernel::recv.data[0].l:
|
||||
case Display::SET_EOF_CB:
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
Kernel::Cap arg = Kernel::get_arg ()
|
||||
switch Iris::recv.data[0].l:
|
||||
case Iris::Display::SET_EOF_CB:
|
||||
Iris::Cap reply = Iris::get_reply ()
|
||||
Iris::Cap arg = Iris::get_arg ()
|
||||
if have_eof:
|
||||
Kernel::free_cap (eof_cb)
|
||||
Kernel::panic (0, "replacing eof_cb")
|
||||
Iris::free_cap (eof_cb)
|
||||
Iris::panic (0, "replacing eof_cb")
|
||||
else:
|
||||
lcd_clr_eof ()
|
||||
Kernel::register_interrupt (IRQ_LCD)
|
||||
Iris::register_interrupt (IRQ_LCD)
|
||||
have_eof = true
|
||||
eof_cb = arg
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (reply)
|
||||
Iris::free_cap (reply)
|
||||
break
|
||||
case Display::GET_INFO:
|
||||
Kernel::panic (0, "get_info isn't defined yet.")
|
||||
case Iris::Display::GET_INFO:
|
||||
Iris::panic (0, "get_info isn't defined yet.")
|
||||
default:
|
||||
Kernel::panic (Kernel::recv.data[0].l, "invalid operation for lcd")
|
||||
Iris::panic (Iris::recv.data[0].l, "invalid operation for lcd")
|
||||
break
|
||||
default:
|
||||
Kernel::panic (0, "invalid master operation type for lcd")
|
||||
Iris::panic (0, "invalid master operation type for lcd")
|
||||
break
|
||||
@@ -19,11 +19,11 @@
|
||||
#include "devices.hh"
|
||||
#include "keys.hh"
|
||||
|
||||
Kernel::Num start ():
|
||||
Kernel::my_parent.init_done ()
|
||||
Buzzer buzzer = Kernel::my_parent.get_device <Buzzer> ()
|
||||
Keyboard kbd = Kernel::my_parent.get_device <Keyboard> ()
|
||||
Kernel::Cap key = Kernel::my_receiver.create_capability (0)
|
||||
Iris::Num start ():
|
||||
Iris::my_parent.init_done ()
|
||||
Iris::Buzzer buzzer = Iris::my_parent.get_device <Iris::Buzzer> ()
|
||||
Iris::Keyboard kbd = Iris::my_parent.get_device <Iris::Keyboard> ()
|
||||
Iris::Cap key = Iris::my_receiver.create_capability (0)
|
||||
kbd.set_cb (key)
|
||||
// Frequency of the pulse train in millihertz.
|
||||
unsigned mHz = 1000
|
||||
@@ -31,17 +31,17 @@ Kernel::Num start ():
|
||||
unsigned freq = 1000
|
||||
bool running (false)
|
||||
while true:
|
||||
Kernel::wait ()
|
||||
switch Kernel::recv.protected_data.l:
|
||||
Iris::wait ()
|
||||
switch Iris::recv.protected_data.l:
|
||||
case ~0:
|
||||
if running:
|
||||
buzzer.beep (freq, 10, ~0)
|
||||
Kernel::my_receiver.set_alarm (HZ * 1000 / mHz)
|
||||
Iris::my_receiver.set_alarm (HZ * 1000 / mHz)
|
||||
break
|
||||
case 0:
|
||||
if Kernel::recv.data[0].l & Keyboard::RELEASE:
|
||||
if Iris::recv.data[0].l & Iris::Keyboard::RELEASE:
|
||||
break
|
||||
switch Kernel::recv.data[0].l:
|
||||
switch Iris::recv.data[0].l:
|
||||
case Key::VOLUME_UP:
|
||||
freq = freq * 11 / 10
|
||||
break
|
||||
@@ -63,7 +63,7 @@ Kernel::Num start ():
|
||||
case Key::P:
|
||||
running = !running
|
||||
if running:
|
||||
Kernel::my_receiver.set_alarm (0)
|
||||
Iris::my_receiver.set_alarm (0)
|
||||
break
|
||||
break
|
||||
default:
|
||||
|
||||
@@ -37,25 +37,25 @@ class DevKbd:
|
||||
static unsigned const NUM_KEYS = 58
|
||||
static unsigned const keys[NUM_KEYS]
|
||||
unsigned state[NUM_COLS]
|
||||
Kernel::Cap event
|
||||
Iris::Cap event
|
||||
bool is_active
|
||||
bool is_scanning
|
||||
public:
|
||||
unsigned size ():
|
||||
return NUM_KEYS
|
||||
void send_keys (unsigned first, Kernel::Cap target):
|
||||
void send_keys (unsigned first, Iris::Cap target):
|
||||
unsigned d[4]
|
||||
unsigned i
|
||||
for i = 0; first + i < NUM_KEYS && i < 4; ++i:
|
||||
d[i] = keys[first + i]
|
||||
for ; i < 4; ++i:
|
||||
d[i] = ~0
|
||||
target.invoke (Kernel::Num (d[0], d[1]), Kernel::Num (d[2], d[3]))
|
||||
target.invoke (Iris::Num (d[0], d[1]), Iris::Num (d[2], d[3]))
|
||||
bool scanning ():
|
||||
return is_scanning
|
||||
void inactive ():
|
||||
if is_active:
|
||||
Kernel::free_cap (event)
|
||||
Iris::free_cap (event)
|
||||
is_active = false
|
||||
void check (unsigned col, unsigned rowdata):
|
||||
for unsigned r = 0; r < NUM_ROWS; ++r:
|
||||
@@ -63,7 +63,7 @@ class DevKbd:
|
||||
continue
|
||||
unsigned code = encode[r][col]
|
||||
if rowdata & (1 << ROWS[r]):
|
||||
code |= Keyboard::RELEASE
|
||||
code |= Iris::Keyboard::RELEASE
|
||||
if is_active:
|
||||
event.invoke (code)
|
||||
state[col] = rowdata
|
||||
@@ -101,7 +101,7 @@ class DevKbd:
|
||||
gpio_as_interrupt (ROWS_PORT, high, true, true)
|
||||
gpio_as_interrupt (ROWS_PORT, low, false, true)
|
||||
gpio_unmask_irq (ROWS_PORT, ALL_ROWS)
|
||||
void active (Kernel::Cap cb):
|
||||
void active (Iris::Cap cb):
|
||||
inactive ()
|
||||
event = cb
|
||||
is_active = true
|
||||
@@ -167,7 +167,7 @@ unsigned const DevKbd::keys[NUM_KEYS] = {
|
||||
|
||||
class PowerButton:
|
||||
bool state, started
|
||||
Kernel::Cap cb
|
||||
Iris::Cap cb
|
||||
public:
|
||||
void scan ():
|
||||
if !started:
|
||||
@@ -176,16 +176,16 @@ class PowerButton:
|
||||
bool s = gpio_get_port (3) & (1 << 29)
|
||||
if s != state:
|
||||
state = s
|
||||
cb.invoke (state ? Keyboard::RELEASE : 0)
|
||||
cb.invoke (state ? Iris::Keyboard::RELEASE : 0)
|
||||
gpio_as_interrupt (3, 1 << 29, !state, true)
|
||||
gpio_unmask_irq (3, 1 << 29)
|
||||
PowerButton ():
|
||||
gpio_as_gpio (3, 29)
|
||||
state = true
|
||||
started = false
|
||||
void set_cb (Kernel::Cap c):
|
||||
void set_cb (Iris::Cap c):
|
||||
if started:
|
||||
Kernel::free_cap (cb)
|
||||
Iris::free_cap (cb)
|
||||
else:
|
||||
started = true
|
||||
cb = c
|
||||
@@ -196,100 +196,100 @@ enum codes:
|
||||
KBD_DEV = 32
|
||||
PWR
|
||||
|
||||
Kernel::Num start ():
|
||||
Iris::Num start ():
|
||||
map_gpio ()
|
||||
|
||||
DevKbd kbd
|
||||
PowerButton pwr
|
||||
|
||||
Device dev = Kernel::my_receiver.create_capability (KBD_DEV)
|
||||
Keyboard pw = Kernel::my_receiver.create_capability (PWR)
|
||||
Kernel::my_parent.provide_device <Keyboard> (dev.copy (), 0)
|
||||
Kernel::my_parent.provide_device <Keyboard> (pw.copy (), 1)
|
||||
Kernel::free_cap (dev)
|
||||
Kernel::free_cap (pw)
|
||||
Kernel::my_parent.init_done ()
|
||||
Iris::Device dev = Iris::my_receiver.create_capability (KBD_DEV)
|
||||
Iris::Keyboard pw = Iris::my_receiver.create_capability (PWR)
|
||||
Iris::my_parent.provide_device <Iris::Keyboard> (dev.copy (), 0)
|
||||
Iris::my_parent.provide_device <Iris::Keyboard> (pw.copy (), 1)
|
||||
Iris::free_cap (dev)
|
||||
Iris::free_cap (pw)
|
||||
Iris::my_parent.init_done ()
|
||||
if kbd.scanning ():
|
||||
Kernel::my_receiver.set_alarm (SCAN_INTERVAL)
|
||||
Iris::my_receiver.set_alarm (SCAN_INTERVAL)
|
||||
unsigned user (0), power_user (0)
|
||||
unsigned next_user (0)
|
||||
Kernel::register_interrupt (IRQ_GPIO3)
|
||||
Iris::register_interrupt (IRQ_GPIO3)
|
||||
while true:
|
||||
Kernel::wait ()
|
||||
switch Kernel::recv.protected_data.h:
|
||||
Iris::wait ()
|
||||
switch Iris::recv.protected_data.h:
|
||||
case ~0:
|
||||
// Alarm.
|
||||
kbd.scan ()
|
||||
if kbd.scanning ():
|
||||
Kernel::my_receiver.set_alarm (SCAN_INTERVAL)
|
||||
Iris::my_receiver.set_alarm (SCAN_INTERVAL)
|
||||
break
|
||||
case 0:
|
||||
switch Kernel::recv.protected_data.l:
|
||||
switch Iris::recv.protected_data.l:
|
||||
case IRQ_GPIO3:
|
||||
// Interrupt.
|
||||
pwr.scan ()
|
||||
kbd.scan ()
|
||||
if kbd.scanning ():
|
||||
Kernel::my_receiver.set_alarm (SCAN_INTERVAL)
|
||||
Kernel::register_interrupt (IRQ_GPIO3)
|
||||
Iris::my_receiver.set_alarm (SCAN_INTERVAL)
|
||||
Iris::register_interrupt (IRQ_GPIO3)
|
||||
break
|
||||
case PWR:
|
||||
// Power button request.
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
Kernel::Cap arg = Kernel::get_arg ()
|
||||
Device::host (PWR, power_user, reply, arg)
|
||||
Iris::Cap reply = Iris::get_reply ()
|
||||
Iris::Cap arg = Iris::get_arg ()
|
||||
Iris::Device::host (PWR, power_user, reply, arg)
|
||||
break
|
||||
case KBD_DEV:
|
||||
// Keyboard device control request.
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
Kernel::Cap arg = Kernel::get_arg ()
|
||||
Device::host (KBD_DEV, user, reply, arg)
|
||||
Iris::Cap reply = Iris::get_reply ()
|
||||
Iris::Cap arg = Iris::get_arg ()
|
||||
Iris::Device::host (KBD_DEV, user, reply, arg)
|
||||
break
|
||||
default:
|
||||
break
|
||||
break
|
||||
case KBD_DEV:
|
||||
// Keyboard device user request.
|
||||
if Kernel::recv.protected_data.l != user:
|
||||
if Iris::recv.protected_data.l != user:
|
||||
kdebug ("invalid user requesting keyboard\n")
|
||||
Kernel::recv.reply.invoke ()
|
||||
Iris::recv.reply.invoke ()
|
||||
break
|
||||
switch Kernel::recv.data[0].l:
|
||||
case Keyboard::SET_CB:
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
kbd.active (Kernel::get_arg ())
|
||||
switch Iris::recv.data[0].l:
|
||||
case Iris::Keyboard::SET_CB:
|
||||
Iris::Cap reply = Iris::get_reply ()
|
||||
kbd.active (Iris::get_arg ())
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (reply)
|
||||
Iris::free_cap (reply)
|
||||
break
|
||||
case Keyboard::GET_NUM_KEYS:
|
||||
Kernel::recv.reply.invoke (kbd.size ())
|
||||
case Iris::Keyboard::GET_NUM_KEYS:
|
||||
Iris::recv.reply.invoke (kbd.size ())
|
||||
break
|
||||
case Keyboard::GET_KEYS:
|
||||
kbd.send_keys (Kernel::recv.data[0].l, Kernel::recv.reply)
|
||||
case Iris::Keyboard::GET_KEYS:
|
||||
kbd.send_keys (Iris::recv.data[0].l, Iris::recv.reply)
|
||||
break
|
||||
default:
|
||||
kdebug ("keyboard other\n")
|
||||
break
|
||||
break
|
||||
case PWR:
|
||||
if Kernel::recv.protected_data.l != power_user:
|
||||
if Iris::recv.protected_data.l != power_user:
|
||||
kdebug ("invalid user requesting power\n")
|
||||
Kernel::recv.reply.invoke ()
|
||||
Iris::recv.reply.invoke ()
|
||||
break
|
||||
switch Kernel::recv.data[0].l:
|
||||
case Keyboard::SET_CB:
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
pwr.set_cb (Kernel::get_arg ())
|
||||
switch Iris::recv.data[0].l:
|
||||
case Iris::Keyboard::SET_CB:
|
||||
Iris::Cap reply = Iris::get_reply ()
|
||||
pwr.set_cb (Iris::get_arg ())
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (reply)
|
||||
Iris::free_cap (reply)
|
||||
break
|
||||
default:
|
||||
kdebug ("Power button invalid request\n")
|
||||
kdebug_num (Kernel::recv.data[0].l)
|
||||
kdebug_num (Iris::recv.data[0].l)
|
||||
kdebug ("\n")
|
||||
break
|
||||
break
|
||||
default:
|
||||
kdebug ("keyboard unknown num: ")
|
||||
kdebug_num (Kernel::recv.protected_data.h)
|
||||
kdebug_num (Iris::recv.protected_data.h)
|
||||
kdebug ("\n")
|
||||
@@ -53,14 +53,14 @@ enum event_type:
|
||||
TOUCHPAD_EVENT
|
||||
NUM_EVENTS
|
||||
|
||||
static Kernel::Cap events[NUM_EVENTS]
|
||||
static Iris::Cap events[NUM_EVENTS]
|
||||
|
||||
static void event (event_type type, unsigned data):
|
||||
events[type].invoke (data)
|
||||
|
||||
static void set_cb (event_type type):
|
||||
Kernel::free_cap (events[type])
|
||||
events[type] = Kernel::get_arg ()
|
||||
Iris::free_cap (events[type])
|
||||
events[type] = Iris::get_arg ()
|
||||
|
||||
class DevKeyboard:
|
||||
static unsigned const encode[GPIO_KBD_NUM_COLS][GPIO_KBD_NUM_ROWS]
|
||||
@@ -252,72 +252,72 @@ enum codes:
|
||||
LOCKLEDS
|
||||
PWM
|
||||
|
||||
Kernel::Num start ():
|
||||
Iris::Num start ():
|
||||
map_gpio ()
|
||||
map_pwm0 ()
|
||||
|
||||
for unsigned i = 0; i < NUM_EVENTS; ++i:
|
||||
events[i] = Kernel::alloc_cap ()
|
||||
events[i] = Iris::alloc_cap ()
|
||||
|
||||
DevKeyboard kbd
|
||||
Touchpad tp
|
||||
Lockleds leds
|
||||
Pwm pwm
|
||||
|
||||
Kernel::Cap c = Kernel::my_receiver.create_capability (KEYBOARD)
|
||||
Kernel::my_parent.provide_device <Keyboard> (c.copy (), 0)
|
||||
Kernel::free_cap (c)
|
||||
c = Kernel::my_receiver.create_capability (TOUCHPAD)
|
||||
Kernel::my_parent.provide_device <Keyboard> (c.copy (), 1)
|
||||
Kernel::free_cap (c)
|
||||
Kernel::my_parent.init_done ()
|
||||
Iris::Cap c = Iris::my_receiver.create_capability (KEYBOARD)
|
||||
Iris::my_parent.provide_device <Keyboard> (c.copy (), 0)
|
||||
Iris::free_cap (c)
|
||||
c = Iris::my_receiver.create_capability (TOUCHPAD)
|
||||
Iris::my_parent.provide_device <Keyboard> (c.copy (), 1)
|
||||
Iris::free_cap (c)
|
||||
Iris::my_parent.init_done ()
|
||||
|
||||
if kbd.is_scanning ():
|
||||
Kernel::my_receiver.set_alarm (ALARM_INTERVAL)
|
||||
Iris::my_receiver.set_alarm (ALARM_INTERVAL)
|
||||
|
||||
// Enable interrupts. All are in port 0.
|
||||
GPIO_GPIER (GPIO_KBD_ROW_PORT) = (1 << GPIO_TP_LEFT) | (1 << GPIO_TP_RIGHT) | GPIO_KBD_ROW_MASK
|
||||
Kernel::register_interrupt (IRQ_GPIO0)
|
||||
Iris::register_interrupt (IRQ_GPIO0)
|
||||
|
||||
while true:
|
||||
Kernel::schedule ()
|
||||
Kernel::wait ()
|
||||
switch Kernel::recv.protected_data.l:
|
||||
Iris::schedule ()
|
||||
Iris::wait ()
|
||||
switch Iris::recv.protected_data.l:
|
||||
case ~0:
|
||||
// Alarm.
|
||||
kbd.scan ()
|
||||
if kbd.is_scanning ():
|
||||
Kernel::my_receiver.set_alarm (ALARM_INTERVAL)
|
||||
Iris::my_receiver.set_alarm (ALARM_INTERVAL)
|
||||
break
|
||||
case IRQ_GPIO0:
|
||||
// Always scan keyboard and touchpad on any interrupt.
|
||||
kbd.scan ()
|
||||
tp.check_events ()
|
||||
// Reregister the interrupt.
|
||||
Kernel::register_interrupt (IRQ_GPIO0)
|
||||
Iris::register_interrupt (IRQ_GPIO0)
|
||||
break
|
||||
case KEYBOARD:
|
||||
set_cb (KEYBOARD_EVENT)
|
||||
Kernel::recv.reply.invoke ()
|
||||
Iris::recv.reply.invoke ()
|
||||
kbd.send_initial ()
|
||||
event (KEYBOARD_EVENT, ~0)
|
||||
break
|
||||
case TOUCHPAD:
|
||||
set_cb (TOUCHPAD_EVENT)
|
||||
Kernel::recv.reply.invoke ()
|
||||
Iris::recv.reply.invoke ()
|
||||
tp.send_initial ()
|
||||
event (TOUCHPAD_EVENT, ~0)
|
||||
break
|
||||
case LOCKLEDS:
|
||||
leds.set (Kernel::recv.data[0].l)
|
||||
Kernel::recv.reply.invoke ()
|
||||
leds.set (Iris::recv.data[0].l)
|
||||
Iris::recv.reply.invoke ()
|
||||
break
|
||||
case PWM:
|
||||
pwm.set_backlight (Kernel::recv.data[0].l)
|
||||
Kernel::recv.reply.invoke ()
|
||||
pwm.set_backlight (Iris::recv.data[0].l)
|
||||
Iris::recv.reply.invoke ()
|
||||
break
|
||||
default:
|
||||
kdebug ("invalid gpio operation ")
|
||||
kdebug_num (Kernel::recv.protected_data.l)
|
||||
kdebug_num (Iris::recv.protected_data.l)
|
||||
kdebug ("\n")
|
||||
break
|
||||
Reference in New Issue
Block a user