mirror of
git://projects.qi-hardware.com/iris.git
synced 2024-12-29 20:04:34 +02:00
working fat reader
This commit is contained in:
parent
8968030551
commit
a277156a2e
1
.gitignore
vendored
1
.gitignore
vendored
@ -22,3 +22,4 @@ mips/nanonote/server/install-sh
|
|||||||
mips/nanonote/server/missing
|
mips/nanonote/server/missing
|
||||||
mips/nanonote/server/usb-server
|
mips/nanonote/server/usb-server
|
||||||
fs/
|
fs/
|
||||||
|
iris-sd.tar
|
||||||
|
18
devices.hhp
18
devices.hhp
@ -60,7 +60,7 @@ namespace Iris:
|
|||||||
/// Helper function for get_block.
|
/// Helper function for get_block.
|
||||||
static Page _create_paying_page ():
|
static Page _create_paying_page ():
|
||||||
Page ret = my_memory.create_page ()
|
Page ret = my_memory.create_page ()
|
||||||
ret.set_flags (Page::PAYING, Page::PAYING)
|
ret.set_flags (Page::PAYING)
|
||||||
return ret
|
return ret
|
||||||
/// Get a block from the string; place it at offset on page. This need not be implemented for strings smaller than PAGE_SIZE. All arguments must be aligned.
|
/// Get a block from the string; place it at offset on page. This need not be implemented for strings smaller than PAGE_SIZE. All arguments must be aligned.
|
||||||
Cap get_block (Num idx, unsigned size = PAGE_SIZE, unsigned offset = 0, Page ret = _create_paying_page ()):
|
Cap get_block (Num idx, unsigned size = PAGE_SIZE, unsigned offset = 0, Page ret = _create_paying_page ()):
|
||||||
@ -304,25 +304,11 @@ namespace Iris:
|
|||||||
void unlock ():
|
void unlock ():
|
||||||
call (CAP_MASTER_DIRECT | UNLOCK)
|
call (CAP_MASTER_DIRECT | UNLOCK)
|
||||||
|
|
||||||
// A filesystem turns a String into a Directory.
|
|
||||||
struct Filesystem : public Device:
|
|
||||||
Filesystem (Cap c = Cap ()) : Device (c):
|
|
||||||
enum request:
|
|
||||||
USE_DEVICE = WDirectory::ID
|
|
||||||
USE_DEVICE_RO
|
|
||||||
ID
|
|
||||||
WDirectory use_device (WString dev):
|
|
||||||
ocall (dev, CAP_MASTER_DIRECT | USE_DEVICE)
|
|
||||||
return get_arg ()
|
|
||||||
Directory use_device_ro (String dev):
|
|
||||||
ocall (dev, CAP_MASTER_DIRECT | USE_DEVICE_RO)
|
|
||||||
return get_arg ()
|
|
||||||
|
|
||||||
// Stream interface.
|
// Stream interface.
|
||||||
struct Stream : public Cap:
|
struct Stream : public Cap:
|
||||||
Stream (Cap c = Cap ()) : Cap (c):
|
Stream (Cap c = Cap ()) : Cap (c):
|
||||||
enum request:
|
enum request:
|
||||||
READ = Filesystem::ID
|
READ = Directory::ID
|
||||||
WRITE
|
WRITE
|
||||||
ID
|
ID
|
||||||
// Try to read size bytes. Returns the number of bytes successfully read.
|
// Try to read size bytes. Returns the number of bytes successfully read.
|
||||||
|
12
iris.hhp
12
iris.hhp
@ -375,8 +375,8 @@ namespace Iris:
|
|||||||
set_info (PC, pc)
|
set_info (PC, pc)
|
||||||
void set_sp (unsigned sp):
|
void set_sp (unsigned sp):
|
||||||
set_info (SP, sp)
|
set_info (SP, sp)
|
||||||
void set_flags (unsigned value, unsigned mask):
|
void set_flags (unsigned set, unsigned reset = 0):
|
||||||
set_info (FLAGS, value, mask)
|
set_info (FLAGS, set, set | reset)
|
||||||
unsigned get_pc ():
|
unsigned get_pc ():
|
||||||
return get_info (PC)
|
return get_info (PC)
|
||||||
unsigned get_sp ():
|
unsigned get_sp ():
|
||||||
@ -384,9 +384,9 @@ namespace Iris:
|
|||||||
unsigned get_flags ():
|
unsigned get_flags ():
|
||||||
return get_info (FLAGS)
|
return get_info (FLAGS)
|
||||||
void run (bool run = true):
|
void run (bool run = true):
|
||||||
set_flags (run ? RUNNING : 0, RUNNING)
|
set_flags (run ? RUNNING : 0, run ? 0 : RUNNING)
|
||||||
void wait (bool wait):
|
void wait (bool wait):
|
||||||
set_flags (wait ? WAITING : 0, WAITING)
|
set_flags (wait ? WAITING : 0, wait ? 0 : WAITING)
|
||||||
inline unsigned use (Caps caps, unsigned slot = alloc_slot ())
|
inline unsigned use (Caps caps, unsigned slot = alloc_slot ())
|
||||||
inline Caps get_caps (unsigned slot)
|
inline Caps get_caps (unsigned slot)
|
||||||
unsigned get_num_caps ():
|
unsigned get_num_caps ():
|
||||||
@ -461,8 +461,8 @@ namespace Iris:
|
|||||||
ocall (target, Num (CAP_MASTER_DIRECT | SHARE, flags))
|
ocall (target, 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 set, unsigned reset = 0):
|
||||||
call (CAP_MASTER_DIRECT | SET_FLAGS, Num (new_flags, mask))
|
call (CAP_MASTER_DIRECT | SET_FLAGS, Num (set, set | reset))
|
||||||
return recv.data[0].l == NO_ERROR
|
return recv.data[0].l == NO_ERROR
|
||||||
unsigned physical_address ():
|
unsigned physical_address ():
|
||||||
return my_thread.ocall (*this, CAP_MASTER_DIRECT | Thread::PRIV_PHYSICAL_ADDRESS).l
|
return my_thread.ocall (*this, CAP_MASTER_DIRECT | Thread::PRIV_PHYSICAL_ADDRESS).l
|
||||||
|
@ -81,8 +81,9 @@ long file name: stored in directory entries immediately before the 8.3 name (las
|
|||||||
01 a 5 unicode characters.
|
01 a 5 unicode characters.
|
||||||
0b 1 attribute: 000rsh0v.
|
0b 1 attribute: 000rsh0v.
|
||||||
0c 1 0
|
0c 1 0
|
||||||
0d 1 checksum
|
0d 1 checksum of short filename.
|
||||||
0e c 6 unicode characters.
|
0e c 6 unicode characters.
|
||||||
1a 2 0
|
1a 2 0
|
||||||
1c 4 2 unicode characters.
|
1c 4 2 unicode characters.
|
||||||
|
|
||||||
|
checksum is name[0] rotated 11 times, name[1] 10 times, etc and all added up.
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
load = 0x80000000
|
load = 0x80000000
|
||||||
UDC_BOOT=1
|
UDC_BOOT=1
|
||||||
|
|
||||||
ARCH_CXXFLAGS = -DNUM_THREADS=2
|
|
||||||
ARCH_CPPFLAGS = -I. -Imips -Imips/nanonote -Wa,-mips32 -DNANONOTE -DUSE_SERIAL
|
ARCH_CPPFLAGS = -I. -Imips -Imips/nanonote -Wa,-mips32 -DNANONOTE -DUSE_SERIAL
|
||||||
CROSS = mipsel-linux-gnu-
|
CROSS = mipsel-linux-gnu-
|
||||||
OBJDUMP = $(CROSS)objdump
|
OBJDUMP = $(CROSS)objdump
|
||||||
@ -32,18 +31,23 @@ arch_headers = mips/arch.hh mips/nanonote/jz4740.hh mips/nanonote/board.hh
|
|||||||
udc_boot_programs = udc
|
udc_boot_programs = udc
|
||||||
sd_boot_programs = sd+mmc partition fat
|
sd_boot_programs = sd+mmc partition fat
|
||||||
standard_boot_programs = bootinit
|
standard_boot_programs = bootinit
|
||||||
ifdef UDC_BOOT
|
|
||||||
boot_threads = $(standard_boot_programs) $(udc_boot_programs)
|
|
||||||
threadlist = mips/nanonote/threadlist-udc
|
|
||||||
INIT_FLAGS = -DUDC_BOOT
|
|
||||||
else
|
|
||||||
boot_threads = $(standard_boot_programs) $(sd_boot_programs)
|
|
||||||
threadlist = mips/nanonote/threadlist-sd
|
|
||||||
INIT_FLAGS = -DSD_BOOT
|
|
||||||
endif
|
|
||||||
programs = init gpio lcd bsquare ball buzzer metronome elfrun alarm gui nand test $(udc_boot_programs) $(sd_boot_programs) $(standard_boot_programs)
|
programs = init gpio lcd bsquare ball buzzer metronome elfrun alarm gui nand test $(udc_boot_programs) $(sd_boot_programs) $(standard_boot_programs)
|
||||||
|
|
||||||
|
ifdef UDC_BOOT
|
||||||
|
boot_threads = $(standard_boot_programs) $(udc_boot_programs)
|
||||||
|
threadlist = mips/nanonote/threadlist-udc
|
||||||
|
ARCH_CXXFLAGS = -DNUM_THREADS=2
|
||||||
all: test
|
all: test
|
||||||
|
else
|
||||||
|
boot_threads = $(standard_boot_programs) $(sd_boot_programs)
|
||||||
|
threadlist = mips/nanonote/threadlist-sd
|
||||||
|
ARCH_CXXFLAGS = -DNUM_THREADS=4
|
||||||
|
all: iris-sd.tar
|
||||||
|
iris-sd.tar: $(addprefix fs/,$(addsuffix .elf,$(programs))) iris.raw init.config
|
||||||
|
mkimage -a $(load) -e a$(shell /bin/sh -c '$(OBJDUMP) -t iris.elf | grep __start$$ | cut -b2-8') -n Iris -d iris.raw fs/uimage | sed -e 's/:/;/g'
|
||||||
|
cd fs && tar cvf ../$@ uimage init.config $(addsuffix .elf,$(programs)) --dereference
|
||||||
|
endif
|
||||||
|
|
||||||
test: iris.raw mips/nanonote/server/usb-server mips/nanonote/sdram-setup.raw $(addsuffix .elf,$(addprefix fs/,$(programs))) fs/init.config
|
test: iris.raw mips/nanonote/server/usb-server mips/nanonote/sdram-setup.raw $(addsuffix .elf,$(addprefix fs/,$(programs))) fs/init.config
|
||||||
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
|
||||||
@ -66,7 +70,7 @@ mips/nanonote/sdram-setup.elf: mips/nanonote/sdram-setup.ld
|
|||||||
mips/nanonote/sdram-setup.elf: LDFLAGS = --omagic -T mips/nanonote/sdram-setup.ld
|
mips/nanonote/sdram-setup.elf: LDFLAGS = --omagic -T mips/nanonote/sdram-setup.ld
|
||||||
$(threadlist).o: $(addprefix fs/,$(addsuffix .elf,$(boot_threads)))
|
$(threadlist).o: $(addprefix fs/,$(addsuffix .elf,$(boot_threads)))
|
||||||
mips/boot.o: TARGET_FLAGS = -DMEMORY_SIZE="32 << 20"
|
mips/boot.o: TARGET_FLAGS = -DMEMORY_SIZE="32 << 20"
|
||||||
mips/init.o: TARGET_FLAGS = -I/usr/include $(INIT_FLAGS)
|
mips/init.o: TARGET_FLAGS = -I/usr/include
|
||||||
source/bootinit.o: TARGET_FLAGS = -I/usr/include
|
source/bootinit.o: TARGET_FLAGS = -I/usr/include
|
||||||
source/elfrun.o: TARGET_FLAGS = -I/usr/include
|
source/elfrun.o: TARGET_FLAGS = -I/usr/include
|
||||||
source/gpio.ccp: source/nanonote-gpio.ccp
|
source/gpio.ccp: source/nanonote-gpio.ccp
|
||||||
|
@ -322,7 +322,6 @@ static void dump_devices ():
|
|||||||
std::cerr << "\nSetting: " << Iris::Setting::ID
|
std::cerr << "\nSetting: " << Iris::Setting::ID
|
||||||
std::cerr << "\nDirectory: " << Iris::Directory::ID
|
std::cerr << "\nDirectory: " << Iris::Directory::ID
|
||||||
std::cerr << "\nWDirectory: " << Iris::WDirectory::ID
|
std::cerr << "\nWDirectory: " << Iris::WDirectory::ID
|
||||||
std::cerr << "\nFilesystem: " << Iris::Filesystem::ID
|
|
||||||
std::cerr << "\nStream: " << Iris::Stream::ID
|
std::cerr << "\nStream: " << Iris::Stream::ID
|
||||||
std::cerr << "\n"
|
std::cerr << "\n"
|
||||||
|
|
||||||
|
@ -21,11 +21,11 @@
|
|||||||
|
|
||||||
.balign 0x1000
|
.balign 0x1000
|
||||||
thread0:
|
thread0:
|
||||||
.incbin "bootinit.elf"
|
.incbin "fs/bootinit.elf"
|
||||||
|
|
||||||
.balign 0x1000
|
.balign 0x1000
|
||||||
thread1:
|
thread1:
|
||||||
.incbin "udc.elf"
|
.incbin "fs/udc.elf"
|
||||||
|
|
||||||
.balign 0x1000
|
.balign 0x1000
|
||||||
thread2:
|
thread2:
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#pypp 0
|
#pypp 0
|
||||||
// Iris: micro-kernel for a capability-based operating system.
|
// Iris: micro-kernel for a capability-based operating system.
|
||||||
// boot-programs/bootinit.ccp: Bootstrapping code.
|
// source/bootinit.ccp: Bootstrapping code.
|
||||||
// Copyright 2009 Bas Wijnen <wijnen@debian.org>
|
// Copyright 2009-2010 Bas Wijnen <wijnen@debian.org>
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#define ELFRUN_NAME "elfrun.elf"
|
#define ELFRUN_NAME "elfrun.elf"
|
||||||
#define INIT_NAME "init.elf"
|
#define INIT_NAME "init.elf"
|
||||||
|
|
||||||
#define NUM_SLOTS 8
|
#define NUM_SLOTS 8
|
||||||
#define NUM_CAPS 32
|
#define NUM_CAPS 32
|
||||||
|
|
||||||
@ -45,7 +46,7 @@ void *operator new[] (unsigned size):
|
|||||||
unsigned pages = ((size - rest) + PAGE_SIZE - 1) >> PAGE_BITS
|
unsigned pages = ((size - rest) + PAGE_SIZE - 1) >> PAGE_BITS
|
||||||
for unsigned p = 0; p < pages; ++p:
|
for unsigned p = 0; p < pages; ++p:
|
||||||
Iris::Page page = Iris::my_memory.create_page ()
|
Iris::Page page = Iris::my_memory.create_page ()
|
||||||
page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME, Iris::Page::PAYING | Iris::Page::FRAME)
|
page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME)
|
||||||
Iris::my_memory.map (page, _free + rest + (p << PAGE_BITS))
|
Iris::my_memory.map (page, _free + rest + (p << PAGE_BITS))
|
||||||
Iris::free_cap (page)
|
Iris::free_cap (page)
|
||||||
_free += size
|
_free += size
|
||||||
@ -63,35 +64,86 @@ static Iris::Page bss_page
|
|||||||
|
|
||||||
// Get the initial block device and filesystem.
|
// Get the initial block device and filesystem.
|
||||||
static Iris::Directory receive_devices ():
|
static Iris::Directory receive_devices ():
|
||||||
Iris::String data
|
Iris::String device
|
||||||
Iris::Filesystem fs
|
bool have_device = false
|
||||||
bool have_data = false, have_fs = false
|
Iris::Cap reply[2]
|
||||||
for unsigned i = 0; i < 2; ++i:
|
bool have_reply[2]
|
||||||
|
have_reply[0] = false
|
||||||
|
have_reply[1] = false
|
||||||
|
unsigned next = 2
|
||||||
|
while true:
|
||||||
Iris::wait ()
|
Iris::wait ()
|
||||||
if Iris::recv.data[0].l != Iris::Parent::PROVIDE_CAPABILITY:
|
kdebug_num (Iris::recv.protected_data.l, 1)
|
||||||
Iris::panic (Iris::recv.data[0].l, "Invalid bootstrap request.")
|
kdebug (": ")
|
||||||
switch Iris::recv.data[1].l:
|
if Iris::recv.protected_data.l == 0:
|
||||||
case Iris::String::ID:
|
kdebug ("sd detect event device request\n")
|
||||||
if have_data:
|
// SD detection event device request.
|
||||||
Iris::panic (0, "duplicate device.")
|
// Ignore all; that will result in the driver thinking there is a card.
|
||||||
data = Iris::get_arg ()
|
Iris::recv.reply.invoke ()
|
||||||
Iris::recv.reply.invoke ()
|
continue
|
||||||
have_data = true
|
switch Iris::recv.data[0].l:
|
||||||
|
case Iris::Parent::PROVIDE_CAPABILITY:
|
||||||
|
switch Iris::recv.data[1].l:
|
||||||
|
case Iris::String::ID:
|
||||||
|
case Iris::WString::ID:
|
||||||
|
// Ignore other partitions.
|
||||||
|
Iris::Cap r = Iris::get_reply ()
|
||||||
|
if Iris::recv.data[0].h != 0:
|
||||||
|
kdebug ("ignoring non-0 partition\n")
|
||||||
|
else:
|
||||||
|
if have_device:
|
||||||
|
Iris::panic (0, "double device provided")
|
||||||
|
device = Iris::get_arg ()
|
||||||
|
if have_reply[next - 2]:
|
||||||
|
kdebug ("string provided (used)\n")
|
||||||
|
reply[next++ - 2].invoke (0, 0, device.copy ())
|
||||||
|
Iris::free_cap (device)
|
||||||
|
else:
|
||||||
|
kdebug ("string provided (stored)\n")
|
||||||
|
have_device = true
|
||||||
|
r.invoke ()
|
||||||
|
Iris::free_cap (r)
|
||||||
|
break
|
||||||
|
case Iris::Directory::ID:
|
||||||
|
kdebug ("directory provided\n")
|
||||||
|
Iris::Directory ret = Iris::get_arg ()
|
||||||
|
Iris::recv.reply.invoke ()
|
||||||
|
return ret
|
||||||
|
default:
|
||||||
|
Iris::panic (Iris::recv.data[1].l, "invalid capability type provided by boot thread")
|
||||||
break
|
break
|
||||||
case Iris::Filesystem::ID:
|
case Iris::Parent::GET_CAPABILITY:
|
||||||
if have_fs:
|
if Iris::recv.data[1].l == Iris::Event::ID:
|
||||||
Iris::panic (0, "duplicate filesystem.")
|
kdebug ("event requested\n")
|
||||||
fs = Iris::get_arg ()
|
// Detection of sd card.
|
||||||
Iris::recv.reply.invoke ()
|
Iris::Cap reply = Iris::get_reply ()
|
||||||
have_fs = true
|
Iris::Cap event = Iris::my_receiver.create_capability (0)
|
||||||
|
reply.invoke (0, 0, event.copy ())
|
||||||
|
Iris::free_cap (event)
|
||||||
|
Iris::free_cap (reply)
|
||||||
|
break
|
||||||
|
if Iris::recv.data[1].l != Iris::String::ID && Iris::recv.data[1].l != Iris::WString::ID:
|
||||||
|
Iris::panic (Iris::recv.data[1].l, "invalid capability type requested by boot thread")
|
||||||
|
if next == Iris::recv.protected_data.l && have_device:
|
||||||
|
kdebug ("string requested (sent)\n")
|
||||||
|
Iris::recv.reply.invoke (0, 0, device.copy ())
|
||||||
|
Iris::free_cap (device)
|
||||||
|
have_device = false
|
||||||
|
++next
|
||||||
|
else:
|
||||||
|
kdebug ("string requested (not sent)\n")
|
||||||
|
reply[Iris::recv.protected_data.l - 2] = Iris::get_reply ()
|
||||||
|
have_reply[Iris::recv.protected_data.l - 2] = true
|
||||||
break
|
break
|
||||||
|
case Iris::Parent::INIT_DONE:
|
||||||
|
kdebug ("init done\n")
|
||||||
|
// Ignore.
|
||||||
|
Iris::recv.reply.invoke ()
|
||||||
|
break
|
||||||
|
case Iris::Parent::EXIT:
|
||||||
|
Iris::panic (Iris::recv.protected_data.l, "boot thread exits")
|
||||||
default:
|
default:
|
||||||
Iris::panic (Iris::recv.data[1].l, "unexpected device")
|
Iris::panic (Iris::recv.protected_data.l, "invalid boot request")
|
||||||
// Initialize the root file system.
|
|
||||||
Iris::Directory root = fs.use_device_ro (data.copy ())
|
|
||||||
Iris::free_cap (data)
|
|
||||||
Iris::free_cap (fs)
|
|
||||||
return root
|
|
||||||
|
|
||||||
static bool stringcmp (char const *s1, char const *s2, unsigned size):
|
static bool stringcmp (char const *s1, char const *s2, unsigned size):
|
||||||
for unsigned t = 0; t < size; ++t:
|
for unsigned t = 0; t < size; ++t:
|
||||||
@ -137,7 +189,7 @@ static void run (Iris::String data, Iris::Memory parent_memory, Iris::Cap parent
|
|||||||
//kdebug ("\n")
|
//kdebug ("\n")
|
||||||
Iris::set_recv_arg (Iris::Cap (slot, p))
|
Iris::set_recv_arg (Iris::Cap (slot, p))
|
||||||
Iris::my_memory.create_page ()
|
Iris::my_memory.create_page ()
|
||||||
Iris::Page (slot, p).set_flags (Iris::Page::PAYING, Iris::Page::PAYING)
|
Iris::Page (slot, p).set_flags (Iris::Page::PAYING)
|
||||||
data.get_block (p << PAGE_BITS, PAGE_SIZE, 0, Iris::Cap (slot, p))
|
data.get_block (p << PAGE_BITS, PAGE_SIZE, 0, Iris::Cap (slot, p))
|
||||||
Iris::my_memory.map (Iris::Cap (slot, p), (unsigned)&mapping[p << PAGE_BITS])
|
Iris::my_memory.map (Iris::Cap (slot, p), (unsigned)&mapping[p << PAGE_BITS])
|
||||||
Iris::Thread thread = mem.create_thread (NUM_SLOTS)
|
Iris::Thread thread = mem.create_thread (NUM_SLOTS)
|
||||||
@ -190,7 +242,7 @@ static void run (Iris::String data, Iris::Memory parent_memory, Iris::Cap parent
|
|||||||
f = Iris::Page::PAYING | Iris::Page::MAPPED_READONLY
|
f = Iris::Page::PAYING | Iris::Page::MAPPED_READONLY
|
||||||
else:
|
else:
|
||||||
f = Iris::Page::PAYING
|
f = Iris::Page::PAYING
|
||||||
page.set_flags (f, f)
|
page.set_flags (f)
|
||||||
Iris::Page (slot, idx).share (page, 0)
|
Iris::Page (slot, idx).share (page, 0)
|
||||||
//kdebug ("mapping at ")
|
//kdebug ("mapping at ")
|
||||||
//kdebug_num (p)
|
//kdebug_num (p)
|
||||||
@ -222,7 +274,7 @@ static void run (Iris::String data, Iris::Memory parent_memory, Iris::Cap parent
|
|||||||
page = mem.create_page ()
|
page = mem.create_page ()
|
||||||
if Iris::recv.data[0].l != Iris::NO_ERROR:
|
if Iris::recv.data[0].l != Iris::NO_ERROR:
|
||||||
Iris::panic (Iris::recv.data[0].l, "out of memory")
|
Iris::panic (Iris::recv.data[0].l, "out of memory")
|
||||||
if !page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME, Iris::Page::PAYING | Iris::Page::FRAME):
|
if !page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME):
|
||||||
Iris::panic (0, "out of memory")
|
Iris::panic (0, "out of memory")
|
||||||
if !mem.map (page, p):
|
if !mem.map (page, p):
|
||||||
Iris::panic (0, "unable to map bss page")
|
Iris::panic (0, "unable to map bss page")
|
||||||
@ -232,7 +284,7 @@ static void run (Iris::String data, Iris::Memory parent_memory, Iris::Cap parent
|
|||||||
Iris::my_memory.destroy (pages_caps)
|
Iris::my_memory.destroy (pages_caps)
|
||||||
Iris::free_slot (slot)
|
Iris::free_slot (slot)
|
||||||
Iris::Page stackpage = mem.create_page ()
|
Iris::Page stackpage = mem.create_page ()
|
||||||
stackpage.set_flags (Iris::Page::PAYING | Iris::Page::FRAME, Iris::Page::PAYING | Iris::Page::FRAME)
|
stackpage.set_flags (Iris::Page::PAYING | Iris::Page::FRAME)
|
||||||
if Iris::recv.data[0].l != Iris::NO_ERROR || !mem.map (stackpage, 0x7ffff000):
|
if Iris::recv.data[0].l != Iris::NO_ERROR || !mem.map (stackpage, 0x7ffff000):
|
||||||
Iris::panic (Iris::recv.data[0].l, "unable to map initial stack page")
|
Iris::panic (Iris::recv.data[0].l, "unable to map initial stack page")
|
||||||
Iris::free_cap (stackpage)
|
Iris::free_cap (stackpage)
|
||||||
|
98
source/buffer.ccp
Normal file
98
source/buffer.ccp
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
#pypp 0
|
||||||
|
// Iris: micro-kernel for a capability-based operating system.
|
||||||
|
// source/buffer.ccp: block device buffer.
|
||||||
|
// Copyright 2010 Bas Wijnen <wijnen@debian.org>
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#include "iris.hh"
|
||||||
|
#include "devices.hh"
|
||||||
|
|
||||||
|
static unsigned align
|
||||||
|
static Iris::Page page, rpage
|
||||||
|
static unsigned mapping, rmapping
|
||||||
|
static Iris::Num size, current
|
||||||
|
static Iris::String dev
|
||||||
|
|
||||||
|
static void read_block (Iris::Num idx):
|
||||||
|
idx = idx.value () & PAGE_MASK
|
||||||
|
if idx.value () == current.value ():
|
||||||
|
return
|
||||||
|
//kdebug ("buffering block ")
|
||||||
|
//kdebug_num (idx.h)
|
||||||
|
//kdebug (":")
|
||||||
|
//kdebug_num (idx.l)
|
||||||
|
//kdebug ("\n")
|
||||||
|
dev.get_block (idx, PAGE_SIZE, 0, page)
|
||||||
|
//kdebug ("buffered\n")
|
||||||
|
current = idx
|
||||||
|
|
||||||
|
Iris::Num start ():
|
||||||
|
dev = Iris::my_parent.get_capability <Iris::WString> ()
|
||||||
|
align = dev.get_align_bits ()
|
||||||
|
size = dev.get_size ()
|
||||||
|
if align > PAGE_BITS:
|
||||||
|
Iris::panic (align, "invalid alignment value for block device")
|
||||||
|
page = Iris::my_memory.create_page ()
|
||||||
|
rpage = Iris::my_memory.create_page ()
|
||||||
|
page.set_flags (Iris::Page::PAYING)
|
||||||
|
rpage.set_flags (Iris::Page::PAYING)
|
||||||
|
mapping = 0x15000
|
||||||
|
rmapping = 0x17000
|
||||||
|
Iris::my_memory.map (page, mapping)
|
||||||
|
Iris::my_memory.map (rpage, rmapping)
|
||||||
|
current.h = ~0
|
||||||
|
current.l = ~0
|
||||||
|
Iris::Cap cap = Iris::my_receiver.create_capability (0)
|
||||||
|
Iris::my_parent.provide_capability <Iris::WString> (cap.copy ())
|
||||||
|
Iris::free_cap (cap)
|
||||||
|
Iris::my_parent.init_done ()
|
||||||
|
while true:
|
||||||
|
Iris::wait ()
|
||||||
|
switch Iris::recv.data[0].l:
|
||||||
|
case Iris::String::GET_SIZE:
|
||||||
|
Iris::recv.reply.invoke (size)
|
||||||
|
break
|
||||||
|
case Iris::String::GET_ALIGN_BITS:
|
||||||
|
// Use 16 byte alignment to make implementing GET_CHARS easier.
|
||||||
|
Iris::recv.reply.invoke (4)
|
||||||
|
break
|
||||||
|
case Iris::String::GET_CHARS:
|
||||||
|
Iris::Cap reply = Iris::get_reply ()
|
||||||
|
unsigned offset = Iris::recv.data[1].l & ~PAGE_MASK & ~((1 << 4) - 1)
|
||||||
|
read_block (Iris::recv.data[1])
|
||||||
|
unsigned *data = (unsigned *)((char *)mapping)[offset]
|
||||||
|
reply.invoke (Iris::Num (data[0], data[1]), Iris::Num (data[2], data[3]))
|
||||||
|
Iris::free_cap (reply)
|
||||||
|
break
|
||||||
|
case Iris::String::GET_BLOCK:
|
||||||
|
Iris::Cap reply = Iris::get_reply ()
|
||||||
|
Iris::Page arg = Iris::get_arg ()
|
||||||
|
unsigned offset = Iris::recv.data[1].l & ~PAGE_MASK & ~((1 << 4) - 1)
|
||||||
|
unsigned sz = Iris::recv.data[0].h >> 16
|
||||||
|
unsigned roffset = Iris::recv.data[0].h & 0xffff
|
||||||
|
Iris::Num idx = Iris::recv.data[1]
|
||||||
|
arg.set_flags (Iris::Page::FRAME | Iris::Page::PAYING)
|
||||||
|
arg.share (rpage)
|
||||||
|
rpage.set_flags (Iris::Page::FRAME)
|
||||||
|
read_block (idx)
|
||||||
|
for unsigned i = 0; i < sz; ++i:
|
||||||
|
((char *)rmapping)[roffset + i] = ((char *)mapping)[offset + i]
|
||||||
|
rpage.set_flags (0, Iris::Page::FRAME)
|
||||||
|
reply.invoke ()
|
||||||
|
Iris::free_cap (reply)
|
||||||
|
Iris::free_cap (arg)
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
Iris::panic (Iris::recv.data[0].l, "invalid request for buffer")
|
@ -40,7 +40,7 @@ void *operator new[] (unsigned size):
|
|||||||
unsigned pages = ((size - rest) + PAGE_SIZE - 1) >> PAGE_BITS
|
unsigned pages = ((size - rest) + PAGE_SIZE - 1) >> PAGE_BITS
|
||||||
for unsigned p = 0; p < pages; ++p:
|
for unsigned p = 0; p < pages; ++p:
|
||||||
Iris::Page page = Iris::my_memory.create_page ()
|
Iris::Page page = Iris::my_memory.create_page ()
|
||||||
page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME, Iris::Page::PAYING | Iris::Page::FRAME)
|
page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME)
|
||||||
Iris::my_memory.map (page, _free + rest + (p << PAGE_BITS))
|
Iris::my_memory.map (page, _free + rest + (p << PAGE_BITS))
|
||||||
Iris::free_cap (page)
|
Iris::free_cap (page)
|
||||||
_free += size
|
_free += size
|
||||||
@ -173,7 +173,7 @@ static Iris::Caps run (Iris::Caps data, Iris::Memory parent_memory, Iris::Cap pa
|
|||||||
f = Iris::Page::PAYING | Iris::Page::MAPPED_READONLY
|
f = Iris::Page::PAYING | Iris::Page::MAPPED_READONLY
|
||||||
else:
|
else:
|
||||||
f = Iris::Page::PAYING
|
f = Iris::Page::PAYING
|
||||||
page.set_flags (f, f)
|
page.set_flags (f)
|
||||||
Iris::Page (slot, idx).share (page, 0)
|
Iris::Page (slot, idx).share (page, 0)
|
||||||
//kdebug ("mapping at ")
|
//kdebug ("mapping at ")
|
||||||
//kdebug_num (p)
|
//kdebug_num (p)
|
||||||
@ -210,7 +210,7 @@ static Iris::Caps run (Iris::Caps data, Iris::Memory parent_memory, Iris::Cap pa
|
|||||||
page = mem.create_page ()
|
page = mem.create_page ()
|
||||||
if Iris::recv.data[0].l != Iris::NO_ERROR:
|
if Iris::recv.data[0].l != Iris::NO_ERROR:
|
||||||
Iris::panic (Iris::recv.data[0].l, "out of memory")
|
Iris::panic (Iris::recv.data[0].l, "out of memory")
|
||||||
if !page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME, Iris::Page::PAYING | Iris::Page::FRAME):
|
if !page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME):
|
||||||
Iris::panic (0, "out of memory")
|
Iris::panic (0, "out of memory")
|
||||||
if !mem.map (page, p):
|
if !mem.map (page, p):
|
||||||
Iris::panic (0, "unable to map bss page")
|
Iris::panic (0, "unable to map bss page")
|
||||||
@ -229,7 +229,7 @@ static Iris::Caps run (Iris::Caps data, Iris::Memory parent_memory, Iris::Cap pa
|
|||||||
Iris::free_slot (slot)
|
Iris::free_slot (slot)
|
||||||
Iris::free_cap (pages_caps)
|
Iris::free_cap (pages_caps)
|
||||||
Iris::Page stackpage = mem.create_page ()
|
Iris::Page stackpage = mem.create_page ()
|
||||||
stackpage.set_flags (Iris::Page::PAYING | Iris::Page::FRAME, Iris::Page::PAYING | Iris::Page::FRAME)
|
stackpage.set_flags (Iris::Page::PAYING | Iris::Page::FRAME)
|
||||||
if Iris::recv.data[0].l != Iris::NO_ERROR || !mem.map (stackpage, 0x7ffff000):
|
if Iris::recv.data[0].l != Iris::NO_ERROR || !mem.map (stackpage, 0x7ffff000):
|
||||||
Iris::panic (Iris::recv.data[0].l, "unable to map initial stack page")
|
Iris::panic (Iris::recv.data[0].l, "unable to map initial stack page")
|
||||||
Iris::free_cap (stackpage)
|
Iris::free_cap (stackpage)
|
||||||
|
361
source/fat.ccp
361
source/fat.ccp
@ -26,7 +26,7 @@ void *operator new[] (unsigned size):
|
|||||||
unsigned pages = ((size - rest) + PAGE_SIZE - 1) >> PAGE_BITS
|
unsigned pages = ((size - rest) + PAGE_SIZE - 1) >> PAGE_BITS
|
||||||
for unsigned p = 0; p < pages; ++p:
|
for unsigned p = 0; p < pages; ++p:
|
||||||
Iris::Page page = Iris::my_memory.create_page ()
|
Iris::Page page = Iris::my_memory.create_page ()
|
||||||
page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME, Iris::Page::PAYING | Iris::Page::FRAME)
|
page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME)
|
||||||
Iris::my_memory.map (page, _free + rest + (p << PAGE_BITS))
|
Iris::my_memory.map (page, _free + rest + (p << PAGE_BITS))
|
||||||
Iris::free_cap (page)
|
Iris::free_cap (page)
|
||||||
_free += size
|
_free += size
|
||||||
@ -147,15 +147,22 @@ struct Fat:
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
void map_fat_cluster (unsigned c, unsigned offset = 0):
|
void map_fat_cluster (unsigned c, unsigned offset = 0):
|
||||||
read_block ((hidden_sectors + reserved_sectors + ((c * bits + 8 * offset) >> (sector_size_bits + 3))) << sector_size_bits)
|
//unsigned b = current_block.l
|
||||||
|
read_block ((reserved_sectors + ((c * bits + 8 * offset) >> (sector_size_bits + 3))) << sector_size_bits)
|
||||||
|
//if b != current_block.l:
|
||||||
|
//for unsigned i = 0; i < 0x20; ++i:
|
||||||
|
//kdebug (" ")
|
||||||
|
//kdebug_num (data[i], 2)
|
||||||
|
//kdebug ("\n")
|
||||||
|
|
||||||
unsigned make_bits (unsigned orig):
|
unsigned make_bits (unsigned orig):
|
||||||
unsigned ret
|
unsigned ret
|
||||||
for ret = 0; ret < 32; ++ret:
|
for ret = 0; ret < 32; ++ret:
|
||||||
if orig == 1 << ret:
|
if orig == 1 << ret:
|
||||||
return ret
|
return ret
|
||||||
Iris::panic (ret, "non-power of 2")
|
//Iris::panic (orig, "non-power of 2")
|
||||||
return ret
|
kdebug ("not a power of two, using 16\n")
|
||||||
|
return 16
|
||||||
|
|
||||||
void reset ():
|
void reset ():
|
||||||
read_block (0)
|
read_block (0)
|
||||||
@ -182,7 +189,7 @@ struct Fat:
|
|||||||
kdebug ("warning: limiting sectors because of limited device size\n")
|
kdebug ("warning: limiting sectors because of limited device size\n")
|
||||||
|
|
||||||
root_sectors = (root_entries * 32 + (1 << sector_size_bits) - 1) >> sector_size_bits
|
root_sectors = (root_entries * 32 + (1 << sector_size_bits) - 1) >> sector_size_bits
|
||||||
header_sectors = hidden_sectors + reserved_sectors + sectors_per_fat * num_fats + root_sectors
|
header_sectors = reserved_sectors + sectors_per_fat * num_fats + root_sectors
|
||||||
clusters = (sectors - header_sectors) >> sectors_per_cluster_bits
|
clusters = (sectors - header_sectors) >> sectors_per_cluster_bits
|
||||||
unsigned skip
|
unsigned skip
|
||||||
if clusters >= 65525:
|
if clusters >= 65525:
|
||||||
@ -254,6 +261,7 @@ struct Fat:
|
|||||||
bad_clusters = 0
|
bad_clusters = 0
|
||||||
fat = new unsigned[clusters]
|
fat = new unsigned[clusters]
|
||||||
unsigned counted_free_clusters = 0
|
unsigned counted_free_clusters = 0
|
||||||
|
first_free_cluster = ~0
|
||||||
for unsigned c = 0; c < clusters; ++c:
|
for unsigned c = 0; c < clusters; ++c:
|
||||||
// reduced cluster.
|
// reduced cluster.
|
||||||
unsigned rc = c & (1 << sector_size_bits) - 1
|
unsigned rc = c & (1 << sector_size_bits) - 1
|
||||||
@ -288,6 +296,9 @@ struct Fat:
|
|||||||
else if bits == 12 && fat[c] == 0xfff || bits == 16 && fat[c] == 0xffff || bits == 32 && fat[c] == 0xfffffff:
|
else if bits == 12 && fat[c] == 0xfff || bits == 16 && fat[c] == 0xffff || bits == 32 && fat[c] == 0xfffffff:
|
||||||
// Last cluster in chain.
|
// Last cluster in chain.
|
||||||
fat[c] = ~0
|
fat[c] = ~0
|
||||||
|
kdebug ("last cluster: ")
|
||||||
|
kdebug_num (c)
|
||||||
|
kdebug ("\n")
|
||||||
else if bits == 12 && fat[c] == 0xff7 || bits == 16 && fat[c] == 0xfff7 || bits == 32 && fat[c] == 0xffffff7:
|
else if bits == 12 && fat[c] == 0xff7 || bits == 16 && fat[c] == 0xfff7 || bits == 32 && fat[c] == 0xffffff7:
|
||||||
// Bad cluster.
|
// Bad cluster.
|
||||||
fat[c] = first_bad_cluster
|
fat[c] = first_bad_cluster
|
||||||
@ -296,12 +307,24 @@ struct Fat:
|
|||||||
else:
|
else:
|
||||||
// Non-last cluster in chain.
|
// Non-last cluster in chain.
|
||||||
fat[c] -= 2
|
fat[c] -= 2
|
||||||
|
kdebug_num (c)
|
||||||
|
kdebug (" -> ")
|
||||||
|
kdebug_num (fat[c])
|
||||||
|
kdebug ("\n")
|
||||||
unsigned fat_lookup (unsigned first_cluster, unsigned cluster):
|
unsigned fat_lookup (unsigned first_cluster, unsigned cluster):
|
||||||
|
//kdebug ("looking up ")
|
||||||
|
//kdebug_num (first_cluster)
|
||||||
|
//kdebug ("+")
|
||||||
|
//kdebug_num (cluster)
|
||||||
|
//kdebug (":")
|
||||||
while cluster--:
|
while cluster--:
|
||||||
first_cluster = fat[first_cluster]
|
first_cluster = fat[first_cluster]
|
||||||
|
//kdebug ("->")
|
||||||
|
//kdebug_num (first_cluster)
|
||||||
if first_cluster == ~0:
|
if first_cluster == ~0:
|
||||||
kdebug ("sector beyond end of file requested\n")
|
//kdebug ("sector beyond end of file requested\n")
|
||||||
return ~0
|
return ~0
|
||||||
|
//kdebug ("\n")
|
||||||
return first_cluster
|
return first_cluster
|
||||||
struct File:
|
struct File:
|
||||||
Fat *fat
|
Fat *fat
|
||||||
@ -310,22 +333,22 @@ struct Fat:
|
|||||||
char name[11]
|
char name[11]
|
||||||
bool archive, readonly, system, hidden, directory, volume
|
bool archive, readonly, system, hidden, directory, volume
|
||||||
unsigned create_second, create_minute_hour, create_date, access_date, time, date
|
unsigned create_second, create_minute_hour, create_date, access_date, time, date
|
||||||
|
unsigned checksum
|
||||||
void load_cluster (unsigned idx, Iris::Page p = page, unsigned offset = 0):
|
void load_cluster (unsigned idx, Iris::Page p = page, unsigned offset = 0):
|
||||||
unsigned cluster = fat->fat_lookup (first_cluster, idx >> fat->cluster_size_bits)
|
unsigned cluster = fat->fat_lookup (first_cluster, idx >> fat->cluster_size_bits)
|
||||||
kdebug ("loading cluster ")
|
//kdebug ("loading cluster ")
|
||||||
kdebug_num (idx)
|
//kdebug_num (idx)
|
||||||
kdebug ("@")
|
//kdebug ("@")
|
||||||
kdebug_num (cluster)
|
//kdebug_num (cluster)
|
||||||
kdebug (" from file\n")
|
//kdebug (" from file\n")
|
||||||
if cluster == ~0:
|
if cluster == ~0:
|
||||||
kdebug ("invalid cluster requested from file\n")
|
kdebug ("invalid cluster requested from file\n")
|
||||||
return
|
return
|
||||||
read_block ((fat->header_sectors + (Iris::Num (cluster).value () << fat->sectors_per_cluster_bits)) << fat->sector_size_bits, p, 1 << fat->cluster_size_bits, offset)
|
read_block ((fat->header_sectors + (Iris::Num (cluster).value () << fat->sectors_per_cluster_bits)) << fat->sector_size_bits, p, 1 << fat->cluster_size_bits, offset)
|
||||||
kdebug ("sector ")
|
//kdebug ("sector ")
|
||||||
kdebug_num (fat->header_sectors + (Iris::Num (cluster).value () << fat->sectors_per_cluster_bits))
|
//kdebug_num (fat->header_sectors + (Iris::Num (cluster).value () << fat->sectors_per_cluster_bits))
|
||||||
kdebug ("\n")
|
//kdebug ("\n")
|
||||||
void get_dir_entry (unsigned dir, unsigned idx, File *f):
|
char *load_dir_entry (unsigned dir, unsigned idx):
|
||||||
f->fat = this
|
|
||||||
unsigned sector = idx >> (sector_size_bits - 5)
|
unsigned sector = idx >> (sector_size_bits - 5)
|
||||||
unsigned num = (idx << 5) & ~BLOCK_MASK
|
unsigned num = (idx << 5) & ~BLOCK_MASK
|
||||||
Iris::Num hwsector
|
Iris::Num hwsector
|
||||||
@ -333,27 +356,56 @@ struct Fat:
|
|||||||
if sector < root_sectors:
|
if sector < root_sectors:
|
||||||
hwsector = header_sectors - root_sectors + sector
|
hwsector = header_sectors - root_sectors + sector
|
||||||
else:
|
else:
|
||||||
hwsector = ~0
|
return NULL
|
||||||
else:
|
else:
|
||||||
unsigned entry = fat_lookup (dir, sector)
|
unsigned entry = fat_lookup (dir, sector)
|
||||||
if entry == ~0:
|
if entry == ~0:
|
||||||
hwsector = ~0
|
return NULL
|
||||||
else:
|
hwsector = header_sectors + (Iris::Num (entry).value () << sectors_per_cluster_bits)
|
||||||
hwsector = header_sectors + (Iris::Num (entry).value () << sectors_per_cluster_bits)
|
|
||||||
if hwsector.value () == ~0:
|
|
||||||
kdebug ("invalid sector requested from directory\n")
|
|
||||||
f->first_cluster = ~0
|
|
||||||
return
|
|
||||||
read_block (hwsector.value () << sector_size_bits)
|
read_block (hwsector.value () << sector_size_bits)
|
||||||
char *e = &data[num]
|
return &data[num]
|
||||||
|
char *find_idx (unsigned dir, unsigned *idx, unsigned *count = NULL):
|
||||||
|
unsigned todo = *idx + 1
|
||||||
|
char *e
|
||||||
|
if count:
|
||||||
|
*count = 0
|
||||||
|
for *idx = 0; todo; ++*idx:
|
||||||
|
e = load_dir_entry (dir, *idx)
|
||||||
|
if !e:
|
||||||
|
return NULL
|
||||||
|
if (e[0xb] & 0xff) == 0xf:
|
||||||
|
// This is part of a long filename.
|
||||||
|
continue
|
||||||
|
if (e[0] & 0xff) == 0xe5:
|
||||||
|
// This is a deleted file.
|
||||||
|
continue
|
||||||
|
if !e[0]:
|
||||||
|
// This is a free entry.
|
||||||
|
continue
|
||||||
|
if count:
|
||||||
|
++*count
|
||||||
|
--todo
|
||||||
|
--*idx
|
||||||
|
return e
|
||||||
|
unsigned get_dir_size (unsigned dir):
|
||||||
|
unsigned num = 0 - 2
|
||||||
|
unsigned ret
|
||||||
|
find_idx (dir, &num, &ret)
|
||||||
|
return ret
|
||||||
|
bool get_dir_entry (unsigned dir, unsigned idx, File *f):
|
||||||
|
char *e = load_dir_entry (dir, idx)
|
||||||
|
if !e:
|
||||||
|
kdebug ("unable to load dir entry\n")
|
||||||
|
return false
|
||||||
|
f->fat = this
|
||||||
for unsigned i = 0; i < 11; ++i:
|
for unsigned i = 0; i < 11; ++i:
|
||||||
f->name[i] = e[i]
|
f->name[i] = e[i]
|
||||||
f->archive = e[0xb] & 0x20
|
f->readonly = e[0xb] & 0x1
|
||||||
f->readonly = e[0xb] & 0x10
|
f->system = e[0xb] & 0x2
|
||||||
f->system = e[0xb] & 0x8
|
|
||||||
f->hidden = e[0xb] & 0x4
|
f->hidden = e[0xb] & 0x4
|
||||||
f->directory = e[0xb] & 0x2
|
f->volume = e[0xb] & 0x8
|
||||||
f->volume = e[0xb] & 0x1
|
f->directory = e[0xb] & 0x10
|
||||||
|
f->archive = e[0xb] & 0x20
|
||||||
f->create_second = read_num (e + 0xd, 1)
|
f->create_second = read_num (e + 0xd, 1)
|
||||||
f->create_minute_hour = read_num (e + 0xe, 2)
|
f->create_minute_hour = read_num (e + 0xe, 2)
|
||||||
f->create_date = read_num (e + 0x10, 2)
|
f->create_date = read_num (e + 0x10, 2)
|
||||||
@ -362,6 +414,71 @@ struct Fat:
|
|||||||
f->date = read_num (e + 0x18, 1)
|
f->date = read_num (e + 0x18, 1)
|
||||||
f->size = read_num (e + 0x1c, 4)
|
f->size = read_num (e + 0x1c, 4)
|
||||||
f->first_cluster = (read_num (e + 0x14, 2) << 16 | read_num (e + 0x1a, 2)) - 2
|
f->first_cluster = (read_num (e + 0x14, 2) << 16 | read_num (e + 0x1a, 2)) - 2
|
||||||
|
f->checksum = 0
|
||||||
|
for unsigned i = 0; i < 11; ++i:
|
||||||
|
f->checksum = ((((f->checksum & 1) << 7) | ((f->checksum & 0xfe) >> 1)) + f->name[i]) & 0xff
|
||||||
|
//kdebug ("loaded dir entry, first cluster = ")
|
||||||
|
//kdebug_num (f->first_cluster)
|
||||||
|
//kdebug ("\n")
|
||||||
|
return true
|
||||||
|
struct LFN:
|
||||||
|
unsigned ordinal
|
||||||
|
unsigned name[13]
|
||||||
|
unsigned checksum
|
||||||
|
bool load_lfn (unsigned dir, unsigned idx, unsigned t, unsigned checksum, LFN *lfn):
|
||||||
|
if t >= idx:
|
||||||
|
return false
|
||||||
|
char *e = load_dir_entry (dir, idx - t - 1)
|
||||||
|
if (e[0xb] & 0xff) != 0xf:
|
||||||
|
return false
|
||||||
|
lfn->ordinal = read_num (e + 0x00, 1)
|
||||||
|
for unsigned i = 0; i < 5; ++i:
|
||||||
|
lfn->name[i] = read_num (e + 0x01 + 2 * i, 2)
|
||||||
|
lfn->checksum = read_num (e + 0xd, 1)
|
||||||
|
for unsigned i = 0; i < 6; ++i:
|
||||||
|
lfn->name[i + 5] = read_num (e + 0xe + 2 * i, 2)
|
||||||
|
for unsigned i = 0; i < 2; ++i:
|
||||||
|
lfn->name[i + 11] = read_num (e + 0x1c + 2 * i, 2)
|
||||||
|
return true
|
||||||
|
unsigned parse_shortname (File const &f, char *name):
|
||||||
|
if f.name[0] == ' ':
|
||||||
|
Iris::panic (0, "fat name starts with space")
|
||||||
|
unsigned len = 8
|
||||||
|
while f.name[len - 1] == ' ':
|
||||||
|
--len
|
||||||
|
char *ptr = name
|
||||||
|
for unsigned i = 0; i < len; ++i:
|
||||||
|
*ptr++ = f.name[i]
|
||||||
|
if f.name[8] == ' ':
|
||||||
|
return len
|
||||||
|
*ptr++ = '.'
|
||||||
|
len = 3
|
||||||
|
while f.name[8 + len - 1] == ' ':
|
||||||
|
--len
|
||||||
|
for unsigned i = 0; i < len; ++i:
|
||||||
|
*ptr++ = f.name[8 + i]
|
||||||
|
return ptr - name
|
||||||
|
unsigned get_name_size (unsigned dir, unsigned idx, File const &f):
|
||||||
|
LFN lfn
|
||||||
|
unsigned num = 0
|
||||||
|
if !load_lfn (dir, idx, 0, f.checksum, &lfn):
|
||||||
|
// Not a long filename.
|
||||||
|
char n[12]
|
||||||
|
return parse_shortname (f, n)
|
||||||
|
unsigned ordinal = 0
|
||||||
|
while true:
|
||||||
|
if !load_lfn (dir, idx, num, f.checksum, &lfn):
|
||||||
|
Iris::panic (0, "error parsing long filename")
|
||||||
|
if (lfn.ordinal & 0x3f) != ++ordinal:
|
||||||
|
Iris::panic (lfn.ordinal, "error in sequence for long filename")
|
||||||
|
if lfn.ordinal & 0x40:
|
||||||
|
break
|
||||||
|
++num
|
||||||
|
unsigned i
|
||||||
|
for i = 0; i < 13; ++i:
|
||||||
|
if !lfn.name[i]:
|
||||||
|
break
|
||||||
|
return num * 13 + i
|
||||||
|
|
||||||
// Capability encoding.
|
// Capability encoding.
|
||||||
// 0:ROOT_CLUSTER = non fat-32 root directory.
|
// 0:ROOT_CLUSTER = non fat-32 root directory.
|
||||||
@ -379,7 +496,7 @@ Iris::Num start ():
|
|||||||
device_size = dev.get_size ()
|
device_size = dev.get_size ()
|
||||||
data = (char *)0x15000; //alloc_space (1)
|
data = (char *)0x15000; //alloc_space (1)
|
||||||
page = Iris::my_memory.create_page ()
|
page = Iris::my_memory.create_page ()
|
||||||
page.set_flags (Iris::Page::PAYING, Iris::Page::PAYING)
|
page.set_flags (Iris::Page::PAYING)
|
||||||
Iris::my_memory.map (page, (unsigned)data)
|
Iris::my_memory.map (page, (unsigned)data)
|
||||||
|
|
||||||
Fat fat
|
Fat fat
|
||||||
@ -400,6 +517,7 @@ Iris::Num start ():
|
|||||||
Iris::wait ()
|
Iris::wait ()
|
||||||
unsigned dir = Iris::recv.protected_data.h
|
unsigned dir = Iris::recv.protected_data.h
|
||||||
if dir & 0x80000000:
|
if dir & 0x80000000:
|
||||||
|
dir &= ~0x80000000
|
||||||
// File name.
|
// File name.
|
||||||
unsigned idx = Iris::recv.protected_data.l
|
unsigned idx = Iris::recv.protected_data.l
|
||||||
Iris::Cap reply = Iris::get_reply ()
|
Iris::Cap reply = Iris::get_reply ()
|
||||||
@ -407,23 +525,55 @@ Iris::Num start ():
|
|||||||
unsigned size = Iris::recv.data[0].h >> 16
|
unsigned size = Iris::recv.data[0].h >> 16
|
||||||
unsigned cmd = Iris::recv.data[0].l
|
unsigned cmd = Iris::recv.data[0].l
|
||||||
Fat::File f
|
Fat::File f
|
||||||
fat.get_dir_entry (dir & ~0x80000000, idx, &f)
|
if !fat.find_idx (dir, &idx):
|
||||||
|
Iris::panic (Iris::recv.protected_data.l, "invalid index")
|
||||||
|
if !fat.get_dir_entry (dir, idx, &f):
|
||||||
|
Iris::panic (Iris::recv.protected_data.l, "invalid dir entry requested for filename")
|
||||||
switch cmd:
|
switch cmd:
|
||||||
case Iris::String::GET_SIZE:
|
case Iris::String::GET_SIZE:
|
||||||
kdebug ("filename size requested\n")
|
//kdebug ("filename size requested\n")
|
||||||
reply.invoke (11)
|
reply.invoke (fat.get_name_size (dir, idx, f))
|
||||||
break
|
break
|
||||||
case Iris::String::GET_CHARS:
|
case Iris::String::GET_CHARS:
|
||||||
//kdebug ("filename chars requested\n")
|
//kdebug ("filename chars requested\n")
|
||||||
|
//kdebug ("flags: ")
|
||||||
|
//kdebug_char (f.readonly ? 'R' : 'r')
|
||||||
|
//kdebug_char (f.system ? 'S' : 's')
|
||||||
|
//kdebug_char (f.hidden ? 'H' : 'h')
|
||||||
|
//kdebug_char (f.volume ? 'V' : 'v')
|
||||||
|
//kdebug_char (f.directory ? 'D' : 'd')
|
||||||
|
//kdebug_char (f.archive ? 'A' : 'a')
|
||||||
|
//kdebug_char ('\n')
|
||||||
|
|
||||||
/**/union { unsigned u[4]; char c[16]; } u
|
/**/union { unsigned u[4]; char c[16]; } u
|
||||||
for unsigned k = 0; k < 4; ++k:
|
for unsigned k = 0; k < 4; ++k:
|
||||||
u.u[k] = 0
|
u.u[k] = 0
|
||||||
for unsigned k = 0; k + num < 11; ++k:
|
Fat::LFN lfn
|
||||||
u.c[k] = f.name[k + num]
|
if !fat.load_lfn (dir, idx, 0, f.checksum, &lfn):
|
||||||
|
// Not a long filename.
|
||||||
|
char n[12]
|
||||||
|
unsigned len = fat.parse_shortname (f, n)
|
||||||
|
//kdebug ("short filename: ")
|
||||||
|
for unsigned k = 0; k + num < len; ++k:
|
||||||
|
u.c[k] = n[k + num]
|
||||||
|
//kdebug_char (u.c[k])
|
||||||
|
//kdebug ("\n")
|
||||||
|
else:
|
||||||
|
// Very inefficient, but it works: reload everything for every character.
|
||||||
|
//kdebug ("filename: ")
|
||||||
|
for unsigned c = 0; c < 16; ++c:
|
||||||
|
if !fat.load_lfn (dir, idx, (num + c) / 13, f.checksum, &lfn):
|
||||||
|
// Filename isn't this long: keep the rest at 0.
|
||||||
|
break
|
||||||
|
u.c[c] = lfn.name[(num + c) % 13]
|
||||||
|
if u.c[c] == 0:
|
||||||
|
break
|
||||||
|
//kdebug_char (u.c[c])
|
||||||
|
//kdebug ("\n")
|
||||||
reply.invoke (Iris::Num (u.u[0], u.u[1]), Iris::Num (u.u[2], u.u[3]))
|
reply.invoke (Iris::Num (u.u[0], u.u[1]), Iris::Num (u.u[2], u.u[3]))
|
||||||
break
|
break
|
||||||
case Iris::String::GET_ALIGN_BITS:
|
case Iris::String::GET_ALIGN_BITS:
|
||||||
kdebug ("filename align requested\n")
|
//kdebug ("filename align requested\n")
|
||||||
reply.invoke (0)
|
reply.invoke (0)
|
||||||
break
|
break
|
||||||
case Iris::String::GET_BLOCK:
|
case Iris::String::GET_BLOCK:
|
||||||
@ -431,7 +581,7 @@ Iris::Num start ():
|
|||||||
Iris::panic (Iris::recv.data[0].l, "invalid request for fat filename")
|
Iris::panic (Iris::recv.data[0].l, "invalid request for fat filename")
|
||||||
Iris::free_cap (reply)
|
Iris::free_cap (reply)
|
||||||
else if dir:
|
else if dir:
|
||||||
// File.
|
// If it *has* a directory, it *is* a file.
|
||||||
unsigned idx = Iris::recv.protected_data.l
|
unsigned idx = Iris::recv.protected_data.l
|
||||||
Iris::Cap reply = Iris::get_reply ()
|
Iris::Cap reply = Iris::get_reply ()
|
||||||
Iris::Cap arg = Iris::get_arg ()
|
Iris::Cap arg = Iris::get_arg ()
|
||||||
@ -439,15 +589,17 @@ Iris::Num start ():
|
|||||||
unsigned size = Iris::recv.data[0].h >> 16
|
unsigned size = Iris::recv.data[0].h >> 16
|
||||||
unsigned offset = Iris::recv.data[0].h & 0xffff
|
unsigned offset = Iris::recv.data[0].h & 0xffff
|
||||||
unsigned cmd = Iris::recv.data[0].l
|
unsigned cmd = Iris::recv.data[0].l
|
||||||
|
if !fat.find_idx (dir, &idx):
|
||||||
|
Iris::panic (0, "file not found")
|
||||||
Fat::File f
|
Fat::File f
|
||||||
fat.get_dir_entry (dir, idx, &f)
|
fat.get_dir_entry (dir, idx, &f)
|
||||||
switch cmd:
|
switch cmd:
|
||||||
case Iris::String::GET_SIZE:
|
case Iris::String::GET_SIZE:
|
||||||
kdebug ("file size requested\n")
|
//kdebug ("file size requested\n")
|
||||||
reply.invoke (f.size)
|
reply.invoke (f.size)
|
||||||
break
|
break
|
||||||
case Iris::String::GET_CHARS:
|
case Iris::String::GET_CHARS:
|
||||||
kdebug ("file chars requested\n")
|
//kdebug ("file chars requested\n")
|
||||||
unsigned mask = 1 << (fat.cluster_size_bits) - 1
|
unsigned mask = 1 << (fat.cluster_size_bits) - 1
|
||||||
f.load_cluster (num.l & ~mask)
|
f.load_cluster (num.l & ~mask)
|
||||||
unsigned n = num.l & mask & ~0xf
|
unsigned n = num.l & mask & ~0xf
|
||||||
@ -455,14 +607,14 @@ Iris::Num start ():
|
|||||||
reply.invoke (Iris::Num (dat[0], dat[1]), Iris::Num (dat[2], dat[3]))
|
reply.invoke (Iris::Num (dat[0], dat[1]), Iris::Num (dat[2], dat[3]))
|
||||||
break
|
break
|
||||||
case Iris::String::GET_ALIGN_BITS:
|
case Iris::String::GET_ALIGN_BITS:
|
||||||
kdebug ("file align requested\n")
|
//kdebug ("file align requested\n")
|
||||||
reply.invoke (fat.cluster_size_bits)
|
reply.invoke (fat.cluster_size_bits)
|
||||||
break
|
break
|
||||||
case Iris::String::GET_BLOCK:
|
case Iris::String::GET_BLOCK:
|
||||||
kdebug ("file block requested\n")
|
//kdebug ("file block requested\n")
|
||||||
unsigned mask = 1 << (fat.cluster_size_bits) - 1
|
unsigned mask = 1 << (fat.cluster_size_bits) - 1
|
||||||
if offset > PAGE_SIZE:
|
if offset > PAGE_SIZE:
|
||||||
kdebug ("invalid offset requested\n")
|
//kdebug ("invalid offset requested\n")
|
||||||
break
|
break
|
||||||
if size + offset > PAGE_SIZE:
|
if size + offset > PAGE_SIZE:
|
||||||
size = PAGE_SIZE - offset
|
size = PAGE_SIZE - offset
|
||||||
@ -480,71 +632,58 @@ Iris::Num start ():
|
|||||||
Iris::free_cap (arg)
|
Iris::free_cap (arg)
|
||||||
else:
|
else:
|
||||||
// Directory.
|
// Directory.
|
||||||
if Iris::recv.protected_data.l != ROOT_CLUSTER:
|
switch Iris::recv.data[0].l:
|
||||||
// Normal directory.
|
case Iris::Directory::GET_SIZE:
|
||||||
switch Iris::recv.data[0].l:
|
//kdebug ("dir size requested\n")
|
||||||
case Iris::Directory::GET_SIZE:
|
Iris::Cap reply = Iris::get_reply ()
|
||||||
kdebug ("dir size requested\n")
|
reply.invoke (fat.get_dir_size (Iris::recv.protected_data.l))
|
||||||
Iris::recv.reply.invoke ()
|
Iris::free_cap (reply)
|
||||||
break
|
break
|
||||||
case Iris::Directory::GET_NAME:
|
case Iris::Directory::GET_NAME:
|
||||||
kdebug ("dir name requested\n")
|
//kdebug ("dir name requested\n")
|
||||||
Iris::recv.reply.invoke ()
|
Iris::Cap reply = Iris::get_reply ()
|
||||||
break
|
Iris::Cap ret = Iris::my_receiver.create_capability (Iris::Num (Iris::recv.data[1].l, Iris::recv.protected_data.l | 0x80000000))
|
||||||
case Iris::Directory::GET_FILE_RO:
|
reply.invoke (0, 0, ret.copy ())
|
||||||
kdebug ("dir file requested\n")
|
Iris::free_cap (reply)
|
||||||
Iris::Cap reply = Iris::get_reply ()
|
Iris::free_cap (ret)
|
||||||
Iris::Cap ret = Iris::my_receiver.create_capability (Iris::Num (Iris::recv.data[1].l, Iris::recv.protected_data.l))
|
break
|
||||||
reply.invoke (0, 0, ret.copy ())
|
case Iris::Directory::GET_FILE_RO:
|
||||||
Iris::free_cap (reply)
|
//kdebug ("dir file requested\n")
|
||||||
Iris::free_cap (ret)
|
Iris::Cap reply = Iris::get_reply ()
|
||||||
break
|
dir = Iris::recv.protected_data.l
|
||||||
case Iris::Directory::GET_FILE_INFO:
|
unsigned idx = Iris::recv.data[1].l
|
||||||
kdebug ("dir file info requested\n")
|
if !fat.find_idx (dir, &idx):
|
||||||
Iris::recv.reply.invoke ()
|
Iris::panic (0, "file not found")
|
||||||
break
|
Fat::File f
|
||||||
case Iris::Directory::LOCK_RO:
|
fat.get_dir_entry (dir, idx, &f)
|
||||||
case Iris::Directory::UNLOCK_RO:
|
Iris::Cap ret
|
||||||
kdebug ("dir lock or unlock requested\n")
|
if f.directory:
|
||||||
Iris::recv.reply.invoke ()
|
ret = Iris::my_receiver.create_capability (Iris::Num (f.first_cluster, 0))
|
||||||
break
|
else:
|
||||||
default:
|
ret = Iris::my_receiver.create_capability (Iris::Num (idx, dir))
|
||||||
kdebug ("invalid dir operation requested\n")
|
reply.invoke (0, 0, ret.copy ())
|
||||||
Iris::recv.reply.invoke ()
|
Iris::free_cap (reply)
|
||||||
break
|
Iris::free_cap (ret)
|
||||||
else:
|
break
|
||||||
// Non-fat32 root directory.
|
case Iris::Directory::GET_FILE_INFO:
|
||||||
switch Iris::recv.data[0].l:
|
//kdebug ("dir file info requested\n")
|
||||||
case Iris::Directory::GET_SIZE:
|
Iris::Cap reply = Iris::get_reply ()
|
||||||
kdebug ("root size requested\n")
|
dir = Iris::recv.protected_data.l
|
||||||
Iris::recv.reply.invoke (fat.root_entries)
|
unsigned idx = Iris::recv.data[1].l
|
||||||
break
|
if !fat.find_idx (dir, &idx):
|
||||||
case Iris::Directory::GET_NAME:
|
Iris::panic (0, "file not found")
|
||||||
//kdebug ("root name requested\n")
|
unsigned type = Iris::recv.data[0].h
|
||||||
Iris::Cap reply = Iris::get_reply ()
|
Fat::File f
|
||||||
Iris::Cap ret = Iris::my_receiver.create_capability (Iris::Num (Iris::recv.data[1].l, Iris::recv.protected_data.l | 0x80000000))
|
fat.get_dir_entry (dir, idx, &f)
|
||||||
reply.invoke (0, 0, ret.copy ())
|
reply.invoke (f.directory ? 1 : 0)
|
||||||
Iris::free_cap (reply)
|
Iris::free_cap (reply)
|
||||||
Iris::free_cap (ret)
|
break
|
||||||
break
|
case Iris::Directory::LOCK_RO:
|
||||||
case Iris::Directory::GET_FILE_RO:
|
case Iris::Directory::UNLOCK_RO:
|
||||||
kdebug ("root file requested\n")
|
//kdebug ("dir lock or unlock requested\n")
|
||||||
Iris::Cap reply = Iris::get_reply ()
|
Iris::recv.reply.invoke ()
|
||||||
Iris::Cap ret = Iris::my_receiver.create_capability (Iris::Num (Iris::recv.data[1].l, Iris::recv.protected_data.l))
|
break
|
||||||
reply.invoke (0, 0, ret.copy ())
|
default:
|
||||||
Iris::free_cap (reply)
|
//kdebug ("invalid dir operation requested\n")
|
||||||
Iris::free_cap (ret)
|
Iris::recv.reply.invoke ()
|
||||||
break
|
break
|
||||||
case Iris::Directory::GET_FILE_INFO:
|
|
||||||
kdebug ("root file info requested\n")
|
|
||||||
Iris::recv.reply.invoke ()
|
|
||||||
break
|
|
||||||
case Iris::Directory::LOCK_RO:
|
|
||||||
case Iris::Directory::UNLOCK_RO:
|
|
||||||
kdebug ("root lock or unlock requested\n")
|
|
||||||
Iris::recv.reply.invoke ()
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
kdebug ("invalid root operation requested\n")
|
|
||||||
Iris::recv.reply.invoke ()
|
|
||||||
break
|
|
||||||
|
@ -20,6 +20,9 @@
|
|||||||
#include "iris.hh"
|
#include "iris.hh"
|
||||||
#include "keys.hh"
|
#include "keys.hh"
|
||||||
|
|
||||||
|
#define INIT_CONFIG "init.config"
|
||||||
|
#define INIT_CONFIG_SIZE 12
|
||||||
|
|
||||||
#define NUM_SLOTS 8
|
#define NUM_SLOTS 8
|
||||||
#define NUM_CAPS 32
|
#define NUM_CAPS 32
|
||||||
|
|
||||||
@ -45,7 +48,7 @@ void *operator new[] (unsigned size):
|
|||||||
unsigned pages = ((size - rest) + PAGE_SIZE - 1) >> PAGE_BITS
|
unsigned pages = ((size - rest) + PAGE_SIZE - 1) >> PAGE_BITS
|
||||||
for unsigned p = 0; p < pages; ++p:
|
for unsigned p = 0; p < pages; ++p:
|
||||||
Iris::Page page = Iris::my_memory.create_page ()
|
Iris::Page page = Iris::my_memory.create_page ()
|
||||||
page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME, Iris::Page::PAYING | Iris::Page::FRAME)
|
page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME)
|
||||||
Iris::my_memory.map (page, _free + rest + (p << PAGE_BITS))
|
Iris::my_memory.map (page, _free + rest + (p << PAGE_BITS))
|
||||||
Iris::free_cap (page)
|
Iris::free_cap (page)
|
||||||
_free += size
|
_free += size
|
||||||
@ -277,7 +280,6 @@ static Type types[] = {
|
|||||||
{ "Setting", 7, Iris::Setting::ID },
|
{ "Setting", 7, Iris::Setting::ID },
|
||||||
{ "Directory", 9, Iris::Directory::ID },
|
{ "Directory", 9, Iris::Directory::ID },
|
||||||
{ "WDirectory", 10, Iris::WDirectory::ID },
|
{ "WDirectory", 10, Iris::WDirectory::ID },
|
||||||
{ "Filesystem", 10, Iris::Filesystem::ID },
|
|
||||||
{ "Stream", 6, Iris::Stream::ID },
|
{ "Stream", 6, Iris::Stream::ID },
|
||||||
{ "UI", 2, Iris::UI::ID },
|
{ "UI", 2, Iris::UI::ID },
|
||||||
{ NULL, 0, 0 }
|
{ NULL, 0, 0 }
|
||||||
@ -434,6 +436,9 @@ static void parse_line (char *&line, unsigned maxlen):
|
|||||||
char *name = get_filename (line, maxlen, name_len)
|
char *name = get_filename (line, maxlen, name_len)
|
||||||
include (name, name_len)
|
include (name, name_len)
|
||||||
else:
|
else:
|
||||||
|
for unsigned i = 0; i < maxlen; ++i:
|
||||||
|
kdebug_char (start[i])
|
||||||
|
kdebug_char ('\n')
|
||||||
Iris::panic (0, "invalid line in init.config")
|
Iris::panic (0, "invalid line in init.config")
|
||||||
delspace (start, maxlen)
|
delspace (start, maxlen)
|
||||||
if maxlen:
|
if maxlen:
|
||||||
@ -450,7 +455,7 @@ Iris::Num start ():
|
|||||||
elfrun = Iris::my_parent.get_capability <Iris::Elfrun> ()
|
elfrun = Iris::my_parent.get_capability <Iris::Elfrun> ()
|
||||||
sysreq = NULL
|
sysreq = NULL
|
||||||
top_memory = Iris::get_top_memory ()
|
top_memory = Iris::get_top_memory ()
|
||||||
include ("init.config", 12)
|
include (INIT_CONFIG, INIT_CONFIG_SIZE)
|
||||||
kdebug ("killing boot threads\n")
|
kdebug ("killing boot threads\n")
|
||||||
Iris::my_parent.init_done ()
|
Iris::my_parent.init_done ()
|
||||||
for List <Program>::Item *p = programs.begin (); p; p = p->next:
|
for List <Program>::Item *p = programs.begin (); p; p = p->next:
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
#define SECTOR_BITS 9
|
#define SECTOR_BITS 9
|
||||||
#define BLOCK_MASK (~((1 << SECTOR_BITS) - 1))
|
#define BLOCK_MASK (~((1 << SECTOR_BITS) - 1))
|
||||||
|
|
||||||
|
unsigned bits
|
||||||
|
|
||||||
struct Partition:
|
struct Partition:
|
||||||
static Iris::Num device_size
|
static Iris::Num device_size
|
||||||
unsigned lba_start, lba_size
|
unsigned lba_start, lba_size
|
||||||
@ -28,37 +30,37 @@ struct Partition:
|
|||||||
lba_size = read_num (data + 12)
|
lba_size = read_num (data + 12)
|
||||||
start = Iris::Num (lba_start).value () << SECTOR_BITS
|
start = Iris::Num (lba_start).value () << SECTOR_BITS
|
||||||
size = Iris::Num (lba_size).value () << SECTOR_BITS
|
size = Iris::Num (lba_size).value () << SECTOR_BITS
|
||||||
//kdebug ("Partition read: ")
|
kdebug ("Partition read: ")
|
||||||
//kdebug_num (lba_start)
|
kdebug_num (lba_start)
|
||||||
//kdebug ("+")
|
kdebug ("+")
|
||||||
//kdebug_num (lba_size)
|
kdebug_num (lba_size)
|
||||||
//kdebug ("\n")
|
kdebug ("\n")
|
||||||
|
|
||||||
Iris::Num Partition::device_size
|
Iris::Num Partition::device_size
|
||||||
|
|
||||||
static Iris::WString dev
|
static Iris::WString dev
|
||||||
static void read_block (Iris::Num idx, Iris::Page page, unsigned size = 1 << SECTOR_BITS, unsigned offset = 0):
|
static void read_sector (Iris::Num idx, Iris::Page page, unsigned size = 1 << SECTOR_BITS, unsigned offset = 0):
|
||||||
idx = idx.value () >> SECTOR_BITS
|
|
||||||
offset &= ~PAGE_MASK
|
offset &= ~PAGE_MASK
|
||||||
if size + offset > PAGE_SIZE:
|
if size + offset > PAGE_SIZE:
|
||||||
size = PAGE_SIZE - offset
|
size = PAGE_SIZE - offset
|
||||||
size >>= SECTOR_BITS
|
size >>= SECTOR_BITS
|
||||||
|
idx = idx.value () >> SECTOR_BITS
|
||||||
for unsigned i = 0; i < size; ++i:
|
for unsigned i = 0; i < size; ++i:
|
||||||
dev.get_block ((idx.value () + i) << SECTOR_BITS, 1 << SECTOR_BITS, (i << SECTOR_BITS) + offset, page)
|
dev.get_block ((idx.value () + i) << SECTOR_BITS, 1 << SECTOR_BITS, (i << SECTOR_BITS) + offset, page)
|
||||||
|
|
||||||
Iris::Num start ():
|
Iris::Num start ():
|
||||||
Partition::device_size = 0
|
Partition::device_size = 0
|
||||||
dev = Iris::my_parent.get_capability <Iris::WString> ()
|
dev = Iris::my_parent.get_capability <Iris::WString> ()
|
||||||
if dev.get_align_bits () > SECTOR_BITS:
|
bits = dev.get_align_bits ()
|
||||||
kdebug ("partitioned device doesn't support 512 byte access")
|
if bits > SECTOR_BITS:
|
||||||
return 1
|
Iris::panic (bits, "partitioned device doesn't support 512 byte access\n")
|
||||||
Partition::device_size = dev.get_size ()
|
Partition::device_size = dev.get_size ()
|
||||||
Iris::Page page = Iris::my_memory.create_page ()
|
Iris::Page page = Iris::my_memory.create_page ()
|
||||||
page.set_flags (Iris::Page::PAYING, Iris::Page::PAYING)
|
page.set_flags (Iris::Page::PAYING)
|
||||||
char *buffer = (char *)0x15000
|
char *buffer = (char *)0x15000
|
||||||
unsigned *ubuffer = (unsigned *)buffer
|
unsigned *ubuffer = (unsigned *)buffer
|
||||||
Iris::my_memory.map (page, (unsigned)buffer)
|
Iris::my_memory.map (page, (unsigned)buffer)
|
||||||
read_block (0, page)
|
read_sector (0, page)
|
||||||
|
|
||||||
if buffer[0x1fe] != 0x55 || (buffer[0x1ff] & 0xff) != 0xaa:
|
if buffer[0x1fe] != 0x55 || (buffer[0x1ff] & 0xff) != 0xaa:
|
||||||
kdebug ("invalid mbr signature\n")
|
kdebug ("invalid mbr signature\n")
|
||||||
@ -78,6 +80,9 @@ Iris::Num start ():
|
|||||||
|
|
||||||
while true:
|
while true:
|
||||||
Iris::wait ()
|
Iris::wait ()
|
||||||
|
//kdebug ("partition received: ")
|
||||||
|
//kdebug_num (Iris::recv.data[0].l)
|
||||||
|
//kdebug ("\n")
|
||||||
switch Iris::recv.data[0].l:
|
switch Iris::recv.data[0].l:
|
||||||
case Iris::String::GET_SIZE:
|
case Iris::String::GET_SIZE:
|
||||||
Iris::recv.reply.invoke (partition[Iris::recv.protected_data.l].size)
|
Iris::recv.reply.invoke (partition[Iris::recv.protected_data.l].size)
|
||||||
@ -87,8 +92,8 @@ Iris::Num start ():
|
|||||||
Iris::Num request = Iris::recv.data[1]
|
Iris::Num request = Iris::recv.data[1]
|
||||||
Iris::Num offset = (partition[Iris::recv.protected_data.l].start.value () + (request.value () & BLOCK_MASK)) & 0xf
|
Iris::Num offset = (partition[Iris::recv.protected_data.l].start.value () + (request.value () & BLOCK_MASK)) & 0xf
|
||||||
unsigned page_offset = request.l & ~BLOCK_MASK
|
unsigned page_offset = request.l & ~BLOCK_MASK
|
||||||
page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME, Iris::Page::PAYING | Iris::Page::FRAME)
|
page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME)
|
||||||
read_block (offset, page)
|
read_sector (offset, page)
|
||||||
reply.invoke (Iris::Num (ubuffer[page_offset >> 2 + 0], ubuffer[page_offset >> 2 + 1]), Iris::Num (ubuffer[page_offset >> 2 + 2], ubuffer[page_offset >> 2 + 3]))
|
reply.invoke (Iris::Num (ubuffer[page_offset >> 2 + 0], ubuffer[page_offset >> 2 + 1]), Iris::Num (ubuffer[page_offset >> 2 + 2], ubuffer[page_offset >> 2 + 3]))
|
||||||
page.set_flags (0, Iris::Page::PAYING | Iris::Page::FRAME)
|
page.set_flags (0, Iris::Page::PAYING | Iris::Page::FRAME)
|
||||||
Iris::free_cap (reply)
|
Iris::free_cap (reply)
|
||||||
@ -116,7 +121,7 @@ Iris::Num start ():
|
|||||||
//kdebug (":")
|
//kdebug (":")
|
||||||
//kdebug_num (Iris::Num (offset.value () + p.value ()).l)
|
//kdebug_num (Iris::Num (offset.value () + p.value ()).l)
|
||||||
//kdebug ("\n")
|
//kdebug ("\n")
|
||||||
read_block (offset.value () + p.value (), arg, size, out_offset)
|
read_sector (offset.value () + p.value (), arg, size, out_offset)
|
||||||
reply.invoke ()
|
reply.invoke ()
|
||||||
Iris::free_cap (reply)
|
Iris::free_cap (reply)
|
||||||
Iris::free_cap (arg)
|
Iris::free_cap (arg)
|
||||||
|
@ -66,11 +66,12 @@ class Mmc:
|
|||||||
unsigned get_read_block_size ():
|
unsigned get_read_block_size ():
|
||||||
return read_block_size
|
return read_block_size
|
||||||
unsigned get_block_bits ():
|
unsigned get_block_bits ():
|
||||||
return csd.read_bl_len > csd.write_bl_len ? csd.read_bl_len : csd.write_bl_len
|
return hc ? 9 : csd.read_bl_len > csd.write_bl_len ? csd.read_bl_len : csd.write_bl_len
|
||||||
void fill_page (Iris::Page page, Iris::Num address, unsigned size, unsigned offset)
|
void fill_page (Iris::Page page, Iris::Num address, unsigned size, unsigned offset)
|
||||||
private:
|
private:
|
||||||
unsigned rca
|
unsigned rca
|
||||||
bool have_sdmem, have_io
|
bool have_sdmem, have_io
|
||||||
|
bool hc
|
||||||
CID cid
|
CID cid
|
||||||
CSD csd
|
CSD csd
|
||||||
unsigned num_blocks, read_block_size
|
unsigned num_blocks, read_block_size
|
||||||
@ -94,7 +95,8 @@ bool Mmc::send (unsigned cmd, unsigned arg, Response_type response_type, unsigne
|
|||||||
Iris::panic (0, "crc error in mmc response")
|
Iris::panic (0, "crc error in mmc response")
|
||||||
return false
|
return false
|
||||||
if stat & MSC_STAT_TIME_OUT_RES:
|
if stat & MSC_STAT_TIME_OUT_RES:
|
||||||
//kdebug ("time out waiting for mmc response\n")
|
kdebug ("time out waiting for mmc response\n")
|
||||||
|
MSC_IREG = MSC_IREG_END_CMD_RES
|
||||||
return false
|
return false
|
||||||
if response_type == R2:
|
if response_type == R2:
|
||||||
unsigned d = MSC_RES
|
unsigned d = MSC_RES
|
||||||
@ -161,20 +163,28 @@ bool Mmc::send (unsigned cmd, unsigned arg, Response_type response_type, unsigne
|
|||||||
// 1 0.1 15.4
|
// 1 0.1 15.4
|
||||||
csd.tmp_write_protect = d & 0x10
|
csd.tmp_write_protect = d & 0x10
|
||||||
// Ignore file_format. 2 (+ 2) 0.4 16.0 ***
|
// Ignore file_format. 2 (+ 2) 0.4 16.0 ***
|
||||||
read_block_size = 1 << csd.read_bl_len
|
read_block_size = hc ? 512 : 1 << csd.read_bl_len
|
||||||
num_blocks = (csd.c_size + 1) << (csd.c_size_mult + 2)
|
num_blocks = (csd.c_size + 1) << (csd.c_size_mult + 2)
|
||||||
|
if hc:
|
||||||
|
if csd.read_bl_len < 9:
|
||||||
|
num_blocks >>= 9 - csd.read_bl_len
|
||||||
|
else:
|
||||||
|
num_blocks <<= csd.read_bl_len - 9
|
||||||
else if response_type != NONE:
|
else if response_type != NONE:
|
||||||
unsigned r = MSC_RES
|
unsigned r = MSC_RES
|
||||||
if response_type == R3:
|
if response_type == R3:
|
||||||
if r >> 8 != 0x3f:
|
if r >> 8 != 0x3f:
|
||||||
Iris::panic (r, "r3 response was not 3f")
|
Iris::panic (r, "r3 response was not 3f")
|
||||||
else if r >> 8 != cmd:
|
else if r >> 8 != cmd:
|
||||||
|
kdebug ("stat: ")
|
||||||
|
kdebug_num (MSC_STAT)
|
||||||
Iris::panic (r, "response doesn't match command")
|
Iris::panic (r, "response doesn't match command")
|
||||||
r <<= 24
|
r <<= 24
|
||||||
r |= MSC_RES << 8
|
r |= MSC_RES << 8
|
||||||
r |= MSC_RES & 0xff
|
r |= MSC_RES & 0xff
|
||||||
if response:
|
if response:
|
||||||
*response = r
|
*response = r
|
||||||
|
else:
|
||||||
//kdebug ("extra response fifo read: ")
|
//kdebug ("extra response fifo read: ")
|
||||||
//for unsigned i = 0; i < 9; ++i:
|
//for unsigned i = 0; i < 9; ++i:
|
||||||
//kdebug (" ")
|
//kdebug (" ")
|
||||||
@ -225,21 +235,10 @@ void Mmc::reset ():
|
|||||||
// Start the clock.
|
// Start the clock.
|
||||||
MSC_STRPCL = MSC_STRPCL_CLOCK_CONTROL_START
|
MSC_STRPCL = MSC_STRPCL_CLOCK_CONTROL_START
|
||||||
// Set cards, if any, to idle.
|
// Set cards, if any, to idle.
|
||||||
MSC_CMD = 0
|
send (0, 0, NONE)
|
||||||
MSC_CMDAT = MSC_CMDAT_RESPONSE_NONE
|
|
||||||
Iris::register_interrupt (IRQ_MSC)
|
|
||||||
msc_start_op ()
|
|
||||||
Iris::wait_for_interrupt (IRQ_MSC)
|
|
||||||
msc_ireg_clear_end_cmd_res ()
|
|
||||||
|
|
||||||
// Reset SDIO device, if any.
|
// Reset SDIO device, if any.
|
||||||
MSC_CMD = 52
|
send (52, 0x88000c08, R5)
|
||||||
MSC_ARG = 0x88000C08
|
|
||||||
MSC_CMDAT = MSC_CMDAT_RESPONSE_R5
|
|
||||||
Iris::register_interrupt (IRQ_MSC)
|
|
||||||
msc_start_op ()
|
|
||||||
Iris::wait_for_interrupt (IRQ_MSC)
|
|
||||||
msc_ireg_clear_end_cmd_res ()
|
|
||||||
|
|
||||||
void Mmc::check_mmc ():
|
void Mmc::check_mmc ():
|
||||||
//kdebug ("checking mmc\n")
|
//kdebug ("checking mmc\n")
|
||||||
@ -253,11 +252,10 @@ void Mmc::check_mmc ():
|
|||||||
|
|
||||||
void Mmc::check_sdmem ():
|
void Mmc::check_sdmem ():
|
||||||
kdebug ("checking sdmem\n")
|
kdebug ("checking sdmem\n")
|
||||||
send (0, 0, NONE)
|
|
||||||
// 2. Send CMD55. Here the default RCA 0x0000 is used for CMD55.
|
// 2. Send CMD55. Here the default RCA 0x0000 is used for CMD55.
|
||||||
// 3. If the response is correct (CMD55 has response), then continue, else go to check MMC.
|
// 3. If the response is correct (CMD55 has response), then continue, else go to check MMC.
|
||||||
unsigned code
|
unsigned code
|
||||||
bool hc = false
|
hc = false
|
||||||
if send (8, 0x1aa, R7, &code) && (code & 0xff) == 0xaa:
|
if send (8, 0x1aa, R7, &code) && (code & 0xff) == 0xaa:
|
||||||
kdebug ("hc\n")
|
kdebug ("hc\n")
|
||||||
hc = true
|
hc = true
|
||||||
@ -357,25 +355,45 @@ void Mmc::fill_page (Iris::Page page, Iris::Num address, unsigned size, unsigned
|
|||||||
if address.h:
|
if address.h:
|
||||||
Iris::panic (0, "page too high: not supported")
|
Iris::panic (0, "page too high: not supported")
|
||||||
return
|
return
|
||||||
unsigned blockmask = ~((1 << get_block_bits ()) - 1)
|
//kdebug ("smc get page ")
|
||||||
|
//kdebug_num (address.l)
|
||||||
|
//kdebug ("+")
|
||||||
|
//kdebug_num (size)
|
||||||
|
//kdebug ("@")
|
||||||
|
//kdebug_num (offset)
|
||||||
|
//kdebug ("\n")
|
||||||
|
unsigned blockmask = ~((1 << 9) - 1)
|
||||||
unsigned p = address.l & blockmask
|
unsigned p = address.l & blockmask
|
||||||
size &= blockmask
|
size &= blockmask
|
||||||
offset &= ~PAGE_MASK
|
offset &= ~PAGE_MASK
|
||||||
if size + offset > PAGE_SIZE:
|
if size + offset > PAGE_SIZE:
|
||||||
size = PAGE_SIZE - offset
|
size = PAGE_SIZE - offset
|
||||||
page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME, Iris::Page::PAYING | Iris::Page::FRAME)
|
page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME)
|
||||||
page.share (buffer_page)
|
page.share (buffer_page)
|
||||||
buffer_page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME, Iris::Page::PAYING | Iris::Page::FRAME)
|
buffer_page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME)
|
||||||
MSC_NOB = 1
|
MSC_NOB = 1
|
||||||
MSC_BLKLEN = read_block_size
|
MSC_BLKLEN = 1 << 9
|
||||||
for unsigned a = 0; a < size; a += 1 << get_block_bits ():
|
for unsigned a = 0; a < size; a += 1 << 9:
|
||||||
|
//kdebug_num (a)
|
||||||
|
//kdebug ("/")
|
||||||
|
//kdebug_num (size)
|
||||||
|
//kdebug (" ==> ")
|
||||||
if !send (17, p + a, DATA):
|
if !send (17, p + a, DATA):
|
||||||
Iris::panic (0, "unable to request data")
|
Iris::panic (0, "unable to request data")
|
||||||
for unsigned aa = 0; aa < read_block_size; aa += 4:
|
for unsigned aa = 0; aa < 1 << 9; aa += 4:
|
||||||
Iris::register_interrupt (IRQ_MSC)
|
while MSC_STAT & MSC_STAT_DATA_FIFO_EMPTY:
|
||||||
Iris::wait_for_interrupt (IRQ_MSC)
|
Iris::register_interrupt (IRQ_MSC)
|
||||||
|
Iris::wait_for_interrupt (IRQ_MSC)
|
||||||
*(unsigned *)(buffer + a + aa + offset) = MSC_RXFIFO
|
*(unsigned *)(buffer + a + aa + offset) = MSC_RXFIFO
|
||||||
|
//unsigned d = *(unsigned *)(buffer + a + aa + offset)
|
||||||
|
//if (aa & 0x3f) == 0:
|
||||||
|
//kdebug ("\n")
|
||||||
|
//for unsigned i = 0; i < 4; ++i:
|
||||||
|
//kdebug (" ")
|
||||||
|
//kdebug_num (d >> (8 * i), 2)
|
||||||
|
//kdebug ("\n")
|
||||||
MSC_IREG = MSC_IREG_DATA_TRAN_DONE
|
MSC_IREG = MSC_IREG_DATA_TRAN_DONE
|
||||||
|
//kdebug ("done filling page\n")
|
||||||
|
|
||||||
static Mmc mmc
|
static Mmc mmc
|
||||||
|
|
||||||
@ -436,7 +454,7 @@ Iris::Num start ():
|
|||||||
Iris::panic (0, "get chars from mmc not supported yet")
|
Iris::panic (0, "get chars from mmc not supported yet")
|
||||||
break
|
break
|
||||||
case Iris::String::GET_ALIGN_BITS:
|
case Iris::String::GET_ALIGN_BITS:
|
||||||
Iris::recv.reply.invoke (mmc.get_block_bits ())
|
Iris::recv.reply.invoke (9)
|
||||||
break
|
break
|
||||||
case Iris::String::GET_BLOCK:
|
case Iris::String::GET_BLOCK:
|
||||||
Iris::Cap reply = Iris::get_reply ()
|
Iris::Cap reply = Iris::get_reply ()
|
||||||
|
@ -19,42 +19,40 @@
|
|||||||
#include <iris.hh>
|
#include <iris.hh>
|
||||||
#include <devices.hh>
|
#include <devices.hh>
|
||||||
|
|
||||||
bool match (char const *a, char const *b):
|
bool match (char const *a, char const *b, unsigned l1, unsigned l2):
|
||||||
for unsigned i = 0; i < 11; ++i:
|
if l1 != l2:
|
||||||
|
return false
|
||||||
|
for unsigned i = 0; i < l1; ++i:
|
||||||
if a[i] != b[i]:
|
if a[i] != b[i]:
|
||||||
return false
|
return false
|
||||||
return true
|
return true
|
||||||
|
|
||||||
Iris::Num start ():
|
static bool print_name (Iris::String name, unsigned indent):
|
||||||
Iris::Directory dir = Iris::my_parent.get_capability <Iris::Directory> ()
|
unsigned l = name.get_size ().l
|
||||||
|
for unsigned i = 0; i < indent; ++i:
|
||||||
|
kdebug_char (' ')
|
||||||
|
char part[16]
|
||||||
|
for unsigned i = 0; i < l; i += 16:
|
||||||
|
name.get_chars (i, part)
|
||||||
|
for unsigned k = 0; k < 16 && i * 16 + k < l; ++k:
|
||||||
|
kdebug_char (part[k])
|
||||||
|
kdebug_char ('\n')
|
||||||
|
return match (part, ".", l, 1) || match (part, "..", l, 2)
|
||||||
|
|
||||||
|
static void print_dir (Iris::Directory dir, unsigned indent):
|
||||||
dir.lock_ro ()
|
dir.lock_ro ()
|
||||||
Iris::Num files = dir.get_size ()
|
Iris::Num files = dir.get_size ()
|
||||||
for Iris::Num i = 0; i.value () < files.value (); i = i.value () + 1:
|
for Iris::Num i = 0; i.value () < files.value (); i = i.value () + 1:
|
||||||
Iris::String f = dir.get_name (i)
|
Iris::String f = dir.get_name (i)
|
||||||
char start[16]
|
bool ignore = print_name (f, indent)
|
||||||
f.get_chars (0, start)
|
if !ignore && dir.get_file_info (i, 0).l & 1:
|
||||||
if match (start, "TEST TXT"):
|
Iris::Directory d = dir.get_file_ro (i)
|
||||||
Iris::free_cap (f)
|
print_dir (d, indent + 4)
|
||||||
f = dir.get_file_ro (i)
|
Iris::free_cap (d)
|
||||||
dir.unlock_ro ()
|
|
||||||
Iris::Page p = f.get_block (0)
|
|
||||||
char *mapping = (char *)0x15000
|
|
||||||
Iris::my_memory.map (p, (unsigned)mapping)
|
|
||||||
for unsigned j = 0; j < PAGE_SIZE; ++j:
|
|
||||||
kdebug_char (mapping[j])
|
|
||||||
kdebug_char ('\n')
|
|
||||||
return 0
|
|
||||||
unsigned i
|
|
||||||
for i = 0; i < 16; ++i:
|
|
||||||
if start[i] != 0:
|
|
||||||
break
|
|
||||||
if i < 16:
|
|
||||||
for i = 0; i < 16; ++i:
|
|
||||||
kdebug_num (start[i], 2)
|
|
||||||
kdebug (" ")
|
|
||||||
for i = 0; i < 16; ++i:
|
|
||||||
kdebug_char (start[i])
|
|
||||||
kdebug ("\n")
|
|
||||||
Iris::free_cap (f)
|
Iris::free_cap (f)
|
||||||
kdebug ("file test.txt not found\n")
|
dir.unlock_ro ()
|
||||||
return 1
|
|
||||||
|
Iris::Num start ():
|
||||||
|
Iris::Directory dir = Iris::my_parent.get_capability <Iris::Directory> ()
|
||||||
|
print_dir (dir, 0)
|
||||||
|
return 0
|
||||||
|
@ -218,7 +218,7 @@ void Udc::init ():
|
|||||||
page = (unsigned *)LCD_FRAMEBUFFER_BASE
|
page = (unsigned *)LCD_FRAMEBUFFER_BASE
|
||||||
p = page
|
p = page
|
||||||
buffer_page = Iris::my_memory.create_page ()
|
buffer_page = Iris::my_memory.create_page ()
|
||||||
buffer_page.set_flags (Iris::Page::FRAME | Iris::Page::PAYING, Iris::Page::FRAME | Iris::Page::PAYING)
|
buffer_page.set_flags (Iris::Page::FRAME | Iris::Page::PAYING)
|
||||||
Iris::my_memory.map (buffer_page, (unsigned)page)
|
Iris::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.
|
||||||
@ -517,7 +517,7 @@ void Udc::irq_out (unsigned cmd):
|
|||||||
*p++ = UDC_FIFO (1)
|
*p++ = UDC_FIFO (1)
|
||||||
if p - page == PAGE_SIZE >> 2:
|
if p - page == PAGE_SIZE >> 2:
|
||||||
buffer_page.share (caller_arg, Iris::Page::FORGET)
|
buffer_page.share (caller_arg, Iris::Page::FORGET)
|
||||||
buffer_page.set_flags (Iris::Page::FRAME, Iris::Page::FRAME)
|
buffer_page.set_flags (Iris::Page::FRAME)
|
||||||
caller.invoke ()
|
caller.invoke ()
|
||||||
Iris::free_cap (caller)
|
Iris::free_cap (caller)
|
||||||
Iris::free_cap (caller_arg)
|
Iris::free_cap (caller_arg)
|
||||||
@ -555,8 +555,6 @@ void Udc::log (unsigned c):
|
|||||||
|
|
||||||
enum pdata:
|
enum pdata:
|
||||||
LOG = 32
|
LOG = 32
|
||||||
FS
|
|
||||||
DATA
|
|
||||||
DIRECTORY
|
DIRECTORY
|
||||||
FILE
|
FILE
|
||||||
NAME
|
NAME
|
||||||
@ -571,12 +569,9 @@ Iris::Num start ():
|
|||||||
__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 ()
|
||||||
Iris::register_interrupt (IRQ_UDC)
|
Iris::register_interrupt (IRQ_UDC)
|
||||||
Iris::Filesystem fs = Iris::my_receiver.create_capability (FS)
|
Iris::Directory dir = Iris::my_receiver.create_capability (DIRECTORY)
|
||||||
Iris::String data = Iris::my_receiver.create_capability (DATA)
|
Iris::my_parent.provide_capability <Iris::Directory> (dir.copy ())
|
||||||
Iris::my_parent.provide_capability <Iris::Filesystem> (fs.copy ())
|
Iris::free_cap (dir)
|
||||||
Iris::my_parent.provide_capability <Iris::String> (data.copy ())
|
|
||||||
Iris::free_cap (fs)
|
|
||||||
Iris::free_cap (data)
|
|
||||||
unsigned state = 0
|
unsigned state = 0
|
||||||
while true:
|
while true:
|
||||||
Iris::wait ()
|
Iris::wait ()
|
||||||
@ -590,45 +585,6 @@ Iris::Num start ():
|
|||||||
case LOG:
|
case LOG:
|
||||||
udc.log (Iris::recv.data[0].l)
|
udc.log (Iris::recv.data[0].l)
|
||||||
break
|
break
|
||||||
case DATA:
|
|
||||||
//kdebug ("data request\n")
|
|
||||||
switch Iris::recv.data[0].l:
|
|
||||||
case Iris::Device::RESET:
|
|
||||||
case Iris::String::GET_SIZE:
|
|
||||||
case Iris::String::GET_CHARS:
|
|
||||||
reply.invoke (0)
|
|
||||||
Iris::free_cap (reply)
|
|
||||||
Iris::free_cap (arg)
|
|
||||||
continue
|
|
||||||
case Iris::String::GET_BLOCK:
|
|
||||||
default:
|
|
||||||
reply.invoke (Iris::ERR_INVALID_OPERATION)
|
|
||||||
Iris::free_cap (reply)
|
|
||||||
Iris::free_cap (arg)
|
|
||||||
continue
|
|
||||||
break
|
|
||||||
case FS:
|
|
||||||
//kdebug ("fs request\n")
|
|
||||||
switch Iris::recv.data[0].l:
|
|
||||||
case Iris::Device::RESET:
|
|
||||||
reply.invoke (0)
|
|
||||||
Iris::free_cap (reply)
|
|
||||||
Iris::free_cap (arg)
|
|
||||||
continue
|
|
||||||
case Iris::Filesystem::USE_DEVICE:
|
|
||||||
case Iris::Filesystem::USE_DEVICE_RO:
|
|
||||||
Iris::Directory dir = Iris::my_receiver.create_capability (DIRECTORY)
|
|
||||||
reply.invoke (0, 0, dir.copy ())
|
|
||||||
Iris::free_cap (dir)
|
|
||||||
Iris::free_cap (reply)
|
|
||||||
Iris::free_cap (arg)
|
|
||||||
continue
|
|
||||||
default:
|
|
||||||
reply.invoke (Iris::ERR_INVALID_OPERATION)
|
|
||||||
Iris::free_cap (reply)
|
|
||||||
Iris::free_cap (arg)
|
|
||||||
continue
|
|
||||||
break
|
|
||||||
case DIRECTORY:
|
case DIRECTORY:
|
||||||
//kdebug ("dir request\n")
|
//kdebug ("dir request\n")
|
||||||
switch Iris::recv.data[0].l:
|
switch Iris::recv.data[0].l:
|
||||||
|
Loading…
Reference in New Issue
Block a user