diff --git a/.gitignore b/.gitignore index d2091cd..5bdeab1 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ mips/nanonote/server/install-sh mips/nanonote/server/missing mips/nanonote/server/usb-server fs/ +iris-sd.tar diff --git a/devices.hhp b/devices.hhp index c2ee586..cd4f1ab 100644 --- a/devices.hhp +++ b/devices.hhp @@ -60,7 +60,7 @@ namespace Iris: /// Helper function for get_block. static Page _create_paying_page (): Page ret = my_memory.create_page () - ret.set_flags (Page::PAYING, Page::PAYING) + ret.set_flags (Page::PAYING) 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. 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 (): 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. struct Stream : public Cap: Stream (Cap c = Cap ()) : Cap (c): enum request: - READ = Filesystem::ID + READ = Directory::ID WRITE ID // Try to read size bytes. Returns the number of bytes successfully read. diff --git a/iris.hhp b/iris.hhp index 1d4b4ef..a839c53 100644 --- a/iris.hhp +++ b/iris.hhp @@ -375,8 +375,8 @@ namespace Iris: set_info (PC, pc) void set_sp (unsigned sp): set_info (SP, sp) - void set_flags (unsigned value, unsigned mask): - set_info (FLAGS, value, mask) + void set_flags (unsigned set, unsigned reset = 0): + set_info (FLAGS, set, set | reset) unsigned get_pc (): return get_info (PC) unsigned get_sp (): @@ -384,9 +384,9 @@ namespace Iris: unsigned get_flags (): return get_info (FLAGS) void run (bool run = true): - set_flags (run ? RUNNING : 0, RUNNING) + set_flags (run ? RUNNING : 0, run ? 0 : RUNNING) 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 Caps get_caps (unsigned slot) unsigned get_num_caps (): @@ -461,8 +461,8 @@ namespace Iris: ocall (target, 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): - call (CAP_MASTER_DIRECT | SET_FLAGS, Num (new_flags, mask)) + bool set_flags (unsigned set, unsigned reset = 0): + call (CAP_MASTER_DIRECT | SET_FLAGS, Num (set, set | reset)) return recv.data[0].l == NO_ERROR unsigned physical_address (): return my_thread.ocall (*this, CAP_MASTER_DIRECT | Thread::PRIV_PHYSICAL_ADDRESS).l diff --git a/mbr+fat.txt b/mbr+fat.txt index 54008d0..9f478ea 100644 --- a/mbr+fat.txt +++ b/mbr+fat.txt @@ -81,8 +81,9 @@ long file name: stored in directory entries immediately before the 8.3 name (las 01 a 5 unicode characters. 0b 1 attribute: 000rsh0v. 0c 1 0 -0d 1 checksum +0d 1 checksum of short filename. 0e c 6 unicode characters. 1a 2 0 1c 4 2 unicode characters. +checksum is name[0] rotated 11 times, name[1] 10 times, etc and all added up. diff --git a/mips/nanonote/Makefile.arch b/mips/nanonote/Makefile.arch index bf69f36..0232d58 100644 --- a/mips/nanonote/Makefile.arch +++ b/mips/nanonote/Makefile.arch @@ -18,7 +18,6 @@ load = 0x80000000 UDC_BOOT=1 -ARCH_CXXFLAGS = -DNUM_THREADS=2 ARCH_CPPFLAGS = -I. -Imips -Imips/nanonote -Wa,-mips32 -DNANONOTE -DUSE_SERIAL CROSS = mipsel-linux-gnu- OBJDUMP = $(CROSS)objdump @@ -32,18 +31,23 @@ arch_headers = mips/arch.hh mips/nanonote/jz4740.hh mips/nanonote/board.hh udc_boot_programs = udc sd_boot_programs = sd+mmc partition fat 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) +ifdef UDC_BOOT +boot_threads = $(standard_boot_programs) $(udc_boot_programs) +threadlist = mips/nanonote/threadlist-udc +ARCH_CXXFLAGS = -DNUM_THREADS=2 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 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 $(threadlist).o: $(addprefix fs/,$(addsuffix .elf,$(boot_threads))) 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/elfrun.o: TARGET_FLAGS = -I/usr/include source/gpio.ccp: source/nanonote-gpio.ccp diff --git a/mips/nanonote/server/usb-server.ccp b/mips/nanonote/server/usb-server.ccp index 39408c7..bc1e89f 100644 --- a/mips/nanonote/server/usb-server.ccp +++ b/mips/nanonote/server/usb-server.ccp @@ -322,7 +322,6 @@ static void dump_devices (): std::cerr << "\nSetting: " << Iris::Setting::ID std::cerr << "\nDirectory: " << Iris::Directory::ID std::cerr << "\nWDirectory: " << Iris::WDirectory::ID - std::cerr << "\nFilesystem: " << Iris::Filesystem::ID std::cerr << "\nStream: " << Iris::Stream::ID std::cerr << "\n" diff --git a/mips/nanonote/threadlist-udc.S b/mips/nanonote/threadlist-udc.S index 1270282..461193a 100644 --- a/mips/nanonote/threadlist-udc.S +++ b/mips/nanonote/threadlist-udc.S @@ -21,11 +21,11 @@ .balign 0x1000 thread0: - .incbin "bootinit.elf" + .incbin "fs/bootinit.elf" .balign 0x1000 thread1: - .incbin "udc.elf" + .incbin "fs/udc.elf" .balign 0x1000 thread2: diff --git a/source/bootinit.ccp b/source/bootinit.ccp index 7da0691..e4dcfdd 100644 --- a/source/bootinit.ccp +++ b/source/bootinit.ccp @@ -1,7 +1,7 @@ #pypp 0 // Iris: micro-kernel for a capability-based operating system. -// boot-programs/bootinit.ccp: Bootstrapping code. -// Copyright 2009 Bas Wijnen +// source/bootinit.ccp: Bootstrapping code. +// Copyright 2009-2010 Bas Wijnen // // 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 @@ -22,6 +22,7 @@ #define ELFRUN_NAME "elfrun.elf" #define INIT_NAME "init.elf" + #define NUM_SLOTS 8 #define NUM_CAPS 32 @@ -45,7 +46,7 @@ void *operator new[] (unsigned size): unsigned pages = ((size - rest) + PAGE_SIZE - 1) >> PAGE_BITS for unsigned p = 0; p < pages; ++p: 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::free_cap (page) _free += size @@ -63,35 +64,86 @@ static Iris::Page bss_page // Get the initial block device and filesystem. static Iris::Directory receive_devices (): - Iris::String data - Iris::Filesystem fs - bool have_data = false, have_fs = false - for unsigned i = 0; i < 2; ++i: + Iris::String device + bool have_device = false + Iris::Cap reply[2] + bool have_reply[2] + have_reply[0] = false + have_reply[1] = false + unsigned next = 2 + while true: Iris::wait () - if Iris::recv.data[0].l != Iris::Parent::PROVIDE_CAPABILITY: - Iris::panic (Iris::recv.data[0].l, "Invalid bootstrap request.") - switch Iris::recv.data[1].l: - case Iris::String::ID: - if have_data: - Iris::panic (0, "duplicate device.") - data = Iris::get_arg () - Iris::recv.reply.invoke () - have_data = true + kdebug_num (Iris::recv.protected_data.l, 1) + kdebug (": ") + if Iris::recv.protected_data.l == 0: + kdebug ("sd detect event device request\n") + // SD detection event device request. + // Ignore all; that will result in the driver thinking there is a card. + Iris::recv.reply.invoke () + continue + 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 - case Iris::Filesystem::ID: - if have_fs: - Iris::panic (0, "duplicate filesystem.") - fs = Iris::get_arg () - Iris::recv.reply.invoke () - have_fs = true + case Iris::Parent::GET_CAPABILITY: + if Iris::recv.data[1].l == Iris::Event::ID: + kdebug ("event requested\n") + // Detection of sd card. + Iris::Cap reply = Iris::get_reply () + 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 + 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: - Iris::panic (Iris::recv.data[1].l, "unexpected device") - // Initialize the root file system. - Iris::Directory root = fs.use_device_ro (data.copy ()) - Iris::free_cap (data) - Iris::free_cap (fs) - return root + Iris::panic (Iris::recv.protected_data.l, "invalid boot request") static bool stringcmp (char const *s1, char const *s2, unsigned size): 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") Iris::set_recv_arg (Iris::Cap (slot, p)) 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)) Iris::my_memory.map (Iris::Cap (slot, p), (unsigned)&mapping[p << PAGE_BITS]) 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 else: f = Iris::Page::PAYING - page.set_flags (f, f) + page.set_flags (f) Iris::Page (slot, idx).share (page, 0) //kdebug ("mapping at ") //kdebug_num (p) @@ -222,7 +274,7 @@ static void run (Iris::String data, Iris::Memory parent_memory, Iris::Cap parent page = mem.create_page () if Iris::recv.data[0].l != Iris::NO_ERROR: 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") if !mem.map (page, p): 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::free_slot (slot) 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): Iris::panic (Iris::recv.data[0].l, "unable to map initial stack page") Iris::free_cap (stackpage) diff --git a/source/buffer.ccp b/source/buffer.ccp new file mode 100644 index 0000000..3008cf6 --- /dev/null +++ b/source/buffer.ccp @@ -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 +// +// 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 . + +#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 () + 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 (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") diff --git a/source/elfrun.ccp b/source/elfrun.ccp index 099c7b5..7378b9b 100644 --- a/source/elfrun.ccp +++ b/source/elfrun.ccp @@ -40,7 +40,7 @@ void *operator new[] (unsigned size): unsigned pages = ((size - rest) + PAGE_SIZE - 1) >> PAGE_BITS for unsigned p = 0; p < pages; ++p: 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::free_cap (page) _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 else: f = Iris::Page::PAYING - page.set_flags (f, f) + page.set_flags (f) Iris::Page (slot, idx).share (page, 0) //kdebug ("mapping at ") //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 () if Iris::recv.data[0].l != Iris::NO_ERROR: 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") if !mem.map (page, p): 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_cap (pages_caps) 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): Iris::panic (Iris::recv.data[0].l, "unable to map initial stack page") Iris::free_cap (stackpage) diff --git a/source/fat.ccp b/source/fat.ccp index 947c068..583435e 100644 --- a/source/fat.ccp +++ b/source/fat.ccp @@ -26,7 +26,7 @@ void *operator new[] (unsigned size): unsigned pages = ((size - rest) + PAGE_SIZE - 1) >> PAGE_BITS for unsigned p = 0; p < pages; ++p: 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::free_cap (page) _free += size @@ -147,15 +147,22 @@ struct Fat: return ret 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 ret for ret = 0; ret < 32; ++ret: if orig == 1 << ret: return ret - Iris::panic (ret, "non-power of 2") - return ret + //Iris::panic (orig, "non-power of 2") + kdebug ("not a power of two, using 16\n") + return 16 void reset (): read_block (0) @@ -182,7 +189,7 @@ struct Fat: kdebug ("warning: limiting sectors because of limited device size\n") 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 unsigned skip if clusters >= 65525: @@ -254,6 +261,7 @@ struct Fat: bad_clusters = 0 fat = new unsigned[clusters] unsigned counted_free_clusters = 0 + first_free_cluster = ~0 for unsigned c = 0; c < clusters; ++c: // reduced cluster. 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: // Last cluster in chain. 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: // Bad cluster. fat[c] = first_bad_cluster @@ -296,12 +307,24 @@ struct Fat: else: // Non-last cluster in chain. fat[c] -= 2 + kdebug_num (c) + kdebug (" -> ") + kdebug_num (fat[c]) + kdebug ("\n") unsigned fat_lookup (unsigned first_cluster, unsigned cluster): + //kdebug ("looking up ") + //kdebug_num (first_cluster) + //kdebug ("+") + //kdebug_num (cluster) + //kdebug (":") while cluster--: first_cluster = fat[first_cluster] + //kdebug ("->") + //kdebug_num (first_cluster) if first_cluster == ~0: - kdebug ("sector beyond end of file requested\n") + //kdebug ("sector beyond end of file requested\n") return ~0 + //kdebug ("\n") return first_cluster struct File: Fat *fat @@ -310,22 +333,22 @@ struct Fat: char name[11] bool archive, readonly, system, hidden, directory, volume 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): unsigned cluster = fat->fat_lookup (first_cluster, idx >> fat->cluster_size_bits) - kdebug ("loading cluster ") - kdebug_num (idx) - kdebug ("@") - kdebug_num (cluster) - kdebug (" from file\n") + //kdebug ("loading cluster ") + //kdebug_num (idx) + //kdebug ("@") + //kdebug_num (cluster) + //kdebug (" from file\n") if cluster == ~0: kdebug ("invalid cluster requested from file\n") 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) - kdebug ("sector ") - kdebug_num (fat->header_sectors + (Iris::Num (cluster).value () << fat->sectors_per_cluster_bits)) - kdebug ("\n") - void get_dir_entry (unsigned dir, unsigned idx, File *f): - f->fat = this + //kdebug ("sector ") + //kdebug_num (fat->header_sectors + (Iris::Num (cluster).value () << fat->sectors_per_cluster_bits)) + //kdebug ("\n") + char *load_dir_entry (unsigned dir, unsigned idx): unsigned sector = idx >> (sector_size_bits - 5) unsigned num = (idx << 5) & ~BLOCK_MASK Iris::Num hwsector @@ -333,27 +356,56 @@ struct Fat: if sector < root_sectors: hwsector = header_sectors - root_sectors + sector else: - hwsector = ~0 + return NULL else: unsigned entry = fat_lookup (dir, sector) if entry == ~0: - hwsector = ~0 - else: - 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 + return NULL + hwsector = header_sectors + (Iris::Num (entry).value () << sectors_per_cluster_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: f->name[i] = e[i] - f->archive = e[0xb] & 0x20 - f->readonly = e[0xb] & 0x10 - f->system = e[0xb] & 0x8 + f->readonly = e[0xb] & 0x1 + f->system = e[0xb] & 0x2 f->hidden = e[0xb] & 0x4 - f->directory = e[0xb] & 0x2 - f->volume = e[0xb] & 0x1 + f->volume = e[0xb] & 0x8 + f->directory = e[0xb] & 0x10 + f->archive = e[0xb] & 0x20 f->create_second = read_num (e + 0xd, 1) f->create_minute_hour = read_num (e + 0xe, 2) f->create_date = read_num (e + 0x10, 2) @@ -362,6 +414,71 @@ struct Fat: f->date = read_num (e + 0x18, 1) f->size = read_num (e + 0x1c, 4) 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. // 0:ROOT_CLUSTER = non fat-32 root directory. @@ -379,7 +496,7 @@ Iris::Num start (): device_size = dev.get_size () data = (char *)0x15000; //alloc_space (1) 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) Fat fat @@ -400,6 +517,7 @@ Iris::Num start (): Iris::wait () unsigned dir = Iris::recv.protected_data.h if dir & 0x80000000: + dir &= ~0x80000000 // File name. unsigned idx = Iris::recv.protected_data.l Iris::Cap reply = Iris::get_reply () @@ -407,23 +525,55 @@ Iris::Num start (): unsigned size = Iris::recv.data[0].h >> 16 unsigned cmd = Iris::recv.data[0].l 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: case Iris::String::GET_SIZE: - kdebug ("filename size requested\n") - reply.invoke (11) + //kdebug ("filename size requested\n") + reply.invoke (fat.get_name_size (dir, idx, f)) break case Iris::String::GET_CHARS: //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 for unsigned k = 0; k < 4; ++k: u.u[k] = 0 - for unsigned k = 0; k + num < 11; ++k: - u.c[k] = f.name[k + num] + Fat::LFN lfn + 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])) break case Iris::String::GET_ALIGN_BITS: - kdebug ("filename align requested\n") + //kdebug ("filename align requested\n") reply.invoke (0) break 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::free_cap (reply) else if dir: - // File. + // If it *has* a directory, it *is* a file. unsigned idx = Iris::recv.protected_data.l Iris::Cap reply = Iris::get_reply () Iris::Cap arg = Iris::get_arg () @@ -439,15 +589,17 @@ Iris::Num start (): unsigned size = Iris::recv.data[0].h >> 16 unsigned offset = Iris::recv.data[0].h & 0xffff unsigned cmd = Iris::recv.data[0].l + if !fat.find_idx (dir, &idx): + Iris::panic (0, "file not found") Fat::File f fat.get_dir_entry (dir, idx, &f) switch cmd: case Iris::String::GET_SIZE: - kdebug ("file size requested\n") + //kdebug ("file size requested\n") reply.invoke (f.size) break case Iris::String::GET_CHARS: - kdebug ("file chars requested\n") + //kdebug ("file chars requested\n") unsigned mask = 1 << (fat.cluster_size_bits) - 1 f.load_cluster (num.l & ~mask) 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])) break case Iris::String::GET_ALIGN_BITS: - kdebug ("file align requested\n") + //kdebug ("file align requested\n") reply.invoke (fat.cluster_size_bits) break case Iris::String::GET_BLOCK: - kdebug ("file block requested\n") + //kdebug ("file block requested\n") unsigned mask = 1 << (fat.cluster_size_bits) - 1 if offset > PAGE_SIZE: - kdebug ("invalid offset requested\n") + //kdebug ("invalid offset requested\n") break if size + offset > PAGE_SIZE: size = PAGE_SIZE - offset @@ -480,71 +632,58 @@ Iris::Num start (): Iris::free_cap (arg) else: // Directory. - if Iris::recv.protected_data.l != ROOT_CLUSTER: - // Normal directory. - switch Iris::recv.data[0].l: - case Iris::Directory::GET_SIZE: - kdebug ("dir size requested\n") - Iris::recv.reply.invoke () - break - case Iris::Directory::GET_NAME: - kdebug ("dir name requested\n") - Iris::recv.reply.invoke () - break - case Iris::Directory::GET_FILE_RO: - kdebug ("dir file requested\n") - Iris::Cap reply = Iris::get_reply () - Iris::Cap ret = Iris::my_receiver.create_capability (Iris::Num (Iris::recv.data[1].l, Iris::recv.protected_data.l)) - reply.invoke (0, 0, ret.copy ()) - Iris::free_cap (reply) - Iris::free_cap (ret) - break - case Iris::Directory::GET_FILE_INFO: - kdebug ("dir file info requested\n") - Iris::recv.reply.invoke () - break - case Iris::Directory::LOCK_RO: - case Iris::Directory::UNLOCK_RO: - kdebug ("dir lock or unlock requested\n") - Iris::recv.reply.invoke () - break - default: - kdebug ("invalid dir operation requested\n") - Iris::recv.reply.invoke () - break - else: - // Non-fat32 root directory. - switch Iris::recv.data[0].l: - case Iris::Directory::GET_SIZE: - kdebug ("root size requested\n") - Iris::recv.reply.invoke (fat.root_entries) - break - case Iris::Directory::GET_NAME: - //kdebug ("root name requested\n") - Iris::Cap reply = Iris::get_reply () - Iris::Cap ret = Iris::my_receiver.create_capability (Iris::Num (Iris::recv.data[1].l, Iris::recv.protected_data.l | 0x80000000)) - reply.invoke (0, 0, ret.copy ()) - Iris::free_cap (reply) - Iris::free_cap (ret) - break - case Iris::Directory::GET_FILE_RO: - kdebug ("root file requested\n") - Iris::Cap reply = Iris::get_reply () - Iris::Cap ret = Iris::my_receiver.create_capability (Iris::Num (Iris::recv.data[1].l, Iris::recv.protected_data.l)) - reply.invoke (0, 0, ret.copy ()) - Iris::free_cap (reply) - Iris::free_cap (ret) - 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 + switch Iris::recv.data[0].l: + case Iris::Directory::GET_SIZE: + //kdebug ("dir size requested\n") + Iris::Cap reply = Iris::get_reply () + reply.invoke (fat.get_dir_size (Iris::recv.protected_data.l)) + Iris::free_cap (reply) + break + case Iris::Directory::GET_NAME: + //kdebug ("dir name requested\n") + Iris::Cap reply = Iris::get_reply () + Iris::Cap ret = Iris::my_receiver.create_capability (Iris::Num (Iris::recv.data[1].l, Iris::recv.protected_data.l | 0x80000000)) + reply.invoke (0, 0, ret.copy ()) + Iris::free_cap (reply) + Iris::free_cap (ret) + break + case Iris::Directory::GET_FILE_RO: + //kdebug ("dir file requested\n") + Iris::Cap reply = Iris::get_reply () + dir = Iris::recv.protected_data.l + unsigned idx = Iris::recv.data[1].l + if !fat.find_idx (dir, &idx): + Iris::panic (0, "file not found") + Fat::File f + fat.get_dir_entry (dir, idx, &f) + Iris::Cap ret + if f.directory: + ret = Iris::my_receiver.create_capability (Iris::Num (f.first_cluster, 0)) + else: + ret = Iris::my_receiver.create_capability (Iris::Num (idx, dir)) + reply.invoke (0, 0, ret.copy ()) + Iris::free_cap (reply) + Iris::free_cap (ret) + break + case Iris::Directory::GET_FILE_INFO: + //kdebug ("dir file info requested\n") + Iris::Cap reply = Iris::get_reply () + dir = Iris::recv.protected_data.l + unsigned idx = Iris::recv.data[1].l + if !fat.find_idx (dir, &idx): + Iris::panic (0, "file not found") + unsigned type = Iris::recv.data[0].h + Fat::File f + fat.get_dir_entry (dir, idx, &f) + reply.invoke (f.directory ? 1 : 0) + Iris::free_cap (reply) + break + case Iris::Directory::LOCK_RO: + case Iris::Directory::UNLOCK_RO: + //kdebug ("dir lock or unlock requested\n") + Iris::recv.reply.invoke () + break + default: + //kdebug ("invalid dir operation requested\n") + Iris::recv.reply.invoke () + break diff --git a/source/init.ccp b/source/init.ccp index 9ef8ec7..d4a9cb2 100644 --- a/source/init.ccp +++ b/source/init.ccp @@ -20,6 +20,9 @@ #include "iris.hh" #include "keys.hh" +#define INIT_CONFIG "init.config" +#define INIT_CONFIG_SIZE 12 + #define NUM_SLOTS 8 #define NUM_CAPS 32 @@ -45,7 +48,7 @@ void *operator new[] (unsigned size): unsigned pages = ((size - rest) + PAGE_SIZE - 1) >> PAGE_BITS for unsigned p = 0; p < pages; ++p: 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::free_cap (page) _free += size @@ -277,7 +280,6 @@ static Type types[] = { { "Setting", 7, Iris::Setting::ID }, { "Directory", 9, Iris::Directory::ID }, { "WDirectory", 10, Iris::WDirectory::ID }, - { "Filesystem", 10, Iris::Filesystem::ID }, { "Stream", 6, Iris::Stream::ID }, { "UI", 2, Iris::UI::ID }, { NULL, 0, 0 } @@ -434,6 +436,9 @@ static void parse_line (char *&line, unsigned maxlen): char *name = get_filename (line, maxlen, name_len) include (name, name_len) else: + for unsigned i = 0; i < maxlen; ++i: + kdebug_char (start[i]) + kdebug_char ('\n') Iris::panic (0, "invalid line in init.config") delspace (start, maxlen) if maxlen: @@ -450,7 +455,7 @@ Iris::Num start (): elfrun = Iris::my_parent.get_capability () sysreq = NULL top_memory = Iris::get_top_memory () - include ("init.config", 12) + include (INIT_CONFIG, INIT_CONFIG_SIZE) kdebug ("killing boot threads\n") Iris::my_parent.init_done () for List ::Item *p = programs.begin (); p; p = p->next: diff --git a/source/partition.ccp b/source/partition.ccp index 4485857..734a091 100644 --- a/source/partition.ccp +++ b/source/partition.ccp @@ -6,6 +6,8 @@ #define SECTOR_BITS 9 #define BLOCK_MASK (~((1 << SECTOR_BITS) - 1)) +unsigned bits + struct Partition: static Iris::Num device_size unsigned lba_start, lba_size @@ -28,37 +30,37 @@ struct Partition: lba_size = read_num (data + 12) start = Iris::Num (lba_start).value () << SECTOR_BITS size = Iris::Num (lba_size).value () << SECTOR_BITS - //kdebug ("Partition read: ") - //kdebug_num (lba_start) - //kdebug ("+") - //kdebug_num (lba_size) - //kdebug ("\n") + kdebug ("Partition read: ") + kdebug_num (lba_start) + kdebug ("+") + kdebug_num (lba_size) + kdebug ("\n") Iris::Num Partition::device_size static Iris::WString dev -static void read_block (Iris::Num idx, Iris::Page page, unsigned size = 1 << SECTOR_BITS, unsigned offset = 0): - idx = idx.value () >> SECTOR_BITS +static void read_sector (Iris::Num idx, Iris::Page page, unsigned size = 1 << SECTOR_BITS, unsigned offset = 0): offset &= ~PAGE_MASK if size + offset > PAGE_SIZE: size = PAGE_SIZE - offset size >>= SECTOR_BITS + idx = idx.value () >> SECTOR_BITS for unsigned i = 0; i < size; ++i: dev.get_block ((idx.value () + i) << SECTOR_BITS, 1 << SECTOR_BITS, (i << SECTOR_BITS) + offset, page) Iris::Num start (): Partition::device_size = 0 dev = Iris::my_parent.get_capability () - if dev.get_align_bits () > SECTOR_BITS: - kdebug ("partitioned device doesn't support 512 byte access") - return 1 + bits = dev.get_align_bits () + if bits > SECTOR_BITS: + Iris::panic (bits, "partitioned device doesn't support 512 byte access\n") Partition::device_size = dev.get_size () 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 unsigned *ubuffer = (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: kdebug ("invalid mbr signature\n") @@ -78,6 +80,9 @@ Iris::Num start (): while true: Iris::wait () + //kdebug ("partition received: ") + //kdebug_num (Iris::recv.data[0].l) + //kdebug ("\n") switch Iris::recv.data[0].l: case Iris::String::GET_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 offset = (partition[Iris::recv.protected_data.l].start.value () + (request.value () & BLOCK_MASK)) & 0xf unsigned page_offset = request.l & ~BLOCK_MASK - page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME, Iris::Page::PAYING | Iris::Page::FRAME) - read_block (offset, page) + page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME) + 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])) page.set_flags (0, Iris::Page::PAYING | Iris::Page::FRAME) Iris::free_cap (reply) @@ -116,7 +121,7 @@ Iris::Num start (): //kdebug (":") //kdebug_num (Iris::Num (offset.value () + p.value ()).l) //kdebug ("\n") - read_block (offset.value () + p.value (), arg, size, out_offset) + read_sector (offset.value () + p.value (), arg, size, out_offset) reply.invoke () Iris::free_cap (reply) Iris::free_cap (arg) diff --git a/source/sd+mmc.ccp b/source/sd+mmc.ccp index fd8a966..556e121 100644 --- a/source/sd+mmc.ccp +++ b/source/sd+mmc.ccp @@ -66,11 +66,12 @@ class Mmc: unsigned get_read_block_size (): return read_block_size 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) private: unsigned rca bool have_sdmem, have_io + bool hc CID cid CSD csd 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") return false 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 if response_type == R2: 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 csd.tmp_write_protect = d & 0x10 // 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) + 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: unsigned r = MSC_RES if response_type == R3: if r >> 8 != 0x3f: Iris::panic (r, "r3 response was not 3f") else if r >> 8 != cmd: + kdebug ("stat: ") + kdebug_num (MSC_STAT) Iris::panic (r, "response doesn't match command") r <<= 24 r |= MSC_RES << 8 r |= MSC_RES & 0xff if response: *response = r + else: //kdebug ("extra response fifo read: ") //for unsigned i = 0; i < 9; ++i: //kdebug (" ") @@ -225,21 +235,10 @@ void Mmc::reset (): // Start the clock. MSC_STRPCL = MSC_STRPCL_CLOCK_CONTROL_START // Set cards, if any, to idle. - MSC_CMD = 0 - 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 () + send (0, 0, NONE) // Reset SDIO device, if any. - MSC_CMD = 52 - 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 () + send (52, 0x88000c08, R5) void Mmc::check_mmc (): //kdebug ("checking mmc\n") @@ -253,11 +252,10 @@ void Mmc::check_mmc (): void Mmc::check_sdmem (): kdebug ("checking sdmem\n") - send (0, 0, NONE) // 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. unsigned code - bool hc = false + hc = false if send (8, 0x1aa, R7, &code) && (code & 0xff) == 0xaa: kdebug ("hc\n") hc = true @@ -357,25 +355,45 @@ void Mmc::fill_page (Iris::Page page, Iris::Num address, unsigned size, unsigned if address.h: Iris::panic (0, "page too high: not supported") 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 size &= blockmask offset &= ~PAGE_MASK if size + offset > PAGE_SIZE: 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) - 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_BLKLEN = read_block_size - for unsigned a = 0; a < size; a += 1 << get_block_bits (): + MSC_BLKLEN = 1 << 9 + for unsigned a = 0; a < size; a += 1 << 9: + //kdebug_num (a) + //kdebug ("/") + //kdebug_num (size) + //kdebug (" ==> ") if !send (17, p + a, DATA): Iris::panic (0, "unable to request data") - for unsigned aa = 0; aa < read_block_size; aa += 4: - Iris::register_interrupt (IRQ_MSC) - Iris::wait_for_interrupt (IRQ_MSC) + for unsigned aa = 0; aa < 1 << 9; aa += 4: + while MSC_STAT & MSC_STAT_DATA_FIFO_EMPTY: + Iris::register_interrupt (IRQ_MSC) + Iris::wait_for_interrupt (IRQ_MSC) *(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 + //kdebug ("done filling page\n") static Mmc mmc @@ -436,7 +454,7 @@ Iris::Num start (): Iris::panic (0, "get chars from mmc not supported yet") break case Iris::String::GET_ALIGN_BITS: - Iris::recv.reply.invoke (mmc.get_block_bits ()) + Iris::recv.reply.invoke (9) break case Iris::String::GET_BLOCK: Iris::Cap reply = Iris::get_reply () diff --git a/source/test.ccp b/source/test.ccp index 8fb94a0..9ff4a99 100644 --- a/source/test.ccp +++ b/source/test.ccp @@ -19,42 +19,40 @@ #include #include -bool match (char const *a, char const *b): - for unsigned i = 0; i < 11; ++i: +bool match (char const *a, char const *b, unsigned l1, unsigned l2): + if l1 != l2: + return false + for unsigned i = 0; i < l1; ++i: if a[i] != b[i]: return false return true -Iris::Num start (): - Iris::Directory dir = Iris::my_parent.get_capability () +static bool print_name (Iris::String name, unsigned indent): + 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 () Iris::Num files = dir.get_size () for Iris::Num i = 0; i.value () < files.value (); i = i.value () + 1: Iris::String f = dir.get_name (i) - char start[16] - f.get_chars (0, start) - if match (start, "TEST TXT"): - Iris::free_cap (f) - f = dir.get_file_ro (i) - 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") + bool ignore = print_name (f, indent) + if !ignore && dir.get_file_info (i, 0).l & 1: + Iris::Directory d = dir.get_file_ro (i) + print_dir (d, indent + 4) + Iris::free_cap (d) Iris::free_cap (f) - kdebug ("file test.txt not found\n") - return 1 + dir.unlock_ro () + +Iris::Num start (): + Iris::Directory dir = Iris::my_parent.get_capability () + print_dir (dir, 0) + return 0 diff --git a/source/udc.ccp b/source/udc.ccp index 9f9e981..af375b6 100644 --- a/source/udc.ccp +++ b/source/udc.ccp @@ -218,7 +218,7 @@ void Udc::init (): page = (unsigned *)LCD_FRAMEBUFFER_BASE p = 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) // 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) if p - page == PAGE_SIZE >> 2: 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 () Iris::free_cap (caller) Iris::free_cap (caller_arg) @@ -555,8 +555,6 @@ void Udc::log (unsigned c): enum pdata: LOG = 32 - FS - DATA DIRECTORY FILE NAME @@ -571,12 +569,9 @@ Iris::Num start (): __asm__ volatile ("li $a0, 1\nlw $a1, %0\nbreak" :: "m"(logcap.code): "a0", "a1", "memory") udc.init () Iris::register_interrupt (IRQ_UDC) - Iris::Filesystem fs = Iris::my_receiver.create_capability (FS) - Iris::String data = Iris::my_receiver.create_capability (DATA) - Iris::my_parent.provide_capability (fs.copy ()) - Iris::my_parent.provide_capability (data.copy ()) - Iris::free_cap (fs) - Iris::free_cap (data) + Iris::Directory dir = Iris::my_receiver.create_capability (DIRECTORY) + Iris::my_parent.provide_capability (dir.copy ()) + Iris::free_cap (dir) unsigned state = 0 while true: Iris::wait () @@ -590,45 +585,6 @@ Iris::Num start (): case LOG: udc.log (Iris::recv.data[0].l) 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: //kdebug ("dir request\n") switch Iris::recv.data[0].l: