diff --git a/alloc.ccp b/alloc.ccp
index 13f2050..d2792b7 100644
--- a/alloc.ccp
+++ b/alloc.ccp
@@ -308,6 +308,8 @@ void kMemory::free_thread (kThread *thread):
free_obj (thread, (void **)&threads)
void kMemory::free_message (kReceiver *owner, kMessage *message):
+ for unsigned i = 0; i < 2; ++i:
+ message->caps.cap (i)->invalidate ()
if !message->next:
owner->last_message = (kMessageP)message->prev
free_obj (message, (void **)&owner->messages)
@@ -405,3 +407,98 @@ void kPage::forget ():
frame = 0
flags &= ~(Kernel::Page::FRAME | Kernel::Page::SHARED | Kernel::Page::PHYSICAL | Kernel::Page::UNCACHED)
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)
diff --git a/boot-programs/buzzer.ccp b/boot-programs/buzzer.ccp
index 0fbea4f..f6fb5ce 100644
--- a/boot-programs/buzzer.ccp
+++ b/boot-programs/buzzer.ccp
@@ -23,10 +23,9 @@
class DevBuzzer:
static unsigned const pwm = 4
Kernel::Cap event
- bool is_active, is_beeping
+ bool is_beeping
public:
DevBuzzer ():
- is_active = false
is_beeping = false
gpio_as_pwm4 ()
tcu_stop_counter (pwm)
@@ -38,8 +37,8 @@ class DevBuzzer:
return
tcu_stop_counter (pwm)
event.invoke ()
- is_active = false
Kernel::free_cap (event)
+ is_beeping = false
void beep (unsigned freq, unsigned ms, Kernel::Cap cb):
stop ()
event = cb
@@ -115,12 +114,11 @@ Kernel::Num start ():
break
switch Kernel::recv.data[0].l:
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 reply = Kernel::get_reply ()
buzzer.beep (Kernel::recv.data[1].l, Kernel::recv.data[1].h, arg)
reply.invoke ()
- Kernel::free_cap (arg)
Kernel::free_cap (reply)
break
case Buzzer::STOP:
diff --git a/boot-programs/crt0.ccp b/boot-programs/crt0.ccp
index efd1702..cd5a0d9 100644
--- a/boot-programs/crt0.ccp
+++ b/boot-programs/crt0.ccp
@@ -17,6 +17,7 @@
// along with this program. If not, see .
#include "iris.hh"
+#include "devices.hh"
// For some unknown reason, gcc needs this to be defined.
unsigned __gxx_personality_v0
@@ -33,7 +34,7 @@ namespace Kernel:
Thread my_thread
Memory my_memory
Cap my_call
- Cap my_parent
+ Parent my_parent
__recv_data_t recv
void print_caps ():
diff --git a/boot-programs/init.ccp b/boot-programs/init.ccp
index e996ad2..431d305 100644
--- a/boot-programs/init.ccp
+++ b/boot-programs/init.ccp
@@ -19,28 +19,50 @@
#include "devices.hh"
#include "iris.hh"
-static Keyboard kbd, sysreq
-static Buzzer buzzer
+static Keyboard sysreq
static Device kbd_dev, buz_dev
-static List kbd_names
static unsigned slot
// Event types.
enum type:
- MEMORY
- KBDDEV
- KBD
- KEYNAMES
SYSREQ
+ KBDDEV
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 ():
unsigned state = 0
Kernel::Caps caps = Kernel::my_memory.create_caps (32)
slot = caps.use ()
- Kernel::set_recv_arg (Kernel::Cap (slot, MEMORY))
- Kernel::Cap driver_memory = Kernel::my_memory.create_memory ()
+ Kernel::Caps slot0 = Kernel::my_thread.get_caps (0)
+ Kernel::Cap user
+ unsigned device
while true:
Kernel::wait ()
Kernel::Cap reply = Kernel::get_reply ()
@@ -59,44 +81,38 @@ static void setup ():
default:
kdebug ("unexpected keyboard\n")
break
+ reply.invoke ()
+ Kernel::free_cap (reply)
break
case Buzzer::ID:
caps.set (BUZDEV, arg.copy ())
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
default:
+ kdebug ("unknown setup request for init\n")
+ reply.invoke ()
Kernel::free_cap (reply)
Kernel::free_cap (arg)
- kdebug ("unknown setup request for init\n")
continue
- reply.invoke ()
- Kernel::free_cap (reply)
Kernel::free_cap (arg)
- if ++state == 3:
+ if ++state == 4:
break
// sysreq
+ kdebug ("using sysreq\n")
Kernel::Cap cb = Kernel::my_receiver.create_capability (SYSREQ)
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)
-
-//char const *decode_kbd = "0123456789abcdefghijklmnopqrstuvwxyz!@#$%^&*() T\n[],.-=/\\;|`'UDLREIKBPFZMS{}CA\":"
-char const *decode_kbd = "0123456789abcdefghijklmnopqrstuvwxyz!@#$*T\nE& B=UDLR+-F^CA"
+ // First user reply.
+ kdebug ("sending first user reply\n")
+ user_reply (user, device)
+ Kernel::free_cap (user)
Kernel::Num start ():
setup ()
@@ -112,20 +128,11 @@ Kernel::Num start ():
else:
kdebug ("pressed.\n\n")
break
- case KBD:
- unsigned code = Kernel::recv.data[0].l
- if code & Keyboard::RELEASE:
- kdebug_char ('-')
- else:
- kdebug_char ('+')
- buzzer.beep (2000, 100, 0)
- 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)
+ default:
+ if Kernel::recv.data[0].l != Parent::GET_DEVICE:
+ kdebug ("invalid call from user\n")
+ break
+ Kernel::Cap reply = Kernel::get_reply ()
+ user_reply (reply, Kernel::recv.data[1].l)
+ Kernel::free_cap (reply)
break
diff --git a/boot-programs/lcd.ccp b/boot-programs/lcd.ccp
index 7a354b9..2b9b85f 100644
--- a/boot-programs/lcd.ccp
+++ b/boot-programs/lcd.ccp
@@ -27,9 +27,15 @@ extern unsigned char const charset[127-32][6]
#define assert(x) do { while (!(x)) kdebug ("assertion failed " #x); } while (0)
+#if defined (TRENDTAC)
// For now, support only 16 bpp.
// Screen is 800x480 tft.
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)
static unsigned physical_descriptor
@@ -40,21 +46,49 @@ struct Descriptor:
unsigned id
unsigned cmd
-#if defined (TRENDTAC)
static void reset ():
- LCD_CTRL = LCD_CTRL_BPP_16 | LCD_CTRL_BST_16
- LCD_VSYNC = vs
- LCD_HSYNC = hs
- LCD_DAV = (vs << 16) | (vs + v)
- LCD_DAH = (hs << 16) | (hs + h)
- LCD_VAT = ((hs + h) << 16) | (vs + v)
+#if defined (TRENDTAC)
+ unsigned fps = 60
+ // Vertical timings.
+ unsigned vps = 0, vpe = vps + 20, vds = vpe, vde = vds + v, vt = vde
+ // Horizontal timings.
+ 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 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 ()
- unsigned pixclock = fps * (hs + h) * (vs + v)
+ unsigned pixclock = fps * (ht + extra * (hde - hds)) * vt
+
+ #if defined (TRENDTAC)
unsigned pllout = cpm_get_pllout ()
CPM_CFCR2 = pllout / pixclock - 1
@@ -63,18 +97,29 @@ static void reset ():
assert (val <= 0xf)
cpm_set_lcdclk_div (val)
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 ()
LCD_DA0 = physical_descriptor
lcd_set_ena ()
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):
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 }
for unsigned k = 0; k < 6; ++k:
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 void inc_logx ():
- if ++log_x >= 800 / 6:
+ if ++log_x >= h / 6:
log_x = 1
- if ++log_y >= 480 / 8:
+ if ++log_y >= v / 8:
log_y = 1
static void log_char (unsigned ch):
switch ch:
case '\n':
- while log_x < 800 / 6:
+ while log_x < h / 6:
putchar (log_x++, log_y, ' ')
inc_logx ()
break
@@ -138,22 +183,22 @@ Kernel::Num start ():
p.alloc_physical (physical + i * PAGE_SIZE, false, true)
Kernel::my_memory.map (p, (unsigned)LCD_FRAMEBUFFER_BASE + i * PAGE_SIZE)
Kernel::free_cap (p)
- for unsigned y = 0; y < 480; ++y:
- unsigned g = (y << 6) / 480
- unsigned olr = 0, ob = ((25 * y * y) << 5) / (9 * 800 * 800 + 25 * 480 * 480)
- for unsigned x = 0; x < 800; ++x:
- unsigned r = (x << 5) / 800
- unsigned b = ((9 * x * x + 25 * y * y) << 5) / (9 * 800 * 800 + 25 * 480 * 480)
+ for unsigned y = 0; y < v; ++y:
+ unsigned g = (y << 6) / v
+ unsigned olr = 0, ob = ((25 * y * y) << 5) / (9 * h * h + 25 * v * v)
+ for unsigned x = 0; x < h; ++x:
+ unsigned r = (x << 5) / h
+ unsigned b = ((9 * x * x + 25 * y * y) << 5) / (9 * h * h + 25 * v * v)
if r != olr:
olr = r
r = 0x1f
unsigned oyb = b
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:
ob = b
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)
physical_descriptor = p.physical_address () + ((unsigned)&descriptor & ~PAGE_MASK)
Kernel::free_cap (p)
@@ -166,11 +211,12 @@ Kernel::Num start ():
reset ()
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")
+ #endif
- ((Init)Kernel::my_parent).register_lcd ()
-
- Kernel::Cap eof_cb = Kernel::alloc_cap ()
+ Kernel::Cap eof_cb
+ bool have_eof = false
while true:
Kernel::wait ()
//log_msg ()
@@ -180,11 +226,15 @@ Kernel::Num start ():
eof_cb.invoke ()
break
case Init::LCD_SET_EOF_CB:
- Kernel::free_cap (eof_cb)
- eof_cb = Kernel::recv.arg
- Kernel::recv.arg = Kernel::alloc_cap ()
- Kernel::recv.reply.invoke ()
+ if have_eof:
+ Kernel::free_cap (eof_cb)
+ else:
+ have_eof = true
+ eof_cb = Kernel::get_arg ()
+ Kernel::Cap reply = Kernel::get_reply ()
Kernel::register_interrupt (IRQ_LCD)
+ reply.invoke ()
+ Kernel::free_cap (reply)
break
case Init::LCD_LOG:
log_char (Kernel::recv.data[0].l)
diff --git a/boot-programs/metronome.ccp b/boot-programs/metronome.ccp
new file mode 100644
index 0000000..a0f0a30
--- /dev/null
+++ b/boot-programs/metronome.ccp
@@ -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
+//
+// 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 .
+
+#include "devices.hh"
+#include "keys.hh"
+
+Kernel::Num start ():
+ kdebug ("metronome started\n")
+ Buzzer buzzer = Kernel::my_parent.get_device ()
+ Keyboard kbd = Kernel::my_parent.get_device ()
+ 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
diff --git a/boot-programs/nanonote-gpio.ccp b/boot-programs/nanonote-gpio.ccp
index 64a3cee..7b7b7a3 100644
--- a/boot-programs/nanonote-gpio.ccp
+++ b/boot-programs/nanonote-gpio.ccp
@@ -19,6 +19,7 @@
#include "devices.hh"
#define ARCH
#include "arch.hh"
+#include "keys.hh"
//#define QI
#define SCAN_INTERVAL HZ / 50
@@ -33,27 +34,8 @@ class DevKbd:
static unsigned const COLS[NUM_COLS]
static unsigned const ROWS[NUM_ROWS]
static unsigned const encode[NUM_ROWS][NUM_COLS]
- enum Keys:
- #ifdef QI
- 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]
+ static unsigned const NUM_KEYS = 58
+ static unsigned const keys[NUM_KEYS]
unsigned state[NUM_COLS]
Kernel::Cap event
bool is_active
@@ -61,27 +43,14 @@ class DevKbd:
public:
unsigned size ():
return NUM_KEYS
- unsigned get_name_size (unsigned n):
- if n >= NUM_KEYS:
- return 0
- unsigned ret = 0
- for char const *p = names[n]; *p; ++p:
- ++ret
- return ret
- void send_name (unsigned n, Kernel::Cap c, Kernel::Num offset):
- 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]))
+ void send_keys (unsigned first, Kernel::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]))
bool scanning ():
return is_scanning
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::encode[NUM_ROWS][NUM_COLS] = {
#ifdef QI
- { F1, F2, F3, F4, F5, F6, F7, ~0 },
- { Q, W, E, R, T, Y, U, I },
- { A, S, D, F, G, H, J, K },
- { ESCAPE, Z, X, C, V, B, N, M },
- { TAB, CAPS, BACKSLASH, QUOTE, COMMA, PERIOD, SLASH, UP },
- { O, L, EQUAL, ARROW, SPACE, QI, CTRL, LEFT },
- { F8, P, BACKSPACE, ENTER, VOLUP, VOLDOWN, DOWN, RIGHT },
- { SHIFT, ALT, FN, ~0, ~0, ~0, ~0, ~0 }
+ { Key::F1, Key::F2, Key::F3, Key::F4, Key::F5, Key::F6, Key::F7, ~0 },
+ { Key::Q, Key::W, Key::E, Key::R, Key::T, Key::Y, Key::U, Key::I },
+ { Key::A, Key::S, Key::D, Key::F, Key::G, Key::H, Key::J, Key::K },
+ { Key::ESCAPE, Key::Z, Key::X, Key::C, Key::V, Key::B, Key::N, Key::M },
+ { Key::TAB, Key::CAPS, Key::BACKSLASH, Key::QUOTE, Key::COMMA, Key::PERIOD, Key::SLASH, Key::UP },
+ { Key::O, Key::L, Key::EQUAL, Key::ARROW, Key::SPACE, Key::QI, Key::CTRL, Key::LEFT },
+ { Key::F8, Key::P, Key::BACKSPACE, Key::ENTER, Key::VOLUME_UP, Key::VOLUME_DOWN, Key::DOWN, Key::RIGHT },
+ { Key::SHIFT, Key::ALT, Key::FN, ~0, ~0, ~0, ~0, ~0 }
#else
- { ESCAPE, TAB, F1, F2, F3, F4, MP3, ~0 },
- { N1, N2, N3, N4, N5, N6, N7, N8 },
- { Q, W, E, R, T, Y, U, I },
- { A, S, D, F, G, H, J, K },
- { Z, X, C, V, B, N, M, UP },
- { N9, O, L, ALT, CAPS, SPACE, EQUALS, LEFT },
- { BACKSPACE, N0, P, ENTER, VOLUP, VOLDOWN, DOWN, RIGHT },
- { FN, SHIFT, CTRL, ~0, ~0, ~0, ~0, ~0 }
+ { Key::ESCAPE, Key::TAB, Key::F1, Key::F2, Key::F3, Key::F4, Key::SPECIAL + 0, ~0 },
+ { Key::N1, Key::N2, Key::N3, Key::N4, Key::N5, Key::N6, Key::N7, Key::N8 },
+ { Key::Q, Key::W, Key::E, Key::R, Key::T, Key::Y, Key::U, Key::I },
+ { Key::A, Key::S, Key::D, Key::F, Key::G, Key::H, Key::J, Key::K },
+ { Key::Z, Key::X, Key::C, Key::V, Key::B, Key::N, Key::M, Key::UP },
+ { Key::N9, Key::O, Key::L, Key::LEFT_ALT, Key::CAPS_LOCK, Key::SPACE, Key::EQUALS, Key::LEFT },
+ { Key::BACKSPACE, Key::N0, Key::P, Key::ENTER, Key::VOLUME_UP, Key::VOLUME_DOWN, Key::DOWN, Key::RIGHT },
+ { Key::FN, Key::LEFT_SHIFT, Key::LEFT_CONTROL, ~0, ~0, ~0, ~0, ~0 }
#endif
}
-char const *const DevKbd::names[NUM_KEYS] = {
+unsigned const DevKbd::keys[NUM_KEYS] = {
#ifdef QI
- "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", "\\", "'", ",", ".", "/", "=", "space",
- "escape", "enter", "backspace",
- "up", "down", "left", "right",
- "caps lock", "arrow", "qi", "left control", "volume up", "volume down", "left shift", "left alt", "fn"
+ Key::F1, Key::F2, Key::F3, Key::F4, Key::F5, Key::F6, Key::F7,
+ Key::Q, Key::W, Key::E, Key::R, Key::T, Key::Y, Key::U, Key::I,
+ Key::A, Key::S, Key::D, Key::F, Key::G, Key::H, Key::J, Key::K,
+ Key::ESCAPE, Key::Z, Key::X, Key::C, Key::V, Key::B, Key::N, Key::M,
+ Key::TAB, Key::CAPS, Key::BACKSLASH, Key::QUOTE, Key::COMMA, Key::PERIOD, Key::SLASH, Key::UP,
+ Key::O, Key::L, Key::EQUAL, Key::ARROW, Key::SPACE, Key::QI, Key::CTRL, Key::LEFT,
+ 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
- "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
- "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 lock", "tab", "enter", "escape", "mp3", "space", "backspace", "=",
- "up", "down", "left", "right",
- "volume up", "volume down",
- "fn", "left shift", "left control", "left alt"
+ Key::ESCAPE, Key::TAB, Key::F1, Key::F2, Key::F3, Key::F4, Key::SPECIAL + 0,
+ Key::N1, Key::N2, Key::N3, Key::N4, Key::N5, Key::N6, Key::N7, Key::N8,
+ Key::Q, Key::W, Key::E, Key::R, Key::T, Key::Y, Key::U, Key::I,
+ Key::A, Key::S, Key::D, Key::F, Key::G, Key::H, Key::J, Key::K,
+ Key::Z, Key::X, Key::C, Key::V, Key::B, Key::N, Key::M, Key::UP,
+ Key::N9, Key::O, Key::L, Key::LEFT_ALT, Key::CAPS_LOCK, Key::SPACE, Key::EQUALS, Key::LEFT,
+ Key::BACKSPACE, Key::N0, Key::P, Key::ENTER, Key::VOLUME_UP, Key::VOLUME_DOWN, Key::DOWN, Key::RIGHT,
+ Key::FN, Key::LEFT_SHIFT, Key::LEFT_CONTROL
#endif
}
@@ -222,12 +192,10 @@ class PowerButton:
enum codes:
KBD_DEV = 32
- KBD_LIST
PWR
Kernel::Num start ():
map_gpio ()
- map_tcu ()
DevKbd kbd
PowerButton pwr
@@ -242,7 +210,6 @@ Kernel::Num start ():
Kernel::my_receiver.set_alarm (SCAN_INTERVAL)
unsigned user (~0)
unsigned next_user (0)
- List list = List (Kernel::my_receiver.create_capability (KBD_LIST))
Kernel::register_interrupt (IRQ_GPIO3)
while true:
Kernel::wait ()
@@ -307,24 +274,6 @@ Kernel::Num start ():
kdebug ("\n")
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:
break
break
@@ -337,29 +286,23 @@ Kernel::Num start ():
switch Kernel::recv.data[0].l:
case Keyboard::SET_CB:
kdebug ("set cb\n")
+ Kernel::Cap reply = Kernel::get_reply ()
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
case Keyboard::GET_KEYS:
kdebug ("get keys\n")
- Kernel::recv.reply.invoke (0, 0, list)
+ kbd.send_keys (Kernel::recv.data[0].l, Kernel::recv.reply)
break
default:
kdebug ("other\n")
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:
kdebug ("unknown num: ")
kdebug_num (Kernel::recv.protected_data.h)
diff --git a/boot-programs/devices.hhp b/devices.hhp
similarity index 93%
rename from boot-programs/devices.hhp
rename to devices.hhp
index 38fb9e8..ec60ff5 100644
--- a/boot-programs/devices.hhp
+++ b/devices.hhp
@@ -75,11 +75,26 @@ struct WString : public String:
void set_page (Kernel::Num idx, Kernel::Page page):
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 _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.
struct Device : public Kernel::Cap:
Device (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
enum request:
- CREATE_USER = WString::ID
+ CREATE_USER = Parent::ID
DESTROY_USER
UNUSE
USE
@@ -104,6 +119,7 @@ struct Keyboard : public Kernel::Cap:
Keyboard (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
enum request:
SET_CB = Device::ID
+ GET_NUM_KEYS
GET_KEYS
ID
// 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.
void set_cb (Kernel::Cap 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.
- List get_keys ():
- icall (CAP_MASTER_DIRECT | GET_KEYS)
- return List (Kernel::get_arg ())
+ unsigned get_num_keys ():
+ return call (CAP_MASTER_DIRECT | GET_NUM_KEYS).l
+ void get_keys (unsigned first):
+ call (CAP_MASTER_DIRECT | GET_KEYS, first)
// Buzzer interface.
struct Buzzer : public Kernel::Cap:
diff --git a/invoke.ccp b/invoke.ccp
index b22beaa..83ef494 100644
--- a/invoke.ccp
+++ b/invoke.ccp
@@ -19,33 +19,32 @@
#include "kernel.hh"
static void log_message (char const *prefix, unsigned target, unsigned pdata, kCapability::Context *c):
- if !dbg_code.l:
- dbg_log (prefix)
- dbg_log (": caller=")
- dbg_log_num ((unsigned)old_current)
- dbg_log ("; target=")
- dbg_log_num (target)
+ dbg_log (prefix)
+ dbg_log (": caller=")
+ dbg_log_num ((unsigned)old_current)
+ dbg_log ("; 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_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_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")
+ 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):
dpanic (code, "raise")
@@ -104,8 +103,8 @@ bool kReceiver::try_deliver ():
if m->protected_data.value () == reply_protected_data.value ():
protected_only = false
break
- if !m:
- return false
+ if !m:
+ return false
bool dummy
kCapRef c = owner->find_capability (owner->recv_reply, &dummy)
if c.valid ():
@@ -121,7 +120,7 @@ bool kReceiver::try_deliver ():
// Send a message to a receiver; try to deliver it immediately.
bool kReceiver::send_message (Kernel::Num protected_data, kCapability::Context *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:
protected_only = false
bool dummy
@@ -145,16 +144,6 @@ bool kReceiver::send_message (Kernel::Num protected_data, kCapability::Context *
if !msg:
return false
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:
msg->data[i] = c->data[i]
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)
if reply_target:
reply_target->send_message (reply_protected, &c)
+ c.arg->invalidate ()
else:
dpanic (0, "nothing to reply to")
- c.arg->invalidate ()
static void receiver_invoke (unsigned cmd, unsigned target, Kernel::Num protected_data, kCapability::Context *c):
kReceiver *receiver = (kReceiver *)protected_data.l
@@ -713,6 +702,8 @@ static void print_cap (kCapRef cap, kCapRef self):
dbg_log_char ('!')
else:
dbg_log_char ('=')
+ dbg_log_num ((unsigned)cap->target)
+ dbg_log_char (':')
dbg_log_num (cap->protected_data.l)
for kCapRef c = cap->children; c.valid (); c = c->sibling_next:
print_cap (c, self)
@@ -746,12 +737,9 @@ static void caps_invoke (unsigned cmd, unsigned target, Kernel::Num protected_da
return
case Kernel::Caps::PRINT & REQUEST_MASK:
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")
return
+ dbg_code.h = (unsigned)caps->cap (c->data[1].l)
kCapRef cap (caps, c->data[1].l)
kCapRef orig (caps, c->data[1].l)
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):
// Kernel calling convention:
// 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.
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.
- ((kReceiver *)protected_data.l)->protected_only = target == (CAPTYPE_RECEIVER | Kernel::Receiver::CALL)
+ // This is a call capability. reply is the capability to call.
+ kReceiver *owner = (kReceiver *)protected_data.l
+ owner->protected_only = target == (CAPTYPE_RECEIVER | Kernel::Receiver::CALL)
if must_wait:
old_current->wait ()
if !reply_target:
@@ -825,6 +814,7 @@ static void kernel_invoke (unsigned target, Kernel::Num protected_data, kCapabil
c->reply.reset ()
reply_target = (kReceiver *)protected_data.l
reply_protected = reply_target->reply_protected_data
+ kReceiver *r = reply_target
kernel_invoke ((unsigned)call_target->target, call_target->protected_data, c)
return
if must_wait:
diff --git a/iris.hhp b/iris.hhp
index 05e02d1..12d8761 100644
--- a/iris.hhp
+++ b/iris.hhp
@@ -65,6 +65,8 @@
// This constant signifies that no capability is passed.
#define CAP_NONE (~CAP_COPY)
+struct Parent
+
namespace Kernel:
enum Exception_code:
NO_ERROR
@@ -161,7 +163,7 @@ namespace Kernel:
extern Thread my_thread
extern Memory my_memory
extern Cap my_call
- extern Cap my_parent
+ extern Parent my_parent
extern __recv_data_t recv
inline Cap get_reply ():
diff --git a/kernel.hhp b/kernel.hhp
index cbe9b92..0991fc4 100644
--- a/kernel.hhp
+++ b/kernel.hhp
@@ -137,11 +137,12 @@ struct kReceiver : public kObject:
Kernel::Num reply_protected_data
bool protected_only
// 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 orphan ()
bool try_deliver ()
bool send_message (Kernel::Num protected_data, kCapability::Context *c)
+ void check (unsigned line)
struct kPage : public kObject:
unsigned frame
@@ -205,6 +206,8 @@ struct kMemory : public kObject:
void free_memory (kMemory *mem)
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.
extern "C":
@@ -219,7 +222,12 @@ extern "C":
void dbg_log_num (unsigned num, unsigned digits = 8)
void dbg_send (unsigned num, unsigned bits)
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 dbg_print() top_memory.print (__LINE__, 0)
#else
#define dbg_log_char(x) do {} while (0)
#define dbg_log(x) do {} while (0)
diff --git a/keys.hhp b/keys.hhp
new file mode 100644
index 0000000..3b2b573
--- /dev/null
+++ b/keys.hhp
@@ -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
+//
+// 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 .
+
+#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
diff --git a/memory.ccp b/memory.ccp
index 5c244f3..757f3a6 100644
--- a/memory.ccp
+++ b/memory.ccp
@@ -34,6 +34,7 @@ void check_impl (kObject *o, unsigned num, char const *msg):
for ; o; o = o->next:
if (unsigned)o >= (unsigned)free_begin && (unsigned)o < (unsigned)free_end:
panic (num, msg)
+void print_free ():
#endif
#else
@@ -129,11 +130,20 @@ void phys_free (unsigned page, unsigned num):
n->num = num
#ifndef NDEBUG
-void check_impl (kObject *o, unsigned num, char const *msg):
- for ; o; o = (kObject *)o->next:
- for kFreePages *p = first_free; p; p = p->next:
- if (unsigned)o >= (unsigned)p && (unsigned)o < (unsigned)p + p->num * PAGE_SIZE:
- panic (num, msg)
+bool check_free (kObject *o, unsigned size):
+ for kFreePages *p = first_free; p; p = p->next:
+ if (unsigned)o + size > (unsigned)p && (unsigned)o < (unsigned)p + p->num * PAGE_SIZE:
+ return false
+ 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
@@ -142,6 +152,8 @@ void check_memory (kMemory *mem, unsigned num, char const *msg):
check_impl (mem->pages, num, msg)
check_impl (mem->threads, 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->memories, num, msg)
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):
check_memory (&top_memory, num, msg)
+ top_memory.check (num)
#endif
unsigned raw_zalloc ():
diff --git a/mips/interrupts.ccp b/mips/interrupts.ccp
index 43ff434..eaac778 100644
--- a/mips/interrupts.ccp
+++ b/mips/interrupts.ccp
@@ -131,20 +131,18 @@ void flush_tlb (unsigned asid):
__asm__ volatile ("tlbwi")
static void arch_invoke ():
- kCapRef target
- target = old_current->find_capability (old_current->arch.v[0], &must_wait)
+ kCapRef target = old_current->find_capability (old_current->arch.v[0], &must_wait)
do_schedule = false
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:
- bool dummy
old_current->recv_reply = old_current->arch.t[2]
old_current->recv_arg = old_current->arch.t[3]
if !target.valid ():
if must_wait:
old_current->wait ()
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[1] = Kernel::Num (old_current->arch.a[2], old_current->arch.a[3])
target->invoke (&msg)
diff --git a/mips/nanonote/Makefile.arch b/mips/nanonote/Makefile.arch
index 5a5d7c2..04809b2 100644
--- a/mips/nanonote/Makefile.arch
+++ b/mips/nanonote/Makefile.arch
@@ -17,7 +17,7 @@
load = 0x80000000
-ARCH_CXXFLAGS = -DNUM_THREADS=4
+ARCH_CXXFLAGS = -DNUM_THREADS=5
ARCH_CPPFLAGS = -I. -Imips -Imips/nanonote -Wa,-mips32 -DNANONOTE -DUSE_SERIAL
CROSS = mipsel-linux-gnu-
OBJDUMP = $(CROSS)objdump
@@ -28,7 +28,7 @@ LDFLAGS = --omagic -Ttext $(load)
arch_iris_sources = mips/interrupts.cc mips/arch.cc
boot_sources = mips/init.cc mips/nanonote/board.cc
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
./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
$(boot_threads): TARGET_FLAGS = -I.
$(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
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))
$(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
diff --git a/mips/nanonote/board.ccp b/mips/nanonote/board.ccp
index ce27307..92e8782 100644
--- a/mips/nanonote/board.ccp
+++ b/mips/nanonote/board.ccp
@@ -54,4 +54,5 @@ void board_init ():
UART0_DLLR = uart_div
UART0_LCR = UARTLCR_WLEN_8 | UARTLCR_STOP1
UART0_FCR = UARTFCR_UUE | UARTFCR_FE | UARTFCR_RFLS | UARTFCR_TFLS
+ dbg_code.l = 1
dbg_log ("Serial port initialized\n")
diff --git a/mips/nanonote/threadlist.S b/mips/nanonote/threadlist.S
index 4187f9a..c46ae99 100644
--- a/mips/nanonote/threadlist.S
+++ b/mips/nanonote/threadlist.S
@@ -35,7 +35,11 @@ thread2:
thread3:
.incbin "buzzer"
+ .balign 0x1000
thread4:
+ .incbin "metronome"
+
+thread5:
// Everything from here may be freed after kernel initialization.
init_start:
@@ -46,3 +50,4 @@ thread_start:
.word thread2
.word thread3
.word thread4
+ .word thread5
diff --git a/panic.ccp b/panic.ccp
index 67864fc..52eb924 100644
--- a/panic.ccp
+++ b/panic.ccp
@@ -21,6 +21,8 @@
#ifdef USE_SERIAL
void dbg_log_char (unsigned ch):
+ if dbg_code.l == 0:
+ return
while !(UART0_LSR & UARTLSR_TDRQ):
UART0_TDR = ch
#else
diff --git a/schedule.ccp b/schedule.ccp
index a1abd5d..2357472 100644
--- a/schedule.ccp
+++ b/schedule.ccp
@@ -90,6 +90,6 @@ void schedule ():
void timer_interrupt ():
kReceiver *recv, *next
for recv = first_alarm; recv; recv = next:
- next = (kReceiver *)recv->next
+ next = (kReceiver *)recv->next_alarm
alarm_tick (recv)
//schedule ()