mirror of
git://projects.qi-hardware.com/iris.git
synced 2025-04-21 12:27:27 +03:00
lists and bugfixes
This commit is contained in:
@@ -68,10 +68,16 @@ class Mmc:
|
||||
return read_block_size
|
||||
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 read_page (Iris::Page page, Iris::Num address, unsigned size, unsigned offset)
|
||||
void wait_write ()
|
||||
void add_cb (Iris::Listitem item):
|
||||
cb_list.add_item (item)
|
||||
private:
|
||||
void set_block (unsigned block)
|
||||
unsigned current_block_num
|
||||
bool dirty
|
||||
unsigned *current_block
|
||||
unsigned rca
|
||||
bool have_sdmem, have_io
|
||||
bool hc
|
||||
@@ -79,6 +85,7 @@ class Mmc:
|
||||
CSD csd
|
||||
unsigned num_blocks, read_block_size
|
||||
Iris::Page buffer_page
|
||||
Iris::List cb_list
|
||||
static unsigned const buffer = 0x15000
|
||||
|
||||
bool Mmc::send (unsigned cmd, unsigned arg, Response_type response_type, unsigned *response):
|
||||
@@ -129,6 +136,9 @@ bool Mmc::send (unsigned cmd, unsigned arg, Response_type response_type, unsigne
|
||||
d = MSC_RES
|
||||
cid.year = 2000 + (d >> 4 & 0xff)
|
||||
cid.month = d & 0xf
|
||||
#if 1
|
||||
Iris::debug ("CID: mid=%x, oid=%x %x, pnm=%x %x %x %x %x, prv=%x, psn=%x, year=%x, month=%x\n", cid.mid, cid.oid[0], cid.oid[1], cid.pnm[0], cid.pnm[1], cid.pnm[2], cid.pnm[3], cid.pnm[4], cid.prv, cid.psn, cid.year, cid.month)
|
||||
#endif
|
||||
else:
|
||||
// Header (8) 1.0 1.0
|
||||
// Read out csd.
|
||||
@@ -175,6 +185,15 @@ bool Mmc::send (unsigned cmd, unsigned arg, Response_type response_type, unsigne
|
||||
num_blocks >>= 9 - csd.read_bl_len
|
||||
else:
|
||||
num_blocks <<= csd.read_bl_len - 9
|
||||
#if 1
|
||||
Iris::debug ("CSD: size=%x<<%x, r/w len=%x/%x, %s, %s, %s\n", csd.c_size, csd.c_size_mult, csd.read_bl_len, csd.write_bl_len, csd.copy ? "copy" : "no copy", csd.perm_write_protect ? "fixed write protect" : "no fixed write protect", csd.tmp_write_protect ? "write protect" : "no write protect")
|
||||
#endif
|
||||
unsigned c_size
|
||||
unsigned c_size_mult
|
||||
unsigned read_bl_len, write_bl_len
|
||||
bool copy
|
||||
bool perm_write_protect
|
||||
bool tmp_write_protect
|
||||
else if response_type != NONE:
|
||||
unsigned r = MSC_RES
|
||||
if response_type == R3:
|
||||
@@ -203,6 +222,10 @@ bool Mmc::send (unsigned cmd, unsigned arg, Response_type response_type, unsigne
|
||||
return true
|
||||
|
||||
void Mmc::reset ():
|
||||
current_block_num = ~0
|
||||
dirty = false
|
||||
cb_list = Iris::my_memory.create_list ()
|
||||
current_block = (unsigned *)(buffer + PAGE_SIZE)
|
||||
// Create a buffer to use for data transfer.
|
||||
buffer_page = Iris::my_memory.create_page ()
|
||||
Iris::my_memory.map (buffer_page, buffer)
|
||||
@@ -348,6 +371,20 @@ void Mmc::detect ():
|
||||
kdebug (" = ")
|
||||
kdebug_num (num_blocks * read_block_size)
|
||||
kdebug ("\n")
|
||||
// Set up buffer memory.
|
||||
for unsigned i = 0; i < 1 << csd.write_bl_len; i += PAGE_SIZE:
|
||||
Iris::Page p = Iris::my_memory.create_page ()
|
||||
p.set_flags (Iris::Page::PAYING | Iris::Page::FRAME)
|
||||
Iris::my_memory.map (p, (unsigned)current_block + i)
|
||||
Iris::free_cap (p)
|
||||
Iris::Listitem item = cb_list.get_next ()
|
||||
while item.code != Iris::Cap ().code:
|
||||
Iris::Cap c = cb_list.get_cap (item)
|
||||
c.invoke (0, ~0)
|
||||
Iris::free_cap (c)
|
||||
Iris::Listitem nextitem = cb_list.get_next (item);
|
||||
Iris::free_cap (item)
|
||||
item = nextitem
|
||||
|
||||
void Mmc::release ():
|
||||
kdebug ("mmc release\n")
|
||||
@@ -355,87 +392,94 @@ void Mmc::release ():
|
||||
have_sdmem = false
|
||||
have_io = false
|
||||
read_block_size = 0
|
||||
if num_blocks != 0:
|
||||
for unsigned i = 0; i < 1 << csd.write_bl_len; i += PAGE_SIZE:
|
||||
Iris::Page p = Iris::my_memory.mapping ((void *)((unsigned)current_block + i))
|
||||
Iris::my_memory.destroy (p)
|
||||
Iris::free_cap (p)
|
||||
if dirty:
|
||||
Iris::debug ("Warning: sd/mmc card removed before data was written to it")
|
||||
current_block_num = ~0
|
||||
dirty = false
|
||||
num_blocks = 0
|
||||
Iris::Listitem item = cb_list.get_next ()
|
||||
while item.code != Iris::Cap ().code:
|
||||
Iris::Cap c = cb_list.get_cap (item)
|
||||
c.invoke (0, ~0)
|
||||
Iris::free_cap (c)
|
||||
Iris::Listitem nextitem = cb_list.get_next (item);
|
||||
Iris::free_cap (item)
|
||||
item = nextitem
|
||||
|
||||
void Mmc::interrupt ():
|
||||
kdebug ("mmc interrupt\n")
|
||||
|
||||
void Mmc::fill_page (Iris::Page page, Iris::Num address, unsigned size, unsigned offset):
|
||||
if address.h:
|
||||
Iris::panic (0, "page too high: not supported")
|
||||
void Mmc::set_block (unsigned block):
|
||||
if current_block_num == block:
|
||||
return
|
||||
//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)
|
||||
page.share (buffer_page)
|
||||
buffer_page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME)
|
||||
if dirty && current_block_num != ~0:
|
||||
MSC_NOB = 1
|
||||
MSC_BLKLEN = 1 << csd.write_bl_len
|
||||
if !send (24, (current_block_num << csd.write_bl_len), WR_DATA):
|
||||
Iris::panic (0, "unable to send data")
|
||||
MSC_IMASK = ~MSC_IMASK_TXFIFO_WR_REQ
|
||||
for unsigned a = 0; a < 1 << csd.write_bl_len; a += 4:
|
||||
while MSC_STAT & MSC_STAT_DATA_FIFO_FULL:
|
||||
Iris::register_interrupt (IRQ_MSC)
|
||||
Iris::wait_for_interrupt (IRQ_MSC)
|
||||
MSC_TXFIFO = current_block[a >> 2]
|
||||
MSC_IMASK = ~0
|
||||
MSC_IREG = MSC_IREG_DATA_TRAN_DONE
|
||||
//kdebug ("done writing page\n")
|
||||
current_block_num = block
|
||||
dirty = false
|
||||
MSC_NOB = 1
|
||||
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, RD_DATA):
|
||||
for unsigned a = 0; a < 1 << csd.write_bl_len; a += 1 << 9:
|
||||
if !send (17, (block << csd.write_bl_len) + 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)
|
||||
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")
|
||||
current_block[(a + aa) >> 2] = MSC_RXFIFO
|
||||
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
|
||||
void Mmc::read_page (Iris::Page page, Iris::Num address, unsigned size, unsigned offset):
|
||||
if address.value () >> (csd.write_bl_len + 32):
|
||||
Iris::panic (address.h, "page too high: not supported")
|
||||
unsigned block = address.value () >> csd.write_bl_len
|
||||
unsigned start_pos = address.l & (1 << csd.write_bl_len) - 1
|
||||
set_block (block)
|
||||
unsigned blockmask = ~((1 << 9) - 1)
|
||||
unsigned p = address.l & blockmask
|
||||
size &= blockmask
|
||||
offset &= ~PAGE_MASK
|
||||
offset &= ~PAGE_MASK & ~3
|
||||
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")
|
||||
for unsigned i = 0; i < size; i += 4:
|
||||
((unsigned *)buffer)[(offset + i) >> 2] = current_block[(start_pos + i) >> 2]
|
||||
|
||||
void Mmc::write_page (Iris::Page page, Iris::Num address, unsigned size, unsigned offset):
|
||||
if address.value () >> (csd.write_bl_len + 32):
|
||||
Iris::panic (address.h, "page too high: not supported")
|
||||
unsigned block = address.value () >> csd.write_bl_len
|
||||
unsigned start_pos = address.l & (1 << csd.write_bl_len) - 1
|
||||
set_block (block)
|
||||
unsigned blockmask = ~((1 << 9) - 1)
|
||||
size &= blockmask
|
||||
offset &= ~PAGE_MASK & ~3
|
||||
if size + offset > PAGE_SIZE:
|
||||
size = PAGE_SIZE - offset
|
||||
page.share (buffer_page)
|
||||
buffer_page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME)
|
||||
for unsigned i = 0; i < size; i += 4:
|
||||
current_block[(start_pos + i) >> 2] = ((unsigned *)buffer)[(offset + i) >> 2]
|
||||
dirty = true
|
||||
|
||||
void Mmc::wait_write ():
|
||||
MSC_IMASK = ~MSC_IMASK_PRG_DONE
|
||||
@@ -473,7 +517,7 @@ Iris::Num start ():
|
||||
mmc.detect ()
|
||||
|
||||
cap = Iris::my_receiver.create_capability (REQUEST)
|
||||
Iris::my_parent.provide_capability <Iris::WString> (cap.copy ())
|
||||
Iris::my_parent.provide_capability <Iris::WBlock> (cap.copy ())
|
||||
Iris::free_cap (cap)
|
||||
|
||||
Iris::my_parent.init_done ()
|
||||
@@ -496,21 +540,25 @@ Iris::Num start ():
|
||||
//kdebug ("\n")
|
||||
switch Iris::recv.data[0].l:
|
||||
case Iris::Block::GET_SIZE:
|
||||
Iris::debug ("get size\n")
|
||||
unsigned long long size = mmc.get_num_blocks () * mmc.get_read_block_size ()
|
||||
Iris::recv.reply.invoke (size)
|
||||
break
|
||||
case Iris::Block::GET_ALIGN_BITS:
|
||||
Iris::debug ("get align bits\n")
|
||||
Iris::recv.reply.invoke (9)
|
||||
break
|
||||
case Iris::Block::GET_BLOCK:
|
||||
//Iris::debug ("get block\n")
|
||||
Iris::Cap reply = Iris::get_reply ()
|
||||
Iris::Page page = Iris::get_arg ()
|
||||
mmc.fill_page (page, Iris::recv.data[1], Iris::recv.data[0].h >> 16, Iris::recv.data[0].h & 0xffff)
|
||||
mmc.read_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)
|
||||
break
|
||||
case Iris::WBlock::SET_BLOCK:
|
||||
Iris::debug ("set block\n")
|
||||
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)
|
||||
@@ -519,7 +567,17 @@ Iris::Num start ():
|
||||
Iris::free_cap (reply)
|
||||
mmc.wait_write ()
|
||||
break
|
||||
case Iris::WString::TRUNCATE:
|
||||
case Iris::Block::SET_CHANGE_CB:
|
||||
Iris::debug ("set change cb\n")
|
||||
Iris::Listitem item = Iris::get_arg ()
|
||||
Iris::Cap reply = Iris::get_reply ()
|
||||
mmc.add_cb (item)
|
||||
reply.invoke ()
|
||||
Iris::free_cap (item)
|
||||
Iris::free_cap (reply)
|
||||
break
|
||||
case Iris::WBlock::TRUNCATE:
|
||||
Iris::debug ("truncate\n")
|
||||
// Fall through: don't support resizing.
|
||||
default:
|
||||
Iris::panic (0, "unexpected event for sd+mmc")
|
||||
|
||||
Reference in New Issue
Block a user