mirror of
git://projects.qi-hardware.com/iris.git
synced 2024-11-16 19:05:22 +02:00
work on device swapping
This commit is contained in:
parent
06390fd2d1
commit
cba0cf31e5
5
Makefile
5
Makefile
@ -16,6 +16,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/>.
|
||||||
|
|
||||||
# Define some variables.
|
# Define some variables.
|
||||||
|
SERIAL = /dev/ttyUSB0
|
||||||
CXXFLAGS = -Wno-unused-parameter -fno-strict-aliasing -fno-builtin -nostdinc $(ARCH_CXXFLAGS) -ggdb3
|
CXXFLAGS = -Wno-unused-parameter -fno-strict-aliasing -fno-builtin -nostdinc $(ARCH_CXXFLAGS) -ggdb3
|
||||||
CPPFLAGS = -O5 -fno-inline $(ARCH_CPPFLAGS)
|
CPPFLAGS = -O5 -fno-inline $(ARCH_CPPFLAGS)
|
||||||
CC = $(CROSS)gcc
|
CC = $(CROSS)gcc
|
||||||
@ -54,8 +55,8 @@ clean:
|
|||||||
rm -f *.o boot-programs/*.o $(BUILT_SOURCES) $(ARCH_CLEAN_FILES)
|
rm -f *.o boot-programs/*.o $(BUILT_SOURCES) $(ARCH_CLEAN_FILES)
|
||||||
|
|
||||||
debug:
|
debug:
|
||||||
stty -F /dev/ttyS0 raw 9600
|
stty -F $(SERIAL) raw 9600
|
||||||
cat /dev/ttyS0
|
cat $(SERIAL)
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
.PRECIOUS: iris.hh kernel.hh boot-programs/crt0.o
|
.PRECIOUS: iris.hh kernel.hh boot-programs/crt0.o
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include "devices.hh"
|
#include "devices.hh"
|
||||||
#include "iris.hh"
|
#include "iris.hh"
|
||||||
|
#include "keys.hh"
|
||||||
#include <elf.h>
|
#include <elf.h>
|
||||||
|
|
||||||
#define NUM_SLOTS 8
|
#define NUM_SLOTS 8
|
||||||
@ -26,6 +27,7 @@
|
|||||||
enum Cap_codes:
|
enum Cap_codes:
|
||||||
SYSREQ = 1 << 16
|
SYSREQ = 1 << 16
|
||||||
THREAD
|
THREAD
|
||||||
|
KEYBOARD
|
||||||
|
|
||||||
static unsigned _free
|
static unsigned _free
|
||||||
extern unsigned _end
|
extern unsigned _end
|
||||||
@ -79,6 +81,7 @@ static Kernel::Caps terminals
|
|||||||
static unsigned terminal_slot
|
static unsigned terminal_slot
|
||||||
static Kernel::Caps memories
|
static Kernel::Caps memories
|
||||||
static unsigned memory_slot
|
static unsigned memory_slot
|
||||||
|
static unsigned *inuse
|
||||||
|
|
||||||
// Get the initial block device and filesystem.
|
// Get the initial block device and filesystem.
|
||||||
static Directory receive_devices ():
|
static Directory receive_devices ():
|
||||||
@ -89,30 +92,24 @@ static Directory receive_devices ():
|
|||||||
for unsigned i = 0; i < 2; ++i:
|
for unsigned i = 0; i < 2; ++i:
|
||||||
Kernel::wait ()
|
Kernel::wait ()
|
||||||
if Kernel::recv.data[0].l != Parent::PROVIDE_DEVICE:
|
if Kernel::recv.data[0].l != Parent::PROVIDE_DEVICE:
|
||||||
kdebug ("Invalid bootstrap request.\n")
|
Kernel::panic (Kernel::recv.data[0].l, "Invalid bootstrap request.")
|
||||||
Kernel::panic (0)
|
|
||||||
switch Kernel::recv.data[1].l:
|
switch Kernel::recv.data[1].l:
|
||||||
case String::ID:
|
case String::ID:
|
||||||
if have_data:
|
if have_data:
|
||||||
kdebug ("duplicate device.\n")
|
Kernel::panic (0, "duplicate device.")
|
||||||
Kernel::panic (0)
|
|
||||||
data_dev = Kernel::get_arg ()
|
data_dev = Kernel::get_arg ()
|
||||||
Kernel::recv.reply.invoke ()
|
Kernel::recv.reply.invoke ()
|
||||||
have_data = true
|
have_data = true
|
||||||
break
|
break
|
||||||
case Filesystem::ID:
|
case Filesystem::ID:
|
||||||
if have_fs:
|
if have_fs:
|
||||||
kdebug ("duplicate filesystem.\n")
|
Kernel::panic (0, "duplicate filesystem.")
|
||||||
Kernel::panic (0)
|
|
||||||
fs_dev = Kernel::get_arg ()
|
fs_dev = Kernel::get_arg ()
|
||||||
Kernel::recv.reply.invoke ()
|
Kernel::recv.reply.invoke ()
|
||||||
have_fs = true
|
have_fs = true
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
kdebug ("unexpected device: ")
|
Kernel::panic (Kernel::recv.data[1].l, "unexpected device")
|
||||||
kdebug_num (Kernel::recv.data[1].l)
|
|
||||||
kdebug_char ('\n')
|
|
||||||
Kernel::panic (0)
|
|
||||||
// Initialize the root file system.
|
// Initialize the root file system.
|
||||||
data = data_dev.create_user (Kernel::my_memory)
|
data = data_dev.create_user (Kernel::my_memory)
|
||||||
data_dev.use (data)
|
data_dev.use (data)
|
||||||
@ -204,8 +201,7 @@ static void run (file *f, bool priv, int id):
|
|||||||
Elf32_Ehdr *header = (Elf32_Ehdr *)mapping
|
Elf32_Ehdr *header = (Elf32_Ehdr *)mapping
|
||||||
for unsigned j = 0; j < SELFMAG; ++j:
|
for unsigned j = 0; j < SELFMAG; ++j:
|
||||||
if header->e_ident[j] != ELFMAG[j]:
|
if header->e_ident[j] != ELFMAG[j]:
|
||||||
kdebug ("invalid ELF magic\n")
|
Kernel::panic (header->e_ident[j], "invalid ELF magic")
|
||||||
Kernel::panic (0)
|
|
||||||
return
|
return
|
||||||
if header->e_ident[EI_CLASS] != ELFCLASS32:
|
if header->e_ident[EI_CLASS] != ELFCLASS32:
|
||||||
kdebug ("invalid ELF class:")
|
kdebug ("invalid ELF class:")
|
||||||
@ -216,21 +212,13 @@ static void run (file *f, bool priv, int id):
|
|||||||
Kernel::panic (0)
|
Kernel::panic (0)
|
||||||
return
|
return
|
||||||
if header->e_ident[EI_DATA] != ELFDATA2LSB:
|
if header->e_ident[EI_DATA] != ELFDATA2LSB:
|
||||||
kdebug ("invalid ELF data\n")
|
Kernel::panic (header->e_ident[EI_DATA], "invalid ELF data")
|
||||||
Kernel::panic (0)
|
|
||||||
return
|
|
||||||
if header->e_ident[EI_VERSION] != EV_CURRENT:
|
if header->e_ident[EI_VERSION] != EV_CURRENT:
|
||||||
kdebug ("invalid ELF version\n")
|
Kernel::panic (header->e_ident[EI_VERSION], "invalid ELF version")
|
||||||
Kernel::panic (0)
|
|
||||||
return
|
|
||||||
if header->e_type != ET_EXEC:
|
if header->e_type != ET_EXEC:
|
||||||
kdebug ("invalid ELF type\n")
|
Kernel::panic (header->e_type, "invalid ELF type")
|
||||||
Kernel::panic (0)
|
|
||||||
return
|
|
||||||
if header->e_machine != EM_MIPS_RS3_LE && header->e_machine != EM_MIPS:
|
if header->e_machine != EM_MIPS_RS3_LE && header->e_machine != EM_MIPS:
|
||||||
kdebug ("invalid ELF machine\n")
|
Kernel::panic (header->e_machine, "invalid ELF machine")
|
||||||
Kernel::panic (0)
|
|
||||||
return
|
|
||||||
thread.set_pc (header->e_entry)
|
thread.set_pc (header->e_entry)
|
||||||
thread.set_sp (0x80000000)
|
thread.set_sp (0x80000000)
|
||||||
for unsigned section = 0; section < header->e_shnum; ++section:
|
for unsigned section = 0; section < header->e_shnum; ++section:
|
||||||
@ -242,8 +230,7 @@ static void run (file *f, bool priv, int id):
|
|||||||
if shdr->sh_type != SHT_NOBITS:
|
if shdr->sh_type != SHT_NOBITS:
|
||||||
unsigned file_offset = shdr->sh_offset >> PAGE_BITS
|
unsigned file_offset = shdr->sh_offset >> PAGE_BITS
|
||||||
if (file_offset + ((shdr->sh_size + PAGE_SIZE - 1) >> PAGE_BITS)) >= (PAGE_SIZE >> 2):
|
if (file_offset + ((shdr->sh_size + PAGE_SIZE - 1) >> PAGE_BITS)) >= (PAGE_SIZE >> 2):
|
||||||
kdebug ("thread too large\n")
|
Kernel::panic (shdr->sh_size, "thread too large")
|
||||||
Kernel::panic (0)
|
|
||||||
return
|
return
|
||||||
for unsigned p = (shdr->sh_addr & PAGE_MASK); p < shdr->sh_addr + shdr->sh_size; p += PAGE_SIZE:
|
for unsigned p = (shdr->sh_addr & PAGE_MASK); p < shdr->sh_addr + shdr->sh_size; p += PAGE_SIZE:
|
||||||
unsigned section_offset = (p - (shdr->sh_addr & PAGE_MASK)) >> PAGE_BITS
|
unsigned section_offset = (p - (shdr->sh_addr & PAGE_MASK)) >> PAGE_BITS
|
||||||
@ -268,14 +255,12 @@ static void run (file *f, bool priv, int id):
|
|||||||
// kdebug (" (readonly)")
|
// kdebug (" (readonly)")
|
||||||
//kdebug ("\n")
|
//kdebug ("\n")
|
||||||
if !mem.map (page, p):
|
if !mem.map (page, p):
|
||||||
kdebug ("unable to map page\n")
|
Kernel::panic (0, "unable to map page")
|
||||||
Kernel::panic (0)
|
|
||||||
return
|
return
|
||||||
Kernel::free_cap (page)
|
Kernel::free_cap (page)
|
||||||
else:
|
else:
|
||||||
if readonly:
|
if readonly:
|
||||||
kdebug ("unwritable bss section\n")
|
Kernel::panic (0, "unwritable bss section")
|
||||||
Kernel::panic (0)
|
|
||||||
return
|
return
|
||||||
for unsigned p = (shdr->sh_addr & PAGE_MASK); p < shdr->sh_addr + shdr->sh_size; p += PAGE_SIZE:
|
for unsigned p = (shdr->sh_addr & PAGE_MASK); p < shdr->sh_addr + shdr->sh_size; p += PAGE_SIZE:
|
||||||
Kernel::Page page = mem.mapping ((void *)p)
|
Kernel::Page page = mem.mapping ((void *)p)
|
||||||
@ -292,26 +277,18 @@ static void run (file *f, bool priv, int id):
|
|||||||
Kernel::free_cap (page)
|
Kernel::free_cap (page)
|
||||||
page = mem.create_page ()
|
page = mem.create_page ()
|
||||||
if Kernel::recv.data[0].l != Kernel::NO_ERROR:
|
if Kernel::recv.data[0].l != Kernel::NO_ERROR:
|
||||||
kdebug ("out of memory\n")
|
Kernel::panic (Kernel::recv.data[0].l, "out of memory")
|
||||||
Kernel::panic (0)
|
|
||||||
return
|
|
||||||
if !page.set_flags (Kernel::Page::PAYING | Kernel::Page::FRAME, Kernel::Page::PAYING | Kernel::Page::FRAME):
|
if !page.set_flags (Kernel::Page::PAYING | Kernel::Page::FRAME, Kernel::Page::PAYING | Kernel::Page::FRAME):
|
||||||
kdebug ("out of memory\n")
|
Kernel::panic (0, "out of memory")
|
||||||
Kernel::panic (0)
|
|
||||||
return
|
|
||||||
if !mem.map (page, p):
|
if !mem.map (page, p):
|
||||||
kdebug ("unable to map bss page\n")
|
Kernel::panic (0, "unable to map bss page")
|
||||||
Kernel::panic (0)
|
|
||||||
return
|
|
||||||
Kernel::free_cap (page)
|
Kernel::free_cap (page)
|
||||||
for unsigned p = 0; p < num_pages; ++p:
|
for unsigned p = 0; p < num_pages; ++p:
|
||||||
Kernel::my_memory.destroy (Kernel::Page (slot, p))
|
Kernel::my_memory.destroy (Kernel::Page (slot, p))
|
||||||
Kernel::Page stackpage = mem.create_page ()
|
Kernel::Page stackpage = mem.create_page ()
|
||||||
stackpage.set_flags (Kernel::Page::PAYING | Kernel::Page::FRAME, Kernel::Page::PAYING | Kernel::Page::FRAME)
|
stackpage.set_flags (Kernel::Page::PAYING | Kernel::Page::FRAME, Kernel::Page::PAYING | Kernel::Page::FRAME)
|
||||||
if Kernel::recv.data[0].l != Kernel::NO_ERROR || !mem.map (stackpage, 0x7ffff000):
|
if Kernel::recv.data[0].l != Kernel::NO_ERROR || !mem.map (stackpage, 0x7ffff000):
|
||||||
kdebug ("unable to map initial stack page\n")
|
Kernel::panic (Kernel::recv.data[0].l, "unable to map initial stack page")
|
||||||
Kernel::panic (0)
|
|
||||||
return
|
|
||||||
Kernel::free_cap (stackpage)
|
Kernel::free_cap (stackpage)
|
||||||
Kernel::Caps caps = mem.create_caps (NUM_CAPS)
|
Kernel::Caps caps = mem.create_caps (NUM_CAPS)
|
||||||
thread.use (caps, 0)
|
thread.use (caps, 0)
|
||||||
@ -405,6 +382,8 @@ static void get_device ():
|
|||||||
unsigned id = Kernel::recv.protected_data.l
|
unsigned id = Kernel::recv.protected_data.l
|
||||||
Dev *d = Dev::find (Kernel::recv.data[1].l, Kernel::recv.data[0].h)
|
Dev *d = Dev::find (Kernel::recv.data[1].l, Kernel::recv.data[0].h)
|
||||||
if d:
|
if d:
|
||||||
|
if inuse[id * Dev::num_devs + d->id] > 0:
|
||||||
|
Kernel::panic (id, "requesting device twice")
|
||||||
kdebug ("giving dev ")
|
kdebug ("giving dev ")
|
||||||
kdebug_num (Kernel::recv.data[1].l)
|
kdebug_num (Kernel::recv.data[1].l)
|
||||||
kdebug (":")
|
kdebug (":")
|
||||||
@ -414,7 +393,12 @@ static void get_device ():
|
|||||||
kdebug (" to ")
|
kdebug (" to ")
|
||||||
kdebug_num (id)
|
kdebug_num (id)
|
||||||
kdebug ("\n")
|
kdebug ("\n")
|
||||||
Kernel::Cap cap = Kernel::Caps (terminal_slot, id).get (d->id)
|
Kernel::Cap cap = d->dev.create_user (Kernel::Memory (memory_slot, id), 0, 0x15000)
|
||||||
|
Kernel::Caps (terminal_slot, id).set (d->id, cap.copy ())
|
||||||
|
for unsigned i = 0; i < num_files; ++i:
|
||||||
|
if inuse[i * Dev::num_devs + d->id] == 2:
|
||||||
|
inuse[i * Dev::num_devs + d->id] = 1
|
||||||
|
inuse[id * Dev::num_devs + d->id] = 2
|
||||||
d->dev.use (cap)
|
d->dev.use (cap)
|
||||||
reply.invoke (0, 0, cap.copy ())
|
reply.invoke (0, 0, cap.copy ())
|
||||||
Kernel::free_cap (cap)
|
Kernel::free_cap (cap)
|
||||||
@ -453,6 +437,10 @@ Kernel::Num start ():
|
|||||||
run (&files[index[i]], files[index[i]].name[0] == '#', i)
|
run (&files[index[i]], files[index[i]].name[0] == '#', i)
|
||||||
kdebug ("running\n")
|
kdebug ("running\n")
|
||||||
handle_init (i)
|
handle_init (i)
|
||||||
|
inuse = new unsigned[num_files * Dev::num_devs]
|
||||||
|
for unsigned f = 0; f < num_files; ++f:
|
||||||
|
for unsigned d = 0; d < Dev::num_devs; ++d:
|
||||||
|
inuse[f * Dev::num_devs + d] = 0
|
||||||
// Notify all programs that they may start.
|
// Notify all programs that they may start.
|
||||||
for unsigned i = 0; i < num_files; ++i:
|
for unsigned i = 0; i < num_files; ++i:
|
||||||
Kernel::Cap (memory_slot, i + num_files).invoke ()
|
Kernel::Cap (memory_slot, i + num_files).invoke ()
|
||||||
@ -462,12 +450,6 @@ Kernel::Num start ():
|
|||||||
Kernel::Memory mem (memory_slot, i)
|
Kernel::Memory mem (memory_slot, i)
|
||||||
Kernel::set_recv_arg (term)
|
Kernel::set_recv_arg (term)
|
||||||
mem.create_caps (Dev::num_devs)
|
mem.create_caps (Dev::num_devs)
|
||||||
unsigned termslot = term.use ()
|
|
||||||
for Dev *d = Dev::devs; d; d = d->next:
|
|
||||||
Kernel::set_recv_arg (Kernel::Cap (termslot, d->id))
|
|
||||||
// The 0x15000 is for the Display; the others don't care about it.
|
|
||||||
d->dev.create_user (mem, 0, 0x15000)
|
|
||||||
Kernel::free_slot (termslot)
|
|
||||||
// set up system request.
|
// set up system request.
|
||||||
Keyboard sysreq = sysreq_dev.create_user (Kernel::my_memory)
|
Keyboard sysreq = sysreq_dev.create_user (Kernel::my_memory)
|
||||||
sysreq_dev.use (sysreq)
|
sysreq_dev.use (sysreq)
|
||||||
@ -476,10 +458,22 @@ Kernel::Num start ():
|
|||||||
sysreq.set_cb (cap.copy ())
|
sysreq.set_cb (cap.copy ())
|
||||||
Kernel::free_cap (sysreq)
|
Kernel::free_cap (sysreq)
|
||||||
Kernel::free_cap (cap)
|
Kernel::free_cap (cap)
|
||||||
|
// set up own capabilities.
|
||||||
|
Dev *display_dev = Dev::find (Display::ID, 0)
|
||||||
|
if !display_dev:
|
||||||
|
Kernel::panic (0, "no display")
|
||||||
|
Display display = display_dev->dev.create_user (Kernel::my_memory, 0, 0x15000)
|
||||||
|
Dev *keyboard_dev = Dev::find (Keyboard::ID, 0)
|
||||||
|
if !keyboard_dev:
|
||||||
|
Kernel::panic (0, "no keyboard")
|
||||||
|
Keyboard keyboard = keyboard_dev->dev.create_user (Kernel::my_memory, 0, 0x15000)
|
||||||
kdebug ("init done\n")
|
kdebug ("init done\n")
|
||||||
root.unlock_ro ()
|
root.unlock_ro ()
|
||||||
Kernel::free_slot (slot)
|
Kernel::free_slot (slot)
|
||||||
Kernel::my_memory.destroy (caps)
|
Kernel::my_memory.destroy (caps)
|
||||||
|
Dev **waiter = new Dev *[num_files]
|
||||||
|
Kernel::Cap keyboard_cb = Kernel::my_receiver.create_capability (Kernel::Num (0, KEYBOARD))
|
||||||
|
bool in_system = false
|
||||||
while true:
|
while true:
|
||||||
Kernel::wait ()
|
Kernel::wait ()
|
||||||
switch Kernel::recv.protected_data.h:
|
switch Kernel::recv.protected_data.h:
|
||||||
@ -487,7 +481,10 @@ Kernel::Num start ():
|
|||||||
// System request.
|
// System request.
|
||||||
if Kernel::recv.data[0].l & Keyboard::RELEASE:
|
if Kernel::recv.data[0].l & Keyboard::RELEASE:
|
||||||
continue
|
continue
|
||||||
kdebug ("system request...\n")
|
keyboard_dev->dev.use (keyboard)
|
||||||
|
display_dev->dev.use (display)
|
||||||
|
keyboard.set_cb (keyboard_cb)
|
||||||
|
in_system = true
|
||||||
continue
|
continue
|
||||||
case THREAD:
|
case THREAD:
|
||||||
// Request for something from a child thread.
|
// Request for something from a child thread.
|
||||||
@ -499,10 +496,59 @@ Kernel::Num start ():
|
|||||||
case Parent::GET_DEVICE:
|
case Parent::GET_DEVICE:
|
||||||
get_device ()
|
get_device ()
|
||||||
break
|
break
|
||||||
|
case Parent::WAIT:
|
||||||
|
unsigned id = Kernel::recv.protected_data.l
|
||||||
|
Dev *dev = Dev::find (Kernel::recv.data[1].l, 0)
|
||||||
|
if id >= num_files:
|
||||||
|
Kernel::panic (0, "invalid id")
|
||||||
|
if !dev:
|
||||||
|
Kernel::panic (0, "invalid dev")
|
||||||
|
switch inuse[id * Dev::num_devs + dev->id]:
|
||||||
|
case 0:
|
||||||
|
Kernel::panic (0, "waiting for non-owned device")
|
||||||
|
case 2:
|
||||||
|
if !in_system:
|
||||||
|
Kernel::recv.reply.invoke ()
|
||||||
|
break
|
||||||
|
// fall through.
|
||||||
|
case 1:
|
||||||
|
Kernel::Cap reply = Kernel::get_reply ()
|
||||||
|
memories.set (id + num_files, reply.copy ())
|
||||||
|
Kernel::free_cap (reply)
|
||||||
|
waiter[id] = dev
|
||||||
|
break
|
||||||
|
break
|
||||||
case Parent::EXIT:
|
case Parent::EXIT:
|
||||||
Kernel::panic (Kernel::recv.protected_data.l, "exit is not supported")
|
Kernel::panic (Kernel::recv.protected_data.l, "exit is not supported")
|
||||||
default:
|
default:
|
||||||
Kernel::panic (Kernel::recv.data[0].l, "invalid operation from child")
|
Kernel::panic (Kernel::recv.data[0].l, "invalid operation from child")
|
||||||
break
|
break
|
||||||
|
case KEYBOARD:
|
||||||
|
if in_system && Kernel::recv.data[0].l == (Key::ENTER | Keyboard::RELEASE):
|
||||||
|
for Dev *d = Dev::devs; d; d = d->next:
|
||||||
|
if d->idx != 0:
|
||||||
|
continue
|
||||||
|
for unsigned i = 0; i < num_files; ++i:
|
||||||
|
if inuse[i * Dev::num_devs + d->id] == 2:
|
||||||
|
Kernel::Cap c = Kernel::Caps (terminal_slot, i).get (d->id)
|
||||||
|
d->dev.use (c)
|
||||||
|
Kernel::free_cap (c)
|
||||||
|
if waiter[i] == d:
|
||||||
|
Kernel::Cap (memory_slot, i + num_files).invoke ()
|
||||||
|
waiter[i] = NULL
|
||||||
|
in_system = false
|
||||||
|
break
|
||||||
|
if Kernel::recv.data[0].l & Keyboard::RELEASE:
|
||||||
|
continue
|
||||||
|
switch Kernel::recv.data[0].l:
|
||||||
|
case Key::UP:
|
||||||
|
case Key::DOWN:
|
||||||
|
case Key::LEFT:
|
||||||
|
case Key::RIGHT:
|
||||||
|
case Key::VOLUME_UP:
|
||||||
|
case Key::VOLUME_DOWN:
|
||||||
|
kdebug ("key pressed.\n")
|
||||||
|
break
|
||||||
|
break
|
||||||
default:
|
default:
|
||||||
Kernel::panic (Kernel::recv.protected_data.h, "unknown source of request")
|
Kernel::panic (Kernel::recv.protected_data.h, "unknown source of request")
|
||||||
|
@ -139,6 +139,7 @@ struct Parent : public Kernel::Cap:
|
|||||||
enum request:
|
enum request:
|
||||||
GET_DEVICE = Device::ID
|
GET_DEVICE = Device::ID
|
||||||
PROVIDE_DEVICE
|
PROVIDE_DEVICE
|
||||||
|
WAIT
|
||||||
GET_MEMORY
|
GET_MEMORY
|
||||||
PROVIDE_MEMORY
|
PROVIDE_MEMORY
|
||||||
INIT_DONE
|
INIT_DONE
|
||||||
@ -151,6 +152,9 @@ struct Parent : public Kernel::Cap:
|
|||||||
// Provide a device handle.
|
// Provide a device handle.
|
||||||
template <typename _T> void provide_device (Device dev, unsigned num = 0):
|
template <typename _T> void provide_device (Device dev, unsigned num = 0):
|
||||||
ocall (dev, Kernel::Num (CAP_MASTER_DIRECT | PROVIDE_DEVICE, num), _T::ID)
|
ocall (dev, Kernel::Num (CAP_MASTER_DIRECT | PROVIDE_DEVICE, num), _T::ID)
|
||||||
|
// Wait until a device is used by the caller again.
|
||||||
|
template <typename _T> void wait (unsigned num = 0):
|
||||||
|
call (Kernel::Num (CAP_MASTER_DIRECT | WAIT, num), _T::ID)
|
||||||
// Get memory paid for by another thread, which cannot be inspected or changed by that thread. The memory can be inspected and changed by the user (owning both threads). The call will fail when the threads are not owned by the same user.
|
// Get memory paid for by another thread, which cannot be inspected or changed by that thread. The memory can be inspected and changed by the user (owning both threads). The call will fail when the threads are not owned by the same user.
|
||||||
Kernel::Memory get_memory (Kernel::Cap target):
|
Kernel::Memory get_memory (Kernel::Cap target):
|
||||||
iocall (target, CAP_MASTER_DIRECT | GET_MEMORY)
|
iocall (target, CAP_MASTER_DIRECT | GET_MEMORY)
|
||||||
|
@ -296,9 +296,9 @@ static void memory_invoke (unsigned cmd, unsigned target, Kernel::Num protected_
|
|||||||
kThread *ret = mem->alloc_thread (c->data[1].l)
|
kThread *ret = mem->alloc_thread (c->data[1].l)
|
||||||
if ret:
|
if ret:
|
||||||
reply_cap (CAPTYPE_THREAD | CAP_MASTER, (unsigned)ret, &ret->refs)
|
reply_cap (CAPTYPE_THREAD | CAP_MASTER, (unsigned)ret, &ret->refs)
|
||||||
//kdebug ("created thread: ")
|
kdebug ("created thread: ")
|
||||||
//kdebug_num ((unsigned)ret)
|
kdebug_num ((unsigned)ret)
|
||||||
//kdebug ("\n")
|
kdebug ("\n")
|
||||||
else:
|
else:
|
||||||
dpanic (0x23311992, "out of memory creating thread")
|
dpanic (0x23311992, "out of memory creating thread")
|
||||||
reply_num (Kernel::ERR_OUT_OF_MEMORY)
|
reply_num (Kernel::ERR_OUT_OF_MEMORY)
|
||||||
@ -838,7 +838,7 @@ static void caps_invoke (unsigned cmd, unsigned target, Kernel::Num protected_da
|
|||||||
kdebug ('\n')
|
kdebug ('\n')
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
dpanic (0, "invalid caps operation")
|
dpanic (cmd, "invalid caps operation")
|
||||||
reply_num (Kernel::ERR_INVALID_OPERATION)
|
reply_num (Kernel::ERR_INVALID_OPERATION)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -344,7 +344,7 @@ void kCapability::invoke (kCapability::Context *c):
|
|||||||
::invoke (target, protected_data, c)
|
::invoke (target, protected_data, c)
|
||||||
kCapability *kCaps::cap (unsigned idx):
|
kCapability *kCaps::cap (unsigned idx):
|
||||||
if idx >= size:
|
if idx >= size:
|
||||||
dpanic (idx, "invalid capability requested\n")
|
dpanic (idx, "invalid capability requested")
|
||||||
return NULL
|
return NULL
|
||||||
return &caps[idx]
|
return &caps[idx]
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ 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
|
boot_threads = init udc
|
||||||
programs = \#nanonote-gpio \#buzzer \#lcd metronome ball
|
programs = \#nanonote-gpio \#buzzer \#lcd metronome ball display-emu
|
||||||
|
|
||||||
all: test
|
all: test
|
||||||
|
|
||||||
@ -78,12 +78,8 @@ server:
|
|||||||
servers:
|
servers:
|
||||||
while : ; do $(MAKE) server ; done
|
while : ; do $(MAKE) server ; done
|
||||||
|
|
||||||
monitor:
|
|
||||||
stty -F /dev/ttyS0 raw 9600
|
|
||||||
cat /dev/ttyS0
|
|
||||||
|
|
||||||
setup:
|
setup:
|
||||||
x-terminal-emulator -e make monitor
|
x-terminal-emulator -e make debug
|
||||||
x-terminal-emulator -e make servers
|
x-terminal-emulator -e make servers
|
||||||
|
|
||||||
ARCH_CLEAN_FILES = $(boot_sources) $(addsuffix .elf,$(boot_threads)) $(arch_headers) devices.hh keys.hh mips/*.o mips/nanonote/*.o source/charset.data iris.elf iris.raw mips/nanonote/sdram-setup.elf mips/nanonote/sdram-setup.raw
|
ARCH_CLEAN_FILES = $(boot_sources) $(addsuffix .elf,$(boot_threads)) $(arch_headers) devices.hh keys.hh mips/*.o mips/nanonote/*.o source/charset.data iris.elf iris.raw mips/nanonote/sdram-setup.elf mips/nanonote/sdram-setup.raw
|
||||||
|
10
plan
10
plan
@ -26,3 +26,13 @@ top
|
|||||||
- - - - program
|
- - - - program
|
||||||
- - user session
|
- - user session
|
||||||
...
|
...
|
||||||
|
|
||||||
|
te doen:
|
||||||
|
- caps in init met een cap per process
|
||||||
|
- die cap bevat caps in target memory met een cap per service
|
||||||
|
- die cap bevat een user van de service
|
||||||
|
- sysreq is geen aangeboden service, usbfs wel
|
||||||
|
- sysreq schakelt tussen running processes incl. user switching.
|
||||||
|
|
||||||
|
- display interface: put pixel commando
|
||||||
|
- typewriter: print toetsen op scherm; shell?
|
||||||
|
@ -178,7 +178,7 @@ static void reset ():
|
|||||||
// Reset the controller.
|
// Reset the controller.
|
||||||
write_reg (BACKLIGHT1, 0x1e)
|
write_reg (BACKLIGHT1, 0x1e)
|
||||||
// Enable display.
|
// Enable display.
|
||||||
write_reg (BACKLIGHT1, 0x5f)
|
write_reg (BACKLIGHT1, 0x5e)
|
||||||
// Set data to rgbrgbrgb input, with a delta color filter.
|
// Set data to rgbrgbrgb input, with a delta color filter.
|
||||||
write_reg (COLOR, 0x01)
|
write_reg (COLOR, 0x01)
|
||||||
#endif
|
#endif
|
||||||
@ -361,16 +361,12 @@ Kernel::Num start ():
|
|||||||
Kernel::free_cap (reply)
|
Kernel::free_cap (reply)
|
||||||
Kernel::free_cap (arg)
|
Kernel::free_cap (arg)
|
||||||
break
|
break
|
||||||
Kernel::Caps caps = mem.create_caps (4)
|
|
||||||
caps.set (1, mem.copy ())
|
|
||||||
unsigned slot = caps.use ()
|
|
||||||
unsigned physical = mem.alloc_range (pages)
|
unsigned physical = mem.alloc_range (pages)
|
||||||
if physical & ~PAGE_MASK:
|
if physical & ~PAGE_MASK:
|
||||||
kdebug ("can't allocate framebuffer\n")
|
kdebug ("can't allocate framebuffer\n")
|
||||||
Kernel::panic (0)
|
Kernel::panic (0)
|
||||||
assert (physical & PAGE_MASK && ~physical)
|
assert (physical & PAGE_MASK && ~physical)
|
||||||
Kernel::set_recv_arg (Kernel::Cap (slot, 0))
|
Kernel::Cap ret = Kernel::my_receiver.create_capability (Kernel::Num (physical, LCD))
|
||||||
Kernel::my_receiver.create_capability (Kernel::Num (physical, LCD))
|
|
||||||
for unsigned i = 0; i < pages; ++i:
|
for unsigned i = 0; i < pages; ++i:
|
||||||
Kernel::Page p = mem.create_page ()
|
Kernel::Page p = mem.create_page ()
|
||||||
p.alloc_physical (physical + (i << PAGE_BITS), false, true)
|
p.alloc_physical (physical + (i << PAGE_BITS), false, true)
|
||||||
@ -378,13 +374,13 @@ Kernel::Num start ():
|
|||||||
//Kernel::panic (0xdeaddead)
|
//Kernel::panic (0xdeaddead)
|
||||||
mem.map (p, address + (i << PAGE_BITS))
|
mem.map (p, address + (i << PAGE_BITS))
|
||||||
Kernel::free_cap (p)
|
Kernel::free_cap (p)
|
||||||
Kernel::free_slot (slot)
|
reply.invoke (0, 0, ret.copy ())
|
||||||
reply.invoke (0, 0, caps.copy ())
|
Kernel::free_cap (ret)
|
||||||
Kernel::free_cap (caps)
|
|
||||||
break
|
break
|
||||||
case Device::DESTROY_USER:
|
case Device::DESTROY_USER:
|
||||||
unsigned slot = Kernel::Caps (arg).use ()
|
//Kernel::Memory mem (arg)
|
||||||
unsigned physical = Kernel::my_receiver.get_protected (Kernel::Cap (slot, 0)).l
|
unsigned address = Kernel::recv.data[1].l & PAGE_MASK
|
||||||
|
unsigned physical = Kernel::my_receiver.get_protected (arg).l
|
||||||
if physical == ~0:
|
if physical == ~0:
|
||||||
kdebug ("unable to destroy framebuffer with wrong cap0\n")
|
kdebug ("unable to destroy framebuffer with wrong cap0\n")
|
||||||
Kernel::panic (0)
|
Kernel::panic (0)
|
||||||
@ -394,22 +390,18 @@ Kernel::Num start ():
|
|||||||
#ifdef NANONOTE
|
#ifdef NANONOTE
|
||||||
write_reg (BACKLIGHT1, 0x5e)
|
write_reg (BACKLIGHT1, 0x5e)
|
||||||
#endif
|
#endif
|
||||||
Kernel::Memory mem = Kernel::Cap (slot, 1)
|
//for unsigned i = 0; i < pages; ++i:
|
||||||
for unsigned i = 0; i < pages; ++i:
|
//if address != ~0:
|
||||||
mem.destroy (Kernel::Cap (slot, 2 + i))
|
//Kernel::Page p = mem.mapping ((void *)(address + (i << PAGE_BITS)))
|
||||||
mem.destroy (arg)
|
//mem.destroy (p)
|
||||||
Kernel::free_slot (slot)
|
//Kernel::free_cap (p)
|
||||||
reply.invoke ()
|
reply.invoke ()
|
||||||
break
|
break
|
||||||
case Device::USE:
|
case Device::USE:
|
||||||
Kernel::Cap first = Kernel::Caps (arg).get (0)
|
unsigned physical = Kernel::my_receiver.get_protected (arg).l
|
||||||
unsigned physical = Kernel::my_receiver.get_protected (first).l
|
|
||||||
if physical == ~0:
|
if physical == ~0:
|
||||||
kdebug ("unable to use framebuffer with wrong cap0\n")
|
Kernel::panic (0, "unable to use framebuffer with wrong cap0")
|
||||||
Kernel::panic (0)
|
bool was_unused = descriptor.frame == 0
|
||||||
break
|
|
||||||
Kernel::free_cap (first)
|
|
||||||
bool was_unused = descriptor.frame == ~0
|
|
||||||
descriptor.frame = physical
|
descriptor.frame = physical
|
||||||
unsigned dptr = (unsigned)&descriptor
|
unsigned dptr = (unsigned)&descriptor
|
||||||
__asm__ volatile ("lw $a0, %0\ncache 0x15, 0($a0)" :: "m"(dptr) : "memory", "a0")
|
__asm__ volatile ("lw $a0, %0\ncache 0x15, 0($a0)" :: "m"(dptr) : "memory", "a0")
|
||||||
@ -421,18 +413,15 @@ Kernel::Num start ():
|
|||||||
reply.invoke ()
|
reply.invoke ()
|
||||||
break
|
break
|
||||||
case Device::UNUSE:
|
case Device::UNUSE:
|
||||||
Kernel::Cap first = Kernel::Caps (arg).get (0)
|
unsigned physical = Kernel::my_receiver.get_protected (arg).l
|
||||||
unsigned physical = Kernel::my_receiver.get_protected (first).l
|
|
||||||
if physical == ~0:
|
if physical == ~0:
|
||||||
kdebug ("unable to unuse framebuffer with wrong cap0\n")
|
Kernel::panic (0, "unable to unuse framebuffer with wrong cap0")
|
||||||
Kernel::panic (0)
|
|
||||||
break
|
|
||||||
Kernel::free_cap (first)
|
|
||||||
if descriptor.frame == physical:
|
if descriptor.frame == physical:
|
||||||
lcd_clr_ena ()
|
lcd_clr_ena ()
|
||||||
#ifdef NANONOTE
|
#ifdef NANONOTE
|
||||||
write_reg (BACKLIGHT1, 0x5e)
|
write_reg (BACKLIGHT1, 0x5e)
|
||||||
#endif
|
#endif
|
||||||
|
descriptor.frame = 0
|
||||||
reply.invoke ()
|
reply.invoke ()
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
@ -480,8 +469,8 @@ Kernel::Num start ():
|
|||||||
break
|
break
|
||||||
case LCD:
|
case LCD:
|
||||||
if descriptor.frame != Kernel::recv.protected_data.l:
|
if descriptor.frame != Kernel::recv.protected_data.l:
|
||||||
kdebug ("invalid user requesting lcd\n")
|
//Kernel::panic (0, "invalid user requesting lcd")
|
||||||
Kernel::panic (0)
|
Kernel::recv.reply.invoke (~0)
|
||||||
break
|
break
|
||||||
switch Kernel::recv.data[0].l:
|
switch Kernel::recv.data[0].l:
|
||||||
case Display::SET_EOF_CB:
|
case Display::SET_EOF_CB:
|
||||||
@ -489,8 +478,7 @@ Kernel::Num start ():
|
|||||||
Kernel::Cap arg = Kernel::get_arg ()
|
Kernel::Cap arg = Kernel::get_arg ()
|
||||||
if have_eof:
|
if have_eof:
|
||||||
Kernel::free_cap (eof_cb)
|
Kernel::free_cap (eof_cb)
|
||||||
kdebug ("replacing eof_cb\n")
|
Kernel::panic (0, "replacing eof_cb")
|
||||||
Kernel::panic (0)
|
|
||||||
else:
|
else:
|
||||||
lcd_clr_eof ()
|
lcd_clr_eof ()
|
||||||
Kernel::register_interrupt (IRQ_LCD)
|
Kernel::register_interrupt (IRQ_LCD)
|
||||||
@ -500,10 +488,9 @@ Kernel::Num start ():
|
|||||||
Kernel::free_cap (reply)
|
Kernel::free_cap (reply)
|
||||||
break
|
break
|
||||||
case Display::GET_INFO:
|
case Display::GET_INFO:
|
||||||
kdebug ("get_info isn't defined yet.\n")
|
Kernel::panic (0, "get_info isn't defined yet.")
|
||||||
Kernel::panic (0)
|
|
||||||
default:
|
default:
|
||||||
Kernel::panic (0, "invalid operation for lcd")
|
Kernel::panic (Kernel::recv.data[0].l, "invalid operation for lcd")
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
Kernel::panic (0, "invalid master operation type for lcd")
|
Kernel::panic (0, "invalid master operation type for lcd")
|
||||||
|
@ -4,10 +4,9 @@
|
|||||||
|
|
||||||
static unsigned *framebuffer
|
static unsigned *framebuffer
|
||||||
static int const r = 10
|
static int const r = 10
|
||||||
|
static int colour
|
||||||
|
|
||||||
void ball (int x, int y, bool print):
|
void ball (int x, int y, bool print):
|
||||||
static unsigned bg
|
|
||||||
static unsigned count
|
|
||||||
for int ty = y - r; ty < y + r; ++ty:
|
for int ty = y - r; ty < y + r; ++ty:
|
||||||
if ty < 0 || ty >= 240:
|
if ty < 0 || ty >= 240:
|
||||||
continue
|
continue
|
||||||
@ -16,16 +15,13 @@ void ball (int x, int y, bool print):
|
|||||||
continue
|
continue
|
||||||
if (x - tx) * (x - tx) + (y - ty) * (y - ty) > r * r:
|
if (x - tx) * (x - tx) + (y - ty) * (y - ty) > r * r:
|
||||||
continue
|
continue
|
||||||
framebuffer[ty * 320 + tx] = (print ? 0xffffff : bg)
|
framebuffer[ty * 320 + tx] = (print ? colour : 0)
|
||||||
if ++count >= 30:
|
|
||||||
bg += 0x010307
|
|
||||||
count = 0
|
|
||||||
|
|
||||||
Kernel::Num start ():
|
Kernel::Num start ():
|
||||||
Kernel::my_parent.init_done ()
|
Kernel::my_parent.init_done ()
|
||||||
|
colour = 0xffffff
|
||||||
framebuffer = (unsigned *)0x15000
|
framebuffer = (unsigned *)0x15000
|
||||||
Kernel::Caps caps = Kernel::my_parent.get_device <Display> ()
|
Display display = Kernel::my_parent.get_device <Display> (0x10000)
|
||||||
Display display = caps.get (0)
|
|
||||||
int x = r, y = r, dx = 3, dy = 0
|
int x = r, y = r, dx = 3, dy = 0
|
||||||
Kernel::Cap eof = Kernel::my_receiver.create_capability (0)
|
Kernel::Cap eof = Kernel::my_receiver.create_capability (0)
|
||||||
while true:
|
while true:
|
||||||
|
@ -871,7 +871,6 @@ import sys
|
|||||||
|
|
||||||
charsize = 25 * 4 + 1
|
charsize = 25 * 4 + 1
|
||||||
for c in range (128 - 32):
|
for c in range (128 - 32):
|
||||||
line = []
|
|
||||||
for l in range (8):
|
for l in range (8):
|
||||||
offset = 2 + c * charsize + 25 * (l >> 1) + 12 * (l & 1)
|
offset = 2 + c * charsize + 25 * (l >> 1) + 12 * (l & 1)
|
||||||
ln = ""
|
ln = ""
|
||||||
|
61
source/display-emu.ccp
Normal file
61
source/display-emu.ccp
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#pypp 0
|
||||||
|
#include <devices.hh>
|
||||||
|
#include <iris.hh>
|
||||||
|
|
||||||
|
Kernel::Num start ():
|
||||||
|
Device d = Kernel::my_receiver.create_capability (0)
|
||||||
|
Kernel::my_parent.provide_device <Display> (d.copy (), 0x10000)
|
||||||
|
Kernel::free_cap (d)
|
||||||
|
Kernel::my_parent.init_done ()
|
||||||
|
Display real = Kernel::my_parent.get_device <Display> (0)
|
||||||
|
while true:
|
||||||
|
Kernel::wait ()
|
||||||
|
Kernel::Cap arg = Kernel::get_arg ()
|
||||||
|
Kernel::Cap reply = Kernel::get_reply ()
|
||||||
|
switch Kernel::recv.protected_data.h:
|
||||||
|
case 0:
|
||||||
|
switch Kernel::recv.data[0].l:
|
||||||
|
case Device::CREATE_USER:
|
||||||
|
Kernel::Memory mem (arg)
|
||||||
|
Kernel::Cap target = Kernel::my_receiver.create_capability (Kernel::Num (0, 1))
|
||||||
|
for unsigned i = 0; i < 320 * 240 * 4; i += PAGE_SIZE:
|
||||||
|
Kernel::Page p = Kernel::my_memory.mapping ((void *)(0x15000 + i))
|
||||||
|
Kernel::Page t = mem.create_page ()
|
||||||
|
t.set_flags (Kernel::Page::PAYING, Kernel::Page::PAYING)
|
||||||
|
p.share (t, Kernel::Page::FORGET)
|
||||||
|
mem.map (t, 0x15000 + i)
|
||||||
|
Kernel::my_memory.destroy (t)
|
||||||
|
Kernel::free_cap (t)
|
||||||
|
Kernel::free_cap (p)
|
||||||
|
reply.invoke (0, 0, target)
|
||||||
|
Kernel::free_cap (target)
|
||||||
|
break
|
||||||
|
case Device::DESTROY_USER:
|
||||||
|
Kernel::panic (0, "destroying emulation user")
|
||||||
|
case Device::USE:
|
||||||
|
case Device::UNUSE:
|
||||||
|
reply.invoke ()
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
kdebug_num (Kernel::recv.data[0].l)
|
||||||
|
kdebug ("\n")
|
||||||
|
Kernel::panic (0, "invalid emulation command")
|
||||||
|
break
|
||||||
|
case 1:
|
||||||
|
switch Kernel::recv.data[0].l:
|
||||||
|
case Display::SET_EOF_CB:
|
||||||
|
real.set_eof_cb (arg.copy ())
|
||||||
|
while Kernel::recv.data[0].l != 0:
|
||||||
|
Kernel::my_parent.wait <Display> (0)
|
||||||
|
real.set_eof_cb (arg.copy ())
|
||||||
|
reply.invoke ()
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
kdebug_num (Kernel::recv.data[0].l)
|
||||||
|
kdebug_char ('\n')
|
||||||
|
Kernel::panic (Kernel::recv.data[0].l, "invalid operation on display emulation")
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
Kernel::panic (0, "bug in display emulation")
|
||||||
|
Kernel::free_cap (arg)
|
||||||
|
Kernel::free_cap (reply)
|
Loading…
Reference in New Issue
Block a user