mirror of
git://projects.qi-hardware.com/iris.git
synced 2024-12-29 19:12:25 +02:00
usb fs mostly working
This commit is contained in:
parent
03e74d38d3
commit
7dc6ecb0ea
2
.gitignore
vendored
2
.gitignore
vendored
@ -6,7 +6,7 @@ uimage
|
|||||||
*.elf
|
*.elf
|
||||||
*.cc
|
*.cc
|
||||||
*.hh
|
*.hh
|
||||||
boot-programs/charset.data
|
source/charset.data
|
||||||
mips/nanonote/sdram-setup.raw
|
mips/nanonote/sdram-setup.raw
|
||||||
nanonote-boot
|
nanonote-boot
|
||||||
mips/nanonote/server/.deps/
|
mips/nanonote/server/.deps/
|
||||||
|
@ -38,17 +38,17 @@ namespace Kernel:
|
|||||||
__recv_data_t recv
|
__recv_data_t recv
|
||||||
|
|
||||||
void print_caps ():
|
void print_caps ():
|
||||||
// Assume __caps to be 16.
|
// Assume __caps to be 32.
|
||||||
bool used[16]
|
bool used[32]
|
||||||
for unsigned i = 0; i < 16; ++i:
|
for unsigned i = 0; i < 32; ++i:
|
||||||
used[i] = true
|
used[i] = true
|
||||||
unsigned num = 0
|
unsigned num = 0
|
||||||
for list *i = __first_free_cap; i; i = i->next:
|
for list *i = __first_free_cap; i; i = i->next:
|
||||||
used[i - __cap_admin] = false
|
used[i - __cap_admin] = false
|
||||||
++num
|
++num
|
||||||
kdebug_num (num, 1)
|
kdebug_num (num, 2)
|
||||||
kdebug (":")
|
kdebug (":")
|
||||||
for unsigned i = 0; i < 16; ++i:
|
for unsigned i = 0; i < 32; ++i:
|
||||||
kdebug_char (used[i] ? '#' : '.')
|
kdebug_char (used[i] ? '#' : '.')
|
||||||
kdebug_char ('\n')
|
kdebug_char ('\n')
|
||||||
|
|
||||||
@ -77,6 +77,7 @@ namespace Kernel:
|
|||||||
if !__first_free_slot:
|
if !__first_free_slot:
|
||||||
// Out of slots... Probably best to raise an exception. For now, just return NO_SLOT.
|
// Out of slots... Probably best to raise an exception. For now, just return NO_SLOT.
|
||||||
kdebug ("out of slots!\n")
|
kdebug ("out of slots!\n")
|
||||||
|
Kernel::panic (0)
|
||||||
return ~0
|
return ~0
|
||||||
list *ret = __first_free_slot
|
list *ret = __first_free_slot
|
||||||
__first_free_slot = ret->next
|
__first_free_slot = ret->next
|
||||||
@ -89,6 +90,7 @@ namespace Kernel:
|
|||||||
if !__first_free_cap:
|
if !__first_free_cap:
|
||||||
// Out of caps... Probably best to raise an exception. For now, just return CAP_NONE
|
// Out of caps... Probably best to raise an exception. For now, just return CAP_NONE
|
||||||
kdebug ("out of capabilities!\n")
|
kdebug ("out of capabilities!\n")
|
||||||
|
Kernel::panic (0)
|
||||||
return Cap (0, CAP_NONE)
|
return Cap (0, CAP_NONE)
|
||||||
list *ret = __first_free_cap
|
list *ret = __first_free_cap
|
||||||
__first_free_cap = ret->next
|
__first_free_cap = ret->next
|
||||||
@ -116,7 +118,7 @@ extern "C":
|
|||||||
Kernel::recv.reply = Kernel::alloc_cap ()
|
Kernel::recv.reply = Kernel::alloc_cap ()
|
||||||
Kernel::recv.arg = Kernel::alloc_cap ()
|
Kernel::recv.arg = Kernel::alloc_cap ()
|
||||||
Kernel::Num ret = start ()
|
Kernel::Num ret = start ()
|
||||||
Kernel::my_parent.invoke (~0, ret)
|
Kernel::my_parent.exit (ret)
|
||||||
Kernel::my_memory.destroy (Kernel::my_thread)
|
Kernel::my_memory.destroy (Kernel::my_thread)
|
||||||
// The program no longer exists. If it somehow does, generate an address fault.
|
// The program no longer exists. If it somehow does, generate an address fault.
|
||||||
while true:
|
while true:
|
||||||
|
@ -21,13 +21,13 @@
|
|||||||
#include <elf.h>
|
#include <elf.h>
|
||||||
|
|
||||||
#define NUM_SLOTS 4
|
#define NUM_SLOTS 4
|
||||||
#define NUM_CAPS 16
|
#define NUM_CAPS 32
|
||||||
|
|
||||||
static unsigned _free
|
static unsigned _free
|
||||||
extern unsigned _end
|
extern unsigned _end
|
||||||
|
|
||||||
void init_alloc ():
|
void init_alloc ():
|
||||||
_free = _end
|
_free = (unsigned)&_end
|
||||||
|
|
||||||
char *alloc_space (unsigned pages):
|
char *alloc_space (unsigned pages):
|
||||||
unsigned ret = (_free + PAGE_SIZE - 1) & PAGE_MASK
|
unsigned ret = (_free + PAGE_SIZE - 1) & PAGE_MASK
|
||||||
@ -37,11 +37,9 @@ char *alloc_space (unsigned pages):
|
|||||||
void *operator new[] (unsigned size):
|
void *operator new[] (unsigned size):
|
||||||
void *ret = (void *)_free
|
void *ret = (void *)_free
|
||||||
size = (size + 3) & ~3
|
size = (size + 3) & ~3
|
||||||
unsigned rest = PAGE_SIZE - (size & ~PAGE_MASK)
|
unsigned rest = PAGE_SIZE - (((_free - 1) & ~PAGE_MASK) + 1)
|
||||||
if rest <= size:
|
if rest < size:
|
||||||
_free += size
|
unsigned pages = ((size - rest) + PAGE_SIZE - 1) >> PAGE_BITS
|
||||||
return ret
|
|
||||||
unsigned pages = ((size - rest) + PAGE_SIZE - 1) & PAGE_MASK
|
|
||||||
char *space = alloc_space (pages)
|
char *space = alloc_space (pages)
|
||||||
for unsigned p = 0; p < pages; ++p:
|
for unsigned p = 0; p < pages; ++p:
|
||||||
Kernel::Page page = Kernel::my_memory.create_page ()
|
Kernel::Page page = Kernel::my_memory.create_page ()
|
||||||
@ -49,6 +47,10 @@ void *operator new[] (unsigned size):
|
|||||||
Kernel::my_memory.map (page, (unsigned)&space[p << PAGE_BITS])
|
Kernel::my_memory.map (page, (unsigned)&space[p << PAGE_BITS])
|
||||||
Kernel::free_cap (page)
|
Kernel::free_cap (page)
|
||||||
_free += size
|
_free += size
|
||||||
|
//kdebug_num ((unsigned)ret)
|
||||||
|
//kdebug ("+")
|
||||||
|
//kdebug_num (size)
|
||||||
|
//kdebug ("\n")
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
struct file:
|
struct file:
|
||||||
@ -72,8 +74,8 @@ static Directory receive_devices ():
|
|||||||
String data
|
String data
|
||||||
Filesystem fs
|
Filesystem fs
|
||||||
bool have_data = false, have_fs = false
|
bool have_data = false, have_fs = false
|
||||||
|
Device fs_dev, data_dev
|
||||||
for unsigned i = 0; i < 2; ++i:
|
for unsigned i = 0; i < 2; ++i:
|
||||||
Device dev
|
|
||||||
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")
|
kdebug ("Invalid bootstrap request.\n")
|
||||||
@ -83,23 +85,17 @@ static Directory receive_devices ():
|
|||||||
if have_data:
|
if have_data:
|
||||||
kdebug ("duplicate device.\n")
|
kdebug ("duplicate device.\n")
|
||||||
Kernel::panic (0)
|
Kernel::panic (0)
|
||||||
dev = Kernel::get_arg ()
|
data_dev = Kernel::get_arg ()
|
||||||
have_data = true
|
|
||||||
Kernel::recv.reply.invoke ()
|
Kernel::recv.reply.invoke ()
|
||||||
data = dev.create_user (Kernel::my_memory)
|
have_data = true
|
||||||
dev.use (data)
|
|
||||||
Kernel::free_cap (dev)
|
|
||||||
break
|
break
|
||||||
case Filesystem::ID:
|
case Filesystem::ID:
|
||||||
if have_fs:
|
if have_fs:
|
||||||
kdebug ("duplicate filesystem.\n")
|
kdebug ("duplicate filesystem.\n")
|
||||||
Kernel::panic (0)
|
Kernel::panic (0)
|
||||||
dev = Kernel::get_arg ()
|
fs_dev = Kernel::get_arg ()
|
||||||
have_fs = true
|
|
||||||
fs = dev.create_user (Kernel::my_memory)
|
|
||||||
dev.use (fs)
|
|
||||||
Kernel::free_cap (dev)
|
|
||||||
Kernel::recv.reply.invoke ()
|
Kernel::recv.reply.invoke ()
|
||||||
|
have_fs = true
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
kdebug ("unexpected device: ")
|
kdebug ("unexpected device: ")
|
||||||
@ -107,35 +103,58 @@ static Directory receive_devices ():
|
|||||||
kdebug_char ('\n')
|
kdebug_char ('\n')
|
||||||
Kernel::panic (0)
|
Kernel::panic (0)
|
||||||
// Initialize the root file system.
|
// Initialize the root file system.
|
||||||
|
data = data_dev.create_user (Kernel::my_memory)
|
||||||
|
data_dev.use (data)
|
||||||
|
fs = fs_dev.create_user (Kernel::my_memory)
|
||||||
|
fs_dev.use (fs)
|
||||||
Directory root = fs.use_device_ro (data.copy ())
|
Directory root = fs.use_device_ro (data.copy ())
|
||||||
Kernel::free_cap (data)
|
Kernel::free_cap (data)
|
||||||
Kernel::free_cap (fs)
|
Kernel::free_cap (fs)
|
||||||
|
Kernel::free_cap (data_dev)
|
||||||
|
Kernel::free_cap (fs_dev)
|
||||||
return root
|
return root
|
||||||
|
|
||||||
// Make a list of all files.
|
// Make a list of all files.
|
||||||
static void list_files (Directory root):
|
static void list_files (Directory root):
|
||||||
Kernel::Num fullsize = root.get_size ()
|
Kernel::Num fullsize = root.get_size ()
|
||||||
if fullsize.h != 0:
|
if fullsize.h != 0:
|
||||||
kdebug ("Too many files in bootstrap directory.\n")
|
kdebug ("Too many files in bootstrap directory:")
|
||||||
|
kdebug_num (fullsize.h)
|
||||||
|
kdebug (":")
|
||||||
|
kdebug_num (fullsize.l)
|
||||||
|
kdebug ("\n")
|
||||||
Kernel::panic (0)
|
Kernel::panic (0)
|
||||||
num_files = fullsize.l
|
num_files = fullsize.l
|
||||||
|
kdebug ("files in directory: ")
|
||||||
|
kdebug_num (num_files)
|
||||||
|
kdebug ("\n")
|
||||||
files = new file[num_files]
|
files = new file[num_files]
|
||||||
Kernel::Caps caps = Kernel::my_memory.create_caps (num_files * 2)
|
Kernel::Caps caps = Kernel::my_memory.create_caps (num_files)
|
||||||
unsigned slot = Kernel::alloc_slot ()
|
unsigned slot = Kernel::alloc_slot ()
|
||||||
caps.use (slot)
|
caps.use (slot)
|
||||||
|
Kernel::free_cap (caps)
|
||||||
for unsigned i = 0; i < num_files; ++i:
|
for unsigned i = 0; i < num_files; ++i:
|
||||||
Kernel::set_recv_arg (Kernel::Cap (slot, i * 2))
|
|
||||||
String n = root.get_name (i)
|
String n = root.get_name (i)
|
||||||
n.get_chars (0, files[i].name)
|
n.get_chars (0, files[i].name)
|
||||||
Kernel::set_recv_arg (Kernel::Cap (slot, i * 2 + 1))
|
kdebug ("file: ")
|
||||||
|
for unsigned j = 0; j < 16; ++j:
|
||||||
|
if files[i].name[j] != 0:
|
||||||
|
kdebug_char (files[i].name[j])
|
||||||
|
kdebug_char ('\n')
|
||||||
|
Kernel::free_cap (n)
|
||||||
|
Kernel::set_recv_arg (Kernel::Cap (slot, i))
|
||||||
files[i].string = root.get_file_ro (i)
|
files[i].string = root.get_file_ro (i)
|
||||||
Kernel::Num fullsize = files[i].string.get_size ()
|
Kernel::Num fullsize = files[i].string.get_size ()
|
||||||
if fullsize.h != 0:
|
if fullsize.h != 0:
|
||||||
kdebug ("initial file size too large.\n")
|
kdebug ("initial file size too large: ")
|
||||||
|
kdebug_num (fullsize.h)
|
||||||
|
kdebug (":")
|
||||||
|
kdebug_num (fullsize.l)
|
||||||
|
kdebug (".\n")
|
||||||
Kernel::panic (0)
|
Kernel::panic (0)
|
||||||
files[i].size = fullsize.l
|
files[i].size = fullsize.l
|
||||||
if max_pages < (fullsize.l + PAGE_SIZE - 1) & PAGE_MASK:
|
if max_pages < (fullsize.l + PAGE_SIZE - 1) >> PAGE_BITS:
|
||||||
max_pages = (fullsize.l + PAGE_SIZE - 1) & PAGE_MASK
|
max_pages = (fullsize.l + PAGE_SIZE - 1) >> PAGE_BITS
|
||||||
|
|
||||||
// Sort the list of files.
|
// Sort the list of files.
|
||||||
static bool is_less (file *f1, file *f2):
|
static bool is_less (file *f1, file *f2):
|
||||||
@ -163,11 +182,17 @@ static void sort ():
|
|||||||
|
|
||||||
static void run (file *f, bool priv):
|
static void run (file *f, bool priv):
|
||||||
Kernel::Memory mem = top_memory.create_memory ()
|
Kernel::Memory mem = top_memory.create_memory ()
|
||||||
unsigned num_pages = (f->size + PAGE_SIZE - 1) & PAGE_MASK
|
unsigned num_pages = (f->size + PAGE_SIZE - 1) >> PAGE_BITS
|
||||||
for unsigned p = 0; p < num_pages; ++p:
|
for unsigned p = 0; p < num_pages; ++p:
|
||||||
|
kdebug_num (p)
|
||||||
|
kdebug ("/")
|
||||||
|
kdebug_num (num_pages)
|
||||||
|
kdebug ("\n")
|
||||||
Kernel::set_recv_arg (Kernel::Cap (slot, p))
|
Kernel::set_recv_arg (Kernel::Cap (slot, p))
|
||||||
mem.create_page ()
|
Kernel::my_memory.create_page ()
|
||||||
|
Kernel::Page (slot, p).set_flags (Kernel::Page::PAYING, Kernel::Page::PAYING)
|
||||||
f->string.get_page (p << PAGE_BITS, Kernel::Cap (slot, p))
|
f->string.get_page (p << PAGE_BITS, Kernel::Cap (slot, p))
|
||||||
|
kdebug_line ()
|
||||||
Kernel::my_memory.map (Kernel::Cap (slot, p), (unsigned)&mapping[p << PAGE_BITS])
|
Kernel::my_memory.map (Kernel::Cap (slot, p), (unsigned)&mapping[p << PAGE_BITS])
|
||||||
Kernel::Thread thread = mem.create_thread (NUM_SLOTS)
|
Kernel::Thread thread = mem.create_thread (NUM_SLOTS)
|
||||||
if priv:
|
if priv:
|
||||||
@ -179,7 +204,11 @@ static void run (file *f, bool priv):
|
|||||||
Kernel::panic (0)
|
Kernel::panic (0)
|
||||||
return
|
return
|
||||||
if header->e_ident[EI_CLASS] != ELFCLASS32:
|
if header->e_ident[EI_CLASS] != ELFCLASS32:
|
||||||
kdebug ("invalid ELF class\n")
|
kdebug ("invalid ELF class:")
|
||||||
|
kdebug_num (header->e_ident[EI_CLASS])
|
||||||
|
kdebug (" != ")
|
||||||
|
kdebug_num (ELFCLASS32)
|
||||||
|
kdebug ("\n")
|
||||||
Kernel::panic (0)
|
Kernel::panic (0)
|
||||||
return
|
return
|
||||||
if header->e_ident[EI_DATA] != ELFDATA2LSB:
|
if header->e_ident[EI_DATA] != ELFDATA2LSB:
|
||||||
@ -200,18 +229,24 @@ static void run (file *f, bool priv):
|
|||||||
return
|
return
|
||||||
thread.set_pc (header->e_entry)
|
thread.set_pc (header->e_entry)
|
||||||
thread.set_sp (0x80000000)
|
thread.set_sp (0x80000000)
|
||||||
|
kdebug_line ()
|
||||||
for unsigned section = 0; section < header->e_shnum; ++section:
|
for unsigned section = 0; section < header->e_shnum; ++section:
|
||||||
|
kdebug_line ()
|
||||||
Elf32_Shdr *shdr = (Elf32_Shdr *)((unsigned)mapping + header->e_shoff + section * header->e_shentsize)
|
Elf32_Shdr *shdr = (Elf32_Shdr *)((unsigned)mapping + header->e_shoff + section * header->e_shentsize)
|
||||||
if ~shdr->sh_flags & SHF_ALLOC:
|
if ~shdr->sh_flags & SHF_ALLOC:
|
||||||
continue
|
continue
|
||||||
|
kdebug_line ()
|
||||||
bool readonly = !(shdr->sh_flags & SHF_WRITE)
|
bool readonly = !(shdr->sh_flags & SHF_WRITE)
|
||||||
//bool executable = shdr->sh_flags & SHF_EXEC_INSTR
|
//bool executable = shdr->sh_flags & SHF_EXEC_INSTR
|
||||||
|
kdebug_line ()
|
||||||
if shdr->sh_type != SHT_NOBITS:
|
if shdr->sh_type != SHT_NOBITS:
|
||||||
|
kdebug_line ()
|
||||||
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")
|
kdebug ("thread too large\n")
|
||||||
Kernel::panic (0)
|
Kernel::panic (0)
|
||||||
return
|
return
|
||||||
|
kdebug_line ()
|
||||||
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
|
||||||
unsigned idx = file_offset + section_offset
|
unsigned idx = file_offset + section_offset
|
||||||
@ -220,22 +255,39 @@ static void run (file *f, bool priv):
|
|||||||
// The address already has a mapping; assume that it is correct.
|
// The address already has a mapping; assume that it is correct.
|
||||||
Kernel::free_cap (page)
|
Kernel::free_cap (page)
|
||||||
continue
|
continue
|
||||||
|
Kernel::free_cap (page)
|
||||||
page = mem.create_page ()
|
page = mem.create_page ()
|
||||||
|
page.set_flags (Kernel::Page::PAYING, Kernel::Page::PAYING)
|
||||||
Kernel::Page (slot, idx).share (page, 0)
|
Kernel::Page (slot, idx).share (page, 0)
|
||||||
|
kdebug ("mapping at ")
|
||||||
|
kdebug_num (p)
|
||||||
|
kdebug ("\n")
|
||||||
if !mem.map (page, p, readonly):
|
if !mem.map (page, p, readonly):
|
||||||
kdebug ("unable to map page\n")
|
kdebug ("unable to map page\n")
|
||||||
Kernel::panic (0)
|
Kernel::panic (0)
|
||||||
return
|
return
|
||||||
Kernel::free_cap (page)
|
Kernel::free_cap (page)
|
||||||
|
kdebug_line ()
|
||||||
else:
|
else:
|
||||||
|
kdebug_line ()
|
||||||
if readonly:
|
if readonly:
|
||||||
kdebug ("unwritable bss section\n")
|
kdebug ("unwritable bss section\n")
|
||||||
Kernel::panic (0)
|
Kernel::panic (0)
|
||||||
return
|
return
|
||||||
|
kdebug_line ()
|
||||||
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)
|
||||||
if Kernel::recv.data[0].l == Kernel::NO_ERROR:
|
if Kernel::recv.data[0].l == Kernel::NO_ERROR:
|
||||||
// No error means there is no mapping.
|
// No error means there is a mapping.
|
||||||
|
Kernel::free_cap (page)
|
||||||
|
for unsigned a = p; a < ((p + PAGE_SIZE) & PAGE_MASK); a += 4:
|
||||||
|
if a >= shdr->sh_addr + shdr->sh_size:
|
||||||
|
break
|
||||||
|
if a < shdr->sh_addr:
|
||||||
|
continue
|
||||||
|
((unsigned *)&mapping[p - shdr->sh_addr])[(a & ~PAGE_MASK) >> 2] = 0
|
||||||
|
else:
|
||||||
|
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")
|
kdebug ("out of memory\n")
|
||||||
@ -250,56 +302,103 @@ static void run (file *f, bool priv):
|
|||||||
Kernel::panic (0)
|
Kernel::panic (0)
|
||||||
return
|
return
|
||||||
Kernel::free_cap (page)
|
Kernel::free_cap (page)
|
||||||
else:
|
kdebug_line ()
|
||||||
for unsigned a = p; a < ((p + PAGE_SIZE) & PAGE_MASK); a += 4:
|
kdebug_line ()
|
||||||
if a >= shdr->sh_addr + shdr->sh_size:
|
|
||||||
break
|
|
||||||
if a < shdr->sh_addr:
|
|
||||||
continue
|
|
||||||
((unsigned *)&mapping[p])[(a & ~PAGE_MASK) >> 2] = 0
|
|
||||||
for unsigned p = 0; p <= num_pages; ++p:
|
for unsigned p = 0; p <= num_pages; ++p:
|
||||||
mem.destroy (Kernel::Page (slot, p))
|
Kernel::my_memory.destroy (Kernel::Page (slot, p))
|
||||||
|
kdebug_line ()
|
||||||
Kernel::Page stackpage = mem.create_page ()
|
Kernel::Page stackpage = mem.create_page ()
|
||||||
|
kdebug_line ()
|
||||||
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)
|
||||||
|
kdebug_line ()
|
||||||
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")
|
kdebug ("unable to map initial stack page\n")
|
||||||
Kernel::panic (0)
|
Kernel::panic (0)
|
||||||
return
|
return
|
||||||
|
kdebug_line ()
|
||||||
Kernel::free_cap (stackpage)
|
Kernel::free_cap (stackpage)
|
||||||
Kernel::Caps caps = mem.create_caps (NUM_CAPS)
|
Kernel::Caps caps = mem.create_caps (NUM_CAPS)
|
||||||
|
kdebug_line ()
|
||||||
thread.use (caps, 0)
|
thread.use (caps, 0)
|
||||||
thread.set_info (Kernel::Thread::A0, NUM_SLOTS)
|
thread.set_info (Kernel::Thread::A0, NUM_SLOTS)
|
||||||
thread.set_info (Kernel::Thread::A1, NUM_CAPS)
|
thread.set_info (Kernel::Thread::A1, NUM_CAPS)
|
||||||
|
kdebug_line ()
|
||||||
Kernel::Receiver receiver = mem.create_receiver ()
|
Kernel::Receiver receiver = mem.create_receiver ()
|
||||||
receiver.set_owner (thread.copy ())
|
receiver.set_owner (thread.copy ())
|
||||||
Kernel::Cap call = receiver.create_call_capability ()
|
Kernel::Cap call = receiver.create_call_capability ()
|
||||||
Kernel::Cap parent = Kernel::my_receiver.create_capability (++current_thread)
|
Kernel::Cap parent = Kernel::my_receiver.create_capability (++current_thread)
|
||||||
|
kdebug_line ()
|
||||||
caps.set (__receiver_num, receiver.copy ())
|
caps.set (__receiver_num, receiver.copy ())
|
||||||
caps.set (__thread_num, thread.copy ())
|
caps.set (__thread_num, thread.copy ())
|
||||||
caps.set (__memory_num, mem.copy ())
|
caps.set (__memory_num, mem.copy ())
|
||||||
caps.set (__call_num, call.copy ())
|
caps.set (__call_num, call.copy ())
|
||||||
caps.set (__parent_num, parent.copy ())
|
caps.set (__parent_num, parent.copy ())
|
||||||
|
kdebug_line ()
|
||||||
thread.run ()
|
thread.run ()
|
||||||
|
kdebug_line ()
|
||||||
Kernel::free_cap (receiver)
|
Kernel::free_cap (receiver)
|
||||||
Kernel::free_cap (thread)
|
Kernel::free_cap (thread)
|
||||||
Kernel::free_cap (mem)
|
Kernel::free_cap (mem)
|
||||||
Kernel::free_cap (call)
|
Kernel::free_cap (call)
|
||||||
Kernel::free_cap (parent)
|
Kernel::free_cap (parent)
|
||||||
|
kdebug_line ()
|
||||||
|
Kernel::print_caps ()
|
||||||
|
|
||||||
|
static void dump_devices ():
|
||||||
|
kdebug ("String: ")
|
||||||
|
kdebug_num (String::ID, 3)
|
||||||
|
kdebug ("\nWString: ")
|
||||||
|
kdebug_num (WString::ID, 3)
|
||||||
|
kdebug ("\nDevice: ")
|
||||||
|
kdebug_num (Device::ID, 3)
|
||||||
|
kdebug ("\nParent: ")
|
||||||
|
kdebug_num (Parent::ID, 3)
|
||||||
|
kdebug ("\nKeyboard: ")
|
||||||
|
kdebug_num (Keyboard::ID, 3)
|
||||||
|
kdebug ("\nBuzzer: ")
|
||||||
|
kdebug_num (Buzzer::ID, 3)
|
||||||
|
kdebug ("\nDisplay: ")
|
||||||
|
kdebug_num (Display::ID, 3)
|
||||||
|
kdebug ("\nSetting: ")
|
||||||
|
kdebug_num (Setting::ID, 3)
|
||||||
|
kdebug ("\nDirectory: ")
|
||||||
|
kdebug_num (Directory::ID, 3)
|
||||||
|
kdebug ("\nWDirectory: ")
|
||||||
|
kdebug_num (WDirectory::ID, 3)
|
||||||
|
kdebug ("\nFilesystem: ")
|
||||||
|
kdebug_num (Filesystem::ID, 3)
|
||||||
|
kdebug ("\nStream: ")
|
||||||
|
kdebug_num (Stream::ID, 3)
|
||||||
|
kdebug ("\n")
|
||||||
|
|
||||||
Kernel::Num start ():
|
Kernel::Num start ():
|
||||||
// Wait for the debugging device to be active, in case there is one.
|
// Wait for the debugging device to be active, in case there is one.
|
||||||
Kernel::schedule ()
|
Kernel::schedule ()
|
||||||
|
init_alloc ()
|
||||||
|
dump_devices ()
|
||||||
top_memory = Kernel::get_top_memory ()
|
top_memory = Kernel::get_top_memory ()
|
||||||
Directory root = receive_devices ()
|
Directory root = receive_devices ()
|
||||||
root.lock_ro ()
|
root.lock_ro ()
|
||||||
|
kdebug_line ()
|
||||||
list_files (root)
|
list_files (root)
|
||||||
|
kdebug_line ()
|
||||||
sort ()
|
sort ()
|
||||||
|
kdebug_line ()
|
||||||
Kernel::Caps caps = Kernel::my_memory.create_caps (max_pages)
|
Kernel::Caps caps = Kernel::my_memory.create_caps (max_pages)
|
||||||
|
kdebug ("max pages: ")
|
||||||
|
kdebug_num (max_pages)
|
||||||
|
kdebug ("\n")
|
||||||
slot = caps.use ()
|
slot = caps.use ()
|
||||||
mapping = alloc_space (max_pages)
|
mapping = alloc_space (max_pages)
|
||||||
for unsigned i = 0; i < num_files; ++i:
|
for unsigned i = 0; i < num_files; ++i:
|
||||||
|
kdebug_line ()
|
||||||
run (&files[index[i]], files[index[i]].name[0] == '#')
|
run (&files[index[i]], files[index[i]].name[0] == '#')
|
||||||
|
kdebug_line ()
|
||||||
|
kdebug_line ()
|
||||||
root.unlock_ro ()
|
root.unlock_ro ()
|
||||||
|
kdebug_line ()
|
||||||
Kernel::free_slot (slot)
|
Kernel::free_slot (slot)
|
||||||
|
kdebug_line ()
|
||||||
Kernel::my_memory.destroy (caps)
|
Kernel::my_memory.destroy (caps)
|
||||||
|
kdebug_line ()
|
||||||
return 0
|
return 0
|
||||||
|
@ -108,7 +108,7 @@ class Udc:
|
|||||||
u16 data[size];
|
u16 data[size];
|
||||||
} __attribute__ ((packed))
|
} __attribute__ ((packed))
|
||||||
static unsigned const max_packet_size0 = 64
|
static unsigned const max_packet_size0 = 64
|
||||||
static unsigned const max_packet_size_bulk = 512
|
static unsigned const max_packet_size_bulk = 64
|
||||||
enum Requests:
|
enum Requests:
|
||||||
GET_STATUS = 0
|
GET_STATUS = 0
|
||||||
CLEAR_FEATURE = 1
|
CLEAR_FEATURE = 1
|
||||||
@ -149,28 +149,29 @@ class Udc:
|
|||||||
State state
|
State state
|
||||||
char configuration
|
char configuration
|
||||||
unsigned size
|
unsigned size
|
||||||
|
unsigned rx_request
|
||||||
char const *ptr
|
char const *ptr
|
||||||
unsigned cmd_code, cmd_arg
|
unsigned cmd_code, cmd_arg
|
||||||
bool rebooting
|
bool rebooting
|
||||||
bool vendor (Setup *s, unsigned cmd)
|
bool vendor (Setup *s, unsigned cmd)
|
||||||
bool get_descriptor (unsigned type, unsigned idx, unsigned len)
|
bool get_descriptor (unsigned type, unsigned idx, unsigned len)
|
||||||
bool handle_setup (Setup *s, unsigned cmd)
|
bool handle_setup (Setup *s, unsigned cmd)
|
||||||
|
void irq_usb (unsigned cmd)
|
||||||
|
void irq_in (unsigned cmd)
|
||||||
|
void irq_out (unsigned cmd)
|
||||||
char log_buffer[1000]
|
char log_buffer[1000]
|
||||||
unsigned log_buffer_size
|
unsigned log_buffer_size
|
||||||
unsigned log_buffer_start
|
unsigned log_buffer_start
|
||||||
Kernel::Cap caller
|
Kernel::Cap caller, caller_arg
|
||||||
bool have_caller
|
bool have_caller
|
||||||
|
unsigned *page
|
||||||
|
unsigned *p
|
||||||
|
Kernel::Page buffer_page
|
||||||
public:
|
public:
|
||||||
void init ()
|
void init ()
|
||||||
void log (unsigned c)
|
void log (unsigned c)
|
||||||
void interrupt (unsigned cmd)
|
void interrupt (unsigned cmd)
|
||||||
void send (unsigned code, unsigned arg)
|
void send (unsigned code, unsigned narg, Kernel::Cap reply, Kernel::Cap arg)
|
||||||
void set_caller (Kernel::Cap c):
|
|
||||||
if have_caller:
|
|
||||||
kdebug ("set_caller double-called\n")
|
|
||||||
Kernel::panic (0)
|
|
||||||
caller = c
|
|
||||||
have_caller = true
|
|
||||||
|
|
||||||
Udc::Device Udc::device_descriptor = { sizeof (Device), Device::Type, 0x200, 0, 0, 0, max_packet_size0, 0xfffe, 0x0002, 0x100, 1, 2, 0, 1 }
|
Udc::Device Udc::device_descriptor = { sizeof (Device), Device::Type, 0x200, 0, 0, 0, max_packet_size0, 0xfffe, 0x0002, 0x100, 1, 2, 0, 1 }
|
||||||
Udc::my_config Udc::config_descriptor = {
|
Udc::my_config Udc::config_descriptor = {
|
||||||
@ -212,52 +213,42 @@ void Udc::init ():
|
|||||||
cmd_code = ~0
|
cmd_code = ~0
|
||||||
cmd_arg = 0
|
cmd_arg = 0
|
||||||
|
|
||||||
|
// Use the space which is reserved for the framebuffer, because it will not be in use.
|
||||||
|
// Normally a normal new page should be allocated here, but new isn't implemented at this point.
|
||||||
|
page = (unsigned *)LCD_FRAMEBUFFER_BASE
|
||||||
|
p = page
|
||||||
|
buffer_page = Kernel::my_memory.create_page ()
|
||||||
|
buffer_page.set_flags (Kernel::Page::FRAME | Kernel::Page::PAYING, Kernel::Page::FRAME | Kernel::Page::PAYING)
|
||||||
|
Kernel::my_memory.map (buffer_page, (unsigned)page)
|
||||||
|
|
||||||
// Disconnect from the bus and don't try to get high-speed.
|
// Disconnect from the bus and don't try to get high-speed.
|
||||||
UDC_POWER &= ~(UDC_POWER_SOFTCONN | UDC_POWER_HSENAB)
|
UDC_POWER = 0
|
||||||
|
UDC_TESTMODE = 0
|
||||||
|
UDC_INDEX = 0
|
||||||
state = IDLE
|
state = IDLE
|
||||||
configuration = 0
|
configuration = 0
|
||||||
size = 0
|
size = 0
|
||||||
// exit suspend mode by reading the interrupt register.
|
// exit suspend mode by reading the interrupt register.
|
||||||
cpm_start_udc ()
|
cpm_start_udc ()
|
||||||
unsigned i = UDC_INTRUSB
|
|
||||||
// reset all pending endpoint interrupts.
|
// reset all pending endpoint interrupts.
|
||||||
|
unsigned i = UDC_INTRUSB
|
||||||
i = UDC_INTRIN
|
i = UDC_INTRIN
|
||||||
i = UDC_INTROUT
|
i = UDC_INTROUT
|
||||||
// enable interrupt on bus reset.
|
// enable interrupt on bus reset.
|
||||||
UDC_INTRUSB = UDC_INTR_RESET
|
UDC_INTRUSBE = UDC_INTR_RESET
|
||||||
// enable interrupts on endpoint 0.
|
// enable interrupts on endpoint 0.
|
||||||
UDC_INTRINE |= 1 << 0
|
UDC_INTRINE = 1 << 0
|
||||||
UDC_INDEX = 0
|
// and on out endpoint 1.
|
||||||
|
UDC_INTROUTE = 1 << 1
|
||||||
// Wait a while.
|
// Wait a while.
|
||||||
for unsigned w = 0; w < 10000; ++w:
|
for unsigned w = 0; w < 10000; ++w:
|
||||||
Kernel::schedule ()
|
Kernel::schedule ()
|
||||||
// Connect to the host.
|
// Connect to the host.
|
||||||
UDC_POWER |= UDC_POWER_SOFTCONN
|
UDC_POWER = UDC_POWER_SOFTCONN
|
||||||
|
|
||||||
bool Udc::vendor (Setup *s, unsigned cmd):
|
bool Udc::vendor (Setup *s, unsigned cmd):
|
||||||
if !(s->request_type & 0x80):
|
if !(s->request_type & 0x80):
|
||||||
switch s->request:
|
kdebug ("data to device without size\n")
|
||||||
case Directory::GET_SIZE:
|
|
||||||
if !have_caller:
|
|
||||||
kdebug ("received size from server without a caller waiting\n")
|
|
||||||
Kernel::panic (0)
|
|
||||||
unsigned size_l = UDC_FIFO (0)
|
|
||||||
unsigned size_h = UDC_FIFO (0)
|
|
||||||
caller.invoke (Kernel::Num (size_l, size_h))
|
|
||||||
have_caller = false
|
|
||||||
break
|
|
||||||
case Directory::GET_NAME:
|
|
||||||
if !have_caller:
|
|
||||||
kdebug ("received size from server without a caller waiting\n")
|
|
||||||
Kernel::panic (0)
|
|
||||||
unsigned n[4]
|
|
||||||
for unsigned i = 0; i < 4; ++i:
|
|
||||||
n[i] = UDC_FIFO (0)
|
|
||||||
caller.invoke (Kernel::Num (n[0], n[1]), Kernel::Num (n[2], n[3]))
|
|
||||||
have_caller = false
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
kdebug ("invalid vendor request\n")
|
|
||||||
Kernel::panic (0)
|
Kernel::panic (0)
|
||||||
return true
|
return true
|
||||||
if s->request == 10:
|
if s->request == 10:
|
||||||
@ -267,6 +258,12 @@ bool Udc::vendor (Setup *s, unsigned cmd):
|
|||||||
if cmd_code != ~0:
|
if cmd_code != ~0:
|
||||||
b[0] = cmd_code
|
b[0] = cmd_code
|
||||||
b[1] = cmd_arg
|
b[1] = cmd_arg
|
||||||
|
if cmd_code == Directory::LOCK_RO || cmd_code == Directory::UNLOCK_RO:
|
||||||
|
caller.invoke ()
|
||||||
|
Kernel::free_cap (caller)
|
||||||
|
Kernel::free_cap (caller_arg)
|
||||||
|
have_caller = false
|
||||||
|
//kdebug ("(un)lock response\n")
|
||||||
cmd_code = ~0
|
cmd_code = ~0
|
||||||
else:
|
else:
|
||||||
if log_buffer_start == log_buffer_size:
|
if log_buffer_start == log_buffer_size:
|
||||||
@ -286,12 +283,15 @@ bool Udc::vendor (Setup *s, unsigned cmd):
|
|||||||
state = TX
|
state = TX
|
||||||
return true
|
return true
|
||||||
|
|
||||||
void Udc::send (unsigned code, unsigned arg):
|
void Udc::send (unsigned code, unsigned narg, Kernel::Cap reply, Kernel::Cap arg):
|
||||||
if code != ~0:
|
if cmd_code != ~0:
|
||||||
kdebug ("new code sent while old one wasn't finished.\n")
|
kdebug ("new code sent while old one wasn't finished.\n")
|
||||||
Kernel::panic (0)
|
Kernel::panic (0)
|
||||||
cmd_code = code
|
cmd_code = code
|
||||||
cmd_arg = arg
|
cmd_arg = narg
|
||||||
|
caller = reply
|
||||||
|
caller_arg = arg
|
||||||
|
have_caller = true
|
||||||
|
|
||||||
bool Udc::get_descriptor (unsigned type, unsigned idx, unsigned len):
|
bool Udc::get_descriptor (unsigned type, unsigned idx, unsigned len):
|
||||||
switch type:
|
switch type:
|
||||||
@ -355,6 +355,9 @@ bool Udc::handle_setup (Setup *s, unsigned cmd):
|
|||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
|
UDC_OUTMAXP = 64
|
||||||
|
UDC_OUTCSR = UDC_OUTCSR_CDT | UDC_OUTCSR_FF
|
||||||
|
UDC_OUTCSR = UDC_OUTCSR_CDT | UDC_OUTCSR_FF
|
||||||
break
|
break
|
||||||
case STANDARD_FROM_DEVICE:
|
case STANDARD_FROM_DEVICE:
|
||||||
switch s->request:
|
switch s->request:
|
||||||
@ -385,15 +388,12 @@ bool Udc::handle_setup (Setup *s, unsigned cmd):
|
|||||||
return false
|
return false
|
||||||
return true
|
return true
|
||||||
|
|
||||||
void Udc::interrupt (unsigned cmd):
|
void Udc::irq_usb (unsigned cmd):
|
||||||
unsigned i = UDC_INTRUSB
|
// Reset.
|
||||||
if i & UDC_INTR_RESET:
|
|
||||||
state = IDLE
|
state = IDLE
|
||||||
return
|
|
||||||
i = UDC_INTRIN
|
void Udc::irq_in (unsigned cmd):
|
||||||
if i & (1 << 0):
|
|
||||||
// Interrupt on endpoint 0.
|
// Interrupt on endpoint 0.
|
||||||
UDC_INDEX = 0
|
|
||||||
unsigned csr = UDC_CSR0
|
unsigned csr = UDC_CSR0
|
||||||
if csr & UDC_CSR0_SENTSTALL:
|
if csr & UDC_CSR0_SENTSTALL:
|
||||||
csr &= ~(UDC_CSR0_SENTSTALL | UDC_CSR0_SENDSTALL)
|
csr &= ~(UDC_CSR0_SENTSTALL | UDC_CSR0_SENDSTALL)
|
||||||
@ -410,6 +410,12 @@ void Udc::interrupt (unsigned cmd):
|
|||||||
union { unsigned d[2]; Setup s; } packet
|
union { unsigned d[2]; Setup s; } packet
|
||||||
packet.d[0] = UDC_FIFO (0)
|
packet.d[0] = UDC_FIFO (0)
|
||||||
packet.d[1] = UDC_FIFO (0)
|
packet.d[1] = UDC_FIFO (0)
|
||||||
|
if !(packet.s.request_type & 0x80) && packet.s.length > 0:
|
||||||
|
// More data will follow; delay handling of packet.
|
||||||
|
state = RX
|
||||||
|
UDC_CSR0 = csr | UDC_CSR0_SVDOUTPKTRDY
|
||||||
|
rx_request = packet.s.request
|
||||||
|
return
|
||||||
UDC_CSR0 = csr | UDC_CSR0_DATAEND | UDC_CSR0_SVDOUTPKTRDY
|
UDC_CSR0 = csr | UDC_CSR0_DATAEND | UDC_CSR0_SVDOUTPKTRDY
|
||||||
if !handle_setup (&packet.s, cmd):
|
if !handle_setup (&packet.s, cmd):
|
||||||
csr |= UDC_CSR0_SENDSTALL
|
csr |= UDC_CSR0_SENDSTALL
|
||||||
@ -431,23 +437,116 @@ void Udc::interrupt (unsigned cmd):
|
|||||||
csr |= UDC_CSR0_INPKTRDY | UDC_CSR0_DATAEND
|
csr |= UDC_CSR0_INPKTRDY | UDC_CSR0_DATAEND
|
||||||
break
|
break
|
||||||
case RX:
|
case RX:
|
||||||
// Not supported.
|
// The protocol that is used doesn't allow large packets, so being here always means the entire packet is received.
|
||||||
csr |= UDC_CSR0_SVDOUTPKTRDY | UDC_CSR0_SENDSTALL
|
switch rx_request & 0xff:
|
||||||
|
case Directory::GET_SIZE & 0xff:
|
||||||
|
if !have_caller:
|
||||||
|
kdebug ("received dir size from server without a caller waiting\n")
|
||||||
|
Kernel::panic (0)
|
||||||
|
unsigned size_l = UDC_FIFO (0)
|
||||||
|
unsigned size_h = UDC_FIFO (0)
|
||||||
|
caller.invoke (Kernel::Num (size_l, size_h))
|
||||||
|
Kernel::free_cap (caller)
|
||||||
|
Kernel::free_cap (caller_arg)
|
||||||
|
have_caller = false
|
||||||
|
//kdebug ("get_size response\n")
|
||||||
|
break
|
||||||
|
case Directory::GET_NAME & 0xff:
|
||||||
|
if !have_caller:
|
||||||
|
kdebug ("received filename from server without a caller waiting\n")
|
||||||
|
Kernel::panic (0)
|
||||||
|
unsigned n[4]
|
||||||
|
for unsigned i = 0; i < 4; ++i:
|
||||||
|
n[i] = UDC_FIFO (0)
|
||||||
|
caller.invoke (Kernel::Num (n[0], n[1]), Kernel::Num (n[2], n[3]))
|
||||||
|
Kernel::free_cap (caller)
|
||||||
|
Kernel::free_cap (caller_arg)
|
||||||
|
//kdebug ("get_name response\n")
|
||||||
|
have_caller = false
|
||||||
|
break
|
||||||
|
case ::String::GET_SIZE & 0xff:
|
||||||
|
if !have_caller:
|
||||||
|
kdebug ("received string size from server without a caller waiting\n")
|
||||||
|
Kernel::panic (0)
|
||||||
|
unsigned size_l = UDC_FIFO (0)
|
||||||
|
unsigned size_h = UDC_FIFO (0)
|
||||||
|
caller.invoke (Kernel::Num (size_l, size_h))
|
||||||
|
Kernel::free_cap (caller)
|
||||||
|
Kernel::free_cap (caller_arg)
|
||||||
|
have_caller = false
|
||||||
|
//kdebug ("get_filesize response\n")
|
||||||
|
break
|
||||||
|
case ::String::GET_CHARS & 0xff:
|
||||||
|
if !have_caller:
|
||||||
|
kdebug ("received string char data from server without a caller waiting\n")
|
||||||
|
Kernel::panic (0)
|
||||||
|
unsigned n[4]
|
||||||
|
for unsigned i = 0; i < 4; ++i:
|
||||||
|
n[i] = UDC_FIFO (0)
|
||||||
|
caller.invoke (Kernel::Num (n[0], n[1]), Kernel::Num (n[2], n[3]))
|
||||||
|
Kernel::free_cap (caller)
|
||||||
|
Kernel::free_cap (caller_arg)
|
||||||
|
have_caller = false
|
||||||
|
//kdebug ("get_chars response\n")
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
kdebug ("invalid vendor request: ")
|
||||||
|
kdebug_num (rx_request)
|
||||||
|
kdebug ("\n")
|
||||||
|
Kernel::panic (0)
|
||||||
|
UDC_CSR0 = csr | UDC_CSR0_DATAEND | UDC_CSR0_SVDOUTPKTRDY
|
||||||
state = IDLE
|
state = IDLE
|
||||||
break
|
break
|
||||||
UDC_CSR0 = csr
|
UDC_CSR0 = csr
|
||||||
unsigned i = UDC_INTROUT
|
|
||||||
if i & (1 << 1):
|
void Udc::irq_out (unsigned cmd):
|
||||||
// Interrupt on OUT endpoint 1.
|
// Interrupt on OUT endpoint 1.
|
||||||
UDC_INDEX = 1
|
UDC_INDEX = 1
|
||||||
|
if !have_caller:
|
||||||
|
kdebug ("received bulk data from server without a caller waiting\n")
|
||||||
|
Kernel::panic (0)
|
||||||
|
unsigned size = UDC_OUTCOUNT
|
||||||
unsigned csr = UDC_OUTCSR
|
unsigned csr = UDC_OUTCSR
|
||||||
if !csr & UDC_CSR_OUTPKTRDY:
|
//kdebug ("handling bulk interrupt for ")
|
||||||
kdebug ("unrecognized interrupt on bulk out ep 1\n")
|
//kdebug_num (csr)
|
||||||
return
|
//kdebug (" with ")
|
||||||
for unsigned i = 0; i < 16; ++i:
|
//kdebug_num (size)
|
||||||
|
//kdebug (" bytes.\n")
|
||||||
|
csr &= ~UDC_OUTCSR_OUTPKTRDY
|
||||||
|
for unsigned i = 0; i < size; i += 4:
|
||||||
*p++ = UDC_FIFO (1)
|
*p++ = UDC_FIFO (1)
|
||||||
if p - page == PAGE_SIZE:
|
if p - page == PAGE_SIZE >> 2:
|
||||||
// TODO: notify caller; reset buffer.
|
buffer_page.share (caller_arg, Kernel::Page::FORGET)
|
||||||
|
buffer_page.set_flags (Kernel::Page::FRAME, Kernel::Page::FRAME)
|
||||||
|
caller.invoke ()
|
||||||
|
Kernel::free_cap (caller)
|
||||||
|
Kernel::free_cap (caller_arg)
|
||||||
|
have_caller = false
|
||||||
|
//kdebug ("bulk response\n")
|
||||||
|
p = page
|
||||||
|
UDC_OUTCSR = csr
|
||||||
|
UDC_INDEX = 0
|
||||||
|
|
||||||
|
void Udc::interrupt (unsigned cmd):
|
||||||
|
while true:
|
||||||
|
unsigned usb = UDC_INTRUSB
|
||||||
|
unsigned in = UDC_INTRIN
|
||||||
|
unsigned out = UDC_INTROUT
|
||||||
|
if !(usb & 4) && !(in & 1) && !(out & 2):
|
||||||
|
break
|
||||||
|
//kdebug ("interrupt: ")
|
||||||
|
//kdebug_num (usb, 1)
|
||||||
|
//kdebug ("/")
|
||||||
|
//kdebug_num (in, 1)
|
||||||
|
//kdebug ("/")
|
||||||
|
//kdebug_num (out, 1)
|
||||||
|
//kdebug ("\n")
|
||||||
|
if usb & 4:
|
||||||
|
irq_usb (cmd)
|
||||||
|
if in & 1:
|
||||||
|
irq_in (cmd)
|
||||||
|
if out & 2:
|
||||||
|
irq_out (cmd)
|
||||||
|
|
||||||
void Udc::log (unsigned c):
|
void Udc::log (unsigned c):
|
||||||
if log_buffer_size >= sizeof (log_buffer):
|
if log_buffer_size >= sizeof (log_buffer):
|
||||||
@ -459,6 +558,8 @@ enum pdata:
|
|||||||
FS
|
FS
|
||||||
DATA
|
DATA
|
||||||
DIRECTORY
|
DIRECTORY
|
||||||
|
FILE
|
||||||
|
NAME
|
||||||
|
|
||||||
Kernel::Num start ():
|
Kernel::Num start ():
|
||||||
map_udc ()
|
map_udc ()
|
||||||
@ -466,18 +567,23 @@ Kernel::Num start ():
|
|||||||
map_cpm ()
|
map_cpm ()
|
||||||
Udc udc
|
Udc udc
|
||||||
|
|
||||||
Kernel::Cap logcap = Kernel::my_receiver.create_capability (LOG)
|
//Kernel::Cap logcap = Kernel::my_receiver.create_capability (LOG)
|
||||||
__asm__ volatile ("li $a0, 1\nlw $a1, %0\nbreak" :: "m"(logcap.code): "a0", "a1", "memory")
|
//__asm__ volatile ("li $a0, 1\nlw $a1, %0\nbreak" :: "m"(logcap.code): "a0", "a1", "memory")
|
||||||
udc.init ()
|
udc.init ()
|
||||||
Kernel::register_interrupt (IRQ_UDC)
|
Kernel::register_interrupt (IRQ_UDC)
|
||||||
Device fs_dev = Kernel::my_receiver.create_capability (FS)
|
Device fs_dev = Kernel::my_receiver.create_capability (FS)
|
||||||
Kernel::my_parent.provide_device <Directory> (fs_dev)
|
Device data_dev = Kernel::my_receiver.create_capability (DATA)
|
||||||
|
Kernel::my_parent.provide_device <Filesystem> (fs_dev.copy ())
|
||||||
|
Kernel::my_parent.provide_device <String> (data_dev.copy ())
|
||||||
|
Kernel::free_cap (fs_dev)
|
||||||
|
Kernel::free_cap (data_dev)
|
||||||
unsigned data_current_user = 0, fs_current_user = 0
|
unsigned data_current_user = 0, fs_current_user = 0
|
||||||
unsigned next_user
|
unsigned next_user
|
||||||
unsigned state = 0
|
unsigned state = 0
|
||||||
while true:
|
while true:
|
||||||
Kernel::wait ()
|
Kernel::wait ()
|
||||||
Kernel::Cap reply = Kernel::get_reply ()
|
Kernel::Cap reply = Kernel::get_reply ()
|
||||||
|
Kernel::Cap arg = Kernel::get_arg ()
|
||||||
switch Kernel::recv.protected_data.h:
|
switch Kernel::recv.protected_data.h:
|
||||||
case 0:
|
case 0:
|
||||||
switch Kernel::recv.protected_data.l:
|
switch Kernel::recv.protected_data.l:
|
||||||
@ -489,10 +595,10 @@ Kernel::Num start ():
|
|||||||
udc.log (Kernel::recv.data[0].l)
|
udc.log (Kernel::recv.data[0].l)
|
||||||
break
|
break
|
||||||
case FS:
|
case FS:
|
||||||
Device::host (FS, fs_current_user, reply)
|
Device::host (FS, fs_current_user, reply, arg)
|
||||||
continue
|
continue
|
||||||
case DATA:
|
case DATA:
|
||||||
Device::host (DATA, data_current_user, reply)
|
Device::host (DATA, data_current_user, reply, arg)
|
||||||
continue
|
continue
|
||||||
default:
|
default:
|
||||||
udc.log ('~')
|
udc.log ('~')
|
||||||
@ -501,19 +607,22 @@ Kernel::Num start ():
|
|||||||
udc.log (digit[(Kernel::recv.protected_data.l >> (4 * (7 - i))) & 0xf])
|
udc.log (digit[(Kernel::recv.protected_data.l >> (4 * (7 - i))) & 0xf])
|
||||||
udc.log ('\n')
|
udc.log ('\n')
|
||||||
break
|
break
|
||||||
|
break
|
||||||
case DATA:
|
case DATA:
|
||||||
if data_current_user != Kernel::recv.protected_data.l:
|
if data_current_user != Kernel::recv.protected_data.l:
|
||||||
break
|
break
|
||||||
switch Kernel::recv.data[0].l:
|
switch Kernel::recv.data[0].l:
|
||||||
case String::GET_SIZE:
|
case ::String::GET_SIZE:
|
||||||
case String::GET_CHARS:
|
case ::String::GET_CHARS:
|
||||||
reply.invoke (0)
|
reply.invoke (0)
|
||||||
Kernel::free_cap (reply)
|
Kernel::free_cap (reply)
|
||||||
|
Kernel::free_cap (arg)
|
||||||
continue
|
continue
|
||||||
case String::GET_PAGE:
|
case ::String::GET_PAGE:
|
||||||
default:
|
default:
|
||||||
reply.invoke (Kernel::ERR_INVALID_OPERATION)
|
reply.invoke (Kernel::ERR_INVALID_OPERATION)
|
||||||
Kernel::free_cap (reply)
|
Kernel::free_cap (reply)
|
||||||
|
Kernel::free_cap (arg)
|
||||||
continue
|
continue
|
||||||
break
|
break
|
||||||
case FS:
|
case FS:
|
||||||
@ -526,30 +635,79 @@ Kernel::Num start ():
|
|||||||
reply.invoke (0, 0, dir.copy ())
|
reply.invoke (0, 0, dir.copy ())
|
||||||
Kernel::free_cap (dir)
|
Kernel::free_cap (dir)
|
||||||
Kernel::free_cap (reply)
|
Kernel::free_cap (reply)
|
||||||
|
Kernel::free_cap (arg)
|
||||||
continue
|
continue
|
||||||
default:
|
default:
|
||||||
reply.invoke (Kernel::ERR_INVALID_OPERATION)
|
reply.invoke (Kernel::ERR_INVALID_OPERATION)
|
||||||
Kernel::free_cap (reply)
|
Kernel::free_cap (reply)
|
||||||
|
Kernel::free_cap (arg)
|
||||||
continue
|
continue
|
||||||
|
break
|
||||||
case DIRECTORY:
|
case DIRECTORY:
|
||||||
switch Kernel::recv.data[0].l:
|
switch Kernel::recv.data[0].l:
|
||||||
case Directory::GET_SIZE:
|
|
||||||
case Directory::GET_NAME:
|
case Directory::GET_NAME:
|
||||||
|
Kernel::Cap name = Kernel::my_receiver.create_capability (Kernel::Num (Kernel::recv.data[1].l, NAME))
|
||||||
|
reply.invoke (0, 0, name.copy ())
|
||||||
|
Kernel::free_cap (name)
|
||||||
|
Kernel::free_cap (reply)
|
||||||
|
Kernel::free_cap (arg)
|
||||||
|
continue
|
||||||
|
case Directory::GET_SIZE:
|
||||||
case Directory::LOCK_RO:
|
case Directory::LOCK_RO:
|
||||||
case Directory::UNLOCK_RO:
|
case Directory::UNLOCK_RO:
|
||||||
state = Kernel::recv.data[0].l
|
state = Kernel::recv.data[0].l
|
||||||
if Kernel::recv.data[1].h != 0:
|
if Kernel::recv.data[1].h != 0:
|
||||||
kdebug ("index out of supported range\n")
|
kdebug ("index out of supported range\n")
|
||||||
Kernel::panic (0)
|
Kernel::panic (0)
|
||||||
udc.send (Kernel::recv.data[0].l, Kernel::recv.data[1].l)
|
udc.send (Kernel::recv.data[0].l, Kernel::recv.data[1].l, reply, arg)
|
||||||
Kernel::free_cap (reply)
|
|
||||||
continue
|
continue
|
||||||
case Directory::GET_FILE_RO:
|
case Directory::GET_FILE_RO:
|
||||||
//TODO
|
if Kernel::recv.data[1].h != 0:
|
||||||
|
kdebug ("index out of supported range\n")
|
||||||
|
Kernel::panic (0)
|
||||||
|
//kdebug ("sending file\n")
|
||||||
|
Kernel::Cap file = Kernel::my_receiver.create_capability (Kernel::Num (Kernel::recv.data[1].l, FILE))
|
||||||
|
reply.invoke (0, 0, file.copy ())
|
||||||
|
Kernel::free_cap (file)
|
||||||
|
Kernel::free_cap (reply)
|
||||||
|
Kernel::free_cap (arg)
|
||||||
|
continue
|
||||||
case Directory::GET_FILE_INFO:
|
case Directory::GET_FILE_INFO:
|
||||||
default:
|
default:
|
||||||
reply.invoke (Kernel::ERR_INVALID_OPERATION)
|
reply.invoke (Kernel::ERR_INVALID_OPERATION)
|
||||||
Kernel::free_cap (reply)
|
Kernel::free_cap (reply)
|
||||||
|
Kernel::free_cap (arg)
|
||||||
|
continue
|
||||||
|
break
|
||||||
|
case FILE:
|
||||||
|
switch Kernel::recv.data[0].l:
|
||||||
|
case ::String::GET_SIZE:
|
||||||
|
case ::String::GET_CHARS:
|
||||||
|
case ::String::GET_PAGE:
|
||||||
|
udc.send (Kernel::recv.data[0].l | ((Kernel::recv.data[1].l >> PAGE_BITS) << 16), Kernel::recv.protected_data.l, reply, arg)
|
||||||
|
continue
|
||||||
|
default:
|
||||||
|
reply.invoke (Kernel::ERR_INVALID_OPERATION)
|
||||||
|
Kernel::free_cap (reply)
|
||||||
|
Kernel::free_cap (arg)
|
||||||
|
continue
|
||||||
|
break
|
||||||
|
case NAME:
|
||||||
|
switch Kernel::recv.data[0].l:
|
||||||
|
case ::String::GET_SIZE:
|
||||||
|
reply.invoke (16)
|
||||||
|
Kernel::free_cap (reply)
|
||||||
|
Kernel::free_cap (arg)
|
||||||
|
continue
|
||||||
|
case ::String::GET_CHARS:
|
||||||
|
state = Kernel::recv.data[0].l
|
||||||
|
udc.send (Directory::GET_NAME, Kernel::recv.protected_data.l, reply, arg)
|
||||||
|
continue
|
||||||
|
default:
|
||||||
|
reply.invoke (Kernel::ERR_INVALID_OPERATION)
|
||||||
|
Kernel::free_cap (reply)
|
||||||
|
Kernel::free_cap (arg)
|
||||||
continue
|
continue
|
||||||
reply.invoke ()
|
reply.invoke ()
|
||||||
Kernel::free_cap (reply)
|
Kernel::free_cap (reply)
|
||||||
|
Kernel::free_cap (arg)
|
||||||
|
@ -99,7 +99,7 @@ struct Device : public Kernel::Cap:
|
|||||||
void use (Kernel::Cap user):
|
void use (Kernel::Cap user):
|
||||||
ocall (user, CAP_MASTER_DIRECT | USE)
|
ocall (user, CAP_MASTER_DIRECT | USE)
|
||||||
// Convenience function for threads implementing a device.
|
// Convenience function for threads implementing a device.
|
||||||
static void host (unsigned id, unsigned ¤t_user, Kernel::Cap &reply):
|
static void host (unsigned id, unsigned ¤t_user, Kernel::Cap &reply, Kernel::Cap &arg):
|
||||||
static unsigned last_user
|
static unsigned last_user
|
||||||
switch Kernel::recv.data[0].l:
|
switch Kernel::recv.data[0].l:
|
||||||
case Device::CREATE_USER:
|
case Device::CREATE_USER:
|
||||||
@ -111,20 +111,20 @@ struct Device : public Kernel::Cap:
|
|||||||
reply.invoke (0, 0, c.copy ())
|
reply.invoke (0, 0, c.copy ())
|
||||||
Kernel::free_cap (c)
|
Kernel::free_cap (c)
|
||||||
Kernel::free_cap (reply)
|
Kernel::free_cap (reply)
|
||||||
|
Kernel::free_cap (arg)
|
||||||
break
|
break
|
||||||
case Device::DESTROY_USER:
|
case Device::DESTROY_USER:
|
||||||
reply.invoke ()
|
reply.invoke ()
|
||||||
Kernel::free_cap (reply)
|
Kernel::free_cap (reply)
|
||||||
|
Kernel::free_cap (arg)
|
||||||
break
|
break
|
||||||
case Device::USE:
|
case Device::USE:
|
||||||
Kernel::Cap arg = Kernel::get_arg ()
|
|
||||||
current_user = Kernel::my_receiver.get_protected (arg).l
|
current_user = Kernel::my_receiver.get_protected (arg).l
|
||||||
reply.invoke ()
|
reply.invoke ()
|
||||||
Kernel::free_cap (reply)
|
Kernel::free_cap (reply)
|
||||||
Kernel::free_cap (arg)
|
Kernel::free_cap (arg)
|
||||||
break
|
break
|
||||||
case Device::UNUSE:
|
case Device::UNUSE:
|
||||||
Kernel::Cap arg = Kernel::get_arg ()
|
|
||||||
Kernel::Num p = Kernel::my_receiver.get_protected (arg)
|
Kernel::Num p = Kernel::my_receiver.get_protected (arg)
|
||||||
if p.h == id && current_user == p.l:
|
if p.h == id && current_user == p.l:
|
||||||
current_user = 0
|
current_user = 0
|
||||||
|
41
invoke.ccp
41
invoke.ccp
@ -210,6 +210,16 @@ static void receiver_invoke (unsigned cmd, unsigned target, Kernel::Num protecte
|
|||||||
return
|
return
|
||||||
case Kernel::Receiver::GET_PROTECTED & REQUEST_MASK:
|
case Kernel::Receiver::GET_PROTECTED & REQUEST_MASK:
|
||||||
if !c->arg.valid () || c->arg->target != receiver:
|
if !c->arg.valid () || c->arg->target != receiver:
|
||||||
|
if !c->arg.valid ():
|
||||||
|
dbg_log ("invalid arg\n")
|
||||||
|
else:
|
||||||
|
dbg_log ("target: ")
|
||||||
|
dbg_log_num ((unsigned)c->arg->target)
|
||||||
|
dbg_log ("/")
|
||||||
|
dbg_log_num ((unsigned)c->arg->protected_data.h)
|
||||||
|
dbg_log (":")
|
||||||
|
dbg_log_num ((unsigned)c->arg->protected_data.l)
|
||||||
|
dbg_log ("\n")
|
||||||
dpanic (0, "wrong argument for get_protected")
|
dpanic (0, "wrong argument for get_protected")
|
||||||
reply_num (Kernel::ERR_INVALID_ARGUMENT)
|
reply_num (Kernel::ERR_INVALID_ARGUMENT)
|
||||||
return
|
return
|
||||||
@ -289,6 +299,7 @@ static void memory_invoke (unsigned cmd, unsigned target, Kernel::Num protected_
|
|||||||
kPage *ret = mem->alloc_page ()
|
kPage *ret = mem->alloc_page ()
|
||||||
if ret:
|
if ret:
|
||||||
reply_cap (CAPTYPE_PAGE | CAP_MASTER, (unsigned)ret, &ret->refs)
|
reply_cap (CAPTYPE_PAGE | CAP_MASTER, (unsigned)ret, &ret->refs)
|
||||||
|
dbg_log ("page created\n")
|
||||||
else:
|
else:
|
||||||
dpanic (0x33311992, "out of memory creating page")
|
dpanic (0x33311992, "out of memory creating page")
|
||||||
reply_num (Kernel::ERR_OUT_OF_MEMORY)
|
reply_num (Kernel::ERR_OUT_OF_MEMORY)
|
||||||
@ -574,10 +585,12 @@ static void page_invoke (unsigned cmd, unsigned target, Kernel::Num protected_da
|
|||||||
case Kernel::Page::SHARE & REQUEST_MASK:
|
case Kernel::Page::SHARE & REQUEST_MASK:
|
||||||
if !c->arg.valid ():
|
if !c->arg.valid ():
|
||||||
// Cannot share without a target page.
|
// Cannot share without a target page.
|
||||||
|
dpanic (0, "no target page for share")
|
||||||
reply_num (Kernel::ERR_INVALID_ARGUMENT)
|
reply_num (Kernel::ERR_INVALID_ARGUMENT)
|
||||||
return
|
return
|
||||||
if ((unsigned)c->arg->target & ~REQUEST_MASK) != CAPTYPE_PAGE:
|
if ((unsigned)c->arg->target & ~REQUEST_MASK) != CAPTYPE_PAGE:
|
||||||
// FIXME: This makes it impossible to use a fake kPage capability.
|
// FIXME: This makes it impossible to use a fake kPage capability.
|
||||||
|
dpanic (0, "share target is no page")
|
||||||
reply_num (Kernel::ERR_INVALID_ARGUMENT)
|
reply_num (Kernel::ERR_INVALID_ARGUMENT)
|
||||||
return
|
return
|
||||||
kPage *t = (kPage *)c->arg->protected_data.l
|
kPage *t = (kPage *)c->arg->protected_data.l
|
||||||
@ -585,6 +598,7 @@ static void page_invoke (unsigned cmd, unsigned target, Kernel::Num protected_da
|
|||||||
if c->data[0].h & Kernel::Page::READONLY || cmd & Kernel::Page::READONLY:
|
if c->data[0].h & Kernel::Page::READONLY || cmd & Kernel::Page::READONLY:
|
||||||
t->flags |= Kernel::Page::READONLY
|
t->flags |= Kernel::Page::READONLY
|
||||||
if !(page->flags & Kernel::Page::FRAME):
|
if !(page->flags & Kernel::Page::FRAME):
|
||||||
|
dpanic (0, "sharing nothing results in lost page")
|
||||||
break
|
break
|
||||||
if c->data[0].h & Kernel::Page::COPY:
|
if c->data[0].h & Kernel::Page::COPY:
|
||||||
if ~t->flags & Kernel::Page::PAYING:
|
if ~t->flags & Kernel::Page::PAYING:
|
||||||
@ -606,7 +620,7 @@ static void page_invoke (unsigned cmd, unsigned target, Kernel::Num protected_da
|
|||||||
else:
|
else:
|
||||||
t->flags |= Kernel::Page::FRAME
|
t->flags |= Kernel::Page::FRAME
|
||||||
t->frame = raw_zalloc ()
|
t->frame = raw_zalloc ()
|
||||||
for unsigned i = 0; i <= (c->data[0].h & ~PAGE_MASK); i += 4:
|
for unsigned i = 0; i < PAGE_SIZE; i += 4:
|
||||||
((unsigned *)t->frame)[i >> 2] = d[i >> 2]
|
((unsigned *)t->frame)[i >> 2] = d[i >> 2]
|
||||||
else:
|
else:
|
||||||
if t != page:
|
if t != page:
|
||||||
@ -618,6 +632,7 @@ static void page_invoke (unsigned cmd, unsigned target, Kernel::Num protected_da
|
|||||||
kPage_arch_update_mapping (t)
|
kPage_arch_update_mapping (t)
|
||||||
else:
|
else:
|
||||||
if t == page:
|
if t == page:
|
||||||
|
dpanic (0, "sharing page with itself")
|
||||||
break
|
break
|
||||||
if c->data[0].h & Kernel::Page::FORGET:
|
if c->data[0].h & Kernel::Page::FORGET:
|
||||||
if ~page->flags & Kernel::Page::SHARED:
|
if ~page->flags & Kernel::Page::SHARED:
|
||||||
@ -644,10 +659,13 @@ static void page_invoke (unsigned cmd, unsigned target, Kernel::Num protected_da
|
|||||||
page->share_prev = t
|
page->share_prev = t
|
||||||
if t->share_prev:
|
if t->share_prev:
|
||||||
t->share_prev->share_next = t
|
t->share_prev->share_next = t
|
||||||
|
t->frame = page->frame
|
||||||
|
t->flags |= Kernel::Page::FRAME
|
||||||
kPage_arch_update_mapping (t)
|
kPage_arch_update_mapping (t)
|
||||||
break
|
break
|
||||||
case Kernel::Page::SET_FLAGS & REQUEST_MASK:
|
case Kernel::Page::SET_FLAGS & REQUEST_MASK:
|
||||||
if cmd & Kernel::Page::READONLY:
|
if cmd & Kernel::Page::READONLY:
|
||||||
|
dpanic (0, "setting page flags denied")
|
||||||
reply_num (Kernel::ERR_WRITE_DENIED)
|
reply_num (Kernel::ERR_WRITE_DENIED)
|
||||||
return
|
return
|
||||||
// Always refuse to set reserved flags.
|
// Always refuse to set reserved flags.
|
||||||
@ -655,25 +673,27 @@ static void page_invoke (unsigned cmd, unsigned target, Kernel::Num protected_da
|
|||||||
// Remember the old flags.
|
// Remember the old flags.
|
||||||
unsigned old = page->flags
|
unsigned old = page->flags
|
||||||
// Compute the new flags.
|
// Compute the new flags.
|
||||||
unsigned new_flags = (page->flags & ~c->data[1].h) | (c->data[1].l & c->data[1].h)
|
page->flags = (page->flags & ~c->data[1].h) | (c->data[1].l & c->data[1].h)
|
||||||
|
|
||||||
// If we stop paying, see if the frame is still paid for. If not, free it.
|
// If we stop paying, see if the frame is still paid for. If not, free it.
|
||||||
if ~new_flags & old & Kernel::Page::PAYING:
|
if ~page->flags & old & Kernel::Page::PAYING:
|
||||||
// Decrease the use counter in any case.
|
// Decrease the use counter in any case.
|
||||||
page->address_space->unuse ()
|
page->address_space->unuse ()
|
||||||
if !page_check_payment (page):
|
if !page_check_payment (page):
|
||||||
new_flags &= ~Kernel::Page::FRAME
|
page->flags &= ~Kernel::Page::FRAME
|
||||||
|
|
||||||
// If we start paying, increase the use counter.
|
// If we start paying, increase the use counter.
|
||||||
if new_flags & ~old & Kernel::Page::PAYING:
|
if page->flags & ~old & Kernel::Page::PAYING:
|
||||||
if !page->address_space->use():
|
if !page->address_space->use():
|
||||||
|
dpanic (0, "cannot pay for frame")
|
||||||
// If it doesn't work, refuse to set the flag, and refuse to allocate a frame.
|
// If it doesn't work, refuse to set the flag, and refuse to allocate a frame.
|
||||||
new_flags &= ~(Kernel::Page::PAYING | Kernel::Page::FRAME)
|
page->flags &= ~(Kernel::Page::PAYING | Kernel::Page::FRAME)
|
||||||
|
// However, if there already was a frame, keep it.
|
||||||
if old & Kernel::Page::FRAME:
|
if old & Kernel::Page::FRAME:
|
||||||
new_flags |= Kernel::Page::FRAME
|
page->flags |= Kernel::Page::FRAME
|
||||||
|
|
||||||
// If we want a frame, see if we can get it.
|
// If we want a frame, see if we can get it.
|
||||||
if ~old & new_flags & Kernel::Page::FRAME:
|
if ~old & page->flags & Kernel::Page::FRAME:
|
||||||
kPage *p
|
kPage *p
|
||||||
for p = page; p; p = p->share_prev:
|
for p = page; p; p = p->share_prev:
|
||||||
if p->flags & Kernel::Page::PAYING:
|
if p->flags & Kernel::Page::PAYING:
|
||||||
@ -683,9 +703,10 @@ static void page_invoke (unsigned cmd, unsigned target, Kernel::Num protected_da
|
|||||||
if p->flags & Kernel::Page::PAYING:
|
if p->flags & Kernel::Page::PAYING:
|
||||||
break
|
break
|
||||||
if !p:
|
if !p:
|
||||||
new_flags &= ~Kernel::Page::FRAME
|
dpanic (0, "cannot have frame without payer")
|
||||||
|
page->flags &= ~Kernel::Page::FRAME
|
||||||
// If we can get the new frame, get it.
|
// If we can get the new frame, get it.
|
||||||
if ~old & new_flags & Kernel::Page::FRAME:
|
if ~old & page->flags & Kernel::Page::FRAME:
|
||||||
page->frame = page->address_space->zalloc ()
|
page->frame = page->address_space->zalloc ()
|
||||||
kPage_arch_update_mapping (page)
|
kPage_arch_update_mapping (page)
|
||||||
break
|
break
|
||||||
|
8
iris.hhp
8
iris.hhp
@ -433,9 +433,9 @@ namespace Kernel:
|
|||||||
enum share_detail:
|
enum share_detail:
|
||||||
// Operation details for PAGE_SHARE
|
// Operation details for PAGE_SHARE
|
||||||
// Forget the source page during the operation. This makes it a move.
|
// Forget the source page during the operation. This makes it a move.
|
||||||
FORGET
|
FORGET = 1
|
||||||
// Make the target independent of the source (make a copy if needed).
|
// Make the target independent of the source (make a copy if needed).
|
||||||
COPY
|
COPY = 2
|
||||||
// Make the target unwritable.
|
// Make the target unwritable.
|
||||||
//READONLY: use the value from request.
|
//READONLY: use the value from request.
|
||||||
enum flag_values:
|
enum flag_values:
|
||||||
@ -452,7 +452,7 @@ namespace Kernel:
|
|||||||
// This is a read-only flag, saying if this is uncachable memory.
|
// This is a read-only flag, saying if this is uncachable memory.
|
||||||
UNCACHED = 0x20
|
UNCACHED = 0x20
|
||||||
void share (Cap target, unsigned flags):
|
void share (Cap target, unsigned flags):
|
||||||
ocall (target, CAP_MASTER_DIRECT | SHARE, flags)
|
ocall (target, Kernel::Num (CAP_MASTER_DIRECT | SHARE, flags))
|
||||||
unsigned get_flags ():
|
unsigned get_flags ():
|
||||||
return call (CAP_MASTER_DIRECT | GET_FLAGS).l
|
return call (CAP_MASTER_DIRECT | GET_FLAGS).l
|
||||||
bool set_flags (unsigned new_flags, unsigned mask):
|
bool set_flags (unsigned new_flags, unsigned mask):
|
||||||
@ -587,7 +587,7 @@ Kernel::Num start ()
|
|||||||
#define kdebug(str) do { const char *s = (str); while (*s) { kdebug_char (*s); ++s; } } while (0)
|
#define kdebug(str) do { const char *s = (str); while (*s) { kdebug_char (*s); ++s; } } while (0)
|
||||||
#define __stringify2(x) #x
|
#define __stringify2(x) #x
|
||||||
#define __stringify(x) __stringify2 (x)
|
#define __stringify(x) __stringify2 (x)
|
||||||
#define kdebug_line() do { kdebug (__stringify (__LINE__)); kdebug_char ('\n'); } while (0)
|
#define kdebug_line() do { kdebug (__FILE__ ":"); kdebug (__PRETTY_FUNCTION__); kdebug (":"); kdebug (__stringify (__LINE__)); kdebug_char ('\n'); } while (0)
|
||||||
|
|
||||||
static void kdebug_num (unsigned n, unsigned digits = 8):
|
static void kdebug_num (unsigned n, unsigned digits = 8):
|
||||||
unsigned i
|
unsigned i
|
||||||
|
@ -252,8 +252,8 @@ struct kMemory : public kObject:
|
|||||||
// Functions which can be called from assembly must not be mangled.
|
// Functions which can be called from assembly must not be mangled.
|
||||||
extern "C":
|
extern "C":
|
||||||
// Panic. n is sent over caps led. message is sent to dbg_caps (when in use).
|
// Panic. n is sent over caps led. message is sent to dbg_caps (when in use).
|
||||||
#define panic(n, m) panic_impl ((n), __LINE__, __PRETTY_FUNCTION__, (m))
|
#define panic(n, m) panic_impl ((n), __stringify (__LINE__), __PRETTY_FUNCTION__, (m))
|
||||||
void panic_impl (unsigned n, unsigned line, char const *name, char const *message = "")
|
void panic_impl (unsigned n, char const *line, char const *name, char const *message = "")
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
EXTERN Kernel::Num dbg_code
|
EXTERN Kernel::Num dbg_code
|
||||||
EXTERN kCapRef dbg_cap
|
EXTERN kCapRef dbg_cap
|
||||||
@ -324,6 +324,8 @@ void kCapability::invoke (kCapability::Context *c):
|
|||||||
::invoke (target, protected_data, c)
|
::invoke (target, protected_data, c)
|
||||||
|
|
||||||
#define assert(x) do { if (!(x)) panic (__LINE__, "assertion failed"); } while (0)
|
#define assert(x) do { if (!(x)) panic (__LINE__, "assertion failed"); } while (0)
|
||||||
#define dbg_log_line() do { dbg_log ("debug: "); dbg_log (__PRETTY_FUNCTION__); dbg_log (" line "); dbg_log_num (__LINE__); dbg_log_char ('\n'); } while (0)
|
#define __stringify2(x) #x
|
||||||
|
#define __stringify(x) __stringify2 (x)
|
||||||
|
#define dbg_log_line() do { dbg_log (__FILE__ ":"); dbg_log (__PRETTY_FUNCTION__); dbg_log (":"); dbg_log (__stringify (__LINE__)); dbg_log_char ('\n'); } while (0)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -190,6 +190,7 @@ static void free_page (arch_page_table *t, arch_page *p):
|
|||||||
static unsigned make_entry_lo (kPage *page, bool readonly):
|
static unsigned make_entry_lo (kPage *page, bool readonly):
|
||||||
//dbg_log_line ()
|
//dbg_log_line ()
|
||||||
if !page->frame:
|
if !page->frame:
|
||||||
|
dbg_log ("not mapping because there is no frame\n")
|
||||||
return 0
|
return 0
|
||||||
unsigned flags
|
unsigned flags
|
||||||
if page->flags & Kernel::Page::UNCACHED:
|
if page->flags & Kernel::Page::UNCACHED:
|
||||||
@ -204,7 +205,7 @@ static unsigned make_entry_lo (kPage *page, bool readonly):
|
|||||||
bool kMemory_arch_map (kMemory *mem, kPage *page, unsigned address, bool readonly):
|
bool kMemory_arch_map (kMemory *mem, kPage *page, unsigned address, bool readonly):
|
||||||
//dbg_log_line ()
|
//dbg_log_line ()
|
||||||
if address >= 0x80000000:
|
if address >= 0x80000000:
|
||||||
panic (0x32134293, "trying to map to kernel address")
|
dpanic (address, "trying to map to kernel address")
|
||||||
return false
|
return false
|
||||||
address &= PAGE_MASK
|
address &= PAGE_MASK
|
||||||
if !mem->arch.directory:
|
if !mem->arch.directory:
|
||||||
@ -258,6 +259,9 @@ bool kMemory_arch_map (kMemory *mem, kPage *page, unsigned address, bool readonl
|
|||||||
mem->unmap ((kPage *)table[idx + 0x200], address)
|
mem->unmap ((kPage *)table[idx + 0x200], address)
|
||||||
table[idx] = make_entry_lo (page, readonly)
|
table[idx] = make_entry_lo (page, readonly)
|
||||||
table[idx + 0x200] = (unsigned)p
|
table[idx + 0x200] = (unsigned)p
|
||||||
|
dbg_log ("mapped at address ")
|
||||||
|
dbg_log_num (address)
|
||||||
|
dbg_log_char ('\n')
|
||||||
p->mapping = address + readonly
|
p->mapping = address + readonly
|
||||||
p->page = page
|
p->page = page
|
||||||
p->next_mapped = page->arch.first_mapped
|
p->next_mapped = page->arch.first_mapped
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
#include <elf.h>
|
#include <elf.h>
|
||||||
|
|
||||||
#define NUM_SLOTS 4
|
#define NUM_SLOTS 4
|
||||||
#define NUM_CAPS 16
|
#define NUM_CAPS 32
|
||||||
|
|
||||||
static void init_idle ():
|
static void init_idle ():
|
||||||
// initialize idle task as if it is currently running.
|
// initialize idle task as if it is currently running.
|
||||||
|
@ -31,11 +31,10 @@ 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 metronome lcd
|
programs = nanonote-gpio buzzer metronome lcd
|
||||||
|
|
||||||
all: test $(addsuffix .elf,$(addprefix fs/,$(programs)))
|
all: test
|
||||||
|
|
||||||
test: iris.raw mips/nanonote/server/usb-server mips/nanonote/sdram-setup.raw
|
test: iris.raw mips/nanonote/server/usb-server mips/nanonote/sdram-setup.raw $(addsuffix .elf,$(addprefix fs/,$(programs)))
|
||||||
echo "reboot 0xa$(shell /bin/sh -c '$(OBJDUMP) -t iris.elf | grep __start$$ | cut -b2-8')" | nc localhost 5050
|
echo "reboot 0xa$(shell /bin/sh -c '$(OBJDUMP) -t iris.elf | grep __start$$ | cut -b2-8')" | nc localhost 5050
|
||||||
.PHONY: test
|
|
||||||
|
|
||||||
mips/nanonote/server/usb-server: mips/nanonote/server/usb-server.ccp mips/nanonote/server/Makefile.am mips/nanonote/server/configure.ac
|
mips/nanonote/server/usb-server: mips/nanonote/server/usb-server.ccp mips/nanonote/server/Makefile.am mips/nanonote/server/configure.ac
|
||||||
$(MAKE) -C mips/nanonote/server
|
$(MAKE) -C mips/nanonote/server
|
||||||
@ -59,10 +58,11 @@ mips/init.o: TARGET_FLAGS = -I/usr/include
|
|||||||
boot-programs/init.o: TARGET_FLAGS = -I/usr/include
|
boot-programs/init.o: TARGET_FLAGS = -I/usr/include
|
||||||
$(addsuffix .elf,$(boot_threads)): TARGET_FLAGS = -I.
|
$(addsuffix .elf,$(boot_threads)): TARGET_FLAGS = -I.
|
||||||
$(addsuffix .elf,$(boot_threads)): LDFLAGS = -EL
|
$(addsuffix .elf,$(boot_threads)): LDFLAGS = -EL
|
||||||
|
$(addprefix fs/,$(addsuffix .elf,$(programs))): LDFLAGS = -EL
|
||||||
$(addprefix boot-programs/,$(addsuffix .cc,$(boot_threads))): devices.hh keys.hh
|
$(addprefix boot-programs/,$(addsuffix .cc,$(boot_threads))): devices.hh keys.hh
|
||||||
boot-programs/lcd.o: boot-programs/charset.data
|
source/lcd.o: source/charset.data
|
||||||
|
|
||||||
boot-programs/charset.data: boot-programs/charset
|
source/charset.data: source/charset
|
||||||
$< > $@
|
$< > $@
|
||||||
|
|
||||||
%.o:%.S Makefile Makefile.arch mips/arch.hh
|
%.o:%.S Makefile Makefile.arch mips/arch.hh
|
||||||
@ -78,7 +78,15 @@ server:
|
|||||||
servers:
|
servers:
|
||||||
while : ; do $(MAKE) server ; done
|
while : ; do $(MAKE) server ; done
|
||||||
|
|
||||||
ARCH_CLEAN_FILES = $(boot_sources) $(addsuffix .elf,$(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
|
monitor:
|
||||||
|
stty -F /dev/ttyS0 raw 9600
|
||||||
|
cat /dev/ttyS0
|
||||||
|
|
||||||
|
setup:
|
||||||
|
x-terminal-emulator -e make monitor
|
||||||
|
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
|
||||||
|
|
||||||
.PRECIOUS: mips/arch.hh mips/nanonote/jz4740.hh mips/nanonote/board.hh
|
.PRECIOUS: mips/arch.hh mips/nanonote/jz4740.hh mips/nanonote/board.hh
|
||||||
.PHONY: server
|
.PHONY: test all monitor server servers setup
|
||||||
|
@ -1883,13 +1883,13 @@ void cdelay (unsigned cs):
|
|||||||
#define UDC_TESTMODE REG8 (UDC_BASE + 0x0f) // USB test mode 8-bit
|
#define UDC_TESTMODE REG8 (UDC_BASE + 0x0f) // USB test mode 8-bit
|
||||||
|
|
||||||
#define UDC_CSR0 REG8 (UDC_BASE + 0x12) // EP0 CSR 8-bit
|
#define UDC_CSR0 REG8 (UDC_BASE + 0x12) // EP0 CSR 8-bit
|
||||||
#define UDC_INMAXP(ep) REG16 (UDC_BASE + 0x100 + 0x10 * (ep) + 0x10) // EP1-2 IN Max Pkt Size 16-bit
|
#define UDC_INMAXP REG16 (UDC_BASE + 0x10) // EP1-2 IN Max Pkt Size 16-bit
|
||||||
#define UDC_INCSR(ep) REG16 (UDC_BASE + 0x100 + 0x10 * (ep) + 0x12) // EP1-2 IN CSR LSB 8/16bit
|
#define UDC_INCSR REG16 (UDC_BASE + 0x12) // EP1-2 IN CSR LSB 8/16bit
|
||||||
#define UDC_INCSRH(ep) REG8 (UDC_BASE + 0x100 + 0x10 * (ep) + 0x13) // EP1-2 IN CSR MSB 8-bit
|
#define UDC_INCSRH REG8 (UDC_BASE + 0x13) // EP1-2 IN CSR MSB 8-bit
|
||||||
#define UDC_OUTMAXP(ep) REG16 (UDC_BASE + 0x100 + 0x10 * (ep) + 0x14) // EP1 OUT Max Pkt Size 16-bit
|
#define UDC_OUTMAXP REG16 (UDC_BASE + 0x14) // EP1 OUT Max Pkt Size 16-bit
|
||||||
#define UDC_OUTCSR(ep) REG16 (UDC_BASE + 0x100 + 0x10 * (ep) + 0x16) // EP1 OUT CSR LSB 8/16bit
|
#define UDC_OUTCSR REG16 (UDC_BASE + 0x16) // EP1 OUT CSR LSB 8/16bit
|
||||||
#define UDC_OUTCSRH(ep) REG8 (UDC_BASE + 0x100 + 0x10 * (ep) + 0x17) // EP1 OUT CSR MSB 8-bit
|
#define UDC_OUTCSRH REG8 (UDC_BASE + 0x17) // EP1 OUT CSR MSB 8-bit
|
||||||
#define UDC_OUTCOUNT(ep) REG16 (UDC_BASE + 0x100 + 0x10 * (ep) + 0x18) // bytes in EP0/1 OUT FIFO 16-bit
|
#define UDC_OUTCOUNT REG16 (UDC_BASE + 0x18) // bytes in EP0/1 OUT FIFO 16-bit
|
||||||
|
|
||||||
#define UDC_FIFO(ep) REG32 (UDC_BASE + 0x20 + 4 * (ep))
|
#define UDC_FIFO(ep) REG32 (UDC_BASE + 0x20 + 4 * (ep))
|
||||||
#define UDC_FIFO8(ep) REG8 (UDC_BASE + 0x20 + 4 * (ep))
|
#define UDC_FIFO8(ep) REG8 (UDC_BASE + 0x20 + 4 * (ep))
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include <shevek/server.hh>
|
#include <shevek/server.hh>
|
||||||
#include <shevek/args.hh>
|
#include <shevek/args.hh>
|
||||||
#include <shevek/dir.hh>
|
#include <shevek/dir.hh>
|
||||||
|
#include <shevek/error.hh>
|
||||||
#include "devices.hh"
|
#include "devices.hh"
|
||||||
|
|
||||||
struct client
|
struct client
|
||||||
@ -70,15 +71,15 @@ struct data:
|
|||||||
void get_device (unsigned vendor, unsigned product, unsigned tries)
|
void get_device (unsigned vendor, unsigned product, unsigned tries)
|
||||||
void poll ()
|
void poll ()
|
||||||
|
|
||||||
|
static std::string files ("fs")
|
||||||
struct Name:
|
struct Name:
|
||||||
char name[16]
|
char name[16]
|
||||||
std::string full
|
std::string full
|
||||||
Name (std::string const &n):
|
Name (std::string const &n):
|
||||||
full = n
|
full = files + '/' + n
|
||||||
memset (name, 0, 16)
|
memset (name, 0, 16)
|
||||||
memcpy (name, n.data (), n.size () > 16 ? 16 : n.size ())
|
memcpy (name, n.data (), n.size () > 16 ? 16 : n.size ())
|
||||||
static std::vector <Name> dir
|
static std::vector <Name> dir
|
||||||
static std::string files (".")
|
|
||||||
unsigned lock (0)
|
unsigned lock (0)
|
||||||
|
|
||||||
void data::poll ():
|
void data::poll ():
|
||||||
@ -101,6 +102,12 @@ void data::poll ():
|
|||||||
break
|
break
|
||||||
case Directory::GET_SIZE:
|
case Directory::GET_SIZE:
|
||||||
unsigned long long size = dir.size ()
|
unsigned long long size = dir.size ()
|
||||||
|
std::cerr << "sending dir size\n"
|
||||||
|
std::cerr << Directory::GET_SIZE << '\n'
|
||||||
|
char *str = (char *)&size
|
||||||
|
for unsigned i = 0; i < 8; ++i:
|
||||||
|
std::cerr << " " << (unsigned)(str[i] & 0xff)
|
||||||
|
std::cerr << '\n'
|
||||||
if usb_control_msg (handle, USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, Directory::GET_SIZE, 0, 0, (char *)&size, 8, timeout) != 8:
|
if usb_control_msg (handle, USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, Directory::GET_SIZE, 0, 0, (char *)&size, 8, timeout) != 8:
|
||||||
std::cerr << "unable to send size to device: " << usb_strerror () << std::endl
|
std::cerr << "unable to send size to device: " << usb_strerror () << std::endl
|
||||||
usb_release_interface (handle, 0)
|
usb_release_interface (handle, 0)
|
||||||
@ -115,6 +122,7 @@ void data::poll ():
|
|||||||
usb_close (handle)
|
usb_close (handle)
|
||||||
handle = NULL
|
handle = NULL
|
||||||
return
|
return
|
||||||
|
std::cerr << "sending filename\n"
|
||||||
if usb_control_msg (handle, USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, Directory::GET_NAME, 0, 0, dir[buffer[1]].name, 16, timeout) != 16:
|
if usb_control_msg (handle, USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, Directory::GET_NAME, 0, 0, dir[buffer[1]].name, 16, timeout) != 16:
|
||||||
std::cerr << "unable to send name to device: " << usb_strerror () << std::endl
|
std::cerr << "unable to send name to device: " << usb_strerror () << std::endl
|
||||||
usb_release_interface (handle, 0)
|
usb_release_interface (handle, 0)
|
||||||
@ -123,13 +131,17 @@ void data::poll ():
|
|||||||
return
|
return
|
||||||
continue
|
continue
|
||||||
case Directory::LOCK_RO:
|
case Directory::LOCK_RO:
|
||||||
|
std::cerr << "lock\n"
|
||||||
if !lock++:
|
if !lock++:
|
||||||
|
std::cerr << "freezing file list\n"
|
||||||
shevek::dir d (files)
|
shevek::dir d (files)
|
||||||
dir.clear ()
|
dir.clear ()
|
||||||
for shevek::dir::const_iterator i = d.begin (); i == d.end (); ++i:
|
for shevek::dir::const_iterator i = d.begin (); i != d.end (); ++i:
|
||||||
|
if !i->name.empty () && i->name[0] != '.':
|
||||||
dir.push_back (Name (i->name))
|
dir.push_back (Name (i->name))
|
||||||
continue
|
continue
|
||||||
case Directory::UNLOCK_RO:
|
case Directory::UNLOCK_RO:
|
||||||
|
std::cerr << "unlock\n"
|
||||||
if !lock:
|
if !lock:
|
||||||
std::cerr << "unlocking without lock" << std::endl
|
std::cerr << "unlocking without lock" << std::endl
|
||||||
usb_release_interface (handle, 0)
|
usb_release_interface (handle, 0)
|
||||||
@ -139,19 +151,22 @@ void data::poll ():
|
|||||||
if !--lock:
|
if !--lock:
|
||||||
dir.clear ()
|
dir.clear ()
|
||||||
continue
|
continue
|
||||||
case Directory::GET_FILE_RO:
|
case String::GET_PAGE:
|
||||||
unsigned f = buffer[0] >> 16
|
if buffer[1] >= dir.size ():
|
||||||
if f >= dir.size ():
|
|
||||||
std::cerr << "reading invalid file" << std::endl
|
std::cerr << "reading invalid file" << std::endl
|
||||||
usb_release_interface (handle, 0)
|
usb_release_interface (handle, 0)
|
||||||
usb_close (handle)
|
usb_close (handle)
|
||||||
handle = NULL
|
handle = NULL
|
||||||
return
|
return
|
||||||
std::ifstream file (dir[f].full.c_str ())
|
unsigned pos = buffer[0] >> 16
|
||||||
file.seekg (buffer[1] << 12)
|
std::cerr << "getting data from " << pos << '\n'
|
||||||
|
std::ifstream file (dir[buffer[1]].full.c_str ())
|
||||||
|
file.seekg (pos << 12)
|
||||||
char page[1 << 12]
|
char page[1 << 12]
|
||||||
memset (page, 0, 1 << 12)
|
memset (page, 0, 1 << 12)
|
||||||
file.read (page, 1 << 12)
|
file.read (page, 1 << 12)
|
||||||
|
shevek::dump (std::string (page, 32), std::cerr)
|
||||||
|
std::cerr << "sending bulk\n"
|
||||||
for unsigned i = 0; i < (1 << 12); i += 64:
|
for unsigned i = 0; i < (1 << 12); i += 64:
|
||||||
if usb_bulk_write (handle, 1 | USB_ENDPOINT_OUT, &page[i], 64, timeout) != 64:
|
if usb_bulk_write (handle, 1 | USB_ENDPOINT_OUT, &page[i], 64, timeout) != 64:
|
||||||
std::cerr << "unable to send file to device: " << usb_strerror () << std::endl
|
std::cerr << "unable to send file to device: " << usb_strerror () << std::endl
|
||||||
@ -160,15 +175,33 @@ void data::poll ():
|
|||||||
handle = NULL
|
handle = NULL
|
||||||
return
|
return
|
||||||
continue
|
continue
|
||||||
|
case String::GET_SIZE:
|
||||||
|
if buffer[1] >= dir.size ():
|
||||||
|
std::cerr << "reading invalid file size" << std::endl
|
||||||
|
usb_release_interface (handle, 0)
|
||||||
|
usb_close (handle)
|
||||||
|
handle = NULL
|
||||||
|
return
|
||||||
|
std::ifstream file (dir[buffer[1]].full.c_str ())
|
||||||
|
file.seekg (0, std::ios_base::end)
|
||||||
|
unsigned long long size = file.tellg ()
|
||||||
|
std::cerr << "sending file size " << size << "\n"
|
||||||
|
if usb_control_msg (handle, USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, String::GET_SIZE, 0, 0, (char *)&size, 8, timeout) != 8:
|
||||||
|
std::cerr << "unable to send size to device: " << usb_strerror () << std::endl
|
||||||
|
usb_release_interface (handle, 0)
|
||||||
|
usb_close (handle)
|
||||||
|
handle = NULL
|
||||||
|
return
|
||||||
|
continue
|
||||||
default:
|
default:
|
||||||
std::cerr << "invalid request" << std::endl
|
std::cerr << "invalid request " << buffer[0] << std::endl
|
||||||
usb_release_interface (handle, 0)
|
usb_release_interface (handle, 0)
|
||||||
usb_close (handle)
|
usb_close (handle)
|
||||||
handle = NULL
|
handle = NULL
|
||||||
return
|
return
|
||||||
// If the code reaches this point, break out of the loop. The loop continues if a continue statement is reached.
|
// If the code reaches this point, break out of the loop. The loop continues if a continue statement is reached.
|
||||||
break
|
break
|
||||||
(shevek::absolute_time () + shevek::relative_time (1, 0)).schedule (sigc::mem_fun (*this, &data::poll))
|
(shevek::absolute_time () + shevek::relative_time (0, 100000000)).schedule (sigc::mem_fun (*this, &data::poll))
|
||||||
|
|
||||||
struct client : public shevek::server <client, data *>::connection:
|
struct client : public shevek::server <client, data *>::connection:
|
||||||
static Glib::RefPtr <client> create ():
|
static Glib::RefPtr <client> create ():
|
||||||
@ -225,7 +258,7 @@ void data::get_device (unsigned vendor, unsigned product, unsigned tries):
|
|||||||
usb_close (handle)
|
usb_close (handle)
|
||||||
handle = NULL
|
handle = NULL
|
||||||
continue
|
continue
|
||||||
(shevek::absolute_time () + shevek::relative_time (1, 0)).schedule (sigc::mem_fun (*this, &data::poll))
|
(shevek::absolute_time () + shevek::relative_time (0, 100000000)).schedule (sigc::mem_fun (*this, &data::poll))
|
||||||
return
|
return
|
||||||
if i + 1 < tries:
|
if i + 1 < tries:
|
||||||
//std::cerr << "failed to find device, still trying...\n"
|
//std::cerr << "failed to find device, still trying...\n"
|
||||||
@ -277,6 +310,21 @@ void data::boot (unsigned entry):
|
|||||||
return
|
return
|
||||||
std::cerr << "(re)booted NanoNote\n"
|
std::cerr << "(re)booted NanoNote\n"
|
||||||
|
|
||||||
|
static void dump_devices ():
|
||||||
|
std::cerr << std::hex << "String: " << String::ID
|
||||||
|
std::cerr << "\nWString: " << WString::ID
|
||||||
|
std::cerr << "\nDevice: " << Device::ID
|
||||||
|
std::cerr << "\nParent: " << Parent::ID
|
||||||
|
std::cerr << "\nKeyboard: " << Keyboard::ID
|
||||||
|
std::cerr << "\nBuzzer: " << Buzzer::ID
|
||||||
|
std::cerr << "\nDisplay: " << Display::ID
|
||||||
|
std::cerr << "\nSetting: " << Setting::ID
|
||||||
|
std::cerr << "\nDirectory: " << Directory::ID
|
||||||
|
std::cerr << "\nWDirectory: " << WDirectory::ID
|
||||||
|
std::cerr << "\nFilesystem: " << Filesystem::ID
|
||||||
|
std::cerr << "\nStream: " << Stream::ID
|
||||||
|
std::cerr << "\n"
|
||||||
|
|
||||||
int main (int argc, char **argv):
|
int main (int argc, char **argv):
|
||||||
usb_init ()
|
usb_init ()
|
||||||
std::string port ("5050")
|
std::string port ("5050")
|
||||||
@ -285,5 +333,6 @@ int main (int argc, char **argv):
|
|||||||
}
|
}
|
||||||
shevek::args args (argc, argv, opts, 0, 0, "device server for testing Iris on NanoNote", "2009")
|
shevek::args args (argc, argv, opts, 0, 0, "device server for testing Iris on NanoNote", "2009")
|
||||||
data d (port)
|
data d (port)
|
||||||
|
dump_devices ()
|
||||||
shevek::loop ()
|
shevek::loop ()
|
||||||
return 0
|
return 0
|
||||||
|
@ -45,7 +45,7 @@ void dbg_log_num (unsigned num, unsigned digits):
|
|||||||
return
|
return
|
||||||
|
|
||||||
#if 1 || defined (NDEBUG)
|
#if 1 || defined (NDEBUG)
|
||||||
static void panic_message (unsigned n, unsigned line, char const *name, char const *message):
|
static void panic_message (unsigned n, const char *line, char const *name, char const *message):
|
||||||
dbg_log ("Panic: caller = ")
|
dbg_log ("Panic: caller = ")
|
||||||
if old_current:
|
if old_current:
|
||||||
dbg_log_num (old_current->id, 2)
|
dbg_log_num (old_current->id, 2)
|
||||||
@ -57,7 +57,7 @@ static void panic_message (unsigned n, unsigned line, char const *name, char con
|
|||||||
dbg_log ("; ")
|
dbg_log ("; ")
|
||||||
dbg_log (name)
|
dbg_log (name)
|
||||||
dbg_log_char (':')
|
dbg_log_char (':')
|
||||||
dbg_log_num (line)
|
dbg_log (line)
|
||||||
dbg_log (": ")
|
dbg_log (": ")
|
||||||
dbg_log (message)
|
dbg_log (message)
|
||||||
dbg_log_char ('/')
|
dbg_log_char ('/')
|
||||||
@ -73,7 +73,7 @@ static void panic_message (unsigned n, unsigned line, char const *name, char con
|
|||||||
dbg_log_num (a)
|
dbg_log_num (a)
|
||||||
dbg_log_char ('\n')
|
dbg_log_char ('\n')
|
||||||
|
|
||||||
void panic_impl (unsigned n, unsigned line, char const *name, char const *message):
|
void panic_impl (unsigned n, const char *line, char const *name, char const *message):
|
||||||
// Stop all threads.
|
// Stop all threads.
|
||||||
while first_scheduled:
|
while first_scheduled:
|
||||||
first_scheduled->unrun ()
|
first_scheduled->unrun ()
|
||||||
@ -133,7 +133,7 @@ void dbg_send (unsigned n, unsigned bits):
|
|||||||
delay (50)
|
delay (50)
|
||||||
set_leds (false, false)
|
set_leds (false, false)
|
||||||
delay (50)
|
delay (50)
|
||||||
void panic_impl (unsigned n, unsigned line, char const *name, char const *message):
|
void panic_impl (unsigned n, const char *line, char const *name, char const *message):
|
||||||
unsigned epc
|
unsigned epc
|
||||||
cp0_get (CP0_EPC, epc)
|
cp0_get (CP0_EPC, epc)
|
||||||
dbg_send (epc, 32)
|
dbg_send (epc, 32)
|
||||||
|
@ -38,9 +38,9 @@ namespace Kernel:
|
|||||||
__recv_data_t recv
|
__recv_data_t recv
|
||||||
|
|
||||||
void print_caps ():
|
void print_caps ():
|
||||||
// Assume __caps to be 16.
|
// Assume __caps to be 32.
|
||||||
bool used[16]
|
bool used[32]
|
||||||
for unsigned i = 0; i < 16; ++i:
|
for unsigned i = 0; i < 32; ++i:
|
||||||
used[i] = true
|
used[i] = true
|
||||||
unsigned num = 0
|
unsigned num = 0
|
||||||
for list *i = __first_free_cap; i; i = i->next:
|
for list *i = __first_free_cap; i; i = i->next:
|
||||||
@ -48,7 +48,7 @@ namespace Kernel:
|
|||||||
++num
|
++num
|
||||||
kdebug_num (num, 1)
|
kdebug_num (num, 1)
|
||||||
kdebug (":")
|
kdebug (":")
|
||||||
for unsigned i = 0; i < 16; ++i:
|
for unsigned i = 0; i < 32; ++i:
|
||||||
kdebug_char (used[i] ? '#' : '.')
|
kdebug_char (used[i] ? '#' : '.')
|
||||||
kdebug_char ('\n')
|
kdebug_char ('\n')
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
#define ARCH
|
#define ARCH
|
||||||
#include "arch.hh"
|
#include "arch.hh"
|
||||||
|
|
||||||
__asm__ volatile (".section .rodata\n.globl charset\ncharset:\n.incbin \"boot-programs/charset.data\"\n.section .text")
|
__asm__ volatile (".section .rodata\n.globl charset\ncharset:\n.incbin \"source/charset.data\"\n.section .text")
|
||||||
extern unsigned char const charset[127-32][8][6]
|
extern unsigned char const charset[127-32][8][6]
|
||||||
|
|
||||||
#define assert(x) do { if (!(x)) { kdebug ("assertion failed " #x); while (true) {} } } while (0)
|
#define assert(x) do { if (!(x)) { kdebug ("assertion failed " #x); while (true) {} } } while (0)
|
||||||
|
Loading…
Reference in New Issue
Block a user