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

make booting from sd work

This commit is contained in:
Bas Wijnen 2010-07-08 12:38:36 +02:00
parent a277156a2e
commit 19f1d128d0
9 changed files with 128 additions and 54 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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