1
0
mirror of git://projects.qi-hardware.com/iris.git synced 2025-04-21 12:27:27 +03:00

compiling again with new capability scheme

This commit is contained in:
Bas Wijnen
2009-08-17 23:11:15 +02:00
parent 7b99ba0bdf
commit a892e9cfc0
21 changed files with 1616 additions and 2053 deletions

View File

@@ -1,41 +0,0 @@
// Iris: micro-kernel for a capability-based operating system.
// boot-programs/init.S: Startup code for initial Threads.
// 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/>.
.globl __start
.globl __my_receiver
.globl __my_thread
.globl __my_memory
.globl __my_call
.globl __my_parent
.set noreorder
__start:
bal 1f
__hack_label:
nop
.word _gp
1:
lw $gp, 0($ra)
la $t9, main
la $ra, 1f
jr $t9
nop
1:
// This should not be reached: generate an address fault.
b 1b
lw $a0, -4($zero)

117
boot-programs/crt0.ccp Normal file
View File

@@ -0,0 +1,117 @@
#pypp 0
// Iris: micro-kernel for a capability-based operating system.
// boot-programs/init.S: Startup code for initial Threads.
// 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 "iris.hh"
// For some unknown reason, gcc needs this to be defined.
unsigned __gxx_personality_v0
struct list:
list *prev, *next
static unsigned __slots, __caps
static list *__slot_admin, *__cap_admin
static list *__first_free_slot, *__first_free_cap
Receiver __my_receiver
Thread __my_thread
Memory __my_memory
Caps __my_caps
Cap __my_call
Cap __my_parent
Caps __tmp_caps
void free_slot (unsigned slot):
__slot_admin[slot].prev = NULL
__slot_admin[slot].next = __first_free_slot
if __slot_admin[slot].next:
__slot_admin[slot].next->prev = &__slot_admin[slot]
__first_free_slot = &__slot_admin[slot]
void free_cap (Cap cap):
list *l = &__cap_admin[cap.idx ()]
l->prev = NULL
l->next = __first_free_cap
if l->next:
l->next->prev = l
__first_free_cap = l
unsigned alloc_slot ():
if !__first_free_slot:
// Out of slots... Probably best to raise an exception. For now, just return NO_SLOT.
return ~0
list *ret = __first_free_slot
__first_free_slot = ret->next
if ret->next:
ret->next->prev = NULL
unsigned alloc_cap ():
if !__first_free_cap:
// Out of caps... Probably best to raise an exception. For now, just return NO_SLOT.
return ~0
list *ret = __first_free_cap
__first_free_cap = ret->next
if ret->next:
ret->next->prev = NULL
return ret - __slot_admin
extern "C":
void __main (unsigned slots, unsigned caps, list *slot_admin, list *cap_admin):
__slots = slots
__caps = caps
__slot_admin = slot_admin
__cap_admin = cap_admin
__first_free_slot = NULL
for unsigned i = 1; i < __slots; ++i:
free_slot (i)
__first_free_cap = NULL
for unsigned i = 7; i < __caps; ++i:
free_cap (Cap (0, i))
__my_receiver = Cap (0, __receiver_num)
__my_thread = Cap (0, __thread_num)
__my_memory = Cap (0, __memory_num)
__my_caps = Cap (0, __caps_num)
__my_call = Cap (0, __call_num)
__my_parent = Cap (0, __parent_num)
__tmp_caps = Cap (0, __tmp_num)
Num ret = start ()
__my_parent.invoke (~0, ret)
__my_memory.destroy (__my_thread)
// The program no longer exists. If it somehow does, generate an address fault.
while true:
*(volatile unsigned *)~0
__asm__ volatile ("\t.globl __start\n"
"\t.set noreorder\n"
"__start:\n"
"\tbal 1f\n"
"__hack_label:\n"
"\tnop\n"
"\t.word _gp\n"
"1:\n"
"\tlw $gp, 0($ra)\n"
"\tsll $v0, $a0, 3\n"
"\tsll $v1, $a1, 3\n"
"\tsubu $sp, $sp, $v0\n"
"\tmove $a2, $sp\n"
"\tsubu $sp, $sp, $v1\n"
"\tmove $a3, $sp\n"
"\tla $t9, __main\n"
"\tjr $t9\n"
"\tnop\n"
"\t.set reorder")

View File

@@ -19,7 +19,7 @@
#ifndef __IRIS_DEVICES_HH
#define __IRIS_DEVICES_HH
#include "iris.h"
#include "iris.hh"
// This shouldn't really be here. But where should it be?
// Requests made by initial threads to tell init about themselves.
@@ -27,136 +27,150 @@ enum init_requests:
INIT_SET_GPIO
INIT_SET_LCD
// List interface.
template <typename _T> //
struct List : public Cap:
List (Cap c = Cap ()) : Cap (c):
// TODO
struct String : public Cap:
String (Cap c = Cap ()) : Cap (c):
// TODO
// Keyboard interface.
enum Keyboard_request:
KEYBOARD_SET_CB
KEYBOARD_GET_KEYS
// Set the event callback. Currently pressed keys emit a key press event to the new callback immediately, plus a ~0 to signal the end of such events.
static __inline__ void keyboard_set_cb (Capability kbd, Capability cb):
invoke_11 (kbd, cb, KEYBOARD_SET_CB)
// At event: the callback is called with a keycode. One bit defines if it's a press or release event.
#define KEYBOARD_RELEASE (1 << 31)
// Get a list of keys on this keyboard. The key codes start at zero with no gaps. The returned capability is a read-only list of strings.
static __inline__ void keyboard_get_keys (Capability target, Capability kbd):
call_c01 (kbd, target, KEYBOARD_GET_KEYS)
struct Keyboard : public Cap:
Keyboard (Cap c = Cap ()) : Cap (c):
enum request:
SET_CB
GET_KEYS
// At event: the callback is called with a keycode. One bit defines if it's a press or release event.
enum constant:
RELEASE = 1 << 31
// Set the event callback. Currently pressed keys emit a key press event to the new callback immediately, plus a ~0 to signal the end of such events.
void set_cb (Cap cb):
invoke (cb, CAP_MASTER_DIRECT | SET_CB)
// Get a list of keys on this keyboard. The key codes start at zero with no gaps.
void get_keys (List <String> ret):
call (ret, CAP_MASTER_DIRECT | GET_KEYS)
// Display interface.
// Startup: disp_set_eof_cb, disp_create_fb, disp_use_fb, disp_info
// Register an end-of-frame callback.
// At end of frame, the callback is invoked and forgotten. It must be reregistered to keep a stream of events.
static __inline__ void display_set_eof_cb (Capability disp_set_eof_cb, Capability cb):
invoke_10 (disp_set_eof_cb, cb)
// Create a framebuffer for the display. When not in use, it can be freed by the user.
// The pages must be cappages holding Page capabilities. They are filled by the display.
// The passed numbers must be 0 or match a mode that the device can use.
// The returned number is the physical address of the framebuffer. It can be used with display_use_framebuffer.
static __inline__ unsigned display_create_framebuffer (Capability disp_create_fb, Capability page0, Capability page1 = 0, Capability page2 = 0, unsigned w = 0, unsigned h = 0, unsigned mode = 0):
return call_n33 (disp_create_fb, page0, page1, page2, w, h, mode)
// Use a framebuffer. The address must have been returned from display_create_framebuffer.
// w, h and mode must match the values given at creation time.
// unuse_cb is called the next time this operation is requested.
static __inline__ void display_use_framebuffer (Capability disp_use_fb, unsigned addr, Capability unuse_cb, unsigned w = 0, unsigned h = 0, unsigned mode = 0):
invoke_11 (disp_use_fb, unuse_cb, addr)
// Get information about the display.
static __inline__ void display_get_info (Capability disp_info):
// TODO: Interface is to be designed.
struct Display : public Cap:
Display (Cap c = Cap ()) : Cap (c):
enum request:
EOF_CB
CREATE_FB
USE_FB
GET_INFO
// Register an end-of-frame callback.
// At end of frame, the callback is invoked and forgotten. It must be reregistered to keep a stream of events.
void set_eof_cb (Cap cb):
invoke (cb, CAP_MASTER_DIRECT | EOF_CB)
// Create a framebuffer for the display. When not in use, it can be freed by the user.
// The pages must be cappages holding Page capabilities. They are filled by the display.
// The passed numbers must be 0 or match a mode that the device can use.
// The returned number is the physical address of the framebuffer. It can be used with display_use_framebuffer.
unsigned create_framebuffer (Caps pages, unsigned w = 0, unsigned h = 0, unsigned mode = 0):
return call (pages, Num (CAP_MASTER_DIRECT | CREATE_FB, 0), Num ((w << 16) | h, mode)).l
// Use a framebuffer. The address must have been returned from display_create_framebuffer.
// w, h and mode must match the values given at creation time.
// unuse_cb is called the next time this operation is requested for this display.
void use_framebuffer (unsigned addr, Cap unuse_cb = Cap (), unsigned w = 0, unsigned h = 0, unsigned mode = 0):
invoke (unuse_cb, Num (CAP_MASTER_DIRECT | USE_FB, addr), Num ((w << 16) | h, mode))
// Get information about the display.
void get_info ():
// TODO: Interface is to be designed.
// File system interface.
// This may not be a server, so there need not be a startup phase. Instead, capabilities can implement certain interfaces: directory, file, stream, seekable file, mappable file. Normal files implement at least stream or seekable file. Directories implement directory.
enum File_request:
FILE_INFO
FILE_CLOSE
FILE_COPY_HANDLE
DIRECTORY_GET_SIZE
DIRECTORY_GET_NAME
DIRECTORY_GET_FILE
DIRECTORY_GET_FILE_INFO
DIRECTORY_CREATE_FILE
DIRECTORY_DELETE_FILE
FILE_STREAM_READ
FILE_STREAM_WRITE
FILE_SEEKABLE_READ
FILE_SEEKABLE_WRITE
FILE_SEEKABLE_TRUNCATE
// File interface.
// Get information about the file.
static __inline__ unsigned long long file_get_info (Capability file, unsigned type):
return call_l02 (file, FILE_INFO, type)
// Close a file. If this is a directory, it implicitly closes all files opened from it.
static __inline__ void file_close (Capability file):
invoke_01 (file, FILE_CLOSE)
// Copy a file handle. This can be useful for closing all children at once. The new handle itself is a child of the original handle.
static __inline__ void file_copy_handle (Capability target, Capability file):
call_c01 (file, target, FILE_COPY_HANDLE)
// filesystem-related interfaces: file, directory, stream, seekable, mappable.
// Normal files implement at least stream or seekable file. Directories implement directory.
struct File : public Cap:
File (Cap c = Cap ()) : Cap (c):
enum request:
INFO
CLOSE
MAP_HANDLE
// Get information about the file.
Num get_info (unsigned type, Caps ret = Cap ()):
return call (ret, Num (CAP_MASTER_DIRECT | INFO, type))
// Close a file. If this is a directory, it implicitly closes all files opened from it.
void close ():
invoke (CAP_MASTER_DIRECT | CLOSE)
// Map a file handle. This can be useful for closing all children at once. The new handle itself is a child of the original handle.
File map_handle (File ret):
call (ret, CAP_MASTER_DIRECT | MAP_HANDLE)
// Directory interface.
// Get the number of entries in this directory.
static __inline__ unsigned long long directory_get_size (Capability dir):
return call_l01 (dir, DIRECTORY_GET_SIZE)
// Get the filename. The return value is the size of the string, the page is filled with the string itself.
static __inline__ unsigned directory_get_name (Capability dir, unsigned long long idx, Capability page):
return call_n13 (dir, page, DIRECTORY_GET_NAME, idx & 0xffffffff, idx >> 32)
// Get the file.
static __inline__ void directory_get_file (Capability target, Capability dir, unsigned long long idx, Capability page):
call_c03 (dir, target, DIRECTORY_GET_FILE, idx & 0xffffffff, idx >> 32)
// Get file info. This returns the same information as file_get_info, without opening the file.
static __inline__ unsigned long long directory_get_file_info (Capability dir, unsigned long long idx, unsigned type):
return call_l04 (dir, DIRECTORY_GET_FILE_INFO, idx & 0xffffffff, idx >> 32, type)
// Create a new file. After this, any index may map to a different file.
static __inline__ void directory_create_file (Capability target, Capability dir, unsigned long long idx, Capability page):
call_c03 (dir, target, DIRECTORY_CREATE_FILE, idx & 0xffffffff, idx >> 32)
// Delete a file. After this, any index may map to a different file.
static __inline__ void directory_delete_file (Capability target, Capability dir, unsigned long long idx, Capability page):
call_c03 (dir, target, DIRECTORY_DELETE_FILE, idx & 0xffffffff, idx >> 32)
struct Directory : public File:
Directory (Cap c = Cap ()) : File (c):
enum request:
GET_SIZE
GET_NAME
GET_FILE
GET_FILE_INFO
CREATE_FILE
DELETE_FILE
// Get the number of entries in this directory.
Num get_size ():
return call (CAP_MASTER_DIRECT | GET_SIZE)
// Get the filename. The return value is the size of the string, the page is filled with the string itself.
void get_name (Num idx, String target):
call (target, CAP_MASTER_DIRECT | GET_NAME, idx)
// Get the file.
void get_file (Num idx, File ret):
call (ret, CAP_MASTER_DIRECT | GET_FILE, idx)
// Get file info. This returns the same information as file_get_info, without opening the file.
Num get_file_info (Num idx, unsigned type, Caps ret = Cap ()):
return call (ret, Num (CAP_MASTER_DIRECT | GET_FILE_INFO, type), idx)
// Create a new file. After this, any index may map to a different file.
void create_file (String name, File ret):
call (ret, CAP_MASTER_DIRECT | CREATE_FILE)
// Delete a file. After this, any index may map to a different file.
void delete_file (Num idx):
invoke (CAP_MASTER_DIRECT | DELETE_FILE, idx)
// Stream interface.
// Try to read size bytes. Returns the number of bytes successfully read. It cannot be more than PAGE_SIZE.
static __inline__ unsigned file_stream_read (Capability file, Capability page, unsigned size):
return call_n12 (file, page, FILE_STREAM_READ, size)
// Try to write size bytes. Returns the number of bytes successfully written. It cannot be more than PAGE_SIZE.
static __inline__ unsigned file_stream_write (Capability file, Capability page, unsigned size):
return call_n12 (file, page, FILE_STREAM_WRITE, size)
struct Stream : public File:
Stream (Cap c = Cap ()) : File (c):
enum request:
READ
WRITE
// Try to read size bytes. Returns the number of bytes successfully read.
Num read (Num size, String ret):
return call (ret, CAP_MASTER_DIRECT | READ, size)
// Try to write size bytes. Returns the number of bytes successfully written.
Num write (String s, Num size):
return call (s, CAP_MASTER_DIRECT | WRITE, size)
// Seekable file interface.
// Try to read size bytes from position idx. Returns the number of bytes successfully read. It cannot be more than PAGE_SIZE.
static __inline__ unsigned file_seekable_read (Capability file, Capability page, unsigned long long idx, unsigned size):
return call_n14 (file, page, FILE_SEEKABLE_READ, idx & 0xffffffff, idx >> 32, size)
// Try to write size bytes at position idx; the file is extended with zeroes if the write is past the end. Returns the number of bytes successfully written. It cannot be more than PAGE_SIZE.
static __inline__ unsigned file_seekable_write (Capability file, Capability page, unsigned long long idx, unsigned size):
return call_n14 (file, page, FILE_SEEKABLE_WRITE, idx & 0xffffffff, idx >> 32, size)
// Truncate file to size idx. The file is extended with zeroes if it gets longer.
static __inline__ void file_seekable_truncate (Capability file, unsigned long long idx):
call_n03 (file, FILE_SEEKABLE_TRUNCATE, idx & 0xffffffff, idx >> 32)
struct Seekable : public File:
Seekable (Cap c = Cap ()) : File (c):
enum request:
READ
WRITE
TRUNCATE
// Try to read size bytes from position idx. Returns the number of bytes successfully read.
Num read (Num idx, unsigned size, String ret):
return call (ret, Num (CAP_MASTER_DIRECT | READ, size), idx)
// Try to write size bytes at position idx; the file is extended with zeroes if the write is past the end. Returns the number of bytes successfully written.
Num write (Num idx, String s):
return call (s, CAP_MASTER_DIRECT | WRITE, idx)
// Truncate file to size idx. The file is extended with zeroes if it gets longer.
void truncate (Num idx):
invoke (CAP_MASTER_DIRECT | TRUNCATE, idx)
// Mappable file interface.
// TODO: to be designed.
struct Mappable : public Seekable:
Mappable (Cap c = Cap ()) : Seekable (c):
// TODO: to be designed.
// Block device interface.
// Startup: blk_get_size, blk_get_file.
// Get block size.
static __inline__ unsigned block_get_size (Capability blk_get_size):
return call_n00 (blk_get_size)
// Get file capability. Returns a seekable mappable non-stream file.
static __inline__ void block_get_file (Capability target, Capability blk_get_file):
call_c00 (blk_get_file, target)
struct Block_device : public Mappable:
Block_device (Cap c = Cap ()) : Mappable (c):
// TODO: to be designed.
// TODO.

View File

@@ -58,14 +58,17 @@ enum cap_type:
CAP_TOUCHPAD
CAP_LOCKLEDS
CAP_PWM
NUM_EVENT_TYPES
static Caps events = Cap (0, 6)
static void event (event_type type, unsigned data):
invoke_01 (11 + type, data)
Cap (2, type - 32).invoke (data)
static void set_cb (event_type type):
capability_clone (11 + type, 6)
static void set_cb (Cap cap, event_type type):
cap.clone (events, type - 32)
class Keyboard:
class DevKeyboard:
static unsigned const encode[GPIO_KBD_NUM_COLS][GPIO_KBD_NUM_ROWS]
unsigned keys[GPIO_KBD_NUM_COLS]
bool scanning
@@ -74,7 +77,7 @@ class Keyboard:
if (data ^ keys[col]) & (1 << row):
unsigned code = encode[col][row]
if data & (1 << row):
code |= KEYBOARD_RELEASE
code |= Keyboard::RELEASE
event (KEYBOARD_EVENT, code)
keys[col] = data
// If any keys are pressed, scanning is required.
@@ -127,7 +130,7 @@ class Keyboard:
gpio_irq_high (GPIO_KBD_ROW_PORT, i)
// Reenable interrupts.
GPIO_GPIER (GPIO_KBD_ROW_PORT) |= GPIO_KBD_ROW_MASK
Keyboard ():
DevKeyboard ():
// Set all columns to output without pull-ups when set as input.
GPIO_GPPUR (GPIO_KBD_COL_PORT) &= ~GPIO_KBD_COL_MASK
GPIO_GPDIR (GPIO_KBD_COL_PORT) |= GPIO_KBD_COL_MASK
@@ -152,9 +155,9 @@ enum Keys:
ESC, INSERT, DELETE, BACKSPACE, PAUSE, FN, ZZZ, MENU, SYSRQ
LSHIFT, RSHIFT, CTRL, ALT
CAPS, NUM
NONE = ~0 & ~KEYBOARD_RELEASE
NONE = ~Keyboard::RELEASE
unsigned const Keyboard::encode[GPIO_KBD_NUM_COLS][GPIO_KBD_NUM_ROWS] = {
unsigned const DevKeyboard::encode[GPIO_KBD_NUM_COLS][GPIO_KBD_NUM_ROWS] = {
{ PAUSE, NONE, NONE, NONE, NONE, NONE, CTRL, F5 },
{ Q, TAB, A, ESC, Z, NONE, BACKQUOTE, N1 },
{ W, CAPS, S, EXTRA, X, NONE, NONE, N2 },
@@ -251,61 +254,60 @@ class Pwm:
GPIO_GPDR (GPIO_PWM_ENABLE_PORT) &= ~(1 << GPIO_PWM_ENABLE)
// TODO: make it really work as a pwm instead of a switch; check if pwm1 is connected to anything.
int main ():
Num start ():
__my_memory.create_caps (NUM_EVENT_TYPES - 32).clone (__my_caps, 6)
map_gpio ()
map_pwm0 ()
Keyboard kbd
DevKeyboard kbd
Touchpad tp
Lockleds leds
Pwm pwm
// Enable interrupts. All are in port 0.
GPIO_GPIER (GPIO_KBD_ROW_PORT) = (1 << GPIO_TP_LEFT) | (1 << GPIO_TP_RIGHT) | GPIO_KBD_ROW_MASK
register_interrupt (IRQ_GPIO0)
Kernel::register_interrupt (IRQ_GPIO0)
Capability cap_kbd = 7
Capability cap_tp = 8
Capability cap_lockleds = 9
Capability cap_pwm = 10
receiver_create_capability (cap_kbd, __my_receiver, CAP_KEYBOARD)
receiver_create_capability (cap_tp, __my_receiver, CAP_TOUCHPAD)
receiver_create_capability (cap_lockleds, __my_receiver, CAP_LOCKLEDS)
receiver_create_capability (cap_pwm, __my_receiver, CAP_PWM)
Caps c (0, 7)
__my_memory.create_caps (4).clone (__my_caps, 7)
__my_receiver.create_capability (CAP_KEYBOARD).clone (c, 0)
__my_receiver.create_capability (CAP_TOUCHPAD).clone (c, 1)
__my_receiver.create_capability (CAP_LOCKLEDS).clone (c, 2)
__my_receiver.create_capability (CAP_PWM).clone (c, 3)
invoke_41 (__my_parent, cap_copy (cap_kbd), cap_copy (cap_tp), cap_copy (cap_lockleds), cap_copy (cap_pwm), INIT_SET_GPIO)
__my_parent.invoke (c, INIT_SET_GPIO)
if kbd.is_scanning ():
receiver_set_alarm (__my_receiver, ALARM_INTERVAL)
__my_receiver.set_alarm (ALARM_INTERVAL)
while true:
schedule ()
Message msg
wait (&msg, 6, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE)
switch msg.protected_data:
Kernel::schedule ()
Cap::OMessage msg
Kernel::wait (&msg)
switch (unsigned)msg.cap_protected.value ():
case ~0:
// Alarm.
kbd.scan ()
if kbd.is_scanning ():
receiver_set_alarm (__my_receiver, ALARM_INTERVAL)
__my_receiver.set_alarm (ALARM_INTERVAL)
break
case IRQ_GPIO0:
// Always scan keyboard and touchpad on any interrupt.
kbd.scan ()
tp.check_events ()
// Reregister the interrupt.
register_interrupt (IRQ_GPIO0)
Kernel::register_interrupt (IRQ_GPIO0)
break
case CAP_KEYBOARD:
set_cb (KEYBOARD_EVENT)
set_cb (Cap (__tmp_slot, 0), KEYBOARD_EVENT)
kbd.send_initial ()
break
case CAP_TOUCHPAD:
set_cb (TOUCHPAD_EVENT)
set_cb (Cap (__tmp_slot, 0), TOUCHPAD_EVENT)
tp.send_initial ()
break
case CAP_LOCKLEDS:
leds.set (msg.data[0])
leds.set (msg.data[0].l)
break
case CAP_PWM:
pwm.set_backlight (msg.data[0])
pwm.set_backlight (msg.data[0].l)
break

View File

@@ -17,71 +17,70 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "devices.hh"
#include "iris.h"
#include "iris.hh"
static Capability kbd, tp, lockleds, pwm, lcd
static Keyboard kbd, tp
static Display lcd
static Cap lockleds, pwm
// Event types.
enum type:
KBD = 0x10000
TP
static void send (Capability c, unsigned d):
receiver_create_capability (6, __my_receiver, d)
invoke_10 (c, cap_copy (6))
static void setup ():
unsigned state = 0
Capability base = 7
unsigned slot = 2
while true:
Message msg
wait (&msg, base, base + 1, base + 2, base + 3)
switch msg.data[0]:
Cap::OMessage msg
Kernel::wait (&msg, slot)
switch msg.data[0].value ():
case INIT_SET_GPIO:
kdebug ("gpio\n")
kbd = base
tp = base + 1
lockleds = base + 2
pwm = base + 3
base += 4
kbd = Cap (slot, 0)
tp = Cap (slot, 1)
lockleds = Cap (slot, 2)
pwm = Cap (slot, 3)
++slot
++state
break
case INIT_SET_LCD:
kdebug ("lcd\n")
lcd = base
++base
lcd = Cap (slot, 0)
++slot
++state
break
if state == 2:
break
send (kbd, KBD)
send (tp, TP)
invoke_01 (pwm, 1)
kbd.set_cb (__my_receiver.create_capability (KBD).copy ())
tp.set_cb (__my_receiver.create_capability (TP).copy ())
pwm.invoke (1)
char const *decode_kbd = "0123456789abcdefghijklmnopqrstuvwxyz!@#$%^&*() T\n[],.-=/\\;|`'UDLREIKBPFZMS{}CA\":"
int main ():
Num start ():
// Set up lcd first
schedule ()
Kernel::schedule ()
kdebug ("start init\n")
setup ()
kdebug ("run init\n")
while true:
Message msg
wait (&msg, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE)
switch msg.protected_data:
Cap::OMessage msg
Kernel::wait (&msg)
switch msg.cap_protected.value ():
case KBD:
unsigned code = msg.data[0]
if code & KEYBOARD_RELEASE:
unsigned code = msg.data[0].l
if code & Keyboard::RELEASE:
break
kdebug_char (decode_kbd[code])
break
case TP:
unsigned leds = 0
if msg.data[0] & 1:
if msg.data[0].l & 1:
leds |= 0x1
else:
leds |= 0x4
if !(msg.data[0] & 0x10000):
if !(msg.data[0].l & Keyboard::RELEASE):
leds |= 0x2
invoke_01 (lockleds, leds)
lockleds.invoke (leds)
break

View File

@@ -102,36 +102,37 @@ static void log_str (char const *str):
while *str:
log_char (*str++)
static void log_num (unsigned n):
static void log_num (Num n):
char const *encode = "0123456789abcdef"
log_char ('[')
for unsigned i = 0; i < 8; ++i:
log_char (encode[(n >> (4 * (7 - i))) & 0xf])
log_char (encode[(n.h >> (4 * (7 - i))) & 0xf])
log_char (' ')
for unsigned i = 0; i < 8; ++i:
log_char (encode[(n.l >> (4 * (7 - i))) & 0xf])
log_char (']')
static void log_msg (Message *msg):
log_str ("prot:")
log_num (msg->protected_data)
static void log_msg (Cap::OMessage *msg):
log_str ("cap_prot:")
log_num (msg->cap_protected)
log_str ("data:")
for unsigned i = 0; i < 4; ++i:
for unsigned i = 0; i < 2; ++i:
log_num (msg->data[i])
log_str ("cap:")
for unsigned i = 0; i < 4; ++i:
log_num (msg->cap[i])
log_char ('\n')
int main ():
Num start ():
map_lcd ()
map_cpm ()
Descriptor descriptor __attribute__ ((aligned (16)))
unsigned pages = (frame_size + ~PAGE_MASK) >> PAGE_BITS
unsigned physical = alloc_range (__my_memory, pages)
unsigned physical = Kernel::alloc_range (__my_memory, pages)
assert (physical)
for unsigned i = 0; i < pages; ++i:
memory_create_page (6, __my_memory)
alloc_physical (6, physical + i * PAGE_SIZE, 0, 1)
memory_map (__my_memory, 6, (unsigned)LCD_FRAMEBUFFER_BASE + i * PAGE_SIZE, 1)
Page p = __my_memory.create_page ()
p.alloc_physical (physical + i * PAGE_SIZE, false, true)
__my_memory.map (p, (unsigned)LCD_FRAMEBUFFER_BASE + i * PAGE_SIZE, true)
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)
@@ -148,8 +149,9 @@ int main ():
ob = b
b = 0x1f
LCD_FRAMEBUFFER_BASE[y * 800 + x] = (r << 11) | (g << 5) | (b)
memory_mapping (6, __my_memory, &descriptor)
unsigned physical_descriptor = page_physical_address (cap_copy (6)) + ((unsigned)&descriptor & ~PAGE_MASK)
Page p = __my_memory.mapping (&descriptor)
unsigned physical_descriptor = p.physical_address () + ((unsigned)&descriptor & ~PAGE_MASK)
free_cap (p)
descriptor.next = physical_descriptor
descriptor.frame = physical
descriptor.id = 0xdeadbeef
@@ -158,30 +160,26 @@ int main ():
__asm__ volatile ("lw $a0, %0\ncache 0x15, 0($a0)" :: "m"(dptr) : "memory", "a0")
reset (physical_descriptor)
Capability eof_cb = 0
Cap set_eof_cb = __my_receiver.create_capability (LCD_EOF_CB)
__my_parent.invoke (set_eof_cb.copy (), INIT_SET_LCD)
receiver_create_capability (6, __my_receiver, LCD_EOF_CB)
invoke_11 (__my_parent, cap_copy (6), INIT_SET_LCD)
receiver_create_capability (15, __my_receiver, LCD_LOG)
__asm__ volatile ("li $a0, 1\nli $a1, 15\nbreak" ::: "a0", "a1", "memory")
Cap logcap = __my_receiver.create_capability (LCD_LOG)
__asm__ volatile ("li $a0, 1\nlw $a1, %0\nbreak" :: "m"(logcap.code): "a0", "a1", "memory")
unsigned slot = alloc_slot ()
while true:
Message msg
wait (&msg, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE)
Cap::OMessage msg
Kernel::wait (&msg, slot)
//log_msg (&msg)
switch msg.protected_data:
switch msg.cap_protected.value ():
case IRQ_LCD:
lcd_clr_eof ()
if eof_cb:
register_interrupt (IRQ_LCD)
invoke_00 (eof_cb)
Cap (slot, 0).invoke ()
Cap (slot, 0) = Cap ()
break
case LCD_EOF_CB:
eof_cb = msg.cap[0]
if eof_cb:
register_interrupt (IRQ_LCD)
Kernel::register_interrupt (IRQ_LCD)
break
case LCD_LOG:
log_char (msg.data[0])
log_char (msg.data[0].l)
break