1
0
mirror of git://projects.qi-hardware.com/iris.git synced 2024-12-29 20:31:09 +02:00

fix bugs; work on userspace

This commit is contained in:
Bas Wijnen 2009-10-10 01:31:10 +02:00
parent 906f487b01
commit afb496f20b
19 changed files with 615 additions and 267 deletions

View File

@ -308,6 +308,8 @@ void kMemory::free_thread (kThread *thread):
free_obj (thread, (void **)&threads) free_obj (thread, (void **)&threads)
void kMemory::free_message (kReceiver *owner, kMessage *message): void kMemory::free_message (kReceiver *owner, kMessage *message):
for unsigned i = 0; i < 2; ++i:
message->caps.cap (i)->invalidate ()
if !message->next: if !message->next:
owner->last_message = (kMessageP)message->prev owner->last_message = (kMessageP)message->prev
free_obj (message, (void **)&owner->messages) free_obj (message, (void **)&owner->messages)
@ -405,3 +407,98 @@ void kPage::forget ():
frame = 0 frame = 0
flags &= ~(Kernel::Page::FRAME | Kernel::Page::SHARED | Kernel::Page::PHYSICAL | Kernel::Page::UNCACHED) flags &= ~(Kernel::Page::FRAME | Kernel::Page::SHARED | Kernel::Page::PHYSICAL | Kernel::Page::UNCACHED)
kPage_arch_update_mapping (this) kPage_arch_update_mapping (this)
static void check_receiver (kReceiver *r, kCapRef cap, unsigned line):
if (unsigned)cap->target & ~KERNEL_MASK:
if cap->target != r:
dpanic (line, "consistency bug in capabilities")
else:
if cap->protected_data.l != (unsigned)r:
dbg_log ("Buggy: ")
dbg_log_num ((unsigned)r)
dbg_log (" ")
dbg_log_num ((unsigned)cap.caps)
dbg_log (" ")
dbg_log_num ((unsigned)cap.caps->address_space)
dbg_log (" ")
dbg_log_num ((unsigned)cap.deref ())
dbg_log (" ")
dbg_log_num ((unsigned)cap->target)
dbg_log ("/")
dbg_log_num (cap->protected_data.l)
dbg_log ("\n")
dpanic (line, "consistency bug in kernel capabilities")
for kCapRef c = cap->children; c.valid (); c = c->sibling_next:
check_receiver (r, c, line)
void kReceiver::check (unsigned line):
for kCapRef cap = capabilities; cap.valid (); cap = cap->sibling_next:
check_receiver (this, cap, line)
void kMemory::check (unsigned line):
for kReceiver *r = receivers; r; r = (kReceiver *)r->next:
r->check (line)
for kMemory *m = memories; m; m = (kMemory *)m->next:
m->check (line)
static void print_obj (kObject *o):
for kObject *obj = o; o; o = (kObject *)o->next:
dbg_log_num ((unsigned)o)
dbg_log ("->")
dbg_log ("NULL\n")
void kMemory::print (unsigned line, unsigned indent):
if indent == 0:
print_free ()
for unsigned i = 0; i < indent; ++i:
dbg_log_char ('\t')
++indent
dbg_log ("Memory ")
dbg_log_num ((unsigned)this)
dbg_log ("\n")
for unsigned i = 0; i < indent; ++i:
dbg_log_char ('\t')
dbg_log ("frees: ")
for kFree *f = frees; f; f = (kFree *)f->next:
dbg_log_num ((unsigned)f)
dbg_log (":")
unsigned n = (unsigned)NEXT (f)
if n:
n -= (unsigned)f
if n >= PAGE_SIZE:
dpanic (0, "invalid kFree")
dbg_log_num (n, 3)
dbg_log ("->")
dbg_log ("NULL\n")
for unsigned i = 0; i < indent; ++i:
dbg_log_char ('\t')
dbg_log ("pages: ")
print_obj (pages)
for unsigned i = 0; i < indent; ++i:
dbg_log_char ('\t')
dbg_log ("threads: ")
print_obj (threads)
for unsigned i = 0; i < indent; ++i:
dbg_log_char ('\t')
dbg_log ("receivers: ")
for kReceiver *r = receivers; r; r = (kReceiver *)r->next:
dbg_log_num ((unsigned)r)
dbg_log ("(")
for kMessage *m = r->messages; m; m = (kMessage *)m->next:
dbg_log_num ((unsigned)m)
dbg_log ("->")
dbg_log ("NULL)->")
dbg_log ("NULL\n")
for unsigned i = 0; i < indent; ++i:
dbg_log_char ('\t')
dbg_log ("capses: ")
print_obj (capses)
for kMemory *m = memories; m; m = (kMemory *)m->next:
m->print (line, indent)
void check_impl (kObject *o, unsigned num, char const *msg):
for ; o; o = (kObject *)o->next:
unsigned n = (unsigned)NEXT (o)
unsigned size = n ? n - (unsigned)o : PAGE_SIZE - ((unsigned)o & PAGE_MASK)
if !check_free (o, size):
panic (num, msg)

View File

@ -23,10 +23,9 @@
class DevBuzzer: class DevBuzzer:
static unsigned const pwm = 4 static unsigned const pwm = 4
Kernel::Cap event Kernel::Cap event
bool is_active, is_beeping bool is_beeping
public: public:
DevBuzzer (): DevBuzzer ():
is_active = false
is_beeping = false is_beeping = false
gpio_as_pwm4 () gpio_as_pwm4 ()
tcu_stop_counter (pwm) tcu_stop_counter (pwm)
@ -38,8 +37,8 @@ class DevBuzzer:
return return
tcu_stop_counter (pwm) tcu_stop_counter (pwm)
event.invoke () event.invoke ()
is_active = false
Kernel::free_cap (event) Kernel::free_cap (event)
is_beeping = false
void beep (unsigned freq, unsigned ms, Kernel::Cap cb): void beep (unsigned freq, unsigned ms, Kernel::Cap cb):
stop () stop ()
event = cb event = cb
@ -115,12 +114,11 @@ Kernel::Num start ():
break break
switch Kernel::recv.data[0].l: switch Kernel::recv.data[0].l:
case Buzzer::BEEP: case Buzzer::BEEP:
// Volume is not used for this buzzer. // Volume is not used by this buzzer.
Kernel::Cap arg = Kernel::get_arg () Kernel::Cap arg = Kernel::get_arg ()
Kernel::Cap reply = Kernel::get_reply () Kernel::Cap reply = Kernel::get_reply ()
buzzer.beep (Kernel::recv.data[1].l, Kernel::recv.data[1].h, arg) buzzer.beep (Kernel::recv.data[1].l, Kernel::recv.data[1].h, arg)
reply.invoke () reply.invoke ()
Kernel::free_cap (arg)
Kernel::free_cap (reply) Kernel::free_cap (reply)
break break
case Buzzer::STOP: case Buzzer::STOP:

View File

@ -17,6 +17,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "iris.hh" #include "iris.hh"
#include "devices.hh"
// For some unknown reason, gcc needs this to be defined. // For some unknown reason, gcc needs this to be defined.
unsigned __gxx_personality_v0 unsigned __gxx_personality_v0
@ -33,7 +34,7 @@ namespace Kernel:
Thread my_thread Thread my_thread
Memory my_memory Memory my_memory
Cap my_call Cap my_call
Cap my_parent Parent my_parent
__recv_data_t recv __recv_data_t recv
void print_caps (): void print_caps ():

View File

@ -19,28 +19,50 @@
#include "devices.hh" #include "devices.hh"
#include "iris.hh" #include "iris.hh"
static Keyboard kbd, sysreq static Keyboard sysreq
static Buzzer buzzer
static Device kbd_dev, buz_dev static Device kbd_dev, buz_dev
static List <String> kbd_names
static unsigned slot static unsigned slot
// Event types. // Event types.
enum type: enum type:
MEMORY
KBDDEV
KBD
KEYNAMES
SYSREQ SYSREQ
KBDDEV
BUZDEV BUZDEV
BUZZER
static void user_reply (Kernel::Cap target, unsigned dev):
switch dev:
case Keyboard::ID:
// keyboard user
kdebug ("keyboard requested\n")
Kernel::Cap kbd = kbd_dev.create_user (Kernel::Cap ())
kbd_dev.use (kbd)
target.invoke (0, 0, kbd.copy ())
Kernel::free_cap (kbd)
break
case Buzzer::ID:
// buzzer user
kdebug ("buzzer requested\n")
Kernel::Cap buzzer = buz_dev.create_user (Kernel::Cap ())
buz_dev.use (buzzer)
kdebug ("invoking reply: ")
kdebug_num (target.code)
kdebug ("\n")
target.invoke (0, 0, buzzer.copy ())
Kernel::free_cap (buzzer)
break
default:
kdebug ("invalid id requested:")
kdebug_num (dev)
kdebug_char ('\n')
break
static void setup (): static void setup ():
unsigned state = 0 unsigned state = 0
Kernel::Caps caps = Kernel::my_memory.create_caps (32) Kernel::Caps caps = Kernel::my_memory.create_caps (32)
slot = caps.use () slot = caps.use ()
Kernel::set_recv_arg (Kernel::Cap (slot, MEMORY)) Kernel::Caps slot0 = Kernel::my_thread.get_caps (0)
Kernel::Cap driver_memory = Kernel::my_memory.create_memory () Kernel::Cap user
unsigned device
while true: while true:
Kernel::wait () Kernel::wait ()
Kernel::Cap reply = Kernel::get_reply () Kernel::Cap reply = Kernel::get_reply ()
@ -59,44 +81,38 @@ static void setup ():
default: default:
kdebug ("unexpected keyboard\n") kdebug ("unexpected keyboard\n")
break break
reply.invoke ()
Kernel::free_cap (reply)
break break
case Buzzer::ID: case Buzzer::ID:
caps.set (BUZDEV, arg.copy ()) caps.set (BUZDEV, arg.copy ())
buz_dev = Kernel::Cap (slot, BUZDEV) buz_dev = Kernel::Cap (slot, BUZDEV)
reply.invoke ()
Kernel::free_cap (reply)
break
case Parent::GET_DEVICE:
user = reply
device = Kernel::recv.data[1].l
slot0.print (reply.idx ())
break break
default: default:
kdebug ("unknown setup request for init\n")
reply.invoke ()
Kernel::free_cap (reply) Kernel::free_cap (reply)
Kernel::free_cap (arg) Kernel::free_cap (arg)
kdebug ("unknown setup request for init\n")
continue continue
reply.invoke ()
Kernel::free_cap (reply)
Kernel::free_cap (arg) Kernel::free_cap (arg)
if ++state == 3: if ++state == 4:
break break
// sysreq // sysreq
kdebug ("using sysreq\n")
Kernel::Cap cb = Kernel::my_receiver.create_capability (SYSREQ) Kernel::Cap cb = Kernel::my_receiver.create_capability (SYSREQ)
sysreq.set_cb (cb.copy ()) sysreq.set_cb (cb.copy ())
// keyboard user
Kernel::set_recv_arg (Kernel::Cap (slot, KBD))
kbd = kbd_dev.create_user (driver_memory)
kbd_dev.use (kbd)
// keyboard callback
Kernel::set_recv_arg (cb)
Kernel::my_receiver.create_capability (KBD)
kbd.set_cb (cb.copy ())
// keyboard name list
Kernel::set_recv_arg (Kernel::Cap (slot, KEYNAMES))
kbd_names = kbd.get_keys ()
// buzzer user
Kernel::set_recv_arg (Kernel::Cap (slot, BUZZER))
buzzer = buz_dev.create_user (driver_memory)
buz_dev.use (buzzer)
// clean up.
Kernel::free_cap (cb) Kernel::free_cap (cb)
// First user reply.
//char const *decode_kbd = "0123456789abcdefghijklmnopqrstuvwxyz!@#$%^&*() T\n[],.-=/\\;|`'UDLREIKBPFZMS{}CA\":" kdebug ("sending first user reply\n")
char const *decode_kbd = "0123456789abcdefghijklmnopqrstuvwxyz!@#$*T\nE& B=UDLR+-F^CA" user_reply (user, device)
Kernel::free_cap (user)
Kernel::Num start (): Kernel::Num start ():
setup () setup ()
@ -112,20 +128,11 @@ Kernel::Num start ():
else: else:
kdebug ("pressed.\n\n") kdebug ("pressed.\n\n")
break break
case KBD: default:
unsigned code = Kernel::recv.data[0].l if Kernel::recv.data[0].l != Parent::GET_DEVICE:
if code & Keyboard::RELEASE: kdebug ("invalid call from user\n")
kdebug_char ('-') break
else: Kernel::Cap reply = Kernel::get_reply ()
kdebug_char ('+') user_reply (reply, Kernel::recv.data[1].l)
buzzer.beep (2000, 100, 0) Kernel::free_cap (reply)
String name = kbd_names.get (code & ~Keyboard::RELEASE)
unsigned size = name.get_size ().l
char buffer[16]
for unsigned i = 0; i < size; i += 16:
name.get_chars (i, buffer)
for unsigned k = 0; k < size - i && k < 16; ++k:
kdebug_char (buffer[k])
kdebug_char ('\n')
Kernel::free_cap (name)
break break

View File

@ -27,9 +27,15 @@ extern unsigned char const charset[127-32][6]
#define assert(x) do { while (!(x)) kdebug ("assertion failed " #x); } while (0) #define assert(x) do { while (!(x)) kdebug ("assertion failed " #x); } while (0)
#if defined (TRENDTAC)
// For now, support only 16 bpp. // For now, support only 16 bpp.
// Screen is 800x480 tft. // Screen is 800x480 tft.
static unsigned h = 800, v = 480, hs = 80, vs = 20, fps = 60, Bpp = 2 static unsigned h = 800, v = 480, hs = 80, vs = 20, fps = 60, Bpp = 2
#else if defined (NANONOTE)
static unsigned h = 320, v = 240, fps = 70, Bpp = 3
#else
#error unknown board
#endif
#define frame_size (v * h * Bpp) #define frame_size (v * h * Bpp)
static unsigned physical_descriptor static unsigned physical_descriptor
@ -40,21 +46,49 @@ struct Descriptor:
unsigned id unsigned id
unsigned cmd unsigned cmd
#if defined (TRENDTAC)
static void reset (): static void reset ():
LCD_CTRL = LCD_CTRL_BPP_16 | LCD_CTRL_BST_16 #if defined (TRENDTAC)
LCD_VSYNC = vs unsigned fps = 60
LCD_HSYNC = hs // Vertical timings.
LCD_DAV = (vs << 16) | (vs + v) unsigned vps = 0, vpe = vps + 20, vds = vpe, vde = vds + v, vt = vde
LCD_DAH = (hs << 16) | (hs + h) // Horizontal timings.
LCD_VAT = ((hs + h) << 16) | (vs + v) unsigned hps = 0, hpe = hps + 80, hds = hpe, hde = hds + h, ht = hde
unsigned extra = 0
// Bits per pixel.
unsigned bpp = LCD_CTRL_BPP_16
// Configuration.
#define MODE_TFT_GEN 0 #define MODE_TFT_GEN 0
#define VSYNC_N (1 << 8) #define VSYNC_N (1 << 8)
LCD_CFG = MODE_TFT_GEN | VSYNC_N unsigned cfg = MODE_TFT_GEN | VSYNC_N
#elif defined (NANONOTE)
unsigned fps = 70
// Vertical timings.
unsigned vps = 0, vpe = vps + 1, vds = vpe + 20, vde = vds + v, vt = vde + 1
// Horizontal timings.
unsigned hps = 0, hpe = hps + 1, hds = hpe + 140, hde = hds + h, ht = hde + 273
// 3 bytes per pixel, so for the display area 2 extra clocks are sent.
unsigned extra = 2
// Bits per pixel.
unsigned bpp = LCD_CTRL_BPP_18_24
// Configuration.
unsigned cfg = LCD_CFG_MODE_TFT_SERIAL_TFT | LCD_CFG_PCP | LCD_CFG_HSP | LCD_CFG_VSP
#else
#error unknown board
#endif
LCD_CTRL = bpp | LCD_CTRL_BST_16
LCD_VSYNC = (vps << 16) | vpe
LCD_HSYNC = (hps << 16) | hpe
LCD_DAV = (vds << 16) | vde
LCD_DAH = (hds << 16) | hde
LCD_VAT = (ht << 16) | vt
LCD_CFG = cfg
cpm_stop_lcd () cpm_stop_lcd ()
unsigned pixclock = fps * (hs + h) * (vs + v) unsigned pixclock = fps * (ht + extra * (hde - hds)) * vt
#if defined (TRENDTAC)
unsigned pllout = cpm_get_pllout () unsigned pllout = cpm_get_pllout ()
CPM_CFCR2 = pllout / pixclock - 1 CPM_CFCR2 = pllout / pixclock - 1
@ -63,18 +97,29 @@ static void reset ():
assert (val <= 0xf) assert (val <= 0xf)
cpm_set_lcdclk_div (val) cpm_set_lcdclk_div (val)
CPM_CFCR |= CPM_CFCR_UPE CPM_CFCR |= CPM_CFCR_UPE
#elif defined (NANONOTE)
unsigned val = cpm_get_pllout2 () / pclk - 1
if val > 0x3ff:
kdebug ("pixel clock too large\n")
Kernel::panic ()
return
cpm_set_pixdiv (val);
val = cpm_get_pllout () / (pixclock * 3)
if val > 0x1f:
kdebug ("pixel divider too large\n")
Kernel::panic ()
return
cpm_set_ldiv (val)
// Update dividers.
CPM_CPCCR |= CPM_CPCCR_CE
#endif
cpm_start_lcd () cpm_start_lcd ()
LCD_DA0 = physical_descriptor LCD_DA0 = physical_descriptor
lcd_set_ena () lcd_set_ena ()
lcd_enable_eof_intr () lcd_enable_eof_intr ()
#elif defined (NANONOTE)
static void reset ():
// TODO
#else
#error unknown board
#endif
static void putchar (unsigned x, unsigned y, unsigned ch, unsigned fg = 0xffff, unsigned bg = 0x0000): static void putchar (unsigned x, unsigned y, unsigned ch, unsigned fg = 0xffff, unsigned bg = 0x0000):
if ch < 32 || ch > 126: if ch < 32 || ch > 126:
@ -83,19 +128,19 @@ static void putchar (unsigned x, unsigned y, unsigned ch, unsigned fg = 0xffff,
unsigned lookup[2] = { bg, fg } unsigned lookup[2] = { bg, fg }
for unsigned k = 0; k < 6; ++k: for unsigned k = 0; k < 6; ++k:
for unsigned r = 0; r < 8; ++r: for unsigned r = 0; r < 8; ++r:
LCD_FRAMEBUFFER_BASE[(y * 8 + r) * 800 + x * 6 + k] = lookup[charset[ch][k] & (1 << r) ? 1 : 0] LCD_FRAMEBUFFER_BASE[(y * 8 + r) * h + x * 6 + k] = lookup[charset[ch][k] & (1 << r) ? 1 : 0]
static unsigned log_x = 1, log_y = 1 static unsigned log_x = 1, log_y = 1
static void inc_logx (): static void inc_logx ():
if ++log_x >= 800 / 6: if ++log_x >= h / 6:
log_x = 1 log_x = 1
if ++log_y >= 480 / 8: if ++log_y >= v / 8:
log_y = 1 log_y = 1
static void log_char (unsigned ch): static void log_char (unsigned ch):
switch ch: switch ch:
case '\n': case '\n':
while log_x < 800 / 6: while log_x < h / 6:
putchar (log_x++, log_y, ' ') putchar (log_x++, log_y, ' ')
inc_logx () inc_logx ()
break break
@ -138,22 +183,22 @@ Kernel::Num start ():
p.alloc_physical (physical + i * PAGE_SIZE, false, true) p.alloc_physical (physical + i * PAGE_SIZE, false, true)
Kernel::my_memory.map (p, (unsigned)LCD_FRAMEBUFFER_BASE + i * PAGE_SIZE) Kernel::my_memory.map (p, (unsigned)LCD_FRAMEBUFFER_BASE + i * PAGE_SIZE)
Kernel::free_cap (p) Kernel::free_cap (p)
for unsigned y = 0; y < 480; ++y: for unsigned y = 0; y < v; ++y:
unsigned g = (y << 6) / 480 unsigned g = (y << 6) / v
unsigned olr = 0, ob = ((25 * y * y) << 5) / (9 * 800 * 800 + 25 * 480 * 480) unsigned olr = 0, ob = ((25 * y * y) << 5) / (9 * h * h + 25 * v * v)
for unsigned x = 0; x < 800; ++x: for unsigned x = 0; x < h; ++x:
unsigned r = (x << 5) / 800 unsigned r = (x << 5) / h
unsigned b = ((9 * x * x + 25 * y * y) << 5) / (9 * 800 * 800 + 25 * 480 * 480) unsigned b = ((9 * x * x + 25 * y * y) << 5) / (9 * h * h + 25 * v * v)
if r != olr: if r != olr:
olr = r olr = r
r = 0x1f r = 0x1f
unsigned oyb = b unsigned oyb = b
if y > 0: if y > 0:
oyb = ((9 * x * x + 25 * (y - 1) * (y - 1)) << 5) / (9 * 800 * 800 + 25 * 480 * 480) oyb = ((9 * x * x + 25 * (y - 1) * (y - 1)) << 5) / (9 * h * h + 25 * v * v)
if b != ob || b != oyb: if b != ob || b != oyb:
ob = b ob = b
b = 0x1f b = 0x1f
LCD_FRAMEBUFFER_BASE[y * 800 + x] = (r << 11) | (g << 5) | (b) LCD_FRAMEBUFFER_BASE[y * h + x] = (r << 11) | (g << 5) | (b)
Kernel::Page p = Kernel::my_memory.mapping (&descriptor) Kernel::Page p = Kernel::my_memory.mapping (&descriptor)
physical_descriptor = p.physical_address () + ((unsigned)&descriptor & ~PAGE_MASK) physical_descriptor = p.physical_address () + ((unsigned)&descriptor & ~PAGE_MASK)
Kernel::free_cap (p) Kernel::free_cap (p)
@ -166,11 +211,12 @@ Kernel::Num start ():
reset () reset ()
Kernel::Cap logcap = Kernel::my_receiver.create_capability (Init::LCD_LOG) Kernel::Cap logcap = Kernel::my_receiver.create_capability (Init::LCD_LOG)
#if defined (TRENDTAC)
__asm__ volatile ("li $a0, 1\nlw $a1, %0\nbreak" :: "m"(logcap.code): "a0", "a1", "memory") __asm__ volatile ("li $a0, 1\nlw $a1, %0\nbreak" :: "m"(logcap.code): "a0", "a1", "memory")
#endif
((Init)Kernel::my_parent).register_lcd () Kernel::Cap eof_cb
bool have_eof = false
Kernel::Cap eof_cb = Kernel::alloc_cap ()
while true: while true:
Kernel::wait () Kernel::wait ()
//log_msg () //log_msg ()
@ -180,11 +226,15 @@ Kernel::Num start ():
eof_cb.invoke () eof_cb.invoke ()
break break
case Init::LCD_SET_EOF_CB: case Init::LCD_SET_EOF_CB:
Kernel::free_cap (eof_cb) if have_eof:
eof_cb = Kernel::recv.arg Kernel::free_cap (eof_cb)
Kernel::recv.arg = Kernel::alloc_cap () else:
Kernel::recv.reply.invoke () have_eof = true
eof_cb = Kernel::get_arg ()
Kernel::Cap reply = Kernel::get_reply ()
Kernel::register_interrupt (IRQ_LCD) Kernel::register_interrupt (IRQ_LCD)
reply.invoke ()
Kernel::free_cap (reply)
break break
case Init::LCD_LOG: case Init::LCD_LOG:
log_char (Kernel::recv.data[0].l) log_char (Kernel::recv.data[0].l)

View File

@ -0,0 +1,70 @@
#pypp 0
// Iris: micro-kernel for a capability-based operating system.
// boot-programs/metronome.ccp: Userspace program.
// 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 "keys.hh"
Kernel::Num start ():
kdebug ("metronome started\n")
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)
kbd.set_cb (key)
unsigned mHz = 1000
unsigned freq = 1000
Kernel::my_receiver.set_alarm (1)
bool running (true)
while true:
Kernel::wait ()
switch Kernel::recv.protected_data.l:
case ~0:
if running:
buzzer.beep (freq, 10, ~0)
Kernel::my_receiver.set_alarm (HZ * 1000 / mHz)
break
case 0:
if Kernel::recv.data[0].l & Keyboard::RELEASE:
break
switch Kernel::recv.data[0].l:
case Key::VOLUME_UP:
freq = freq * 11 / 10
break
case Key::VOLUME_DOWN:
freq = freq * 9 / 10
break
case Key::LEFT:
mHz = mHz * 101 / 100
break
case Key::RIGHT:
mHz = mHz * 99 / 100
break
case Key::UP:
mHz = mHz * 11 / 10
break
case Key::DOWN:
mHz = mHz * 9 / 10
break
case Key::P:
running = !running
if running:
Kernel::my_receiver.set_alarm (1)
break
break
default:
kdebug ("huh?\n")
break

View File

@ -19,6 +19,7 @@
#include "devices.hh" #include "devices.hh"
#define ARCH #define ARCH
#include "arch.hh" #include "arch.hh"
#include "keys.hh"
//#define QI //#define QI
#define SCAN_INTERVAL HZ / 50 #define SCAN_INTERVAL HZ / 50
@ -33,27 +34,8 @@ class DevKbd:
static unsigned const COLS[NUM_COLS] static unsigned const COLS[NUM_COLS]
static unsigned const ROWS[NUM_ROWS] static unsigned const ROWS[NUM_ROWS]
static unsigned const encode[NUM_ROWS][NUM_COLS] static unsigned const encode[NUM_ROWS][NUM_COLS]
enum Keys: static unsigned const NUM_KEYS = 58
#ifdef QI static unsigned const keys[NUM_KEYS]
A, B, C, D, E, F, G, H, I, J, K, L, M
N, O, P, Q, R, S, T, U, V, W, X, Y, Z
F1, F2, F3, F4, F5, F6, F7, F8
TAB, BACKSLASH, QUOTE, COMMA, PERIOD, SLASH, EQUAL, SPACE
ESCAPE, ENTER, BACKSPACE
UP, DOWN, LEFT, RIGHT
CAPS, ARROW, QI, CTRL, VOLUP, VOLDOWN, SHIFT, ALT, FN
#else
N0, N1, N2, N3, N4, N5, N6, N7, N8, N9
A, B, C, D, E, F, G, H, I, J, K, L, M
N, O, P, Q, R, S, T, U, V, W, X, Y, Z
F1, F2, F3, F4
CAPS, TAB, ENTER, ESCAPE, MP3, SPACE, BACKSPACE, EQUALS
UP, DOWN, LEFT, RIGHT
VOLUP, VOLDOWN
FN, SHIFT, CTRL, ALT
#endif
NUM_KEYS
static char const *const names[NUM_KEYS]
unsigned state[NUM_COLS] unsigned state[NUM_COLS]
Kernel::Cap event Kernel::Cap event
bool is_active bool is_active
@ -61,27 +43,14 @@ class DevKbd:
public: public:
unsigned size (): unsigned size ():
return NUM_KEYS return NUM_KEYS
unsigned get_name_size (unsigned n): void send_keys (unsigned first, Kernel::Cap target):
if n >= NUM_KEYS: unsigned d[4]
return 0 unsigned i
unsigned ret = 0 for i = 0; first + i < NUM_KEYS && i < 4; ++i:
for char const *p = names[n]; *p; ++p: d[i] = keys[first + i]
++ret for ; i < 4; ++i:
return ret d[i] = ~0
void send_name (unsigned n, Kernel::Cap c, Kernel::Num offset): target.invoke (Kernel::Num (d[0], d[1]), Kernel::Num (d[2], d[3]))
if n >= NUM_KEYS:
c.invoke (0, 0)
return
unsigned data[4]
char *d = (char *)data
if offset.value () < get_name_size (n):
unsigned o = offset.l & ~3;
unsigned p
for p = 0; p < 16 && names[n][p + o]; ++p:
*d++ = names[n][p + o]
for ; p < 16; ++p:
*d++ = 0
c.invoke (Kernel::Num (data[0], data[1]), Kernel::Num (data[2], data[3]))
bool scanning (): bool scanning ():
return is_scanning return is_scanning
void inactive (): void inactive ():
@ -155,43 +124,44 @@ unsigned const DevKbd::COLS[NUM_COLS] = { 10, 11, 12, 13, 14, 15, 16, 17 }
unsigned const DevKbd::ROWS[NUM_ROWS] = { 18, 19, 20, 21, 22, 23, 24, 26 } unsigned const DevKbd::ROWS[NUM_ROWS] = { 18, 19, 20, 21, 22, 23, 24, 26 }
unsigned const DevKbd::encode[NUM_ROWS][NUM_COLS] = { unsigned const DevKbd::encode[NUM_ROWS][NUM_COLS] = {
#ifdef QI #ifdef QI
{ F1, F2, F3, F4, F5, F6, F7, ~0 }, { Key::F1, Key::F2, Key::F3, Key::F4, Key::F5, Key::F6, Key::F7, ~0 },
{ Q, W, E, R, T, Y, U, I }, { Key::Q, Key::W, Key::E, Key::R, Key::T, Key::Y, Key::U, Key::I },
{ A, S, D, F, G, H, J, K }, { Key::A, Key::S, Key::D, Key::F, Key::G, Key::H, Key::J, Key::K },
{ ESCAPE, Z, X, C, V, B, N, M }, { Key::ESCAPE, Key::Z, Key::X, Key::C, Key::V, Key::B, Key::N, Key::M },
{ TAB, CAPS, BACKSLASH, QUOTE, COMMA, PERIOD, SLASH, UP }, { Key::TAB, Key::CAPS, Key::BACKSLASH, Key::QUOTE, Key::COMMA, Key::PERIOD, Key::SLASH, Key::UP },
{ O, L, EQUAL, ARROW, SPACE, QI, CTRL, LEFT }, { Key::O, Key::L, Key::EQUAL, Key::ARROW, Key::SPACE, Key::QI, Key::CTRL, Key::LEFT },
{ F8, P, BACKSPACE, ENTER, VOLUP, VOLDOWN, DOWN, RIGHT }, { Key::F8, Key::P, Key::BACKSPACE, Key::ENTER, Key::VOLUME_UP, Key::VOLUME_DOWN, Key::DOWN, Key::RIGHT },
{ SHIFT, ALT, FN, ~0, ~0, ~0, ~0, ~0 } { Key::SHIFT, Key::ALT, Key::FN, ~0, ~0, ~0, ~0, ~0 }
#else #else
{ ESCAPE, TAB, F1, F2, F3, F4, MP3, ~0 }, { Key::ESCAPE, Key::TAB, Key::F1, Key::F2, Key::F3, Key::F4, Key::SPECIAL + 0, ~0 },
{ N1, N2, N3, N4, N5, N6, N7, N8 }, { Key::N1, Key::N2, Key::N3, Key::N4, Key::N5, Key::N6, Key::N7, Key::N8 },
{ Q, W, E, R, T, Y, U, I }, { Key::Q, Key::W, Key::E, Key::R, Key::T, Key::Y, Key::U, Key::I },
{ A, S, D, F, G, H, J, K }, { Key::A, Key::S, Key::D, Key::F, Key::G, Key::H, Key::J, Key::K },
{ Z, X, C, V, B, N, M, UP }, { Key::Z, Key::X, Key::C, Key::V, Key::B, Key::N, Key::M, Key::UP },
{ N9, O, L, ALT, CAPS, SPACE, EQUALS, LEFT }, { Key::N9, Key::O, Key::L, Key::LEFT_ALT, Key::CAPS_LOCK, Key::SPACE, Key::EQUALS, Key::LEFT },
{ BACKSPACE, N0, P, ENTER, VOLUP, VOLDOWN, DOWN, RIGHT }, { Key::BACKSPACE, Key::N0, Key::P, Key::ENTER, Key::VOLUME_UP, Key::VOLUME_DOWN, Key::DOWN, Key::RIGHT },
{ FN, SHIFT, CTRL, ~0, ~0, ~0, ~0, ~0 } { Key::FN, Key::LEFT_SHIFT, Key::LEFT_CONTROL, ~0, ~0, ~0, ~0, ~0 }
#endif #endif
} }
char const *const DevKbd::names[NUM_KEYS] = { unsigned const DevKbd::keys[NUM_KEYS] = {
#ifdef QI #ifdef QI
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", Key::F1, Key::F2, Key::F3, Key::F4, Key::F5, Key::F6, Key::F7,
"n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", Key::Q, Key::W, Key::E, Key::R, Key::T, Key::Y, Key::U, Key::I,
"f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", Key::A, Key::S, Key::D, Key::F, Key::G, Key::H, Key::J, Key::K,
"tab", "\\", "'", ",", ".", "/", "=", "space", Key::ESCAPE, Key::Z, Key::X, Key::C, Key::V, Key::B, Key::N, Key::M,
"escape", "enter", "backspace", Key::TAB, Key::CAPS, Key::BACKSLASH, Key::QUOTE, Key::COMMA, Key::PERIOD, Key::SLASH, Key::UP,
"up", "down", "left", "right", Key::O, Key::L, Key::EQUAL, Key::ARROW, Key::SPACE, Key::QI, Key::CTRL, Key::LEFT,
"caps lock", "arrow", "qi", "left control", "volume up", "volume down", "left shift", "left alt", "fn" Key::F8, Key::P, Key::BACKSPACE, Key::ENTER, Key::VOLUME_UP, Key::VOLUME_DOWN, Key::DOWN, Key::RIGHT,
Key::SHIFT, Key::ALT, Key::FN
#else #else
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", Key::ESCAPE, Key::TAB, Key::F1, Key::F2, Key::F3, Key::F4, Key::SPECIAL + 0,
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", Key::N1, Key::N2, Key::N3, Key::N4, Key::N5, Key::N6, Key::N7, Key::N8,
"n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", Key::Q, Key::W, Key::E, Key::R, Key::T, Key::Y, Key::U, Key::I,
"f1", "f2", "f3", "f4", Key::A, Key::S, Key::D, Key::F, Key::G, Key::H, Key::J, Key::K,
"caps lock", "tab", "enter", "escape", "mp3", "space", "backspace", "=", Key::Z, Key::X, Key::C, Key::V, Key::B, Key::N, Key::M, Key::UP,
"up", "down", "left", "right", Key::N9, Key::O, Key::L, Key::LEFT_ALT, Key::CAPS_LOCK, Key::SPACE, Key::EQUALS, Key::LEFT,
"volume up", "volume down", Key::BACKSPACE, Key::N0, Key::P, Key::ENTER, Key::VOLUME_UP, Key::VOLUME_DOWN, Key::DOWN, Key::RIGHT,
"fn", "left shift", "left control", "left alt" Key::FN, Key::LEFT_SHIFT, Key::LEFT_CONTROL
#endif #endif
} }
@ -222,12 +192,10 @@ class PowerButton:
enum codes: enum codes:
KBD_DEV = 32 KBD_DEV = 32
KBD_LIST
PWR PWR
Kernel::Num start (): Kernel::Num start ():
map_gpio () map_gpio ()
map_tcu ()
DevKbd kbd DevKbd kbd
PowerButton pwr PowerButton pwr
@ -242,7 +210,6 @@ Kernel::Num start ():
Kernel::my_receiver.set_alarm (SCAN_INTERVAL) Kernel::my_receiver.set_alarm (SCAN_INTERVAL)
unsigned user (~0) unsigned user (~0)
unsigned next_user (0) unsigned next_user (0)
List <String> list = List <String> (Kernel::my_receiver.create_capability (KBD_LIST))
Kernel::register_interrupt (IRQ_GPIO3) Kernel::register_interrupt (IRQ_GPIO3)
while true: while true:
Kernel::wait () Kernel::wait ()
@ -307,24 +274,6 @@ Kernel::Num start ():
kdebug ("\n") kdebug ("\n")
break break
break break
case KBD_LIST:
// Keyboard name lookup.
switch Kernel::recv.data[0].l:
case Kernel::Caps::GET:
Kernel::Cap reply = Kernel::get_reply ()
unsigned num = Kernel::recv.data[1].l
Kernel::Cap name = Kernel::my_receiver.create_capability (Kernel::Num (num, KBD_LIST))
reply.invoke (kbd.get_name_size (num), 0, name.copy ())
Kernel::free_cap (name)
Kernel::free_cap (reply)
break
case Kernel::Caps::GET_SIZE:
Kernel::recv.reply.invoke (kbd.size ())
break
default:
kdebug ("invalid list operation\n")
break
break
default: default:
break break
break break
@ -337,29 +286,23 @@ Kernel::Num start ():
switch Kernel::recv.data[0].l: switch Kernel::recv.data[0].l:
case Keyboard::SET_CB: case Keyboard::SET_CB:
kdebug ("set cb\n") kdebug ("set cb\n")
Kernel::Cap reply = Kernel::get_reply ()
kbd.active (Kernel::get_arg ()) kbd.active (Kernel::get_arg ())
Kernel::recv.reply.invoke () reply.invoke ()
Kernel::free_cap (reply)
break
case Keyboard::GET_NUM_KEYS:
kdebug ("get #keys\n")
Kernel::recv.reply.invoke (kbd.size ())
break break
case Keyboard::GET_KEYS: case Keyboard::GET_KEYS:
kdebug ("get keys\n") kdebug ("get keys\n")
Kernel::recv.reply.invoke (0, 0, list) kbd.send_keys (Kernel::recv.data[0].l, Kernel::recv.reply)
break break
default: default:
kdebug ("other\n") kdebug ("other\n")
break break
break break
case KBD_LIST:
switch Kernel::recv.data[0].l:
case String::GET_SIZE:
Kernel::recv.reply.invoke (kbd.get_name_size (Kernel::recv.protected_data.l))
break
case String::GET_CHARS:
kbd.send_name (Kernel::recv.protected_data.l, Kernel::recv.reply, Kernel::recv.data[1])
break
default:
kdebug ("invalid string operation\n")
break
break
default: default:
kdebug ("unknown num: ") kdebug ("unknown num: ")
kdebug_num (Kernel::recv.protected_data.h) kdebug_num (Kernel::recv.protected_data.h)

View File

@ -75,11 +75,26 @@ struct WString : public String:
void set_page (Kernel::Num idx, Kernel::Page page): void set_page (Kernel::Num idx, Kernel::Page page):
ocall (page, CAP_MASTER_DIRECT | SET_PAGE, idx) ocall (page, CAP_MASTER_DIRECT | SET_PAGE, idx)
// Interface for talking to the parent process.
struct Parent : public Kernel::Cap:
Parent (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
enum request:
GET_DEVICE = WString::ID
EXIT
ID
// Get a device handle.
template <typename _T> _T get_device (unsigned num = 0):
icall (CAP_MASTER_DIRECT | GET_DEVICE, Kernel::Num (_T::ID, num))
return Kernel::get_arg ()
// Exit the program. The parent does not reply, but kills the process.
void exit (Kernel::Num code):
call (CAP_MASTER_DIRECT | EXIT, code)
// Every process which wants to be switchable through a terminal must implement this interface. // Every process which wants to be switchable through a terminal must implement this interface.
struct Device : public Kernel::Cap: struct Device : public Kernel::Cap:
Device (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c): Device (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
enum request: enum request:
CREATE_USER = WString::ID CREATE_USER = Parent::ID
DESTROY_USER DESTROY_USER
UNUSE UNUSE
USE USE
@ -104,6 +119,7 @@ struct Keyboard : public Kernel::Cap:
Keyboard (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c): Keyboard (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
enum request: enum request:
SET_CB = Device::ID SET_CB = Device::ID
GET_NUM_KEYS
GET_KEYS GET_KEYS
ID ID
// At event: the callback is called with a keycode. One bit defines if it's a press or release event. // At event: the callback is called with a keycode. One bit defines if it's a press or release event.
@ -112,10 +128,10 @@ struct Keyboard : public Kernel::Cap:
// Set the event callback. Currently pressed keys emit a key press event to the new callback immediately. // Set the event callback. Currently pressed keys emit a key press event to the new callback immediately.
void set_cb (Kernel::Cap cb): void set_cb (Kernel::Cap cb):
ocall (cb, CAP_MASTER_DIRECT | SET_CB) ocall (cb, CAP_MASTER_DIRECT | SET_CB)
// Get a list of keys on this keyboard. The key codes start at zero with no gaps. unsigned get_num_keys ():
List <String> get_keys (): return call (CAP_MASTER_DIRECT | GET_NUM_KEYS).l
icall (CAP_MASTER_DIRECT | GET_KEYS) void get_keys (unsigned first):
return List <String> (Kernel::get_arg ()) call (CAP_MASTER_DIRECT | GET_KEYS, first)
// Buzzer interface. // Buzzer interface.
struct Buzzer : public Kernel::Cap: struct Buzzer : public Kernel::Cap:

View File

@ -19,33 +19,32 @@
#include "kernel.hh" #include "kernel.hh"
static void log_message (char const *prefix, unsigned target, unsigned pdata, kCapability::Context *c): static void log_message (char const *prefix, unsigned target, unsigned pdata, kCapability::Context *c):
if !dbg_code.l: dbg_log (prefix)
dbg_log (prefix) dbg_log (": caller=")
dbg_log (": caller=") dbg_log_num ((unsigned)old_current)
dbg_log_num ((unsigned)old_current) dbg_log ("; target=")
dbg_log ("; target=") dbg_log_num (target)
dbg_log_num (target) dbg_log ("; pdata=")
dbg_log_num (pdata)
dbg_log ("; data=")
dbg_log_num (c->data[0].h)
dbg_log (":")
dbg_log_num (c->data[0].l)
dbg_log (",")
dbg_log_num (c->data[1].h)
dbg_log (":")
dbg_log_num (c->data[1].l)
if c->reply.valid ():
dbg_log ("; reply target=")
dbg_log_num ((unsigned)c->reply->target)
dbg_log ("; pdata=") dbg_log ("; pdata=")
dbg_log_num (pdata) dbg_log_num (c->reply->protected_data.l)
dbg_log ("; data=") if c->arg.valid ():
dbg_log_num (c->data[0].h) dbg_log ("; arg target=")
dbg_log (":") dbg_log_num ((unsigned)c->arg->target)
dbg_log_num (c->data[0].l) dbg_log ("; pdata=")
dbg_log (",") dbg_log_num (c->arg->protected_data.l)
dbg_log_num (c->data[1].h) dbg_log ("\n")
dbg_log (":")
dbg_log_num (c->data[1].l)
if c->reply.valid ():
dbg_log ("; reply target=")
dbg_log_num ((unsigned)c->reply->target)
dbg_log ("; pdata=")
dbg_log_num (c->reply->protected_data.l)
if c->arg.valid ():
dbg_log ("; arg target=")
dbg_log_num ((unsigned)c->arg->target)
dbg_log ("; pdata=")
dbg_log_num (c->arg->protected_data.l)
dbg_log ("\n")
void kThread::raise (unsigned code, unsigned data): void kThread::raise (unsigned code, unsigned data):
dpanic (code, "raise") dpanic (code, "raise")
@ -104,8 +103,8 @@ bool kReceiver::try_deliver ():
if m->protected_data.value () == reply_protected_data.value (): if m->protected_data.value () == reply_protected_data.value ():
protected_only = false protected_only = false
break break
if !m: if !m:
return false return false
bool dummy bool dummy
kCapRef c = owner->find_capability (owner->recv_reply, &dummy) kCapRef c = owner->find_capability (owner->recv_reply, &dummy)
if c.valid (): if c.valid ():
@ -121,7 +120,7 @@ bool kReceiver::try_deliver ():
// Send a message to a receiver; try to deliver it immediately. // Send a message to a receiver; try to deliver it immediately.
bool kReceiver::send_message (Kernel::Num protected_data, kCapability::Context *c): bool kReceiver::send_message (Kernel::Num protected_data, kCapability::Context *c):
//log_message ("send_message", (unsigned)this, protected_data.l, c) //log_message ("send_message", (unsigned)this, protected_data.l, c)
if owner && owner->is_waiting () && (protected_data.value () == reply_protected_data.value () || !protected_only): if owner && owner->is_waiting () && (!protected_only || protected_data.value () == reply_protected_data.value ()):
if protected_only: if protected_only:
protected_only = false protected_only = false
bool dummy bool dummy
@ -145,16 +144,6 @@ bool kReceiver::send_message (Kernel::Num protected_data, kCapability::Context *
if !msg: if !msg:
return false return false
msg->protected_data = protected_data msg->protected_data = protected_data
if protected_only && protected_data.value () == reply_protected_data.value ():
// Put this message in the end (where it will be first seen). Clear the protected_only flag.
protected_only = false
if msg->next:
((kMessage *)msg->next)->prev = NULL
messages = (kMessage *)msg->next
msg->next = NULL
msg->prev = last_message
((kMessage *)msg->prev)->next = msg
last_message = msg
for unsigned i = 0; i < 2; ++i: for unsigned i = 0; i < 2; ++i:
msg->data[i] = c->data[i] msg->data[i] = c->data[i]
msg->caps.clone (0, c->reply, c->copy[0]) msg->caps.clone (0, c->reply, c->copy[0])
@ -194,9 +183,9 @@ static void reply_cap (unsigned target, Kernel::Num protected_data, kCapRef *ref
c.data[0] = Kernel::Num (num, 0) c.data[0] = Kernel::Num (num, 0)
if reply_target: if reply_target:
reply_target->send_message (reply_protected, &c) reply_target->send_message (reply_protected, &c)
c.arg->invalidate ()
else: else:
dpanic (0, "nothing to reply to") dpanic (0, "nothing to reply to")
c.arg->invalidate ()
static void receiver_invoke (unsigned cmd, unsigned target, Kernel::Num protected_data, kCapability::Context *c): static void receiver_invoke (unsigned cmd, unsigned target, Kernel::Num protected_data, kCapability::Context *c):
kReceiver *receiver = (kReceiver *)protected_data.l kReceiver *receiver = (kReceiver *)protected_data.l
@ -713,6 +702,8 @@ static void print_cap (kCapRef cap, kCapRef self):
dbg_log_char ('!') dbg_log_char ('!')
else: else:
dbg_log_char ('=') dbg_log_char ('=')
dbg_log_num ((unsigned)cap->target)
dbg_log_char (':')
dbg_log_num (cap->protected_data.l) dbg_log_num (cap->protected_data.l)
for kCapRef c = cap->children; c.valid (); c = c->sibling_next: for kCapRef c = cap->children; c.valid (); c = c->sibling_next:
print_cap (c, self) print_cap (c, self)
@ -746,12 +737,9 @@ static void caps_invoke (unsigned cmd, unsigned target, Kernel::Num protected_da
return return
case Kernel::Caps::PRINT & REQUEST_MASK: case Kernel::Caps::PRINT & REQUEST_MASK:
if c->data[1].l >= caps->size: if c->data[1].l >= caps->size:
if c->data[1].l == ~0:
// debug: power down.
*((volatile unsigned *)0xa0003020) = 1
return
dpanic (0, "invalid caps for print") dpanic (0, "invalid caps for print")
return return
dbg_code.h = (unsigned)caps->cap (c->data[1].l)
kCapRef cap (caps, c->data[1].l) kCapRef cap (caps, c->data[1].l)
kCapRef orig (caps, c->data[1].l) kCapRef orig (caps, c->data[1].l)
while cap->parent.valid (): while cap->parent.valid ():
@ -796,11 +784,12 @@ static void kill_reply (kReceiver *r):
static void kernel_invoke (unsigned target, Kernel::Num protected_data, kCapability::Context *c): static void kernel_invoke (unsigned target, Kernel::Num protected_data, kCapability::Context *c):
// Kernel calling convention: // Kernel calling convention:
// data[0].l is the request. // data[0].l is the request.
// caps[0] is the reply capability // reply is the reply capability, or (for call capabilities) the target to call.
// other parameters' meanings depend on the operation. // other parameters' meanings depend on the operation.
if target == (CAPTYPE_RECEIVER | Kernel::Receiver::CALL) || target == (CAPTYPE_RECEIVER | Kernel::Receiver::CALL_ASYNC): if target == (CAPTYPE_RECEIVER | Kernel::Receiver::CALL) || target == (CAPTYPE_RECEIVER | Kernel::Receiver::CALL_ASYNC):
// This is a call capability. reply is the capability to call. It should be replaced by the reply capability. // This is a call capability. reply is the capability to call.
((kReceiver *)protected_data.l)->protected_only = target == (CAPTYPE_RECEIVER | Kernel::Receiver::CALL) kReceiver *owner = (kReceiver *)protected_data.l
owner->protected_only = target == (CAPTYPE_RECEIVER | Kernel::Receiver::CALL)
if must_wait: if must_wait:
old_current->wait () old_current->wait ()
if !reply_target: if !reply_target:
@ -825,6 +814,7 @@ static void kernel_invoke (unsigned target, Kernel::Num protected_data, kCapabil
c->reply.reset () c->reply.reset ()
reply_target = (kReceiver *)protected_data.l reply_target = (kReceiver *)protected_data.l
reply_protected = reply_target->reply_protected_data reply_protected = reply_target->reply_protected_data
kReceiver *r = reply_target
kernel_invoke ((unsigned)call_target->target, call_target->protected_data, c) kernel_invoke ((unsigned)call_target->target, call_target->protected_data, c)
return return
if must_wait: if must_wait:

View File

@ -65,6 +65,8 @@
// This constant signifies that no capability is passed. // This constant signifies that no capability is passed.
#define CAP_NONE (~CAP_COPY) #define CAP_NONE (~CAP_COPY)
struct Parent
namespace Kernel: namespace Kernel:
enum Exception_code: enum Exception_code:
NO_ERROR NO_ERROR
@ -161,7 +163,7 @@ namespace Kernel:
extern Thread my_thread extern Thread my_thread
extern Memory my_memory extern Memory my_memory
extern Cap my_call extern Cap my_call
extern Cap my_parent extern Parent my_parent
extern __recv_data_t recv extern __recv_data_t recv
inline Cap get_reply (): inline Cap get_reply ():

View File

@ -137,11 +137,12 @@ struct kReceiver : public kObject:
Kernel::Num reply_protected_data Kernel::Num reply_protected_data
bool protected_only bool protected_only
// This limit is for messages stored in its address space. There is unlimited space if senders provide it. // This limit is for messages stored in its address space. There is unlimited space if senders provide it.
unsigned queue_limit unsigned queue_limit, queue_use
void own (kThreadP o) void own (kThreadP o)
void orphan () void orphan ()
bool try_deliver () bool try_deliver ()
bool send_message (Kernel::Num protected_data, kCapability::Context *c) bool send_message (Kernel::Num protected_data, kCapability::Context *c)
void check (unsigned line)
struct kPage : public kObject: struct kPage : public kObject:
unsigned frame unsigned frame
@ -205,6 +206,8 @@ struct kMemory : public kObject:
void free_memory (kMemory *mem) void free_memory (kMemory *mem)
void free_obj (kObject *obj, void **first) void free_obj (kObject *obj, void **first)
void check (unsigned line)
void print (unsigned line, unsigned indent)
// Functions which can be called from assembly must not be mangled. // Functions which can be called from assembly must not be mangled.
extern "C": extern "C":
@ -219,7 +222,12 @@ extern "C":
void dbg_log_num (unsigned num, unsigned digits = 8) void dbg_log_num (unsigned num, unsigned digits = 8)
void dbg_send (unsigned num, unsigned bits) void dbg_send (unsigned num, unsigned bits)
void check (unsigned num, char const *msg) void check (unsigned num, char const *msg)
#define dbg_check() ::check (__LINE__, __FILE__)
void print_free ()
void check_impl (kObject *o, unsigned num, char const *msg)
bool check_free (kObject *o, unsigned size)
#define dpanic(n, msg) panic (n, msg) #define dpanic(n, msg) panic (n, msg)
#define dbg_print() top_memory.print (__LINE__, 0)
#else #else
#define dbg_log_char(x) do {} while (0) #define dbg_log_char(x) do {} while (0)
#define dbg_log(x) do {} while (0) #define dbg_log(x) do {} while (0)

147
keys.hhp Normal file
View File

@ -0,0 +1,147 @@
#pypp 0
// Iris: micro-kernel for a capability-based operating system.
// boot-programs/keys.hhp: Keycode definitions.
// 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/>.
#ifndef __KEYS_HH
#define __KEYS_HH
namespace Key:
enum codes:
N0 = '0'
N1 = '1'
N2 = '2'
N3 = '3'
N4 = '4'
N5 = '5'
N6 = '6'
N7 = '7'
N8 = '8'
N9 = '9'
A = 'a'
B = 'b'
C = 'c'
D = 'd'
E = 'e'
F = 'f'
G = 'g'
H = 'h'
I = 'i'
J = 'j'
K = 'k'
L = 'l'
M = 'm'
N = 'n'
O = 'o'
P = 'p'
Q = 'q'
R = 'r'
S = 's'
T = 't'
U = 'u'
V = 'v'
W = 'w'
X = 'x'
Y = 'y'
Z = 'z'
ESCAPE = 27
ENTER = '\n'
TAB = '\t'
COMMA = ','
PERIOD = '.'
SLASH = '/'
BACKSLASH = '\\'
SEMICOLON = ';'
QUOTE = '\''
BACKQUOTE = '`'
OPEN_BRACKET = '['
CLOSE_BRACKET = ']'
MINUS = '-'
EQUALS = '='
BACKSPACE = 8
HOME = 11
DELETE = 127
SPACE = ' '
KP_0 = 0x100
KP_1
KP_2
KP_3
KP_4
KP_5
KP_6
KP_7
KP_8
KP_9
KP_PERIOD = '.' + 0x100
KP_ENTER = '\n' + 0x100
KP_PLUS = '+' + 0x100
KP_MINUS = '-' + 0x100
KP_MULTIPLY = '*' + 0x100
KP_DIVIDE = '/' + 0x100
FN = 0x200
F1
F2
F3
F4
F5
F6
F7
F8
F9
F10
F11
F12
F13
F14
F15
F16
F17
F18
F19
F20
F21
F22
F23
F24
POWER_OFF
SLEEP
WAKE_UP
VOLUME_UP
VOLUME_DOWN
UP
DOWN
LEFT
RIGHT
INSERT
END
PAGE_UP
PAGE_DOWN
PRINT_SCREEN
PAUSE
CAPS_LOCK
NUM_LOCK
SCROLL_LOCK
LEFT_SHIFT
RIGHT_SHIFT
LEFT_CONTROL
RIGHT_CONTROL
LEFT_ALT
RIGHT_ALT
LEFT_LOGO
RIGHT_LOGO
MENU
SPECIAL
#endif

View File

@ -34,6 +34,7 @@ void check_impl (kObject *o, unsigned num, char const *msg):
for ; o; o = o->next: for ; o; o = o->next:
if (unsigned)o >= (unsigned)free_begin && (unsigned)o < (unsigned)free_end: if (unsigned)o >= (unsigned)free_begin && (unsigned)o < (unsigned)free_end:
panic (num, msg) panic (num, msg)
void print_free ():
#endif #endif
#else #else
@ -129,11 +130,20 @@ void phys_free (unsigned page, unsigned num):
n->num = num n->num = num
#ifndef NDEBUG #ifndef NDEBUG
void check_impl (kObject *o, unsigned num, char const *msg): bool check_free (kObject *o, unsigned size):
for ; o; o = (kObject *)o->next: for kFreePages *p = first_free; p; p = p->next:
for kFreePages *p = first_free; p; p = p->next: if (unsigned)o + size > (unsigned)p && (unsigned)o < (unsigned)p + p->num * PAGE_SIZE:
if (unsigned)o >= (unsigned)p && (unsigned)o < (unsigned)p + p->num * PAGE_SIZE: return false
panic (num, msg) return true
void print_free ():
dbg_log ("Free pages: ")
for kFreePages *p = first_free; p; p = p->next:
dbg_log_num ((unsigned)p)
dbg_log (":")
dbg_log_num (p->num, 4)
dbg_log ("->")
dbg_log ("NULL\n")
#endif #endif
#endif #endif
@ -142,6 +152,8 @@ void check_memory (kMemory *mem, unsigned num, char const *msg):
check_impl (mem->pages, num, msg) check_impl (mem->pages, num, msg)
check_impl (mem->threads, num, msg) check_impl (mem->threads, num, msg)
check_impl (mem->receivers, num, msg) check_impl (mem->receivers, num, msg)
for kReceiver *r = mem->receivers; r; r = (kReceiver *)r->next:
check_impl (r->messages, num, msg)
check_impl (mem->capses, num, msg) check_impl (mem->capses, num, msg)
check_impl (mem->memories, num, msg) check_impl (mem->memories, num, msg)
for kMemory *m = mem->memories; m; m = (kMemory *)m->next: for kMemory *m = mem->memories; m; m = (kMemory *)m->next:
@ -149,6 +161,7 @@ void check_memory (kMemory *mem, unsigned num, char const *msg):
void check (unsigned num, char const *msg): void check (unsigned num, char const *msg):
check_memory (&top_memory, num, msg) check_memory (&top_memory, num, msg)
top_memory.check (num)
#endif #endif
unsigned raw_zalloc (): unsigned raw_zalloc ():

View File

@ -131,20 +131,18 @@ void flush_tlb (unsigned asid):
__asm__ volatile ("tlbwi") __asm__ volatile ("tlbwi")
static void arch_invoke (): static void arch_invoke ():
kCapRef target kCapRef target = old_current->find_capability (old_current->arch.v[0], &must_wait)
target = old_current->find_capability (old_current->arch.v[0], &must_wait)
do_schedule = false do_schedule = false
kCapability::Context msg kCapability::Context msg
msg.reply = old_current->find_capability (old_current->arch.t[0], &msg.copy[0])
msg.arg = old_current->find_capability (old_current->arch.t[1], &msg.copy[1])
if must_wait: if must_wait:
bool dummy
old_current->recv_reply = old_current->arch.t[2] old_current->recv_reply = old_current->arch.t[2]
old_current->recv_arg = old_current->arch.t[3] old_current->recv_arg = old_current->arch.t[3]
if !target.valid (): if !target.valid ():
if must_wait: if must_wait:
old_current->wait () old_current->wait ()
return return
msg.reply = old_current->find_capability (old_current->arch.t[0], &msg.copy[0])
msg.arg = old_current->find_capability (old_current->arch.t[1], &msg.copy[1])
msg.data[0] = Kernel::Num (old_current->arch.a[0], old_current->arch.a[1]) msg.data[0] = Kernel::Num (old_current->arch.a[0], old_current->arch.a[1])
msg.data[1] = Kernel::Num (old_current->arch.a[2], old_current->arch.a[3]) msg.data[1] = Kernel::Num (old_current->arch.a[2], old_current->arch.a[3])
target->invoke (&msg) target->invoke (&msg)

View File

@ -17,7 +17,7 @@
load = 0x80000000 load = 0x80000000
ARCH_CXXFLAGS = -DNUM_THREADS=4 ARCH_CXXFLAGS = -DNUM_THREADS=5
ARCH_CPPFLAGS = -I. -Imips -Imips/nanonote -Wa,-mips32 -DNANONOTE -DUSE_SERIAL ARCH_CPPFLAGS = -I. -Imips -Imips/nanonote -Wa,-mips32 -DNANONOTE -DUSE_SERIAL
CROSS = mipsel-linux-gnu- CROSS = mipsel-linux-gnu-
OBJDUMP = $(CROSS)objdump OBJDUMP = $(CROSS)objdump
@ -28,7 +28,7 @@ LDFLAGS = --omagic -Ttext $(load)
arch_iris_sources = mips/interrupts.cc mips/arch.cc arch_iris_sources = mips/interrupts.cc mips/arch.cc
boot_sources = mips/init.cc mips/nanonote/board.cc boot_sources = mips/init.cc mips/nanonote/board.cc
arch_headers = mips/arch.hh mips/nanonote/jz4740.hh mips/nanonote/board.hh arch_headers = mips/arch.hh mips/nanonote/jz4740.hh mips/nanonote/board.hh
boot_threads = init udc nanonote-gpio buzzer boot_threads = init udc nanonote-gpio buzzer metronome
test: iris.raw nanonote-boot test: iris.raw nanonote-boot
./nanonote-boot iris.raw 0xa$(shell /bin/sh -c '$(OBJDUMP) -t iris.elf | grep __start$$ | cut -b2-8') ./nanonote-boot iris.raw 0xa$(shell /bin/sh -c '$(OBJDUMP) -t iris.elf | grep __start$$ | cut -b2-8')
@ -50,7 +50,7 @@ mips/entry.o: $(boot_threads)
mips/init.o: TARGET_FLAGS = -I/usr/include mips/init.o: TARGET_FLAGS = -I/usr/include
$(boot_threads): TARGET_FLAGS = -I. $(boot_threads): TARGET_FLAGS = -I.
$(boot_threads): LDFLAGS = -EL $(boot_threads): LDFLAGS = -EL
$(addprefix boot-programs/,$(addsuffix .cc,$(boot_threads))): boot-programs/devices.hh $(addprefix boot-programs/,$(addsuffix .cc,$(boot_threads))): devices.hh keys.hh
lcd: boot-programs/charset.data lcd: boot-programs/charset.data
boot-programs/charset.data: boot-programs/charset boot-programs/charset.data: boot-programs/charset
@ -63,4 +63,4 @@ boot-programs/charset.data: boot-programs/charset
iris.elf: mips/entry.o $(subst .cc,.o,$(iris_sources)) mips/nanonote/threadlist.o mips/boot.o $(subst .cc,.o,$(boot_sources)) iris.elf: mips/entry.o $(subst .cc,.o,$(iris_sources)) mips/nanonote/threadlist.o mips/boot.o $(subst .cc,.o,$(boot_sources))
$(LD) $(LDFLAGS) $^ -o $@ $(LD) $(LDFLAGS) $^ -o $@
ARCH_CLEAN_FILES = $(boot_sources) $(boot_threads) $(arch_headers) boot_programs/devices.hh mips/*.o mips/nanonote/*.o boot-programs/charset.data iris.elf iris.raw mips/nanonote/sdram-setup.elf mips/nanonote/sdram-setup.raw ARCH_CLEAN_FILES = $(boot_sources) $(boot_threads) $(arch_headers) devices.hh keys.hh mips/*.o mips/nanonote/*.o boot-programs/charset.data iris.elf iris.raw mips/nanonote/sdram-setup.elf mips/nanonote/sdram-setup.raw

View File

@ -54,4 +54,5 @@ void board_init ():
UART0_DLLR = uart_div UART0_DLLR = uart_div
UART0_LCR = UARTLCR_WLEN_8 | UARTLCR_STOP1 UART0_LCR = UARTLCR_WLEN_8 | UARTLCR_STOP1
UART0_FCR = UARTFCR_UUE | UARTFCR_FE | UARTFCR_RFLS | UARTFCR_TFLS UART0_FCR = UARTFCR_UUE | UARTFCR_FE | UARTFCR_RFLS | UARTFCR_TFLS
dbg_code.l = 1
dbg_log ("Serial port initialized\n") dbg_log ("Serial port initialized\n")

View File

@ -35,7 +35,11 @@ thread2:
thread3: thread3:
.incbin "buzzer" .incbin "buzzer"
.balign 0x1000
thread4: thread4:
.incbin "metronome"
thread5:
// Everything from here may be freed after kernel initialization. // Everything from here may be freed after kernel initialization.
init_start: init_start:
@ -46,3 +50,4 @@ thread_start:
.word thread2 .word thread2
.word thread3 .word thread3
.word thread4 .word thread4
.word thread5

View File

@ -21,6 +21,8 @@
#ifdef USE_SERIAL #ifdef USE_SERIAL
void dbg_log_char (unsigned ch): void dbg_log_char (unsigned ch):
if dbg_code.l == 0:
return
while !(UART0_LSR & UARTLSR_TDRQ): while !(UART0_LSR & UARTLSR_TDRQ):
UART0_TDR = ch UART0_TDR = ch
#else #else

View File

@ -90,6 +90,6 @@ void schedule ():
void timer_interrupt (): void timer_interrupt ():
kReceiver *recv, *next kReceiver *recv, *next
for recv = first_alarm; recv; recv = next: for recv = first_alarm; recv; recv = next:
next = (kReceiver *)recv->next next = (kReceiver *)recv->next_alarm
alarm_tick (recv) alarm_tick (recv)
//schedule () //schedule ()