mirror of
git://projects.qi-hardware.com/iris.git
synced 2024-12-28 12:32:05 +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
|
||||
*.cc
|
||||
*.hh
|
||||
boot-programs/charset.data
|
||||
source/charset.data
|
||||
mips/nanonote/sdram-setup.raw
|
||||
nanonote-boot
|
||||
mips/nanonote/server/.deps/
|
||||
|
@ -38,17 +38,17 @@ namespace Kernel:
|
||||
__recv_data_t recv
|
||||
|
||||
void print_caps ():
|
||||
// Assume __caps to be 16.
|
||||
bool used[16]
|
||||
for unsigned i = 0; i < 16; ++i:
|
||||
// Assume __caps to be 32.
|
||||
bool used[32]
|
||||
for unsigned i = 0; i < 32; ++i:
|
||||
used[i] = true
|
||||
unsigned num = 0
|
||||
for list *i = __first_free_cap; i; i = i->next:
|
||||
used[i - __cap_admin] = false
|
||||
++num
|
||||
kdebug_num (num, 1)
|
||||
kdebug_num (num, 2)
|
||||
kdebug (":")
|
||||
for unsigned i = 0; i < 16; ++i:
|
||||
for unsigned i = 0; i < 32; ++i:
|
||||
kdebug_char (used[i] ? '#' : '.')
|
||||
kdebug_char ('\n')
|
||||
|
||||
@ -77,6 +77,7 @@ namespace Kernel:
|
||||
if !__first_free_slot:
|
||||
// Out of slots... Probably best to raise an exception. For now, just return NO_SLOT.
|
||||
kdebug ("out of slots!\n")
|
||||
Kernel::panic (0)
|
||||
return ~0
|
||||
list *ret = __first_free_slot
|
||||
__first_free_slot = ret->next
|
||||
@ -89,6 +90,7 @@ namespace Kernel:
|
||||
if !__first_free_cap:
|
||||
// Out of caps... Probably best to raise an exception. For now, just return CAP_NONE
|
||||
kdebug ("out of capabilities!\n")
|
||||
Kernel::panic (0)
|
||||
return Cap (0, CAP_NONE)
|
||||
list *ret = __first_free_cap
|
||||
__first_free_cap = ret->next
|
||||
@ -116,7 +118,7 @@ extern "C":
|
||||
Kernel::recv.reply = Kernel::alloc_cap ()
|
||||
Kernel::recv.arg = Kernel::alloc_cap ()
|
||||
Kernel::Num ret = start ()
|
||||
Kernel::my_parent.invoke (~0, ret)
|
||||
Kernel::my_parent.exit (ret)
|
||||
Kernel::my_memory.destroy (Kernel::my_thread)
|
||||
// The program no longer exists. If it somehow does, generate an address fault.
|
||||
while true:
|
||||
|
@ -21,13 +21,13 @@
|
||||
#include <elf.h>
|
||||
|
||||
#define NUM_SLOTS 4
|
||||
#define NUM_CAPS 16
|
||||
#define NUM_CAPS 32
|
||||
|
||||
static unsigned _free
|
||||
extern unsigned _end
|
||||
|
||||
void init_alloc ():
|
||||
_free = _end
|
||||
_free = (unsigned)&_end
|
||||
|
||||
char *alloc_space (unsigned pages):
|
||||
unsigned ret = (_free + PAGE_SIZE - 1) & PAGE_MASK
|
||||
@ -37,18 +37,20 @@ char *alloc_space (unsigned pages):
|
||||
void *operator new[] (unsigned size):
|
||||
void *ret = (void *)_free
|
||||
size = (size + 3) & ~3
|
||||
unsigned rest = PAGE_SIZE - (size & ~PAGE_MASK)
|
||||
if rest <= size:
|
||||
_free += size
|
||||
return ret
|
||||
unsigned pages = ((size - rest) + PAGE_SIZE - 1) & PAGE_MASK
|
||||
char *space = alloc_space (pages)
|
||||
for unsigned p = 0; p < pages; ++p:
|
||||
Kernel::Page page = Kernel::my_memory.create_page ()
|
||||
page.set_flags (Kernel::Page::PAYING | Kernel::Page::FRAME, Kernel::Page::PAYING | Kernel::Page::FRAME)
|
||||
Kernel::my_memory.map (page, (unsigned)&space[p << PAGE_BITS])
|
||||
Kernel::free_cap (page)
|
||||
unsigned rest = PAGE_SIZE - (((_free - 1) & ~PAGE_MASK) + 1)
|
||||
if rest < size:
|
||||
unsigned pages = ((size - rest) + PAGE_SIZE - 1) >> PAGE_BITS
|
||||
char *space = alloc_space (pages)
|
||||
for unsigned p = 0; p < pages; ++p:
|
||||
Kernel::Page page = Kernel::my_memory.create_page ()
|
||||
page.set_flags (Kernel::Page::PAYING | Kernel::Page::FRAME, Kernel::Page::PAYING | Kernel::Page::FRAME)
|
||||
Kernel::my_memory.map (page, (unsigned)&space[p << PAGE_BITS])
|
||||
Kernel::free_cap (page)
|
||||
_free += size
|
||||
//kdebug_num ((unsigned)ret)
|
||||
//kdebug ("+")
|
||||
//kdebug_num (size)
|
||||
//kdebug ("\n")
|
||||
return ret
|
||||
|
||||
struct file:
|
||||
@ -72,8 +74,8 @@ static Directory receive_devices ():
|
||||
String data
|
||||
Filesystem fs
|
||||
bool have_data = false, have_fs = false
|
||||
Device fs_dev, data_dev
|
||||
for unsigned i = 0; i < 2; ++i:
|
||||
Device dev
|
||||
Kernel::wait ()
|
||||
if Kernel::recv.data[0].l != Parent::PROVIDE_DEVICE:
|
||||
kdebug ("Invalid bootstrap request.\n")
|
||||
@ -83,23 +85,17 @@ static Directory receive_devices ():
|
||||
if have_data:
|
||||
kdebug ("duplicate device.\n")
|
||||
Kernel::panic (0)
|
||||
dev = Kernel::get_arg ()
|
||||
have_data = true
|
||||
data_dev = Kernel::get_arg ()
|
||||
Kernel::recv.reply.invoke ()
|
||||
data = dev.create_user (Kernel::my_memory)
|
||||
dev.use (data)
|
||||
Kernel::free_cap (dev)
|
||||
have_data = true
|
||||
break
|
||||
case Filesystem::ID:
|
||||
if have_fs:
|
||||
kdebug ("duplicate filesystem.\n")
|
||||
Kernel::panic (0)
|
||||
dev = Kernel::get_arg ()
|
||||
have_fs = true
|
||||
fs = dev.create_user (Kernel::my_memory)
|
||||
dev.use (fs)
|
||||
Kernel::free_cap (dev)
|
||||
fs_dev = Kernel::get_arg ()
|
||||
Kernel::recv.reply.invoke ()
|
||||
have_fs = true
|
||||
break
|
||||
default:
|
||||
kdebug ("unexpected device: ")
|
||||
@ -107,35 +103,58 @@ static Directory receive_devices ():
|
||||
kdebug_char ('\n')
|
||||
Kernel::panic (0)
|
||||
// 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 ())
|
||||
Kernel::free_cap (data)
|
||||
Kernel::free_cap (fs)
|
||||
Kernel::free_cap (data_dev)
|
||||
Kernel::free_cap (fs_dev)
|
||||
return root
|
||||
|
||||
// Make a list of all files.
|
||||
static void list_files (Directory root):
|
||||
Kernel::Num fullsize = root.get_size ()
|
||||
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)
|
||||
num_files = fullsize.l
|
||||
kdebug ("files in directory: ")
|
||||
kdebug_num (num_files)
|
||||
kdebug ("\n")
|
||||
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 ()
|
||||
caps.use (slot)
|
||||
Kernel::free_cap (caps)
|
||||
for unsigned i = 0; i < num_files; ++i:
|
||||
Kernel::set_recv_arg (Kernel::Cap (slot, i * 2))
|
||||
String n = root.get_name (i)
|
||||
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)
|
||||
Kernel::Num fullsize = files[i].string.get_size ()
|
||||
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)
|
||||
files[i].size = fullsize.l
|
||||
if max_pages < (fullsize.l + PAGE_SIZE - 1) & PAGE_MASK:
|
||||
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_BITS
|
||||
|
||||
// Sort the list of files.
|
||||
static bool is_less (file *f1, file *f2):
|
||||
@ -163,11 +182,17 @@ static void sort ():
|
||||
|
||||
static void run (file *f, bool priv):
|
||||
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:
|
||||
kdebug_num (p)
|
||||
kdebug ("/")
|
||||
kdebug_num (num_pages)
|
||||
kdebug ("\n")
|
||||
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))
|
||||
kdebug_line ()
|
||||
Kernel::my_memory.map (Kernel::Cap (slot, p), (unsigned)&mapping[p << PAGE_BITS])
|
||||
Kernel::Thread thread = mem.create_thread (NUM_SLOTS)
|
||||
if priv:
|
||||
@ -179,7 +204,11 @@ static void run (file *f, bool priv):
|
||||
Kernel::panic (0)
|
||||
return
|
||||
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)
|
||||
return
|
||||
if header->e_ident[EI_DATA] != ELFDATA2LSB:
|
||||
@ -200,18 +229,24 @@ static void run (file *f, bool priv):
|
||||
return
|
||||
thread.set_pc (header->e_entry)
|
||||
thread.set_sp (0x80000000)
|
||||
kdebug_line ()
|
||||
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)
|
||||
if ~shdr->sh_flags & SHF_ALLOC:
|
||||
continue
|
||||
kdebug_line ()
|
||||
bool readonly = !(shdr->sh_flags & SHF_WRITE)
|
||||
//bool executable = shdr->sh_flags & SHF_EXEC_INSTR
|
||||
kdebug_line ()
|
||||
if shdr->sh_type != SHT_NOBITS:
|
||||
kdebug_line ()
|
||||
unsigned file_offset = shdr->sh_offset >> PAGE_BITS
|
||||
if (file_offset + ((shdr->sh_size + PAGE_SIZE - 1) >> PAGE_BITS)) >= (PAGE_SIZE >> 2):
|
||||
kdebug ("thread too large\n")
|
||||
Kernel::panic (0)
|
||||
return
|
||||
kdebug_line ()
|
||||
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 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.
|
||||
Kernel::free_cap (page)
|
||||
continue
|
||||
Kernel::free_cap (page)
|
||||
page = mem.create_page ()
|
||||
page.set_flags (Kernel::Page::PAYING, Kernel::Page::PAYING)
|
||||
Kernel::Page (slot, idx).share (page, 0)
|
||||
kdebug ("mapping at ")
|
||||
kdebug_num (p)
|
||||
kdebug ("\n")
|
||||
if !mem.map (page, p, readonly):
|
||||
kdebug ("unable to map page\n")
|
||||
Kernel::panic (0)
|
||||
return
|
||||
Kernel::free_cap (page)
|
||||
kdebug_line ()
|
||||
else:
|
||||
kdebug_line ()
|
||||
if readonly:
|
||||
kdebug ("unwritable bss section\n")
|
||||
Kernel::panic (0)
|
||||
return
|
||||
kdebug_line ()
|
||||
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)
|
||||
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 ()
|
||||
if Kernel::recv.data[0].l != Kernel::NO_ERROR:
|
||||
kdebug ("out of memory\n")
|
||||
@ -250,56 +302,103 @@ static void run (file *f, bool priv):
|
||||
Kernel::panic (0)
|
||||
return
|
||||
Kernel::free_cap (page)
|
||||
else:
|
||||
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])[(a & ~PAGE_MASK) >> 2] = 0
|
||||
kdebug_line ()
|
||||
kdebug_line ()
|
||||
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 ()
|
||||
kdebug_line ()
|
||||
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):
|
||||
kdebug ("unable to map initial stack page\n")
|
||||
Kernel::panic (0)
|
||||
return
|
||||
kdebug_line ()
|
||||
Kernel::free_cap (stackpage)
|
||||
Kernel::Caps caps = mem.create_caps (NUM_CAPS)
|
||||
kdebug_line ()
|
||||
thread.use (caps, 0)
|
||||
thread.set_info (Kernel::Thread::A0, NUM_SLOTS)
|
||||
thread.set_info (Kernel::Thread::A1, NUM_CAPS)
|
||||
kdebug_line ()
|
||||
Kernel::Receiver receiver = mem.create_receiver ()
|
||||
receiver.set_owner (thread.copy ())
|
||||
Kernel::Cap call = receiver.create_call_capability ()
|
||||
Kernel::Cap parent = Kernel::my_receiver.create_capability (++current_thread)
|
||||
kdebug_line ()
|
||||
caps.set (__receiver_num, receiver.copy ())
|
||||
caps.set (__thread_num, thread.copy ())
|
||||
caps.set (__memory_num, mem.copy ())
|
||||
caps.set (__call_num, call.copy ())
|
||||
caps.set (__parent_num, parent.copy ())
|
||||
kdebug_line ()
|
||||
thread.run ()
|
||||
kdebug_line ()
|
||||
Kernel::free_cap (receiver)
|
||||
Kernel::free_cap (thread)
|
||||
Kernel::free_cap (mem)
|
||||
Kernel::free_cap (call)
|
||||
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 ():
|
||||
// Wait for the debugging device to be active, in case there is one.
|
||||
Kernel::schedule ()
|
||||
init_alloc ()
|
||||
dump_devices ()
|
||||
top_memory = Kernel::get_top_memory ()
|
||||
Directory root = receive_devices ()
|
||||
root.lock_ro ()
|
||||
kdebug_line ()
|
||||
list_files (root)
|
||||
kdebug_line ()
|
||||
sort ()
|
||||
kdebug_line ()
|
||||
Kernel::Caps caps = Kernel::my_memory.create_caps (max_pages)
|
||||
kdebug ("max pages: ")
|
||||
kdebug_num (max_pages)
|
||||
kdebug ("\n")
|
||||
slot = caps.use ()
|
||||
mapping = alloc_space (max_pages)
|
||||
for unsigned i = 0; i < num_files; ++i:
|
||||
kdebug_line ()
|
||||
run (&files[index[i]], files[index[i]].name[0] == '#')
|
||||
kdebug_line ()
|
||||
kdebug_line ()
|
||||
root.unlock_ro ()
|
||||
kdebug_line ()
|
||||
Kernel::free_slot (slot)
|
||||
kdebug_line ()
|
||||
Kernel::my_memory.destroy (caps)
|
||||
kdebug_line ()
|
||||
return 0
|
||||
|
@ -108,7 +108,7 @@ class Udc:
|
||||
u16 data[size];
|
||||
} __attribute__ ((packed))
|
||||
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:
|
||||
GET_STATUS = 0
|
||||
CLEAR_FEATURE = 1
|
||||
@ -149,28 +149,29 @@ class Udc:
|
||||
State state
|
||||
char configuration
|
||||
unsigned size
|
||||
unsigned rx_request
|
||||
char const *ptr
|
||||
unsigned cmd_code, cmd_arg
|
||||
bool rebooting
|
||||
bool vendor (Setup *s, unsigned cmd)
|
||||
bool get_descriptor (unsigned type, unsigned idx, unsigned len)
|
||||
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]
|
||||
unsigned log_buffer_size
|
||||
unsigned log_buffer_start
|
||||
Kernel::Cap caller
|
||||
Kernel::Cap caller, caller_arg
|
||||
bool have_caller
|
||||
unsigned *page
|
||||
unsigned *p
|
||||
Kernel::Page buffer_page
|
||||
public:
|
||||
void init ()
|
||||
void log (unsigned c)
|
||||
void interrupt (unsigned cmd)
|
||||
void send (unsigned code, unsigned arg)
|
||||
void set_caller (Kernel::Cap c):
|
||||
if have_caller:
|
||||
kdebug ("set_caller double-called\n")
|
||||
Kernel::panic (0)
|
||||
caller = c
|
||||
have_caller = true
|
||||
void send (unsigned code, unsigned narg, Kernel::Cap reply, Kernel::Cap arg)
|
||||
|
||||
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 = {
|
||||
@ -212,53 +213,43 @@ void Udc::init ():
|
||||
cmd_code = ~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.
|
||||
UDC_POWER &= ~(UDC_POWER_SOFTCONN | UDC_POWER_HSENAB)
|
||||
UDC_POWER = 0
|
||||
UDC_TESTMODE = 0
|
||||
UDC_INDEX = 0
|
||||
state = IDLE
|
||||
configuration = 0
|
||||
size = 0
|
||||
// exit suspend mode by reading the interrupt register.
|
||||
cpm_start_udc ()
|
||||
unsigned i = UDC_INTRUSB
|
||||
// reset all pending endpoint interrupts.
|
||||
unsigned i = UDC_INTRUSB
|
||||
i = UDC_INTRIN
|
||||
i = UDC_INTROUT
|
||||
// enable interrupt on bus reset.
|
||||
UDC_INTRUSB = UDC_INTR_RESET
|
||||
UDC_INTRUSBE = UDC_INTR_RESET
|
||||
// enable interrupts on endpoint 0.
|
||||
UDC_INTRINE |= 1 << 0
|
||||
UDC_INDEX = 0
|
||||
UDC_INTRINE = 1 << 0
|
||||
// and on out endpoint 1.
|
||||
UDC_INTROUTE = 1 << 1
|
||||
// Wait a while.
|
||||
for unsigned w = 0; w < 10000; ++w:
|
||||
Kernel::schedule ()
|
||||
// Connect to the host.
|
||||
UDC_POWER |= UDC_POWER_SOFTCONN
|
||||
UDC_POWER = UDC_POWER_SOFTCONN
|
||||
|
||||
bool Udc::vendor (Setup *s, unsigned cmd):
|
||||
if !(s->request_type & 0x80):
|
||||
switch s->request:
|
||||
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)
|
||||
kdebug ("data to device without size\n")
|
||||
Kernel::panic (0)
|
||||
return true
|
||||
if s->request == 10:
|
||||
static unsigned b[2]
|
||||
@ -267,6 +258,12 @@ bool Udc::vendor (Setup *s, unsigned cmd):
|
||||
if cmd_code != ~0:
|
||||
b[0] = cmd_code
|
||||
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
|
||||
else:
|
||||
if log_buffer_start == log_buffer_size:
|
||||
@ -286,12 +283,15 @@ bool Udc::vendor (Setup *s, unsigned cmd):
|
||||
state = TX
|
||||
return true
|
||||
|
||||
void Udc::send (unsigned code, unsigned arg):
|
||||
if code != ~0:
|
||||
void Udc::send (unsigned code, unsigned narg, Kernel::Cap reply, Kernel::Cap arg):
|
||||
if cmd_code != ~0:
|
||||
kdebug ("new code sent while old one wasn't finished.\n")
|
||||
Kernel::panic (0)
|
||||
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):
|
||||
switch type:
|
||||
@ -355,6 +355,9 @@ bool Udc::handle_setup (Setup *s, unsigned cmd):
|
||||
break
|
||||
default:
|
||||
return false
|
||||
UDC_OUTMAXP = 64
|
||||
UDC_OUTCSR = UDC_OUTCSR_CDT | UDC_OUTCSR_FF
|
||||
UDC_OUTCSR = UDC_OUTCSR_CDT | UDC_OUTCSR_FF
|
||||
break
|
||||
case STANDARD_FROM_DEVICE:
|
||||
switch s->request:
|
||||
@ -385,69 +388,165 @@ bool Udc::handle_setup (Setup *s, unsigned cmd):
|
||||
return false
|
||||
return true
|
||||
|
||||
void Udc::interrupt (unsigned cmd):
|
||||
unsigned i = UDC_INTRUSB
|
||||
if i & UDC_INTR_RESET:
|
||||
void Udc::irq_usb (unsigned cmd):
|
||||
// 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
|
||||
return
|
||||
i = UDC_INTRIN
|
||||
if i & (1 << 0):
|
||||
// Interrupt on endpoint 0.
|
||||
UDC_INDEX = 0
|
||||
unsigned csr = UDC_CSR0
|
||||
if csr & UDC_CSR0_SENTSTALL:
|
||||
csr &= ~(UDC_CSR0_SENTSTALL | UDC_CSR0_SENDSTALL)
|
||||
state = IDLE
|
||||
if csr & UDC_CSR0_SETUPEND:
|
||||
csr |= UDC_CSR0_SVDSETUPEND
|
||||
state = IDLE
|
||||
switch state:
|
||||
case IDLE:
|
||||
if rebooting:
|
||||
Kernel::reboot ()
|
||||
if !(csr & UDC_CSR0_OUTPKTRDY):
|
||||
return
|
||||
union { unsigned d[2]; Setup s; } packet
|
||||
packet.d[0] = UDC_FIFO (0)
|
||||
packet.d[1] = UDC_FIFO (0)
|
||||
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
|
||||
if csr & UDC_CSR0_SETUPEND:
|
||||
csr |= UDC_CSR0_SVDSETUPEND
|
||||
state = IDLE
|
||||
switch state:
|
||||
case IDLE:
|
||||
if rebooting:
|
||||
Kernel::reboot ()
|
||||
if !(csr & UDC_CSR0_OUTPKTRDY):
|
||||
return
|
||||
union { unsigned d[2]; Setup s; } packet
|
||||
packet.d[0] = 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
|
||||
if !handle_setup (&packet.s, cmd):
|
||||
csr |= UDC_CSR0_SENDSTALL
|
||||
break
|
||||
case RX:
|
||||
// Not supported.
|
||||
csr |= UDC_CSR0_SVDOUTPKTRDY | UDC_CSR0_SENDSTALL
|
||||
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
|
||||
break
|
||||
UDC_CSR0 = csr
|
||||
unsigned i = UDC_INTROUT
|
||||
if i & (1 << 1):
|
||||
// Interrupt on OUT endpoint 1.
|
||||
UDC_INDEX = 1
|
||||
unsigned csr = UDC_OUTCSR
|
||||
if !csr & UDC_CSR_OUTPKTRDY:
|
||||
kdebug ("unrecognized interrupt on bulk out ep 1\n")
|
||||
return
|
||||
for unsigned i = 0; i < 16; ++i:
|
||||
*p++ = UDC_FIFO (1)
|
||||
if p - page == PAGE_SIZE:
|
||||
// TODO: notify caller; reset buffer.
|
||||
csr |= UDC_CSR0_INPKTRDY | UDC_CSR0_DATAEND
|
||||
break
|
||||
case RX:
|
||||
// The protocol that is used doesn't allow large packets, so being here always means the entire packet is received.
|
||||
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
|
||||
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):
|
||||
if log_buffer_size >= sizeof (log_buffer):
|
||||
@ -459,6 +558,8 @@ enum pdata:
|
||||
FS
|
||||
DATA
|
||||
DIRECTORY
|
||||
FILE
|
||||
NAME
|
||||
|
||||
Kernel::Num start ():
|
||||
map_udc ()
|
||||
@ -466,18 +567,23 @@ Kernel::Num start ():
|
||||
map_cpm ()
|
||||
Udc udc
|
||||
|
||||
Kernel::Cap logcap = Kernel::my_receiver.create_capability (LOG)
|
||||
__asm__ volatile ("li $a0, 1\nlw $a1, %0\nbreak" :: "m"(logcap.code): "a0", "a1", "memory")
|
||||
//Kernel::Cap logcap = Kernel::my_receiver.create_capability (LOG)
|
||||
//__asm__ volatile ("li $a0, 1\nlw $a1, %0\nbreak" :: "m"(logcap.code): "a0", "a1", "memory")
|
||||
udc.init ()
|
||||
Kernel::register_interrupt (IRQ_UDC)
|
||||
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 next_user
|
||||
unsigned state = 0
|
||||
while true:
|
||||
Kernel::wait ()
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
Kernel::Cap arg = Kernel::get_arg ()
|
||||
switch Kernel::recv.protected_data.h:
|
||||
case 0:
|
||||
switch Kernel::recv.protected_data.l:
|
||||
@ -489,10 +595,10 @@ Kernel::Num start ():
|
||||
udc.log (Kernel::recv.data[0].l)
|
||||
break
|
||||
case FS:
|
||||
Device::host (FS, fs_current_user, reply)
|
||||
Device::host (FS, fs_current_user, reply, arg)
|
||||
continue
|
||||
case DATA:
|
||||
Device::host (DATA, data_current_user, reply)
|
||||
Device::host (DATA, data_current_user, reply, arg)
|
||||
continue
|
||||
default:
|
||||
udc.log ('~')
|
||||
@ -501,19 +607,22 @@ Kernel::Num start ():
|
||||
udc.log (digit[(Kernel::recv.protected_data.l >> (4 * (7 - i))) & 0xf])
|
||||
udc.log ('\n')
|
||||
break
|
||||
break
|
||||
case DATA:
|
||||
if data_current_user != Kernel::recv.protected_data.l:
|
||||
break
|
||||
switch Kernel::recv.data[0].l:
|
||||
case String::GET_SIZE:
|
||||
case String::GET_CHARS:
|
||||
case ::String::GET_SIZE:
|
||||
case ::String::GET_CHARS:
|
||||
reply.invoke (0)
|
||||
Kernel::free_cap (reply)
|
||||
Kernel::free_cap (arg)
|
||||
continue
|
||||
case String::GET_PAGE:
|
||||
case ::String::GET_PAGE:
|
||||
default:
|
||||
reply.invoke (Kernel::ERR_INVALID_OPERATION)
|
||||
Kernel::free_cap (reply)
|
||||
Kernel::free_cap (arg)
|
||||
continue
|
||||
break
|
||||
case FS:
|
||||
@ -526,30 +635,79 @@ Kernel::Num start ():
|
||||
reply.invoke (0, 0, dir.copy ())
|
||||
Kernel::free_cap (dir)
|
||||
Kernel::free_cap (reply)
|
||||
Kernel::free_cap (arg)
|
||||
continue
|
||||
default:
|
||||
reply.invoke (Kernel::ERR_INVALID_OPERATION)
|
||||
Kernel::free_cap (reply)
|
||||
Kernel::free_cap (arg)
|
||||
continue
|
||||
break
|
||||
case DIRECTORY:
|
||||
switch Kernel::recv.data[0].l:
|
||||
case Directory::GET_SIZE:
|
||||
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::UNLOCK_RO:
|
||||
state = Kernel::recv.data[0].l
|
||||
if Kernel::recv.data[1].h != 0:
|
||||
kdebug ("index out of supported range\n")
|
||||
Kernel::panic (0)
|
||||
udc.send (Kernel::recv.data[0].l, Kernel::recv.data[1].l)
|
||||
Kernel::free_cap (reply)
|
||||
udc.send (Kernel::recv.data[0].l, Kernel::recv.data[1].l, reply, arg)
|
||||
continue
|
||||
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:
|
||||
default:
|
||||
reply.invoke (Kernel::ERR_INVALID_OPERATION)
|
||||
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
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (reply)
|
||||
Kernel::free_cap (arg)
|
||||
|
@ -99,7 +99,7 @@ struct Device : public Kernel::Cap:
|
||||
void use (Kernel::Cap user):
|
||||
ocall (user, CAP_MASTER_DIRECT | USE)
|
||||
// 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
|
||||
switch Kernel::recv.data[0].l:
|
||||
case Device::CREATE_USER:
|
||||
@ -111,20 +111,20 @@ struct Device : public Kernel::Cap:
|
||||
reply.invoke (0, 0, c.copy ())
|
||||
Kernel::free_cap (c)
|
||||
Kernel::free_cap (reply)
|
||||
Kernel::free_cap (arg)
|
||||
break
|
||||
case Device::DESTROY_USER:
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (reply)
|
||||
Kernel::free_cap (arg)
|
||||
break
|
||||
case Device::USE:
|
||||
Kernel::Cap arg = Kernel::get_arg ()
|
||||
current_user = Kernel::my_receiver.get_protected (arg).l
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (reply)
|
||||
Kernel::free_cap (arg)
|
||||
break
|
||||
case Device::UNUSE:
|
||||
Kernel::Cap arg = Kernel::get_arg ()
|
||||
Kernel::Num p = Kernel::my_receiver.get_protected (arg)
|
||||
if p.h == id && current_user == p.l:
|
||||
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
|
||||
case Kernel::Receiver::GET_PROTECTED & REQUEST_MASK:
|
||||
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")
|
||||
reply_num (Kernel::ERR_INVALID_ARGUMENT)
|
||||
return
|
||||
@ -289,6 +299,7 @@ static void memory_invoke (unsigned cmd, unsigned target, Kernel::Num protected_
|
||||
kPage *ret = mem->alloc_page ()
|
||||
if ret:
|
||||
reply_cap (CAPTYPE_PAGE | CAP_MASTER, (unsigned)ret, &ret->refs)
|
||||
dbg_log ("page created\n")
|
||||
else:
|
||||
dpanic (0x33311992, "out of memory creating page")
|
||||
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:
|
||||
if !c->arg.valid ():
|
||||
// Cannot share without a target page.
|
||||
dpanic (0, "no target page for share")
|
||||
reply_num (Kernel::ERR_INVALID_ARGUMENT)
|
||||
return
|
||||
if ((unsigned)c->arg->target & ~REQUEST_MASK) != CAPTYPE_PAGE:
|
||||
// FIXME: This makes it impossible to use a fake kPage capability.
|
||||
dpanic (0, "share target is no page")
|
||||
reply_num (Kernel::ERR_INVALID_ARGUMENT)
|
||||
return
|
||||
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:
|
||||
t->flags |= Kernel::Page::READONLY
|
||||
if !(page->flags & Kernel::Page::FRAME):
|
||||
dpanic (0, "sharing nothing results in lost page")
|
||||
break
|
||||
if c->data[0].h & Kernel::Page::COPY:
|
||||
if ~t->flags & Kernel::Page::PAYING:
|
||||
@ -606,7 +620,7 @@ static void page_invoke (unsigned cmd, unsigned target, Kernel::Num protected_da
|
||||
else:
|
||||
t->flags |= Kernel::Page::FRAME
|
||||
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]
|
||||
else:
|
||||
if t != page:
|
||||
@ -618,6 +632,7 @@ static void page_invoke (unsigned cmd, unsigned target, Kernel::Num protected_da
|
||||
kPage_arch_update_mapping (t)
|
||||
else:
|
||||
if t == page:
|
||||
dpanic (0, "sharing page with itself")
|
||||
break
|
||||
if c->data[0].h & Kernel::Page::FORGET:
|
||||
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
|
||||
if t->share_prev:
|
||||
t->share_prev->share_next = t
|
||||
t->frame = page->frame
|
||||
t->flags |= Kernel::Page::FRAME
|
||||
kPage_arch_update_mapping (t)
|
||||
break
|
||||
case Kernel::Page::SET_FLAGS & REQUEST_MASK:
|
||||
if cmd & Kernel::Page::READONLY:
|
||||
dpanic (0, "setting page flags denied")
|
||||
reply_num (Kernel::ERR_WRITE_DENIED)
|
||||
return
|
||||
// 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.
|
||||
unsigned old = page->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 ~new_flags & old & Kernel::Page::PAYING:
|
||||
if ~page->flags & old & Kernel::Page::PAYING:
|
||||
// Decrease the use counter in any case.
|
||||
page->address_space->unuse ()
|
||||
if !page_check_payment (page):
|
||||
new_flags &= ~Kernel::Page::FRAME
|
||||
page->flags &= ~Kernel::Page::FRAME
|
||||
|
||||
// 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():
|
||||
dpanic (0, "cannot pay for 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:
|
||||
new_flags |= Kernel::Page::FRAME
|
||||
page->flags |= Kernel::Page::FRAME
|
||||
|
||||
// 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
|
||||
for p = page; p; p = p->share_prev:
|
||||
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:
|
||||
break
|
||||
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 ~old & new_flags & Kernel::Page::FRAME:
|
||||
if ~old & page->flags & Kernel::Page::FRAME:
|
||||
page->frame = page->address_space->zalloc ()
|
||||
kPage_arch_update_mapping (page)
|
||||
break
|
||||
|
8
iris.hhp
8
iris.hhp
@ -433,9 +433,9 @@ namespace Kernel:
|
||||
enum share_detail:
|
||||
// Operation details for PAGE_SHARE
|
||||
// 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).
|
||||
COPY
|
||||
COPY = 2
|
||||
// Make the target unwritable.
|
||||
//READONLY: use the value from request.
|
||||
enum flag_values:
|
||||
@ -452,7 +452,7 @@ namespace Kernel:
|
||||
// This is a read-only flag, saying if this is uncachable memory.
|
||||
UNCACHED = 0x20
|
||||
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 ():
|
||||
return call (CAP_MASTER_DIRECT | GET_FLAGS).l
|
||||
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 __stringify2(x) #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):
|
||||
unsigned i
|
||||
|
@ -252,8 +252,8 @@ struct kMemory : public kObject:
|
||||
// Functions which can be called from assembly must not be mangled.
|
||||
extern "C":
|
||||
// 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))
|
||||
void panic_impl (unsigned n, unsigned line, char const *name, char const *message = "")
|
||||
#define panic(n, m) panic_impl ((n), __stringify (__LINE__), __PRETTY_FUNCTION__, (m))
|
||||
void panic_impl (unsigned n, char const *line, char const *name, char const *message = "")
|
||||
#ifndef NDEBUG
|
||||
EXTERN Kernel::Num dbg_code
|
||||
EXTERN kCapRef dbg_cap
|
||||
@ -324,6 +324,8 @@ void kCapability::invoke (kCapability::Context *c):
|
||||
::invoke (target, protected_data, c)
|
||||
|
||||
#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
|
||||
|
@ -190,6 +190,7 @@ static void free_page (arch_page_table *t, arch_page *p):
|
||||
static unsigned make_entry_lo (kPage *page, bool readonly):
|
||||
//dbg_log_line ()
|
||||
if !page->frame:
|
||||
dbg_log ("not mapping because there is no frame\n")
|
||||
return 0
|
||||
unsigned flags
|
||||
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):
|
||||
//dbg_log_line ()
|
||||
if address >= 0x80000000:
|
||||
panic (0x32134293, "trying to map to kernel address")
|
||||
dpanic (address, "trying to map to kernel address")
|
||||
return false
|
||||
address &= PAGE_MASK
|
||||
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)
|
||||
table[idx] = make_entry_lo (page, readonly)
|
||||
table[idx + 0x200] = (unsigned)p
|
||||
dbg_log ("mapped at address ")
|
||||
dbg_log_num (address)
|
||||
dbg_log_char ('\n')
|
||||
p->mapping = address + readonly
|
||||
p->page = page
|
||||
p->next_mapped = page->arch.first_mapped
|
||||
|
@ -23,7 +23,7 @@
|
||||
#include <elf.h>
|
||||
|
||||
#define NUM_SLOTS 4
|
||||
#define NUM_CAPS 16
|
||||
#define NUM_CAPS 32
|
||||
|
||||
static void init_idle ():
|
||||
// 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
|
||||
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
|
||||
.PHONY: test
|
||||
|
||||
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
|
||||
@ -59,10 +58,11 @@ mips/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)): LDFLAGS = -EL
|
||||
$(addprefix fs/,$(addsuffix .elf,$(programs))): LDFLAGS = -EL
|
||||
$(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
|
||||
@ -78,7 +78,15 @@ server:
|
||||
servers:
|
||||
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
|
||||
.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_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_INCSR(ep) REG16 (UDC_BASE + 0x100 + 0x10 * (ep) + 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_OUTMAXP(ep) REG16 (UDC_BASE + 0x100 + 0x10 * (ep) + 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_OUTCSRH(ep) REG8 (UDC_BASE + 0x100 + 0x10 * (ep) + 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_INMAXP REG16 (UDC_BASE + 0x10) // EP1-2 IN Max Pkt Size 16-bit
|
||||
#define UDC_INCSR REG16 (UDC_BASE + 0x12) // EP1-2 IN CSR LSB 8/16bit
|
||||
#define UDC_INCSRH REG8 (UDC_BASE + 0x13) // EP1-2 IN CSR MSB 8-bit
|
||||
#define UDC_OUTMAXP REG16 (UDC_BASE + 0x14) // EP1 OUT Max Pkt Size 16-bit
|
||||
#define UDC_OUTCSR REG16 (UDC_BASE + 0x16) // EP1 OUT CSR LSB 8/16bit
|
||||
#define UDC_OUTCSRH REG8 (UDC_BASE + 0x17) // EP1 OUT CSR MSB 8-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_FIFO8(ep) REG8 (UDC_BASE + 0x20 + 4 * (ep))
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <shevek/server.hh>
|
||||
#include <shevek/args.hh>
|
||||
#include <shevek/dir.hh>
|
||||
#include <shevek/error.hh>
|
||||
#include "devices.hh"
|
||||
|
||||
struct client
|
||||
@ -70,15 +71,15 @@ struct data:
|
||||
void get_device (unsigned vendor, unsigned product, unsigned tries)
|
||||
void poll ()
|
||||
|
||||
static std::string files ("fs")
|
||||
struct Name:
|
||||
char name[16]
|
||||
std::string full
|
||||
Name (std::string const &n):
|
||||
full = n
|
||||
full = files + '/' + n
|
||||
memset (name, 0, 16)
|
||||
memcpy (name, n.data (), n.size () > 16 ? 16 : n.size ())
|
||||
static std::vector <Name> dir
|
||||
static std::string files (".")
|
||||
unsigned lock (0)
|
||||
|
||||
void data::poll ():
|
||||
@ -101,6 +102,12 @@ void data::poll ():
|
||||
break
|
||||
case Directory::GET_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:
|
||||
std::cerr << "unable to send size to device: " << usb_strerror () << std::endl
|
||||
usb_release_interface (handle, 0)
|
||||
@ -115,6 +122,7 @@ void data::poll ():
|
||||
usb_close (handle)
|
||||
handle = NULL
|
||||
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:
|
||||
std::cerr << "unable to send name to device: " << usb_strerror () << std::endl
|
||||
usb_release_interface (handle, 0)
|
||||
@ -123,13 +131,17 @@ void data::poll ():
|
||||
return
|
||||
continue
|
||||
case Directory::LOCK_RO:
|
||||
std::cerr << "lock\n"
|
||||
if !lock++:
|
||||
std::cerr << "freezing file list\n"
|
||||
shevek::dir d (files)
|
||||
dir.clear ()
|
||||
for shevek::dir::const_iterator i = d.begin (); i == d.end (); ++i:
|
||||
dir.push_back (Name (i->name))
|
||||
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))
|
||||
continue
|
||||
case Directory::UNLOCK_RO:
|
||||
std::cerr << "unlock\n"
|
||||
if !lock:
|
||||
std::cerr << "unlocking without lock" << std::endl
|
||||
usb_release_interface (handle, 0)
|
||||
@ -139,19 +151,22 @@ void data::poll ():
|
||||
if !--lock:
|
||||
dir.clear ()
|
||||
continue
|
||||
case Directory::GET_FILE_RO:
|
||||
unsigned f = buffer[0] >> 16
|
||||
if f >= dir.size ():
|
||||
case String::GET_PAGE:
|
||||
if buffer[1] >= dir.size ():
|
||||
std::cerr << "reading invalid file" << std::endl
|
||||
usb_release_interface (handle, 0)
|
||||
usb_close (handle)
|
||||
handle = NULL
|
||||
return
|
||||
std::ifstream file (dir[f].full.c_str ())
|
||||
file.seekg (buffer[1] << 12)
|
||||
unsigned pos = buffer[0] >> 16
|
||||
std::cerr << "getting data from " << pos << '\n'
|
||||
std::ifstream file (dir[buffer[1]].full.c_str ())
|
||||
file.seekg (pos << 12)
|
||||
char page[1 << 12]
|
||||
memset (page, 0, 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:
|
||||
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
|
||||
@ -160,15 +175,33 @@ void data::poll ():
|
||||
handle = NULL
|
||||
return
|
||||
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:
|
||||
std::cerr << "invalid request" << std::endl
|
||||
std::cerr << "invalid request " << buffer[0] << std::endl
|
||||
usb_release_interface (handle, 0)
|
||||
usb_close (handle)
|
||||
handle = NULL
|
||||
return
|
||||
// If the code reaches this point, break out of the loop. The loop continues if a continue statement is reached.
|
||||
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:
|
||||
static Glib::RefPtr <client> create ():
|
||||
@ -225,7 +258,7 @@ void data::get_device (unsigned vendor, unsigned product, unsigned tries):
|
||||
usb_close (handle)
|
||||
handle = NULL
|
||||
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
|
||||
if i + 1 < tries:
|
||||
//std::cerr << "failed to find device, still trying...\n"
|
||||
@ -277,6 +310,21 @@ void data::boot (unsigned entry):
|
||||
return
|
||||
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):
|
||||
usb_init ()
|
||||
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")
|
||||
data d (port)
|
||||
dump_devices ()
|
||||
shevek::loop ()
|
||||
return 0
|
||||
|
@ -45,7 +45,7 @@ void dbg_log_num (unsigned num, unsigned digits):
|
||||
return
|
||||
|
||||
#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 = ")
|
||||
if old_current:
|
||||
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 (name)
|
||||
dbg_log_char (':')
|
||||
dbg_log_num (line)
|
||||
dbg_log (line)
|
||||
dbg_log (": ")
|
||||
dbg_log (message)
|
||||
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_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.
|
||||
while first_scheduled:
|
||||
first_scheduled->unrun ()
|
||||
@ -133,7 +133,7 @@ void dbg_send (unsigned n, unsigned bits):
|
||||
delay (50)
|
||||
set_leds (false, false)
|
||||
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
|
||||
cp0_get (CP0_EPC, epc)
|
||||
dbg_send (epc, 32)
|
||||
|
@ -38,9 +38,9 @@ namespace Kernel:
|
||||
__recv_data_t recv
|
||||
|
||||
void print_caps ():
|
||||
// Assume __caps to be 16.
|
||||
bool used[16]
|
||||
for unsigned i = 0; i < 16; ++i:
|
||||
// Assume __caps to be 32.
|
||||
bool used[32]
|
||||
for unsigned i = 0; i < 32; ++i:
|
||||
used[i] = true
|
||||
unsigned num = 0
|
||||
for list *i = __first_free_cap; i; i = i->next:
|
||||
@ -48,7 +48,7 @@ namespace Kernel:
|
||||
++num
|
||||
kdebug_num (num, 1)
|
||||
kdebug (":")
|
||||
for unsigned i = 0; i < 16; ++i:
|
||||
for unsigned i = 0; i < 32; ++i:
|
||||
kdebug_char (used[i] ? '#' : '.')
|
||||
kdebug_char ('\n')
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
#define ARCH
|
||||
#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]
|
||||
|
||||
#define assert(x) do { if (!(x)) { kdebug ("assertion failed " #x); while (true) {} } } while (0)
|
||||
|
Loading…
Reference in New Issue
Block a user