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

usb fs mostly working

This commit is contained in:
Bas Wijnen 2010-01-16 16:13:54 +01:00
parent 03e74d38d3
commit 7dc6ecb0ea
16 changed files with 563 additions and 220 deletions

2
.gitignore vendored
View File

@ -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/

View File

@ -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:

View File

@ -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,18 +37,20 @@ 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 char *space = alloc_space (pages)
unsigned pages = ((size - rest) + PAGE_SIZE - 1) & PAGE_MASK for unsigned p = 0; p < pages; ++p:
char *space = alloc_space (pages) Kernel::Page page = Kernel::my_memory.create_page ()
for unsigned p = 0; p < pages; ++p: page.set_flags (Kernel::Page::PAYING | Kernel::Page::FRAME, Kernel::Page::PAYING | Kernel::Page::FRAME)
Kernel::Page page = Kernel::my_memory.create_page () Kernel::my_memory.map (page, (unsigned)&space[p << PAGE_BITS])
page.set_flags (Kernel::Page::PAYING | Kernel::Page::FRAME, Kernel::Page::PAYING | Kernel::Page::FRAME) Kernel::free_cap (page)
Kernel::my_memory.map (page, (unsigned)&space[p << PAGE_BITS])
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

View File

@ -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,53 +213,43 @@ 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: Kernel::panic (0)
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)
return true return true
if s->request == 10: if s->request == 10:
static unsigned b[2] static unsigned b[2]
@ -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,69 +388,165 @@ 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
void Udc::irq_in (unsigned cmd):
// Interrupt on endpoint 0.
unsigned csr = UDC_CSR0
if csr & UDC_CSR0_SENTSTALL:
csr &= ~(UDC_CSR0_SENTSTALL | UDC_CSR0_SENDSTALL)
state = IDLE state = IDLE
return if csr & UDC_CSR0_SETUPEND:
i = UDC_INTRIN csr |= UDC_CSR0_SVDSETUPEND
if i & (1 << 0): state = IDLE
// Interrupt on endpoint 0. switch state:
UDC_INDEX = 0 case IDLE:
unsigned csr = UDC_CSR0 if rebooting:
if csr & UDC_CSR0_SENTSTALL: Kernel::reboot ()
csr &= ~(UDC_CSR0_SENTSTALL | UDC_CSR0_SENDSTALL) if !(csr & UDC_CSR0_OUTPKTRDY):
state = IDLE return
if csr & UDC_CSR0_SETUPEND: union { unsigned d[2]; Setup s; } packet
csr |= UDC_CSR0_SVDSETUPEND packet.d[0] = UDC_FIFO (0)
state = IDLE packet.d[1] = UDC_FIFO (0)
switch state: if !(packet.s.request_type & 0x80) && packet.s.length > 0:
case IDLE: // More data will follow; delay handling of packet.
if rebooting: state = RX
Kernel::reboot () UDC_CSR0 = csr | UDC_CSR0_SVDOUTPKTRDY
if !(csr & UDC_CSR0_OUTPKTRDY): rx_request = packet.s.request
return return
union { unsigned d[2]; Setup s; } packet UDC_CSR0 = csr | UDC_CSR0_DATAEND | UDC_CSR0_SVDOUTPKTRDY
packet.d[0] = UDC_FIFO (0) if !handle_setup (&packet.s, cmd):
packet.d[1] = UDC_FIFO (0) csr |= UDC_CSR0_SENDSTALL
UDC_CSR0 = csr | UDC_CSR0_DATAEND | UDC_CSR0_SVDOUTPKTRDY
if !handle_setup (&packet.s, cmd):
csr |= UDC_CSR0_SENDSTALL
break
if size == 0:
return
// Fall through.
case TX:
unsigned i
for i = 0; (size & ~3) > 0 && i < max_packet_size0; i += 4, size -= 4:
UDC_FIFO (0) = *(unsigned *)ptr
ptr += 4
for ; size > 0 && i < max_packet_size0; ++i, --size:
UDC_FIFO8 (0) = *ptr++
if i == max_packet_size0:
csr |= UDC_CSR0_INPKTRDY
else:
state = IDLE
csr |= UDC_CSR0_INPKTRDY | UDC_CSR0_DATAEND
break break
case RX: if size == 0:
// Not supported. return
csr |= UDC_CSR0_SVDOUTPKTRDY | UDC_CSR0_SENDSTALL // Fall through.
case TX:
unsigned i
for i = 0; (size & ~3) > 0 && i < max_packet_size0; i += 4, size -= 4:
UDC_FIFO (0) = *(unsigned *)ptr
ptr += 4
for ; size > 0 && i < max_packet_size0; ++i, --size:
UDC_FIFO8 (0) = *ptr++
if i == max_packet_size0:
csr |= UDC_CSR0_INPKTRDY
else:
state = IDLE state = IDLE
break csr |= UDC_CSR0_INPKTRDY | UDC_CSR0_DATAEND
UDC_CSR0 = csr break
unsigned i = UDC_INTROUT case RX:
if i & (1 << 1): // The protocol that is used doesn't allow large packets, so being here always means the entire packet is received.
// Interrupt on OUT endpoint 1. switch rx_request & 0xff:
UDC_INDEX = 1 case Directory::GET_SIZE & 0xff:
unsigned csr = UDC_OUTCSR if !have_caller:
if !csr & UDC_CSR_OUTPKTRDY: kdebug ("received dir size from server without a caller waiting\n")
kdebug ("unrecognized interrupt on bulk out ep 1\n") Kernel::panic (0)
return unsigned size_l = UDC_FIFO (0)
for unsigned i = 0; i < 16; ++i: unsigned size_h = UDC_FIFO (0)
*p++ = UDC_FIFO (1) caller.invoke (Kernel::Num (size_l, size_h))
if p - page == PAGE_SIZE: Kernel::free_cap (caller)
// TODO: notify caller; reset buffer. 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
break
UDC_CSR0 = csr
void Udc::irq_out (unsigned cmd):
// Interrupt on OUT endpoint 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
//kdebug ("handling bulk interrupt for ")
//kdebug_num (csr)
//kdebug (" with ")
//kdebug_num (size)
//kdebug (" bytes.\n")
csr &= ~UDC_OUTCSR_OUTPKTRDY
for unsigned i = 0; i < size; i += 4:
*p++ = UDC_FIFO (1)
if p - page == PAGE_SIZE >> 2:
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)

View File

@ -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 &current_user, Kernel::Cap &reply): static void host (unsigned id, unsigned &current_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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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))

View File

@ -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:
dir.push_back (Name (i->name)) if !i->name.empty () && i->name[0] != '.':
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

View File

@ -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)

View File

@ -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')

View File

@ -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)