mirror of
git://projects.qi-hardware.com/iris.git
synced 2025-01-16 22:31:05 +02:00
lists and bugfixes
This commit is contained in:
parent
7e8cc1d25e
commit
f4cac9b3a5
11
devices.hhp
11
devices.hhp
@ -37,6 +37,7 @@ namespace Iris:
|
|||||||
enum request:
|
enum request:
|
||||||
LOCK_RO = 0x2001
|
LOCK_RO = 0x2001
|
||||||
UNLOCK_RO
|
UNLOCK_RO
|
||||||
|
SET_CHANGE_CB
|
||||||
NUM
|
NUM
|
||||||
template <typename _T> //
|
template <typename _T> //
|
||||||
struct Locker : public _Locker_base, public _T:
|
struct Locker : public _Locker_base, public _T:
|
||||||
@ -46,6 +47,12 @@ namespace Iris:
|
|||||||
// Release a read-only lock.
|
// Release a read-only lock.
|
||||||
void unlock_ro ():
|
void unlock_ro ():
|
||||||
_T::call (CAP_MASTER_DIRECT | UNLOCK_RO)
|
_T::call (CAP_MASTER_DIRECT | UNLOCK_RO)
|
||||||
|
// Register a callback when the backing store is changed.
|
||||||
|
// The cb is invoked with data[0] set to the position of the first change and data[1] set to the length of the changed part.
|
||||||
|
// The accuracy of this is not guaranteed. Servers which only want to provide an event should set data[0] == 0, data[1] == ~0.
|
||||||
|
// The change invoke must happen before this function's reply is sent.
|
||||||
|
void set_change_cb (Listitem cb):
|
||||||
|
_T::ocall (cb, CAP_MASTER_DIRECT | SET_CHANGE_CB)
|
||||||
Locker ():
|
Locker ():
|
||||||
Locker (Cap c) : _T (c):
|
Locker (Cap c) : _T (c):
|
||||||
|
|
||||||
@ -130,8 +137,8 @@ namespace Iris:
|
|||||||
struct _WBlock : public Block:
|
struct _WBlock : public Block:
|
||||||
_WBlock (Cap c = Cap ()) : Block (c):
|
_WBlock (Cap c = Cap ()) : Block (c):
|
||||||
enum request:
|
enum request:
|
||||||
TRUNCATE = _Block::ID
|
TRUNCATE = _WString::TRUNCATE
|
||||||
SET_BLOCK
|
SET_BLOCK = _WString::ID
|
||||||
ID
|
ID
|
||||||
/// Set the size of the block. This setting may have a limited range, or not be supported at all.
|
/// Set the size of the block. This setting may have a limited range, or not be supported at all.
|
||||||
void truncate (Num size):
|
void truncate (Num size):
|
||||||
|
18
invoke.ccp
18
invoke.ccp
@ -320,6 +320,22 @@ static void memory_invoke (unsigned cmd, unsigned target, Iris::Num protected_da
|
|||||||
dpanic (0x43311992, "out of memory creating caps")
|
dpanic (0x43311992, "out of memory creating caps")
|
||||||
reply_num (Iris::ERR_OUT_OF_MEMORY)
|
reply_num (Iris::ERR_OUT_OF_MEMORY)
|
||||||
return
|
return
|
||||||
|
case CAPTYPE_LIST:
|
||||||
|
kList *ret = mem->alloc_list ()
|
||||||
|
if ret:
|
||||||
|
reply_cap (CAPTYPE_LIST | CAP_MASTER, (unsigned)ret, &ret->refs)
|
||||||
|
else:
|
||||||
|
dpanic (0x13311995, "out of memory creating list")
|
||||||
|
reply_num (Iris::ERR_OUT_OF_MEMORY)
|
||||||
|
return
|
||||||
|
case CAPTYPE_LISTITEM:
|
||||||
|
kListitem *ret = mem->alloc_listitem ()
|
||||||
|
if ret:
|
||||||
|
reply_cap (CAPTYPE_LISTITEM | CAP_MASTER, (unsigned)ret, &ret->refs)
|
||||||
|
else:
|
||||||
|
dpanic (0x13311997, "out of memory creating list")
|
||||||
|
reply_num (Iris::ERR_OUT_OF_MEMORY)
|
||||||
|
return
|
||||||
default:
|
default:
|
||||||
dpanic (0, "invalid create type")
|
dpanic (0, "invalid create type")
|
||||||
reply_num (Iris::ERR_INVALID_ARGUMENT)
|
reply_num (Iris::ERR_INVALID_ARGUMENT)
|
||||||
@ -873,7 +889,7 @@ static void list_invoke (unsigned cmd, unsigned target, Iris::Num protected_data
|
|||||||
return
|
return
|
||||||
item = item->next_item
|
item = item->next_item
|
||||||
if !item:
|
if !item:
|
||||||
reply_num (0)
|
reply_num (~0)
|
||||||
return
|
return
|
||||||
reply_cap (CAPTYPE_LISTITEM | Iris::Listitem::LIST, (unsigned)item, &item->refs)
|
reply_cap (CAPTYPE_LISTITEM | Iris::Listitem::LIST, (unsigned)item, &item->refs)
|
||||||
return
|
return
|
||||||
|
9
iris.hhp
9
iris.hhp
@ -496,17 +496,26 @@ namespace Iris:
|
|||||||
GET_INFO
|
GET_INFO
|
||||||
SET_INFO
|
SET_INFO
|
||||||
GET_CAP
|
GET_CAP
|
||||||
|
// Get the next listitem from the given one. Use this to loop over all listitems.
|
||||||
Listitem get_next (Listitem current = Listitem ()):
|
Listitem get_next (Listitem current = Listitem ()):
|
||||||
iocall (current, CAP_MASTER_DIRECT | GET_NEXT)
|
iocall (current, CAP_MASTER_DIRECT | GET_NEXT)
|
||||||
|
if recv.data[0].l:
|
||||||
|
return Cap ()
|
||||||
return get_arg ()
|
return get_arg ()
|
||||||
|
// Set the callback. This is called when an item is removed from the list.
|
||||||
|
// When called, data[0] is 0 when the list is now empty; 1 otherwise. data[1] is the removed item's info.
|
||||||
void set_cb (Cap cb):
|
void set_cb (Cap cb):
|
||||||
ocall (cb, CAP_MASTER_DIRECT | SET_CB)
|
ocall (cb, CAP_MASTER_DIRECT | SET_CB)
|
||||||
|
// Add an item to the front of the list.
|
||||||
void add_item (Listitem item):
|
void add_item (Listitem item):
|
||||||
ocall (item, CAP_MASTER_DIRECT | ADD_ITEM)
|
ocall (item, CAP_MASTER_DIRECT | ADD_ITEM)
|
||||||
|
// Return item info.
|
||||||
Num get_info (Listitem item):
|
Num get_info (Listitem item):
|
||||||
return ocall (item, CAP_MASTER_DIRECT | GET_INFO)
|
return ocall (item, CAP_MASTER_DIRECT | GET_INFO)
|
||||||
|
// Set item info.
|
||||||
void set_info (Listitem item, Num info):
|
void set_info (Listitem item, Num info):
|
||||||
ocall (item, CAP_MASTER_DIRECT | SET_INFO, info)
|
ocall (item, CAP_MASTER_DIRECT | SET_INFO, info)
|
||||||
|
// Get item capability.
|
||||||
Cap get_cap (Listitem item):
|
Cap get_cap (Listitem item):
|
||||||
iocall (item, CAP_MASTER_DIRECT | GET_CAP)
|
iocall (item, CAP_MASTER_DIRECT | GET_CAP)
|
||||||
return get_arg ()
|
return get_arg ()
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
start_load = 0x80600000
|
start_load = 0x80400000
|
||||||
load = 0x80000000
|
load = 0x80000000
|
||||||
# Uncomment one of these to select the boot method for the image.
|
# Uncomment one of these to select the boot method for the image.
|
||||||
#UDC_BOOT = yes
|
#UDC_BOOT = yes
|
||||||
@ -27,10 +27,11 @@ boot_sources = mips/init.cc mips/nanonote/board.cc
|
|||||||
arch_headers = mips/arch.hh mips/nanonote/jz4740.hh mips/nanonote/board.hh mips/nand.hh
|
arch_headers = mips/arch.hh mips/nanonote/jz4740.hh mips/nanonote/board.hh mips/nand.hh
|
||||||
udc_boot_programs = udc
|
udc_boot_programs = udc
|
||||||
sd_boot_programs = sd+mmc partition fat
|
sd_boot_programs = sd+mmc partition fat
|
||||||
unbrick_boot_programs = nand usb-mass-storage
|
unbrick_boot_programs = nand sd+mmc usb-mass-storage
|
||||||
standard_boot_programs = bootinit
|
standard_boot_programs = bootinit
|
||||||
|
|
||||||
programs = init gpio lcd bsquare ball buzzer metronome elfrun alarm rtc gui test boot booter $(udc_boot_programs) $(sd_boot_programs) $(unbrick_boot_programs) $(standard_boot_programs)
|
# use sort to remove duplicates.
|
||||||
|
programs = $(sort init gpio lcd bsquare ball buzzer metronome elfrun alarm rtc gui test boot booter $(udc_boot_programs) $(sd_boot_programs) $(unbrick_boot_programs) $(standard_boot_programs))
|
||||||
|
|
||||||
ARCH_CPPFLAGS = -I. -Imips -Imips/nanonote -Wa,-mips32 -DNANONOTE -DUSE_SERIAL
|
ARCH_CPPFLAGS = -I. -Imips -Imips/nanonote -Wa,-mips32 -DNANONOTE -DUSE_SERIAL
|
||||||
CROSS = mipsel-linux-gnu-
|
CROSS = mipsel-linux-gnu-
|
||||||
@ -56,7 +57,7 @@ iris-sd.tar: $(addprefix fs/,$(addsuffix .elf,$(programs))) mips/start.raw.gz fs
|
|||||||
cd fs && tar cvf ../$@ uimage init.config $(addsuffix .elf,$(programs)) --dereference
|
cd fs && tar cvf ../$@ uimage init.config $(addsuffix .elf,$(programs)) --dereference
|
||||||
else
|
else
|
||||||
ifneq ($(UNBRICK),)
|
ifneq ($(UNBRICK),)
|
||||||
boot_threads = $(standard_boot_programs) $(unbrick_boot_programs)
|
boot_threads = $(standard_boot_programs) $(unbrick_boot_programs) sd+mmc
|
||||||
ARCH_CXXFLAGS = -DNUM_THREADS=3
|
ARCH_CXXFLAGS = -DNUM_THREADS=3
|
||||||
BOOT_CPPFLAGS = -DUNBRICK
|
BOOT_CPPFLAGS = -DUNBRICK
|
||||||
all: mips/start.raw
|
all: mips/start.raw
|
||||||
|
@ -23,10 +23,6 @@
|
|||||||
void board_init ():
|
void board_init ():
|
||||||
pll_init ()
|
pll_init ()
|
||||||
cpm_stop_all ()
|
cpm_stop_all ()
|
||||||
#ifndef NDEBUG
|
|
||||||
cpm_start_uart0 ()
|
|
||||||
gpio_as_uart0 ()
|
|
||||||
#endif
|
|
||||||
// Timer interrupts and buzzer.
|
// Timer interrupts and buzzer.
|
||||||
cpm_start_tcu ()
|
cpm_start_tcu ()
|
||||||
// sdram memory.
|
// sdram memory.
|
||||||
@ -42,7 +38,7 @@ void board_init ():
|
|||||||
// buzzer.
|
// buzzer.
|
||||||
gpio_as_pwm4 ()
|
gpio_as_pwm4 ()
|
||||||
// Set up memory.
|
// Set up memory.
|
||||||
setup_sdram ()
|
//setup_sdram ()
|
||||||
// Use some gpio pins for lcd.
|
// Use some gpio pins for lcd.
|
||||||
gpio_as_gpio (2, (1 << 21) | (1 << 22) | (1 << 23))
|
gpio_as_gpio (2, (1 << 21) | (1 << 22) | (1 << 23))
|
||||||
gpio_as_output (2, (1 << 21) | (1 << 22) | (1 << 23))
|
gpio_as_output (2, (1 << 21) | (1 << 22) | (1 << 23))
|
||||||
@ -66,20 +62,7 @@ void board_init ():
|
|||||||
tcu_unmask_full_match_irq (0)
|
tcu_unmask_full_match_irq (0)
|
||||||
tcu_start_counter (0)
|
tcu_start_counter (0)
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
// Set up uart.
|
setup_uart ()
|
||||||
UART0_IER = 0
|
|
||||||
UART0_FCR = 0
|
|
||||||
UART0_MCR = 0
|
|
||||||
UART0_SIRCR = 0
|
|
||||||
UART0_UACR = 0
|
|
||||||
UART0_UMR = 16
|
|
||||||
UART0_LCR = UARTLCR_WLEN_8 | UARTLCR_STOP1 | UARTLCR_DLAB
|
|
||||||
unsigned const baud = 57600
|
|
||||||
unsigned uart_div = 12000000 / 16 / baud
|
|
||||||
UART0_DLHR = (uart_div >> 8) & 0xff
|
|
||||||
UART0_DLLR = uart_div & 0xff
|
|
||||||
UART0_LCR = UARTLCR_WLEN_8 | UARTLCR_STOP1
|
|
||||||
UART0_FCR = UARTFCR_UUE | UARTFCR_FE | UARTFCR_RFLS | UARTFCR_TFLS
|
|
||||||
kdebug ("\n\nSerial port initialized\n")
|
kdebug ("\n\nSerial port initialized\n")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -3701,6 +3701,26 @@ static void setup_sdram ():
|
|||||||
dbg_log_num (EMC_RTCOR, 8)
|
dbg_log_num (EMC_RTCOR, 8)
|
||||||
dbg_log ("\n")
|
dbg_log ("\n")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void setup_uart ():
|
||||||
|
#ifndef NDEBUG
|
||||||
|
// Set up uart.
|
||||||
|
cpm_start_uart0 ()
|
||||||
|
gpio_as_uart0 ()
|
||||||
|
UART0_IER = 0
|
||||||
|
UART0_FCR = 0
|
||||||
|
UART0_MCR = 0
|
||||||
|
UART0_SIRCR = 0
|
||||||
|
UART0_UACR = 0
|
||||||
|
UART0_UMR = 16
|
||||||
|
UART0_LCR = UARTLCR_WLEN_8 | UARTLCR_STOP1 | UARTLCR_DLAB
|
||||||
|
unsigned const baud = 57600
|
||||||
|
unsigned uart_div = 12000000 / 16 / baud
|
||||||
|
UART0_DLHR = (uart_div >> 8) & 0xff
|
||||||
|
UART0_DLLR = uart_div & 0xff
|
||||||
|
UART0_LCR = UARTLCR_WLEN_8 | UARTLCR_STOP1
|
||||||
|
UART0_FCR = UARTFCR_UUE | UARTFCR_FE | UARTFCR_RFLS | UARTFCR_TFLS
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -18,16 +18,22 @@
|
|||||||
|
|
||||||
// This runs like the kernel. In particular, it doesn't want userspace declarations.
|
// This runs like the kernel. In particular, it doesn't want userspace declarations.
|
||||||
#define __KERNEL__
|
#define __KERNEL__
|
||||||
#define dbg_log(x) do {} while (0)
|
|
||||||
#define dbg_log_char(x) do {} while (0)
|
#define dbg_log_char(x) do {} while (0)
|
||||||
|
#define dbg_log(x) do {} while (0)
|
||||||
#define dbg_log_num(...) do {} while (0)
|
#define dbg_log_num(...) do {} while (0)
|
||||||
|
|
||||||
#include "jz4740.hh"
|
#include "jz4740.hh"
|
||||||
|
|
||||||
|
void kdebug (unsigned ch):
|
||||||
|
while !(UART0_LSR & UARTLSR_TDRQ):
|
||||||
|
UART0_TDR = ch
|
||||||
|
while !(UART0_LSR & UARTLSR_TEMT):
|
||||||
|
|
||||||
asm volatile (".set noreorder\n"
|
asm volatile (".set noreorder\n"
|
||||||
"\t.globl __start\n"
|
"\t.globl __start\n"
|
||||||
"\t.text\n"
|
"\t.text\n"
|
||||||
"__start:\n"
|
"__start:\n"
|
||||||
"\tla $sp, 0x80004000\n"
|
"\tnop\n"
|
||||||
"__hack_label:\n"
|
"__hack_label:\n"
|
||||||
"\tmove $a0, $ra\n"
|
"\tmove $a0, $ra\n"
|
||||||
"\tbal 1f\n"
|
"\tbal 1f\n"
|
||||||
@ -35,6 +41,7 @@ asm volatile (".set noreorder\n"
|
|||||||
"\t.word _gp\n"
|
"\t.word _gp\n"
|
||||||
"1:\n"
|
"1:\n"
|
||||||
"\tlw $gp, 0($ra)\n"
|
"\tlw $gp, 0($ra)\n"
|
||||||
|
"\tla $sp, stack + 0x100\n"
|
||||||
"\tla $t9, start_cpp\n"
|
"\tla $t9, start_cpp\n"
|
||||||
"\tmove $ra, $a0\n"
|
"\tmove $ra, $a0\n"
|
||||||
"\tjr $t9\n"
|
"\tjr $t9\n"
|
||||||
@ -43,7 +50,11 @@ asm volatile (".set noreorder\n"
|
|||||||
|
|
||||||
extern "C":
|
extern "C":
|
||||||
void start_cpp ()
|
void start_cpp ()
|
||||||
|
char stack[0x100]
|
||||||
|
|
||||||
void start_cpp ():
|
void start_cpp ():
|
||||||
setup_sdram ()
|
//setup_uart ()
|
||||||
|
//kdebug ('.')
|
||||||
|
//setup_sdram ()
|
||||||
|
//kdebug ('!')
|
||||||
// everything is ok now: return to boot loader to load stage 2.
|
// everything is ok now: return to boot loader to load stage 2.
|
||||||
|
@ -2,7 +2,7 @@ OUTPUT_ARCH(mips)
|
|||||||
ENTRY(__start)
|
ENTRY(__start)
|
||||||
MEMORY
|
MEMORY
|
||||||
{
|
{
|
||||||
ram : ORIGIN = 0x80002000 , LENGTH = 0x100000
|
ram : ORIGIN = 0x80002000 , LENGTH = 0x2000
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTIONS
|
SECTIONS
|
||||||
|
@ -225,6 +225,7 @@ struct client : public shevek::server <client, data *>::connection:
|
|||||||
disconnect ()
|
disconnect ()
|
||||||
|
|
||||||
void data::request (requests r, unsigned data):
|
void data::request (requests r, unsigned data):
|
||||||
|
std::cerr << shevek::ostring ("requesting %08x with data %08x\n", r, data)
|
||||||
if usb_control_msg (handle, USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, r, (data >> 16) & 0xffff, data & 0xffff, NULL, 0, timeout) < 0:
|
if usb_control_msg (handle, USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, r, (data >> 16) & 0xffff, data & 0xffff, NULL, 0, timeout) < 0:
|
||||||
std::cerr << "unable to send control message to NanoNote: " << usb_strerror () << ".\n"
|
std::cerr << "unable to send control message to NanoNote: " << usb_strerror () << ".\n"
|
||||||
usb_release_interface (handle, 0)
|
usb_release_interface (handle, 0)
|
||||||
@ -232,6 +233,7 @@ void data::request (requests r, unsigned data):
|
|||||||
handle = NULL
|
handle = NULL
|
||||||
|
|
||||||
void data::send_file (unsigned address, unsigned size, char const *data):
|
void data::send_file (unsigned address, unsigned size, char const *data):
|
||||||
|
std::cerr << shevek::ostring ("setting data address to 0x%08x\n", address)
|
||||||
request (VR_SET_DATA_ADDRESS, address)
|
request (VR_SET_DATA_ADDRESS, address)
|
||||||
char const *ptr = data
|
char const *ptr = data
|
||||||
while ptr - data < size:
|
while ptr - data < size:
|
||||||
@ -292,7 +294,6 @@ void data::boot (std::string const &filename, unsigned load, unsigned entry):
|
|||||||
request (VR_PROGRAM_START1, STAGE1_ENTRY)
|
request (VR_PROGRAM_START1, STAGE1_ENTRY)
|
||||||
usleep (100)
|
usleep (100)
|
||||||
std::ostringstream stage2
|
std::ostringstream stage2
|
||||||
usb_release_interface (handle, 0)
|
|
||||||
file.close ()
|
file.close ()
|
||||||
file.open (filename.c_str ())
|
file.open (filename.c_str ())
|
||||||
stage2 << file.rdbuf ()
|
stage2 << file.rdbuf ()
|
||||||
|
@ -74,7 +74,7 @@ thread0:
|
|||||||
|
|
||||||
.balign 0x1000
|
.balign 0x1000
|
||||||
thread1:
|
thread1:
|
||||||
.incbin "fs/nand.elf"
|
.incbin "fs/sd+mmc.elf"
|
||||||
|
|
||||||
.balign 0x1000
|
.balign 0x1000
|
||||||
thread2:
|
thread2:
|
||||||
|
@ -68,10 +68,16 @@ class Mmc:
|
|||||||
return read_block_size
|
return read_block_size
|
||||||
unsigned get_block_bits ():
|
unsigned get_block_bits ():
|
||||||
return hc ? 9 : csd.read_bl_len > csd.write_bl_len ? csd.read_bl_len : csd.write_bl_len
|
return hc ? 9 : csd.read_bl_len > csd.write_bl_len ? csd.read_bl_len : csd.write_bl_len
|
||||||
void fill_page (Iris::Page page, Iris::Num address, unsigned size, unsigned offset)
|
|
||||||
void write_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 wait_write ()
|
||||||
|
void add_cb (Iris::Listitem item):
|
||||||
|
cb_list.add_item (item)
|
||||||
private:
|
private:
|
||||||
|
void set_block (unsigned block)
|
||||||
|
unsigned current_block_num
|
||||||
|
bool dirty
|
||||||
|
unsigned *current_block
|
||||||
unsigned rca
|
unsigned rca
|
||||||
bool have_sdmem, have_io
|
bool have_sdmem, have_io
|
||||||
bool hc
|
bool hc
|
||||||
@ -79,6 +85,7 @@ class Mmc:
|
|||||||
CSD csd
|
CSD csd
|
||||||
unsigned num_blocks, read_block_size
|
unsigned num_blocks, read_block_size
|
||||||
Iris::Page buffer_page
|
Iris::Page buffer_page
|
||||||
|
Iris::List cb_list
|
||||||
static unsigned const buffer = 0x15000
|
static unsigned const buffer = 0x15000
|
||||||
|
|
||||||
bool Mmc::send (unsigned cmd, unsigned arg, Response_type response_type, unsigned *response):
|
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
|
d = MSC_RES
|
||||||
cid.year = 2000 + (d >> 4 & 0xff)
|
cid.year = 2000 + (d >> 4 & 0xff)
|
||||||
cid.month = d & 0xf
|
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:
|
else:
|
||||||
// Header (8) 1.0 1.0
|
// Header (8) 1.0 1.0
|
||||||
// Read out csd.
|
// 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
|
num_blocks >>= 9 - csd.read_bl_len
|
||||||
else:
|
else:
|
||||||
num_blocks <<= csd.read_bl_len - 9
|
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:
|
else if response_type != NONE:
|
||||||
unsigned r = MSC_RES
|
unsigned r = MSC_RES
|
||||||
if response_type == R3:
|
if response_type == R3:
|
||||||
@ -203,6 +222,10 @@ bool Mmc::send (unsigned cmd, unsigned arg, Response_type response_type, unsigne
|
|||||||
return true
|
return true
|
||||||
|
|
||||||
void Mmc::reset ():
|
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.
|
// Create a buffer to use for data transfer.
|
||||||
buffer_page = Iris::my_memory.create_page ()
|
buffer_page = Iris::my_memory.create_page ()
|
||||||
Iris::my_memory.map (buffer_page, buffer)
|
Iris::my_memory.map (buffer_page, buffer)
|
||||||
@ -348,6 +371,20 @@ void Mmc::detect ():
|
|||||||
kdebug (" = ")
|
kdebug (" = ")
|
||||||
kdebug_num (num_blocks * read_block_size)
|
kdebug_num (num_blocks * read_block_size)
|
||||||
kdebug ("\n")
|
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 ():
|
void Mmc::release ():
|
||||||
kdebug ("mmc release\n")
|
kdebug ("mmc release\n")
|
||||||
@ -355,87 +392,94 @@ void Mmc::release ():
|
|||||||
have_sdmem = false
|
have_sdmem = false
|
||||||
have_io = false
|
have_io = false
|
||||||
read_block_size = 0
|
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
|
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 ():
|
void Mmc::interrupt ():
|
||||||
kdebug ("mmc interrupt\n")
|
kdebug ("mmc interrupt\n")
|
||||||
|
|
||||||
void Mmc::fill_page (Iris::Page page, Iris::Num address, unsigned size, unsigned offset):
|
void Mmc::set_block (unsigned block):
|
||||||
if address.h:
|
if current_block_num == block:
|
||||||
Iris::panic (0, "page too high: not supported")
|
|
||||||
return
|
return
|
||||||
//kdebug ("smc get page ")
|
if dirty && current_block_num != ~0:
|
||||||
//kdebug_num (address.l)
|
MSC_NOB = 1
|
||||||
//kdebug ("+")
|
MSC_BLKLEN = 1 << csd.write_bl_len
|
||||||
//kdebug_num (size)
|
if !send (24, (current_block_num << csd.write_bl_len), WR_DATA):
|
||||||
//kdebug ("@")
|
Iris::panic (0, "unable to send data")
|
||||||
//kdebug_num (offset)
|
MSC_IMASK = ~MSC_IMASK_TXFIFO_WR_REQ
|
||||||
//kdebug ("\n")
|
for unsigned a = 0; a < 1 << csd.write_bl_len; a += 4:
|
||||||
unsigned blockmask = ~((1 << 9) - 1)
|
while MSC_STAT & MSC_STAT_DATA_FIFO_FULL:
|
||||||
unsigned p = address.l & blockmask
|
Iris::register_interrupt (IRQ_MSC)
|
||||||
size &= blockmask
|
Iris::wait_for_interrupt (IRQ_MSC)
|
||||||
offset &= ~PAGE_MASK
|
MSC_TXFIFO = current_block[a >> 2]
|
||||||
if size + offset > PAGE_SIZE:
|
MSC_IMASK = ~0
|
||||||
size = PAGE_SIZE - offset
|
MSC_IREG = MSC_IREG_DATA_TRAN_DONE
|
||||||
page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME)
|
//kdebug ("done writing page\n")
|
||||||
page.share (buffer_page)
|
current_block_num = block
|
||||||
buffer_page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME)
|
dirty = false
|
||||||
MSC_NOB = 1
|
MSC_NOB = 1
|
||||||
MSC_BLKLEN = 1 << 9
|
MSC_BLKLEN = 1 << 9
|
||||||
for unsigned a = 0; a < size; a += 1 << 9:
|
for unsigned a = 0; a < 1 << csd.write_bl_len; a += 1 << 9:
|
||||||
//kdebug_num (a)
|
if !send (17, (block << csd.write_bl_len) + a, RD_DATA):
|
||||||
//kdebug ("/")
|
|
||||||
//kdebug_num (size)
|
|
||||||
//kdebug (" ==> ")
|
|
||||||
if !send (17, p + a, RD_DATA):
|
|
||||||
Iris::panic (0, "unable to request data")
|
Iris::panic (0, "unable to request data")
|
||||||
MSC_IMASK = ~MSC_IMASK_RXFIFO_RD_REQ
|
MSC_IMASK = ~MSC_IMASK_RXFIFO_RD_REQ
|
||||||
for unsigned aa = 0; aa < 1 << 9; aa += 4:
|
for unsigned aa = 0; aa < 1 << 9; aa += 4:
|
||||||
while MSC_STAT & MSC_STAT_DATA_FIFO_EMPTY:
|
while MSC_STAT & MSC_STAT_DATA_FIFO_EMPTY:
|
||||||
Iris::register_interrupt (IRQ_MSC)
|
Iris::register_interrupt (IRQ_MSC)
|
||||||
Iris::wait_for_interrupt (IRQ_MSC)
|
Iris::wait_for_interrupt (IRQ_MSC)
|
||||||
*(unsigned *)(buffer + a + aa + offset) = MSC_RXFIFO
|
current_block[(a + aa) >> 2] = 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_IMASK = ~0
|
MSC_IMASK = ~0
|
||||||
MSC_IREG = MSC_IREG_DATA_TRAN_DONE
|
MSC_IREG = MSC_IREG_DATA_TRAN_DONE
|
||||||
//kdebug ("done filling page\n")
|
//kdebug ("done filling page\n")
|
||||||
|
|
||||||
void Mmc::write_page (Iris::Page page, Iris::Num address, unsigned size, unsigned offset):
|
void Mmc::read_page (Iris::Page page, Iris::Num address, unsigned size, unsigned offset):
|
||||||
if address.h:
|
if address.value () >> (csd.write_bl_len + 32):
|
||||||
Iris::panic (1, "page too high: not supported")
|
Iris::panic (address.h, "page too high: not supported")
|
||||||
return
|
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 blockmask = ~((1 << 9) - 1)
|
||||||
unsigned p = address.l & blockmask
|
|
||||||
size &= blockmask
|
size &= blockmask
|
||||||
offset &= ~PAGE_MASK
|
offset &= ~PAGE_MASK & ~3
|
||||||
if size + offset > PAGE_SIZE:
|
if size + offset > PAGE_SIZE:
|
||||||
size = PAGE_SIZE - offset
|
size = PAGE_SIZE - offset
|
||||||
page.share (buffer_page)
|
page.share (buffer_page)
|
||||||
buffer_page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME)
|
buffer_page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME)
|
||||||
MSC_NOB = 1
|
for unsigned i = 0; i < size; i += 4:
|
||||||
MSC_BLKLEN = 1 << 9
|
((unsigned *)buffer)[(offset + i) >> 2] = current_block[(start_pos + i) >> 2]
|
||||||
for unsigned a = 0; a < size; a += 1 << 9:
|
|
||||||
//kdebug_num (a)
|
void Mmc::write_page (Iris::Page page, Iris::Num address, unsigned size, unsigned offset):
|
||||||
//kdebug ("/")
|
if address.value () >> (csd.write_bl_len + 32):
|
||||||
//kdebug_num (size)
|
Iris::panic (address.h, "page too high: not supported")
|
||||||
//kdebug ("\n")
|
unsigned block = address.value () >> csd.write_bl_len
|
||||||
if !send (24, p + a, WR_DATA):
|
unsigned start_pos = address.l & (1 << csd.write_bl_len) - 1
|
||||||
Iris::panic (0, "unable to send data")
|
set_block (block)
|
||||||
MSC_IMASK = ~MSC_IMASK_TXFIFO_WR_REQ
|
unsigned blockmask = ~((1 << 9) - 1)
|
||||||
for unsigned aa = 0; aa < 1 << 9; aa += 4:
|
size &= blockmask
|
||||||
while MSC_STAT & MSC_STAT_DATA_FIFO_FULL:
|
offset &= ~PAGE_MASK & ~3
|
||||||
Iris::register_interrupt (IRQ_MSC)
|
if size + offset > PAGE_SIZE:
|
||||||
Iris::wait_for_interrupt (IRQ_MSC)
|
size = PAGE_SIZE - offset
|
||||||
MSC_TXFIFO = *(unsigned *)(buffer + a + aa + offset)
|
page.share (buffer_page)
|
||||||
MSC_IMASK = ~0
|
buffer_page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME)
|
||||||
MSC_IREG = MSC_IREG_DATA_TRAN_DONE
|
for unsigned i = 0; i < size; i += 4:
|
||||||
//kdebug ("done writing page\n")
|
current_block[(start_pos + i) >> 2] = ((unsigned *)buffer)[(offset + i) >> 2]
|
||||||
|
dirty = true
|
||||||
|
|
||||||
void Mmc::wait_write ():
|
void Mmc::wait_write ():
|
||||||
MSC_IMASK = ~MSC_IMASK_PRG_DONE
|
MSC_IMASK = ~MSC_IMASK_PRG_DONE
|
||||||
@ -473,7 +517,7 @@ Iris::Num start ():
|
|||||||
mmc.detect ()
|
mmc.detect ()
|
||||||
|
|
||||||
cap = Iris::my_receiver.create_capability (REQUEST)
|
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::free_cap (cap)
|
||||||
|
|
||||||
Iris::my_parent.init_done ()
|
Iris::my_parent.init_done ()
|
||||||
@ -496,21 +540,25 @@ Iris::Num start ():
|
|||||||
//kdebug ("\n")
|
//kdebug ("\n")
|
||||||
switch Iris::recv.data[0].l:
|
switch Iris::recv.data[0].l:
|
||||||
case Iris::Block::GET_SIZE:
|
case Iris::Block::GET_SIZE:
|
||||||
|
Iris::debug ("get size\n")
|
||||||
unsigned long long size = mmc.get_num_blocks () * mmc.get_read_block_size ()
|
unsigned long long size = mmc.get_num_blocks () * mmc.get_read_block_size ()
|
||||||
Iris::recv.reply.invoke (size)
|
Iris::recv.reply.invoke (size)
|
||||||
break
|
break
|
||||||
case Iris::Block::GET_ALIGN_BITS:
|
case Iris::Block::GET_ALIGN_BITS:
|
||||||
|
Iris::debug ("get align bits\n")
|
||||||
Iris::recv.reply.invoke (9)
|
Iris::recv.reply.invoke (9)
|
||||||
break
|
break
|
||||||
case Iris::Block::GET_BLOCK:
|
case Iris::Block::GET_BLOCK:
|
||||||
|
//Iris::debug ("get block\n")
|
||||||
Iris::Cap reply = Iris::get_reply ()
|
Iris::Cap reply = Iris::get_reply ()
|
||||||
Iris::Page page = Iris::get_arg ()
|
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 ()
|
reply.invoke ()
|
||||||
Iris::free_cap (page)
|
Iris::free_cap (page)
|
||||||
Iris::free_cap (reply)
|
Iris::free_cap (reply)
|
||||||
break
|
break
|
||||||
case Iris::WBlock::SET_BLOCK:
|
case Iris::WBlock::SET_BLOCK:
|
||||||
|
Iris::debug ("set block\n")
|
||||||
Iris::Cap reply = Iris::get_reply ()
|
Iris::Cap reply = Iris::get_reply ()
|
||||||
Iris::Page page = Iris::get_arg ()
|
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)
|
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)
|
Iris::free_cap (reply)
|
||||||
mmc.wait_write ()
|
mmc.wait_write ()
|
||||||
break
|
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.
|
// Fall through: don't support resizing.
|
||||||
default:
|
default:
|
||||||
Iris::panic (0, "unexpected event for sd+mmc")
|
Iris::panic (0, "unexpected event for sd+mmc")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user