mirror of
git://projects.qi-hardware.com/iris.git
synced 2024-12-28 12:39:52 +02:00
make booting from sd work
This commit is contained in:
parent
a277156a2e
commit
19f1d128d0
@ -78,7 +78,7 @@ namespace Iris:
|
||||
/// Set the size of the string. Strings may have a limit to this setting.
|
||||
void truncate (Num size):
|
||||
call (CAP_MASTER_DIRECT | TRUNCATE, size)
|
||||
/// Set exactly 4 characters. The index must be word-aligned.
|
||||
/// Set exactly 4 characters. The index must be aligned. This need not be supported for strings with align larger than 4 bytes.
|
||||
void set_chars (Num idx, char buffer[4]):
|
||||
call (Num (CAP_MASTER_DIRECT | SET_CHARS, *(unsigned *)buffer), idx)
|
||||
/// Overwrite a block from the string with data at offset on the page. This need not be implemented for strings smaller than PAGE_SIZE. The all arguments must be aligned. The caller may lose the frame in the transaction. Only the specified part of the page is used for overwriting data.
|
||||
|
28
init.config
28
init.config
@ -1,24 +1,24 @@
|
||||
# driver <name> = '<filename>' load a file into memory to be run priviledged.
|
||||
# program <name> = '<filename>' load a file into memory to be run normally.
|
||||
#driver driver_lcd = "lcd.elf"
|
||||
#driver driver_buzzer = "buzzer.elf"
|
||||
driver driver_lcd = "lcd.elf"
|
||||
driver driver_buzzer = "buzzer.elf"
|
||||
driver driver_gpio = "gpio.elf"
|
||||
#program alarm = "alarm.elf"
|
||||
#program gui = "gui.elf"
|
||||
#driver nand = "nand.elf"
|
||||
program alarm = "alarm.elf"
|
||||
program gui = "gui.elf"
|
||||
driver nand = "nand.elf"
|
||||
driver sdmmc = "sd+mmc.elf"
|
||||
program partition = "partition.elf"
|
||||
program fat = "fat.elf"
|
||||
program test = "test.elf"
|
||||
|
||||
# receive <name> / <type> [, <index>] = <cap> prepare to accept a capability from a named program.
|
||||
#receive driver_lcd / Display = display
|
||||
#receive driver_lcd / Setting = display_bright
|
||||
#receive driver_buzzer / Buzzer = buzzer
|
||||
receive driver_lcd / Display = display
|
||||
receive driver_lcd / Setting = display_bright
|
||||
receive driver_buzzer / Buzzer = buzzer
|
||||
receive driver_gpio / Keyboard , 0 = keyboard
|
||||
receive driver_gpio / Keyboard , 1 = sysreq
|
||||
receive driver_gpio / Event = sdmmc_gpio
|
||||
#receive alarm / UI = ui
|
||||
receive alarm / UI = ui
|
||||
receive sdmmc / WString = sdmmc
|
||||
receive partition / WString, 0 = p0
|
||||
receive partition / WString, 1 = p1
|
||||
@ -30,11 +30,11 @@
|
||||
sysreq sysreq
|
||||
|
||||
# give <name> / <type> [, <index>] = <cap> give this capability to this program when it requests it.
|
||||
#give gui / UI = ui
|
||||
#give gui / Display = display
|
||||
#give gui / Setting = display_bright
|
||||
#give gui / Buzzer = buzzer
|
||||
#give gui / Keyboard = keyboard
|
||||
give gui / UI = ui
|
||||
give gui / Display = display
|
||||
give gui / Setting = display_bright
|
||||
give gui / Buzzer = buzzer
|
||||
give gui / Keyboard = keyboard
|
||||
give sdmmc / Event = sdmmc_gpio
|
||||
give partition / WString = sdmmc
|
||||
give fat / WString = p0
|
||||
|
@ -16,7 +16,7 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
load = 0x80000000
|
||||
UDC_BOOT=1
|
||||
#UDC_BOOT = set
|
||||
|
||||
ARCH_CPPFLAGS = -I. -Imips -Imips/nanonote -Wa,-mips32 -DNANONOTE -DUSE_SERIAL
|
||||
CROSS = mipsel-linux-gnu-
|
||||
|
@ -23,6 +23,7 @@
|
||||
#define ELFRUN_NAME "elfrun.elf"
|
||||
#define INIT_NAME "init.elf"
|
||||
|
||||
// These numbers are only used for elfrun.
|
||||
#define NUM_SLOTS 8
|
||||
#define NUM_CAPS 32
|
||||
|
||||
|
@ -40,9 +40,9 @@ namespace Iris:
|
||||
__recv_data_t recv
|
||||
|
||||
void print_caps ():
|
||||
// Assume __caps to be 32.
|
||||
bool used[32]
|
||||
for unsigned i = 0; i < 32; ++i:
|
||||
// __caps cannot be larger than 63.
|
||||
bool used[63]
|
||||
for unsigned i = 0; i < __caps; ++i:
|
||||
used[i] = true
|
||||
unsigned num = 0
|
||||
for list *i = __first_free_cap; i; i = i->next:
|
||||
@ -52,7 +52,7 @@ namespace Iris:
|
||||
++num
|
||||
kdebug_num (num, 2)
|
||||
kdebug (":")
|
||||
for unsigned i = 0; i < 32; ++i:
|
||||
for unsigned i = 0; i < __caps; ++i:
|
||||
kdebug_char (used[i] ? '#' : '.')
|
||||
kdebug_char ('\n')
|
||||
|
||||
|
@ -296,9 +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")
|
||||
//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
|
||||
@ -307,10 +307,10 @@ struct Fat:
|
||||
else:
|
||||
// Non-last cluster in chain.
|
||||
fat[c] -= 2
|
||||
kdebug_num (c)
|
||||
kdebug (" -> ")
|
||||
kdebug_num (fat[c])
|
||||
kdebug ("\n")
|
||||
//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)
|
||||
@ -334,20 +334,19 @@ struct Fat:
|
||||
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):
|
||||
void load_cluster (unsigned idx, unsigned offset_in_cluster, 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 (offset_in_cluster)
|
||||
//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")
|
||||
read_block (((fat->header_sectors + (Iris::Num (cluster).value () << fat->sectors_per_cluster_bits)) << fat->sector_size_bits) + offset_in_cluster, p, fat->cluster_size_bits < PAGE_BITS ? 1 << fat->cluster_size_bits : PAGE_SIZE, offset)
|
||||
char *load_dir_entry (unsigned dir, unsigned idx):
|
||||
unsigned sector = idx >> (sector_size_bits - 5)
|
||||
unsigned num = (idx << 5) & ~BLOCK_MASK
|
||||
@ -398,8 +397,11 @@ struct Fat:
|
||||
kdebug ("unable to load dir entry\n")
|
||||
return false
|
||||
f->fat = this
|
||||
//kdebug ("loading dir entry for ")
|
||||
for unsigned i = 0; i < 11; ++i:
|
||||
f->name[i] = e[i]
|
||||
//kdebug_char (f->name[i])
|
||||
//kdebug ("\n")
|
||||
f->readonly = e[0xb] & 0x1
|
||||
f->system = e[0xb] & 0x2
|
||||
f->hidden = e[0xb] & 0x4
|
||||
@ -589,8 +591,6 @@ 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:
|
||||
@ -600,26 +600,30 @@ Iris::Num start ():
|
||||
break
|
||||
case Iris::String::GET_CHARS:
|
||||
//kdebug ("file chars requested\n")
|
||||
unsigned mask = 1 << (fat.cluster_size_bits) - 1
|
||||
f.load_cluster (num.l & ~mask)
|
||||
unsigned mask = (1 << fat.cluster_size_bits) - 1
|
||||
f.load_cluster (num.l & ~mask, num.l & mask)
|
||||
unsigned n = num.l & mask & ~0xf
|
||||
unsigned *dat = (unsigned *)(data + n)
|
||||
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")
|
||||
reply.invoke (fat.cluster_size_bits)
|
||||
reply.invoke (fat.cluster_size_bits <= PAGE_BITS ? fat.cluster_size_bits : PAGE_BITS)
|
||||
break
|
||||
case Iris::String::GET_BLOCK:
|
||||
//kdebug ("file block requested\n")
|
||||
unsigned mask = 1 << (fat.cluster_size_bits) - 1
|
||||
unsigned mask = (1 << fat.cluster_size_bits) - 1
|
||||
//kdebug ("mask = ")
|
||||
//kdebug_num (mask)
|
||||
//kdebug ("\n")
|
||||
if offset > PAGE_SIZE:
|
||||
//kdebug ("invalid offset requested\n")
|
||||
break
|
||||
if size + offset > PAGE_SIZE:
|
||||
Iris::panic (size, "invalid size requested")
|
||||
size = PAGE_SIZE - offset
|
||||
for unsigned i = 0; i < size; i += 1 << fat.cluster_size_bits:
|
||||
f.load_cluster ((num.l & ~mask) + i, arg, i + offset)
|
||||
f.load_cluster ((num.l & ~mask) + i, num.l & mask, arg, i + offset)
|
||||
reply.invoke ()
|
||||
break
|
||||
case Iris::WString::TRUNCATE:
|
||||
@ -652,12 +656,18 @@ Iris::Num start ():
|
||||
Iris::Cap reply = Iris::get_reply ()
|
||||
dir = Iris::recv.protected_data.l
|
||||
unsigned idx = Iris::recv.data[1].l
|
||||
unsigned oldidx = idx
|
||||
if !fat.find_idx (dir, &idx):
|
||||
Iris::panic (0, "file not found")
|
||||
kdebug_num (oldidx)
|
||||
kdebug ("\n")
|
||||
Iris::panic (1, "file not found")
|
||||
Fat::File f
|
||||
fat.get_dir_entry (dir, idx, &f)
|
||||
Iris::Cap ret
|
||||
if f.directory:
|
||||
//kdebug ("dir provided: ")
|
||||
//kdebug_num (f.first_cluster)
|
||||
//kdebug ("\n")
|
||||
ret = Iris::my_receiver.create_capability (Iris::Num (f.first_cluster, 0))
|
||||
else:
|
||||
ret = Iris::my_receiver.create_capability (Iris::Num (idx, dir))
|
||||
@ -670,8 +680,11 @@ Iris::Num start ():
|
||||
Iris::Cap reply = Iris::get_reply ()
|
||||
dir = Iris::recv.protected_data.l
|
||||
unsigned idx = Iris::recv.data[1].l
|
||||
unsigned oldidx = idx
|
||||
if !fat.find_idx (dir, &idx):
|
||||
Iris::panic (0, "file not found")
|
||||
kdebug_num (oldidx)
|
||||
kdebug ("\n")
|
||||
Iris::panic (2, "file not found")
|
||||
unsigned type = Iris::recv.data[0].h
|
||||
Fat::File f
|
||||
fat.get_dir_entry (dir, idx, &f)
|
||||
|
@ -143,6 +143,7 @@ struct Program:
|
||||
Iris::free_cap (cap)
|
||||
thread = caps.get (__thread_num)
|
||||
memory = caps.get (__memory_num)
|
||||
Iris::free_cap (caps)
|
||||
if priv:
|
||||
thread.make_priv ()
|
||||
thread.run ()
|
||||
@ -471,7 +472,8 @@ Iris::Num start ():
|
||||
if Iris::recv.protected_data.l == SYSREQ:
|
||||
if Iris::recv.data[0].l & Iris::Keyboard::RELEASE:
|
||||
continue
|
||||
kdebug ("sysreq event\n")
|
||||
kdebug ("sysreq event: rebooting device\n")
|
||||
Iris::reboot ()
|
||||
continue
|
||||
Program *caller = (Program *)Iris::recv.protected_data.l
|
||||
switch Iris::recv.data[0].l:
|
||||
|
@ -173,8 +173,8 @@ static void read (unsigned a, char *buffer):
|
||||
unsigned errs = (EMC_NFINTS & EMC_NFINTS_ERRCNT_MASK) >> EMC_NFINTS_ERRCNT_BIT
|
||||
|
||||
Iris::Num start ():
|
||||
for unsigned i = 0; i < 30; ++i:
|
||||
Iris::schedule ()
|
||||
kdebug ("reading nand in 10 seconds\n")
|
||||
Iris::sleep (10 * HZ)
|
||||
map_emc ()
|
||||
map_gpio ()
|
||||
|
||||
|
@ -24,7 +24,8 @@ class Mmc:
|
||||
public:
|
||||
enum Response_type:
|
||||
NONE = MSC_CMDAT_RESPONSE_NONE
|
||||
DATA = MSC_CMDAT_RESPONSE_R1 | MSC_CMDAT_DATA_EN
|
||||
RD_DATA = MSC_CMDAT_RESPONSE_R1 | MSC_CMDAT_DATA_EN | MSC_CMDAT_READ
|
||||
WR_DATA = MSC_CMDAT_RESPONSE_R1 | MSC_CMDAT_DATA_EN | MSC_CMDAT_WRITE
|
||||
R1 = MSC_CMDAT_RESPONSE_R1
|
||||
R1B = MSC_CMDAT_RESPONSE_R1 | MSC_CMDAT_BUSY
|
||||
R2 = MSC_CMDAT_RESPONSE_R2
|
||||
@ -68,6 +69,8 @@ class Mmc:
|
||||
unsigned get_block_bits ():
|
||||
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 write_page (Iris::Page page, Iris::Num address, unsigned size, unsigned offset)
|
||||
void wait_write ()
|
||||
private:
|
||||
unsigned rca
|
||||
bool have_sdmem, have_io
|
||||
@ -82,9 +85,11 @@ bool Mmc::send (unsigned cmd, unsigned arg, Response_type response_type, unsigne
|
||||
MSC_CMD = cmd
|
||||
MSC_ARG = arg
|
||||
MSC_CMDAT = response_type
|
||||
MSC_IMASK = ~MSC_IMASK_END_CMD_RES
|
||||
Iris::register_interrupt (IRQ_MSC)
|
||||
msc_start_op ()
|
||||
Iris::wait_for_interrupt (IRQ_MSC)
|
||||
MSC_IMASK = ~0
|
||||
//kdebug ("cmd: ")
|
||||
//kdebug_num (cmd)
|
||||
unsigned stat = MSC_STAT
|
||||
@ -178,6 +183,10 @@ bool Mmc::send (unsigned cmd, unsigned arg, Response_type response_type, unsigne
|
||||
else if r >> 8 != cmd:
|
||||
kdebug ("stat: ")
|
||||
kdebug_num (MSC_STAT)
|
||||
kdebug ("; response: ")
|
||||
kdebug_num (r)
|
||||
kdebug ("; cmd: ")
|
||||
kdebug_num (cmd)
|
||||
Iris::panic (r, "response doesn't match command")
|
||||
r <<= 24
|
||||
r |= MSC_RES << 8
|
||||
@ -199,8 +208,8 @@ void Mmc::reset ():
|
||||
Iris::my_memory.map (buffer_page, buffer)
|
||||
// Reset all state, by faking a release event.
|
||||
release ()
|
||||
// Enable slow clock to msc.
|
||||
CPM_MSCCDR = ~0
|
||||
// Enable 25 MHz clock to msc.
|
||||
CPM_MSCCDR = 13
|
||||
cpm_start_msc ()
|
||||
// Enable msc pins.
|
||||
gpio_as_msc ()
|
||||
@ -223,13 +232,13 @@ void Mmc::reset ():
|
||||
Iris::sleep (1)
|
||||
|
||||
// Initialize registers.
|
||||
MSC_CLKRT = MSC_CLKRT_CLK_RATE_DIV_128
|
||||
MSC_CLKRT = MSC_CLKRT_CLK_RATE_DIV_1
|
||||
MSC_RESTO = 64
|
||||
MSC_RDTO = ~0
|
||||
MSC_BLKLEN = 0x200
|
||||
MSC_NOB = 0
|
||||
MSC_IREG = ~0
|
||||
MSC_IMASK = ~(MSC_IMASK_END_CMD_RES | MSC_IMASK_RXFIFO_RD_REQ | MSC_IMASK_TXFIFO_WR_REQ)
|
||||
MSC_IMASK = ~(MSC_IMASK_END_CMD_RES | MSC_IMASK_RXFIFO_RD_REQ)
|
||||
MSC_ARG = 0
|
||||
|
||||
// Start the clock.
|
||||
@ -237,8 +246,8 @@ void Mmc::reset ():
|
||||
// Set cards, if any, to idle.
|
||||
send (0, 0, NONE)
|
||||
|
||||
// Reset SDIO device, if any.
|
||||
send (52, 0x88000c08, R5)
|
||||
// Reset SDIO device, if any. Don't do this, because it breaks for some reason.
|
||||
//send (52, 0x88000c08, R5)
|
||||
|
||||
void Mmc::check_mmc ():
|
||||
//kdebug ("checking mmc\n")
|
||||
@ -378,8 +387,9 @@ void Mmc::fill_page (Iris::Page page, Iris::Num address, unsigned size, unsigned
|
||||
//kdebug ("/")
|
||||
//kdebug_num (size)
|
||||
//kdebug (" ==> ")
|
||||
if !send (17, p + a, DATA):
|
||||
if !send (17, p + a, RD_DATA):
|
||||
Iris::panic (0, "unable to request data")
|
||||
MSC_IMASK = ~MSC_IMASK_RXFIFO_RD_REQ
|
||||
for unsigned aa = 0; aa < 1 << 9; aa += 4:
|
||||
while MSC_STAT & MSC_STAT_DATA_FIFO_EMPTY:
|
||||
Iris::register_interrupt (IRQ_MSC)
|
||||
@ -392,9 +402,48 @@ void Mmc::fill_page (Iris::Page page, Iris::Num address, unsigned size, unsigned
|
||||
//kdebug (" ")
|
||||
//kdebug_num (d >> (8 * i), 2)
|
||||
//kdebug ("\n")
|
||||
MSC_IMASK = ~0
|
||||
MSC_IREG = MSC_IREG_DATA_TRAN_DONE
|
||||
//kdebug ("done filling page\n")
|
||||
|
||||
void Mmc::write_page (Iris::Page page, Iris::Num address, unsigned size, unsigned offset):
|
||||
if address.h:
|
||||
Iris::panic (1, "page too high: not supported")
|
||||
return
|
||||
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.share (buffer_page)
|
||||
buffer_page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME)
|
||||
MSC_NOB = 1
|
||||
MSC_BLKLEN = 1 << 9
|
||||
for unsigned a = 0; a < size; a += 1 << 9:
|
||||
//kdebug_num (a)
|
||||
//kdebug ("/")
|
||||
//kdebug_num (size)
|
||||
//kdebug ("\n")
|
||||
if !send (24, p + a, WR_DATA):
|
||||
Iris::panic (0, "unable to send data")
|
||||
MSC_IMASK = ~MSC_IMASK_TXFIFO_WR_REQ
|
||||
for unsigned aa = 0; aa < 1 << 9; aa += 4:
|
||||
while MSC_STAT & MSC_STAT_DATA_FIFO_FULL:
|
||||
Iris::register_interrupt (IRQ_MSC)
|
||||
Iris::wait_for_interrupt (IRQ_MSC)
|
||||
MSC_TXFIFO = *(unsigned *)(buffer + a + aa + offset)
|
||||
MSC_IMASK = ~0
|
||||
MSC_IREG = MSC_IREG_DATA_TRAN_DONE
|
||||
//kdebug ("done writing page\n")
|
||||
|
||||
void Mmc::wait_write ():
|
||||
MSC_IMASK = ~MSC_IMASK_PRG_DONE
|
||||
while !MSC_STAT & MSC_STAT_PRG_DONE:
|
||||
Iris::register_interrupt (IRQ_MSC)
|
||||
Iris::wait_for_interrupt (IRQ_MSC)
|
||||
MSC_IREG = MSC_IREG_PRG_DONE
|
||||
|
||||
static Mmc mmc
|
||||
|
||||
enum types:
|
||||
@ -464,10 +513,19 @@ Iris::Num start ():
|
||||
Iris::free_cap (page)
|
||||
Iris::free_cap (reply)
|
||||
break
|
||||
case Iris::WString::SET_CHARS:
|
||||
case Iris::WString::SET_BLOCK:
|
||||
// Fall through: don't support writing yet.
|
||||
Iris::Cap reply = Iris::get_reply ()
|
||||
Iris::Page page = Iris::get_arg ()
|
||||
mmc.write_page (page, Iris::recv.data[1], Iris::recv.data[0].h >> 16, Iris::recv.data[0].h & 0xffff)
|
||||
reply.invoke ()
|
||||
Iris::free_cap (page)
|
||||
Iris::free_cap (reply)
|
||||
mmc.wait_write ()
|
||||
break
|
||||
case Iris::WString::SET_CHARS:
|
||||
// Fall through: don't support writing single characters.
|
||||
case Iris::WString::TRUNCATE:
|
||||
// Fall through: don't support resizing.
|
||||
default:
|
||||
Iris::panic (0, "unexpected event for sd+mmc")
|
||||
break
|
||||
|
Loading…
Reference in New Issue
Block a user