mirror of
git://projects.qi-hardware.com/iris.git
synced 2024-11-14 19:57:11 +02:00
mass storage sort of working, but not nice
This commit is contained in:
parent
87acc47fd9
commit
5f9fd7cc0f
6
Makefile
6
Makefile
@ -27,6 +27,8 @@ headers = kernel.hh iris.hh devices.hh ui.hh keys.hh $(arch_headers)
|
|||||||
iris_sources = panic.cc data.cc alloc.cc memory.cc invoke.cc schedule.cc $(arch_iris_sources)
|
iris_sources = panic.cc data.cc alloc.cc memory.cc invoke.cc schedule.cc $(arch_iris_sources)
|
||||||
BUILT_SOURCES = $(iris_sources) $(boot_sources)
|
BUILT_SOURCES = $(iris_sources) $(boot_sources)
|
||||||
|
|
||||||
|
STRIPFLAG = -S
|
||||||
|
|
||||||
# Include arch-specific rules.
|
# Include arch-specific rules.
|
||||||
include Makefile.arch
|
include Makefile.arch
|
||||||
|
|
||||||
@ -45,11 +47,11 @@ PYPP = /usr/bin/pypp
|
|||||||
|
|
||||||
%.elf: boot-programs/crt0.o boot-programs/%.o
|
%.elf: boot-programs/crt0.o boot-programs/%.o
|
||||||
$(LD) $(LDFLAGS) $(filter %.o,$^) -o $@
|
$(LD) $(LDFLAGS) $(filter %.o,$^) -o $@
|
||||||
$(OBJCOPY) -S $(OBJCOPYFLAGS) $@
|
$(OBJCOPY) $(STRIPFLAG) $(OBJCOPYFLAGS) $@
|
||||||
|
|
||||||
fs/%.elf: source/crt0.o source/%.o fs/init.config
|
fs/%.elf: source/crt0.o source/%.o fs/init.config
|
||||||
$(LD) $(LDFLAGS) $(filter %.o,$^) -o $@
|
$(LD) $(LDFLAGS) $(filter %.o,$^) -o $@
|
||||||
$(OBJCOPY) -S $(OBJCOPYFLAGS) $@
|
$(OBJCOPY) $(STRIPFLAG) $(OBJCOPYFLAGS) $@
|
||||||
|
|
||||||
fs/%: %
|
fs/%: %
|
||||||
test -d fs || mkdir fs
|
test -d fs || mkdir fs
|
||||||
|
27
alloc.ccp
27
alloc.ccp
@ -517,12 +517,39 @@ void kMemory::free_memory (kMemory *mem):
|
|||||||
panic (0, "kernel memory leak: memory still in use")
|
panic (0, "kernel memory leak: memory still in use")
|
||||||
free_obj (mem, (void **)&memories)
|
free_obj (mem, (void **)&memories)
|
||||||
|
|
||||||
|
void kPage::check_payment ():
|
||||||
|
kPage *p
|
||||||
|
for p = this; p; p = p->share_prev:
|
||||||
|
if p->flags & Iris::Page::PAYING:
|
||||||
|
return
|
||||||
|
for p = share_next; p; p = p->share_next:
|
||||||
|
if p->flags & Iris::Page::PAYING:
|
||||||
|
return
|
||||||
|
// No kPage is paying for this frame anymore.
|
||||||
|
raw_pfree (frame)
|
||||||
|
kPage *next
|
||||||
|
for p = share_prev, next = (p ? p->share_prev : NULL); p; p = next, next = p->share_prev:
|
||||||
|
p->frame = NULL
|
||||||
|
p->share_prev = NULL
|
||||||
|
p->share_next = NULL
|
||||||
|
p->flags &= ~(Iris::Page::SHARED | Iris::Page::FRAME)
|
||||||
|
kPage_arch_update_mapping (p)
|
||||||
|
for p = this, next = p->share_next; p; p = next, next = p->share_next:
|
||||||
|
p->frame = NULL
|
||||||
|
p->share_prev = NULL
|
||||||
|
p->share_next = NULL
|
||||||
|
p->flags &= ~(Iris::Page::SHARED | Iris::Page::FRAME)
|
||||||
|
kPage_arch_update_mapping (p)
|
||||||
|
|
||||||
void kPage::forget ():
|
void kPage::forget ():
|
||||||
if share_prev || share_next:
|
if share_prev || share_next:
|
||||||
if share_prev:
|
if share_prev:
|
||||||
share_prev->share_next = share_next
|
share_prev->share_next = share_next
|
||||||
if share_next:
|
if share_next:
|
||||||
share_next->share_prev = share_prev
|
share_next->share_prev = share_prev
|
||||||
|
share_next->check_payment ()
|
||||||
|
else:
|
||||||
|
share_prev->check_payment ()
|
||||||
share_prev = NULL
|
share_prev = NULL
|
||||||
share_next = NULL
|
share_next = NULL
|
||||||
else:
|
else:
|
||||||
|
33
invoke.ccp
33
invoke.ccp
@ -577,30 +577,6 @@ static void thread_invoke (unsigned cmd, unsigned target, Iris::Num protected_da
|
|||||||
reply_num (0)
|
reply_num (0)
|
||||||
return
|
return
|
||||||
|
|
||||||
static void page_check_payment (kPage *page):
|
|
||||||
kPage *p
|
|
||||||
for p = page; p; p = p->share_prev:
|
|
||||||
if p->flags & Iris::Page::PAYING:
|
|
||||||
return
|
|
||||||
for p = page->share_next; p; p = p->share_next:
|
|
||||||
if p->flags & Iris::Page::PAYING:
|
|
||||||
return
|
|
||||||
// No kPage is paying for this frame anymore.
|
|
||||||
raw_pfree (page->frame)
|
|
||||||
kPage *next
|
|
||||||
for p = page->share_prev, next = (p ? p->share_prev : NULL); p; p = next, next = p->share_prev:
|
|
||||||
p->frame = NULL
|
|
||||||
p->share_prev = NULL
|
|
||||||
p->share_next = NULL
|
|
||||||
p->flags &= ~(Iris::Page::SHARED | Iris::Page::FRAME)
|
|
||||||
kPage_arch_update_mapping (p)
|
|
||||||
for p = page, next = p->share_next; p; p = next, next = p->share_next:
|
|
||||||
p->frame = NULL
|
|
||||||
p->share_prev = NULL
|
|
||||||
p->share_next = NULL
|
|
||||||
p->flags &= ~(Iris::Page::SHARED | Iris::Page::FRAME)
|
|
||||||
kPage_arch_update_mapping (p)
|
|
||||||
|
|
||||||
static void page_invoke (unsigned cmd, unsigned target, Iris::Num protected_data, kCapability::Context *c):
|
static void page_invoke (unsigned cmd, unsigned target, Iris::Num protected_data, kCapability::Context *c):
|
||||||
kPage *page = (kPage *)protected_data.l
|
kPage *page = (kPage *)protected_data.l
|
||||||
switch cmd & ~Iris::Page::READONLY:
|
switch cmd & ~Iris::Page::READONLY:
|
||||||
@ -653,7 +629,7 @@ static void page_invoke (unsigned cmd, unsigned target, Iris::Num protected_data
|
|||||||
page->share_prev->share_next = page->share_next
|
page->share_prev->share_next = page->share_next
|
||||||
page->share_next = NULL
|
page->share_next = NULL
|
||||||
page->share_prev = NULL
|
page->share_prev = NULL
|
||||||
page_check_payment (other)
|
other->check_payment ()
|
||||||
else:
|
else:
|
||||||
t->flags |= Iris::Page::FRAME
|
t->flags |= Iris::Page::FRAME
|
||||||
t->frame = raw_zalloc ()
|
t->frame = raw_zalloc ()
|
||||||
@ -697,7 +673,7 @@ static void page_invoke (unsigned cmd, unsigned target, Iris::Num protected_data
|
|||||||
page->share_prev = NULL
|
page->share_prev = NULL
|
||||||
page->share_next = NULL
|
page->share_next = NULL
|
||||||
page->forget ()
|
page->forget ()
|
||||||
page_check_payment (t)
|
t->check_payment ()
|
||||||
else:
|
else:
|
||||||
t->share_prev = page->share_prev
|
t->share_prev = page->share_prev
|
||||||
t->share_next = page
|
t->share_next = page
|
||||||
@ -727,7 +703,7 @@ static void page_invoke (unsigned cmd, unsigned target, Iris::Num protected_data
|
|||||||
if ~page->flags & old & Iris::Page::PAYING:
|
if ~page->flags & old & Iris::Page::PAYING:
|
||||||
// Decrease the use counter in any case.
|
// Decrease the use counter in any case.
|
||||||
page->address_space->unuse ()
|
page->address_space->unuse ()
|
||||||
page_check_payment (page)
|
page->check_payment ()
|
||||||
|
|
||||||
// If we start paying, increase the use counter.
|
// If we start paying, increase the use counter.
|
||||||
if page->flags & ~old & Iris::Page::PAYING:
|
if page->flags & ~old & Iris::Page::PAYING:
|
||||||
@ -747,6 +723,9 @@ static void page_invoke (unsigned cmd, unsigned target, Iris::Num protected_data
|
|||||||
else:
|
else:
|
||||||
page->frame = page->address_space->zalloc ()
|
page->frame = page->address_space->zalloc ()
|
||||||
kPage_arch_update_mapping (page)
|
kPage_arch_update_mapping (page)
|
||||||
|
// If we lose a frame, handle it.
|
||||||
|
if old & ~page->flags & Iris::Page::FRAME:
|
||||||
|
page->forget ()
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
dpanic (0, "invalid page operation")
|
dpanic (0, "invalid page operation")
|
||||||
|
@ -171,6 +171,7 @@ struct kPage : public kObject:
|
|||||||
kPageP share_prev, share_next
|
kPageP share_prev, share_next
|
||||||
kPage_arch arch
|
kPage_arch arch
|
||||||
void forget ()
|
void forget ()
|
||||||
|
void check_payment ()
|
||||||
|
|
||||||
struct kCaps : public kObject:
|
struct kCaps : public kObject:
|
||||||
_slot_data first_slot
|
_slot_data first_slot
|
||||||
|
@ -20,6 +20,9 @@
|
|||||||
// The following defines are taken from mtd/nand.h in the Linux source.
|
// The following defines are taken from mtd/nand.h in the Linux source.
|
||||||
// Everything not in the nand datasheet is thrown out.
|
// Everything not in the nand datasheet is thrown out.
|
||||||
|
|
||||||
|
//#define dbgl() debug ("%s:%d\n", __PRETTY_FUNCTION__, __LINE__)
|
||||||
|
#define dbgl()
|
||||||
|
|
||||||
// Standard NAND flash commands
|
// Standard NAND flash commands
|
||||||
#define CMD_READ0 0
|
#define CMD_READ0 0
|
||||||
#define CMD_READSTART 0x30
|
#define CMD_READSTART 0x30
|
||||||
@ -118,7 +121,7 @@ static void reset ():
|
|||||||
static bool read (unsigned a, char *buffer):
|
static bool read (unsigned a, char *buffer):
|
||||||
unsigned column = a & ((1 << page_bits) - 1)
|
unsigned column = a & ((1 << page_bits) - 1)
|
||||||
unsigned row = a >> page_bits
|
unsigned row = a >> page_bits
|
||||||
debug ("reading %x:", a)
|
//debug ("reading %x:", a)
|
||||||
// Read oob information first.
|
// Read oob information first.
|
||||||
char error[12]
|
char error[12]
|
||||||
// Spare space (starts at 1 << page_bits)
|
// Spare space (starts at 1 << page_bits)
|
||||||
@ -145,18 +148,20 @@ static bool read (unsigned a, char *buffer):
|
|||||||
valid = true
|
valid = true
|
||||||
break
|
break
|
||||||
if !valid:
|
if !valid:
|
||||||
debug ("invalid page for nand read: %x\n", a)
|
//debug ("invalid page for nand read: %x\n", a)
|
||||||
|
for unsigned i = 0; i < 1 << (9 - 2); ++i:
|
||||||
|
((unsigned *)buffer)[i] = ~0
|
||||||
return false
|
return false
|
||||||
col = (1 << page_bits) + 6 + 9 * (column >> 9)
|
col = (1 << page_bits) + 6 + 9 * (column >> 9)
|
||||||
cmd (CMD_RNDOUT)
|
cmd (CMD_RNDOUT)
|
||||||
addr (col)
|
addr (col)
|
||||||
addr (col >> 8)
|
addr (col >> 8)
|
||||||
cmd (CMD_RNDOUTSTART)
|
cmd (CMD_RNDOUTSTART)
|
||||||
debug ("parity data:")
|
//debug ("parity data:")
|
||||||
for unsigned t = 0; t < 9; ++t:
|
for unsigned t = 0; t < 9; ++t:
|
||||||
error[t] = rdata ()
|
error[t] = rdata ()
|
||||||
debug (" %x", error[t] & 0xff)
|
//debug (" %x", error[t] & 0xff)
|
||||||
debug ("\n")
|
//debug ("\n")
|
||||||
cmd (CMD_RNDOUT)
|
cmd (CMD_RNDOUT)
|
||||||
addr (column)
|
addr (column)
|
||||||
addr (column >> 8)
|
addr (column >> 8)
|
||||||
@ -168,10 +173,8 @@ static bool read (unsigned a, char *buffer):
|
|||||||
for unsigned t = 0; t < 9; ++t:
|
for unsigned t = 0; t < 9; ++t:
|
||||||
((volatile char *)&EMC_NFPAR (0))[t] = error[t]
|
((volatile char *)&EMC_NFPAR (0))[t] = error[t]
|
||||||
EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_RS | EMC_NFECR_RS_DECODING | EMC_NFECR_PRDY
|
EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_RS | EMC_NFECR_RS_DECODING | EMC_NFECR_PRDY
|
||||||
debug ("before\n")
|
|
||||||
while !(EMC_NFINTS & EMC_NFINTS_DECF):
|
while !(EMC_NFINTS & EMC_NFINTS_DECF):
|
||||||
DELAY ()
|
DELAY ()
|
||||||
debug ("after\n")
|
|
||||||
unsigned ints = EMC_NFINTS
|
unsigned ints = EMC_NFINTS
|
||||||
if ints & EMC_NFINTS_UNCOR:
|
if ints & EMC_NFINTS_UNCOR:
|
||||||
debug ("uncorrectable error in nand at %x\n", a)
|
debug ("uncorrectable error in nand at %x\n", a)
|
||||||
@ -191,16 +194,17 @@ static bool read (unsigned a, char *buffer):
|
|||||||
buffer[byte + 1] = data >> 8
|
buffer[byte + 1] = data >> 8
|
||||||
for unsigned i = 0; i < 0x10; ++i:
|
for unsigned i = 0; i < 0x10; ++i:
|
||||||
if (buffer[i] & 0xff) < 0x10:
|
if (buffer[i] & 0xff) < 0x10:
|
||||||
debug (" 0")
|
//debug (" 0")
|
||||||
else:
|
else:
|
||||||
debug (" ")
|
//debug (" ")
|
||||||
debug ("%x", buffer[i] & 0xff)
|
//debug ("%x", buffer[i] & 0xff)
|
||||||
debug ("\n")
|
//debug ("\n")
|
||||||
return true
|
return true
|
||||||
|
|
||||||
static void write (unsigned a, char *buffer):
|
static void write (unsigned a, char *buffer):
|
||||||
|
dbgl ()
|
||||||
unsigned row = a >> page_bits
|
unsigned row = a >> page_bits
|
||||||
//debug ("writing: %x/%x: ", a, row)
|
//debug ("writing: %x/%x\n", a, row)
|
||||||
cmd (CMD_SEQIN)
|
cmd (CMD_SEQIN)
|
||||||
addr (0)
|
addr (0)
|
||||||
addr (0)
|
addr (0)
|
||||||
@ -208,7 +212,9 @@ static void write (unsigned a, char *buffer):
|
|||||||
addr (row >> 8)
|
addr (row >> 8)
|
||||||
addr (row >> 16)
|
addr (row >> 16)
|
||||||
char ecc[4][12]
|
char ecc[4][12]
|
||||||
|
dbgl ()
|
||||||
for unsigned i = 0; i < 0x4; ++i:
|
for unsigned i = 0; i < 0x4; ++i:
|
||||||
|
dbgl ()
|
||||||
bool all_ff = true
|
bool all_ff = true
|
||||||
EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_RS | EMC_NFECR_RS_ENCODING | EMC_NFECR_ERST
|
EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_RS | EMC_NFECR_RS_ENCODING | EMC_NFECR_ERST
|
||||||
//debug ("writing data from %x\n", (unsigned)buffer + i * 0x200)
|
//debug ("writing data from %x\n", (unsigned)buffer + i * 0x200)
|
||||||
@ -219,15 +225,19 @@ static void write (unsigned a, char *buffer):
|
|||||||
if !all_ff:
|
if !all_ff:
|
||||||
while !(EMC_NFINTS & EMC_NFINTS_ENCF):
|
while !(EMC_NFINTS & EMC_NFINTS_ENCF):
|
||||||
DELAY ()
|
DELAY ()
|
||||||
|
dbgl ()
|
||||||
for unsigned t = 0; t < 9; ++t:
|
for unsigned t = 0; t < 9; ++t:
|
||||||
ecc[i][t] = ((volatile char *)&EMC_NFPAR (0))[t]
|
ecc[i][t] = ((volatile char *)&EMC_NFPAR (0))[t]
|
||||||
|
dbgl ()
|
||||||
//debug ("parity for %x:", i * 0x200 + a)
|
//debug ("parity for %x:", i * 0x200 + a)
|
||||||
//for unsigned t = 0; t < 9; ++t:
|
//for unsigned t = 0; t < 9; ++t:
|
||||||
//debug (" %x", ecc[i][t] & 0xff)
|
//debug (" %x", ecc[i][t] & 0xff)
|
||||||
//kdebug ("\n")
|
//kdebug ("\n")
|
||||||
else:
|
else:
|
||||||
|
dbgl ()
|
||||||
for unsigned t = 0; t < 9; ++t:
|
for unsigned t = 0; t < 9; ++t:
|
||||||
ecc[i][t] = 0xff
|
ecc[i][t] = 0xff
|
||||||
|
dbgl ()
|
||||||
// Spare space (starts at 1 << page_bits)
|
// Spare space (starts at 1 << page_bits)
|
||||||
// 0: unused
|
// 0: unused
|
||||||
// 2: detect valid data (at least 1 byte == 0 means valid)
|
// 2: detect valid data (at least 1 byte == 0 means valid)
|
||||||
@ -243,9 +253,11 @@ static void write (unsigned a, char *buffer):
|
|||||||
for unsigned i = 0; i < 4; ++i:
|
for unsigned i = 0; i < 4; ++i:
|
||||||
for unsigned j = 0; j < 9; ++j:
|
for unsigned j = 0; j < 9; ++j:
|
||||||
wdata (ecc[i][j])
|
wdata (ecc[i][j])
|
||||||
|
dbgl ()
|
||||||
cmd (CMD_PAGEPROG)
|
cmd (CMD_PAGEPROG)
|
||||||
// Wait at least 100 ns.
|
// Wait at least 100 ns.
|
||||||
DELAY ()
|
DELAY ()
|
||||||
|
dbgl ()
|
||||||
cmd (CMD_READ0)
|
cmd (CMD_READ0)
|
||||||
addr (0)
|
addr (0)
|
||||||
addr (0)
|
addr (0)
|
||||||
@ -253,7 +265,9 @@ static void write (unsigned a, char *buffer):
|
|||||||
addr (row >> 8)
|
addr (row >> 8)
|
||||||
addr (row >> 16)
|
addr (row >> 16)
|
||||||
cmd (CMD_READSTART)
|
cmd (CMD_READSTART)
|
||||||
|
dbgl ()
|
||||||
for unsigned i = 0; i < 4; ++i:
|
for unsigned i = 0; i < 4; ++i:
|
||||||
|
dbgl ()
|
||||||
EMC_NFINTS = 0
|
EMC_NFINTS = 0
|
||||||
EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_RS | EMC_NFECR_RS_DECODING | EMC_NFECR_ERST
|
EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_RS | EMC_NFECR_RS_DECODING | EMC_NFECR_ERST
|
||||||
for unsigned t = 0; t < 0x200; ++t:
|
for unsigned t = 0; t < 0x200; ++t:
|
||||||
@ -278,22 +292,26 @@ static void write (unsigned a, char *buffer):
|
|||||||
unsigned offset= bit & 7
|
unsigned offset= bit & 7
|
||||||
unsigned byte = bit / 8
|
unsigned byte = bit / 8
|
||||||
debug ("error detected by parity: %x on %x+%d\n", mask, byte, offset)
|
debug ("error detected by parity: %x on %x+%d\n", mask, byte, offset)
|
||||||
|
dbgl ()
|
||||||
for unsigned i = 0; i < 6; ++i:
|
for unsigned i = 0; i < 6; ++i:
|
||||||
if rdata () != 0:
|
if rdata () != 0:
|
||||||
debug ("extra data not 0 at byte %d\n", i)
|
debug ("extra data not 0 at byte %d\n", i)
|
||||||
|
dbgl ()
|
||||||
for unsigned i = 0; i < 4; ++i:
|
for unsigned i = 0; i < 4; ++i:
|
||||||
for unsigned j = 0; j < 9; ++j:
|
for unsigned j = 0; j < 9; ++j:
|
||||||
unsigned r = rdata () & 0xff
|
unsigned r = rdata () & 0xff
|
||||||
if r != (ecc[i][j] & 0xff):
|
if r != (ecc[i][j] & 0xff):
|
||||||
debug ("ecc doesn't match: %x != %x\n", r, ecc[i][j] & 0xff)
|
debug ("ecc doesn't match: %x != %x\n", r, ecc[i][j] & 0xff)
|
||||||
debug ("nand program %x:", a)
|
dbgl ()
|
||||||
|
//debug ("nand program %x:", a)
|
||||||
for unsigned i = 0; i < 0x10; ++i:
|
for unsigned i = 0; i < 0x10; ++i:
|
||||||
if (buffer[i] & 0xff) < 0x10:
|
if (buffer[i] & 0xff) < 0x10:
|
||||||
debug (" 0")
|
//debug (" 0")
|
||||||
else:
|
else:
|
||||||
debug (" ")
|
//debug (" ")
|
||||||
debug ("%x", buffer[i] & 0xff)
|
//debug ("%x", buffer[i] & 0xff)
|
||||||
debug ("\n")
|
dbgl ()
|
||||||
|
//debug ("\n")
|
||||||
|
|
||||||
static void erase (unsigned a):
|
static void erase (unsigned a):
|
||||||
unsigned row = a >> page_bits
|
unsigned row = a >> page_bits
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
asm volatile ("\t.set noreorder\n"
|
asm volatile ("\t.set noreorder\n"
|
||||||
"\t.text\n"
|
"\t.text\n"
|
||||||
"\t.globl __start\n"
|
"\t.globl __start\n"
|
||||||
|
"\t.globl addr_0\n"
|
||||||
|
"addr_0:\n"
|
||||||
"\t.word ~0\n"
|
"\t.word ~0\n"
|
||||||
"__start:\n"
|
"__start:\n"
|
||||||
"\tbal 1f\n"
|
"\tbal 1f\n"
|
||||||
@ -33,6 +35,40 @@ asm volatile ("\t.set noreorder\n"
|
|||||||
"\tla $t9, nandboot_start\n"
|
"\tla $t9, nandboot_start\n"
|
||||||
"\tjr $t9\n"
|
"\tjr $t9\n"
|
||||||
"\tnop\n"
|
"\tnop\n"
|
||||||
|
"\t.fill 0x1b8 - (. - addr_0)\n"
|
||||||
|
"\t.word 0xd2b9e1a8\n" // Disk signature.
|
||||||
|
"\t.short 0x0000\n"
|
||||||
|
|
||||||
|
"\t.byte 0x00\n" // bootable: no.
|
||||||
|
"\t.byte 0x00, 0x02, 0x00\n" // first sector chs.
|
||||||
|
"\t.byte 0x83\n" // type.
|
||||||
|
"\t.byte 0x08, 0x18, 0x00\n" // last sector chs.
|
||||||
|
"\t.byte 0x01, 0x00, 0x00, 0x00\n" // first sector, lba.
|
||||||
|
"\t.byte 0xff, 0x01, 0x00, 0x00\n" // size, lba.
|
||||||
|
|
||||||
|
"\t.byte 0x00\n" // bootable: no.
|
||||||
|
"\t.byte 0x08, 0x19, 0x00\n" // first sector chs.
|
||||||
|
"\t.byte 0x83\n" // type.
|
||||||
|
"\t.byte 0x05, 0xe1, 0xf3\n" // last sector chs.
|
||||||
|
"\t.byte 0x00, 0x02, 0x00, 0x00\n" // first sector, lba: 256 kB.
|
||||||
|
"\t.byte 0x00, 0xfe, 0x1f, 0x00\n" // size, lba: 1 GB - first.
|
||||||
|
|
||||||
|
"\t.byte 0\n" // bootable: no.
|
||||||
|
"\t.byte 0, 0, 0\n" // first sector chs.
|
||||||
|
"\t.byte 0\n" // type.
|
||||||
|
"\t.byte 0, 0, 0\n" // last sector chs.
|
||||||
|
"\t.byte 0, 0, 0, 0\n" // first sector, lba.
|
||||||
|
"\t.byte 0, 0, 0, 0\n" // size, lba.
|
||||||
|
|
||||||
|
"\t.byte 0\n" // bootable: no.
|
||||||
|
"\t.byte 0, 0, 0\n" // first sector chs.
|
||||||
|
"\t.byte 0\n" // type.
|
||||||
|
"\t.byte 0, 0, 0\n" // last sector chs.
|
||||||
|
"\t.byte 0, 0, 0, 0\n" // first sector, lba.
|
||||||
|
"\t.byte 0, 0, 0, 0\n" // size, lba.
|
||||||
|
|
||||||
|
"\t.byte 0x55, 0xaa\n" // mbr signature.
|
||||||
|
|
||||||
"\t.set reorder")
|
"\t.set reorder")
|
||||||
|
|
||||||
#define __KERNEL__
|
#define __KERNEL__
|
||||||
|
@ -249,11 +249,11 @@ static bool get_name (char *&line, unsigned &len, char *&name, unsigned &name_le
|
|||||||
while name_len < len && isnamechar (line[name_len]):
|
while name_len < len && isnamechar (line[name_len]):
|
||||||
++name_len
|
++name_len
|
||||||
name = new char[name_len]
|
name = new char[name_len]
|
||||||
kdebug ("name: ")
|
//kdebug ("name: ")
|
||||||
for unsigned i = 0; i < name_len; ++i:
|
for unsigned i = 0; i < name_len; ++i:
|
||||||
name[i] = line[i]
|
name[i] = line[i]
|
||||||
kdebug_char (name[i])
|
//kdebug_char (name[i])
|
||||||
kdebug_char ('\n')
|
//kdebug_char ('\n')
|
||||||
line += name_len
|
line += name_len
|
||||||
len -= name_len
|
len -= name_len
|
||||||
delspace (line, len)
|
delspace (line, len)
|
||||||
|
@ -20,22 +20,30 @@
|
|||||||
#define ARCH
|
#define ARCH
|
||||||
#include "arch.hh"
|
#include "arch.hh"
|
||||||
|
|
||||||
#define debug //Iris::debug
|
#define debug Iris::debug
|
||||||
#define DELAY Iris::schedule
|
#define DELAY Iris::schedule
|
||||||
#include "nand.hh"
|
#include "nand.hh"
|
||||||
|
#undef debug
|
||||||
|
|
||||||
static unsigned *cache
|
static unsigned *cache
|
||||||
static bool dirty
|
static bool dirty
|
||||||
static unsigned current_block
|
static unsigned current_block
|
||||||
|
|
||||||
static void sync ():
|
static void sync ():
|
||||||
debug ("erasing %x\n", current_block << block_bits)
|
Iris::debug ("erasing %x\n", current_block << block_bits)
|
||||||
//erase (current_block << block_bits)
|
erase (current_block << block_bits)
|
||||||
for unsigned p = 0; p < 1 << (block_bits - 9); ++p:
|
for unsigned p = 0; p < 1 << (block_bits - page_bits); ++p:
|
||||||
debug ("writing %x\n", (current_block << block_bits) + (p << 9))
|
write ((current_block << block_bits) + (p << page_bits), (char *)&cache[p << (page_bits - 2)])
|
||||||
//write ((current_block << block_bits) + (p << 9), &cache[p << (9 - 2)])
|
|
||||||
|
|
||||||
static void read_block (unsigned b):
|
static void read_block (unsigned b):
|
||||||
|
if b == current_block:
|
||||||
|
return
|
||||||
|
if current_block != ~0 && dirty:
|
||||||
|
sync ()
|
||||||
|
current_block = b
|
||||||
|
//kdebug ("setting current block to ")
|
||||||
|
//kdebug_num (b)
|
||||||
|
//kdebug ("\n")
|
||||||
for unsigned p = 0; p < 1 << (block_bits - 9); ++p:
|
for unsigned p = 0; p < 1 << (block_bits - 9); ++p:
|
||||||
read ((b << block_bits) + (p << 9), (char *)&cache[p << (9 - 2)])
|
read ((b << block_bits) + (p << 9), (char *)&cache[p << (9 - 2)])
|
||||||
dirty = false
|
dirty = false
|
||||||
@ -103,21 +111,28 @@ Iris::Num start ():
|
|||||||
unsigned row = Iris::recv.data[1].value () >> 9
|
unsigned row = Iris::recv.data[1].value () >> 9
|
||||||
unsigned block = row >> (block_bits - 9)
|
unsigned block = row >> (block_bits - 9)
|
||||||
row &= (1 << (block_bits - 9)) - 1
|
row &= (1 << (block_bits - 9)) - 1
|
||||||
if block != current_block:
|
|
||||||
if current_block != ~0 && dirty:
|
|
||||||
sync ()
|
|
||||||
current_block = block
|
|
||||||
read_block (block)
|
|
||||||
unsigned offset = Iris::recv.data[0].h & 0xe00
|
unsigned offset = Iris::recv.data[0].h & 0xe00
|
||||||
unsigned size = Iris::recv.data[0].h >> 16
|
unsigned size = Iris::recv.data[0].h >> 16
|
||||||
if size + offset >= 0x1000:
|
if size + offset >= 0x1000:
|
||||||
size = 0x1000 - offset
|
size = 0x1000 - offset
|
||||||
|
#if 0
|
||||||
|
kdebug ("get ")
|
||||||
|
kdebug_num (block)
|
||||||
|
kdebug (":")
|
||||||
|
kdebug_num (row)
|
||||||
|
kdebug ("+")
|
||||||
|
kdebug_num (size)
|
||||||
|
kdebug ("@")
|
||||||
|
kdebug_num (offset)
|
||||||
|
kdebug ("\n")
|
||||||
|
#endif
|
||||||
|
read_block (block)
|
||||||
Iris::Cap reply = Iris::get_reply ()
|
Iris::Cap reply = Iris::get_reply ()
|
||||||
Iris::Page page = Iris::get_arg ()
|
Iris::Page page = Iris::get_arg ()
|
||||||
page.share (tmp)
|
page.share (tmp)
|
||||||
tmp.set_flags (Iris::Page::FRAME)
|
tmp.set_flags (Iris::Page::FRAME)
|
||||||
for unsigned t = 0; t < size >> 2; ++t:
|
for unsigned t = 0; t < size >> 2; ++t:
|
||||||
tmp_addr[(offset >> 2) + t] = cache[(offset >> 2) + t + (row << 9)]
|
tmp_addr[(offset >> 2) + t] = cache[t + (row << (9 - 2))]
|
||||||
tmp.set_flags (0, Iris::Page::FRAME)
|
tmp.set_flags (0, Iris::Page::FRAME)
|
||||||
reply.invoke ()
|
reply.invoke ()
|
||||||
Iris::free_cap (reply)
|
Iris::free_cap (reply)
|
||||||
@ -126,26 +141,38 @@ Iris::Num start ():
|
|||||||
case Iris::WBlock::SET_BLOCK:
|
case Iris::WBlock::SET_BLOCK:
|
||||||
unsigned row = Iris::recv.data[1].value () >> 9
|
unsigned row = Iris::recv.data[1].value () >> 9
|
||||||
unsigned block = row >> (block_bits - 9)
|
unsigned block = row >> (block_bits - 9)
|
||||||
if block != current_block:
|
row &= (1 << (block_bits - 9)) - 1
|
||||||
if current_block != ~0 && dirty:
|
|
||||||
sync ()
|
|
||||||
current_block = block
|
|
||||||
read_block (block)
|
|
||||||
unsigned offset = Iris::recv.data[0].h & 0xe00
|
unsigned offset = Iris::recv.data[0].h & 0xe00
|
||||||
unsigned size = Iris::recv.data[0].h >> 16
|
unsigned size = Iris::recv.data[0].h >> 16
|
||||||
if size + offset >= 0x1000:
|
if size + offset >= 0x1000:
|
||||||
size = 0x1000 - offset
|
size = 0x1000 - offset
|
||||||
|
#if 0
|
||||||
|
kdebug ("set ")
|
||||||
|
kdebug_num (block)
|
||||||
|
kdebug (":")
|
||||||
|
kdebug_num (row)
|
||||||
|
kdebug ("+")
|
||||||
|
kdebug_num (size)
|
||||||
|
kdebug ("@")
|
||||||
|
kdebug_num (offset)
|
||||||
|
kdebug ("\n")
|
||||||
|
#endif
|
||||||
|
//kdebug_num (current_block)
|
||||||
|
//kdebug ("/")
|
||||||
|
read_block (block)
|
||||||
Iris::Cap reply = Iris::get_reply ()
|
Iris::Cap reply = Iris::get_reply ()
|
||||||
Iris::Page page = Iris::get_arg ()
|
Iris::Page page = Iris::get_arg ()
|
||||||
page.share (tmp)
|
page.share (tmp)
|
||||||
tmp.set_flags (Iris::Page::FRAME)
|
tmp.set_flags (Iris::Page::FRAME)
|
||||||
for unsigned t = 0; t < size >> 2; ++t:
|
for unsigned t = 0; t < size; t += 4:
|
||||||
cache[(offset >> 2) + t + (row << 9)] = tmp_addr[(offset >> 2) + t]
|
cache[(offset + t + (row << 9)) >> 2] = tmp_addr[(offset + t) >> 2]
|
||||||
tmp.set_flags (0, Iris::Page::FRAME)
|
tmp.set_flags (0, Iris::Page::FRAME)
|
||||||
reply.invoke ()
|
reply.invoke ()
|
||||||
Iris::free_cap (reply)
|
Iris::free_cap (reply)
|
||||||
Iris::free_cap (page)
|
Iris::free_cap (page)
|
||||||
dirty = true
|
dirty = true
|
||||||
|
//kdebug_num (current_block)
|
||||||
|
//kdebug ("!")
|
||||||
break
|
break
|
||||||
case Iris::WBlock::TRUNCATE:
|
case Iris::WBlock::TRUNCATE:
|
||||||
default:
|
default:
|
||||||
|
@ -281,9 +281,8 @@ void Udc::init (Iris::WBlock b):
|
|||||||
UDC_OUTCSR = UDC_OUTCSR_CDT | UDC_OUTCSR_FF
|
UDC_OUTCSR = UDC_OUTCSR_CDT | UDC_OUTCSR_FF
|
||||||
UDC_INDEX = 2
|
UDC_INDEX = 2
|
||||||
UDC_INMAXP = max_packet_size_bulk
|
UDC_INMAXP = max_packet_size_bulk
|
||||||
UDC_INCSRH = UDC_INCSRH_MODE
|
UDC_INCSR = (UDC_INCSRH_MODE << 8) | UDC_INCSR_CDT | UDC_INCSR_FF
|
||||||
UDC_INCSR = UDC_INCSR_CDT | UDC_INCSR_FF
|
UDC_INCSR = (UDC_INCSRH_MODE << 8) | UDC_INCSR_CDT | UDC_INCSR_FF
|
||||||
UDC_INCSR = UDC_INCSR_CDT | UDC_INCSR_FF
|
|
||||||
// exit suspend mode by reading the interrupt register.
|
// exit suspend mode by reading the interrupt register.
|
||||||
unsigned i = UDC_INTRUSB
|
unsigned i = UDC_INTRUSB
|
||||||
// reset all pending endpoint interrupts.
|
// reset all pending endpoint interrupts.
|
||||||
@ -325,10 +324,31 @@ void Udc::send_padded (char const *data, unsigned length, unsigned maxlength):
|
|||||||
residue = maxlength - len
|
residue = maxlength - len
|
||||||
len = (len + 3) & ~3
|
len = (len + 3) & ~3
|
||||||
send (2, data, len, maxlength)
|
send (2, data, len, maxlength)
|
||||||
|
//Iris::debug ("sending %x, valid %x\n", maxlength, len)
|
||||||
while len + 3 < maxlength:
|
while len + 3 < maxlength:
|
||||||
UDC_FIFO (2) = 0
|
UDC_FIFO (2) = 0
|
||||||
len += 4
|
len += 4
|
||||||
|
if len % max_packet_size_bulk == 0:
|
||||||
|
// This doesn't ever happen, because the largest packet we send is smaller than max_packet_size_bulk.
|
||||||
|
Iris::debug ("sending at len %x\n", len)
|
||||||
|
UDC_INCSR |= UDC_INCSR_INPKTRDY
|
||||||
|
while true:
|
||||||
|
Iris::register_interrupt (IRQ_UDC)
|
||||||
|
Iris::wait_for_interrupt (IRQ_UDC)
|
||||||
|
kdebug ("interrupt pad0\n")
|
||||||
|
unsigned usb = UDC_INTRUSB
|
||||||
|
unsigned in = UDC_INTRIN
|
||||||
|
if usb & 4 || in & 1:
|
||||||
|
//kdebug ("general interrupt pad0\t")
|
||||||
|
if !handle_interrupt (usb & 4, in & 1):
|
||||||
|
return
|
||||||
|
unsigned out = UDC_INTROUT
|
||||||
|
if out & 2:
|
||||||
|
Iris::panic (0, "out interrupt while waiting for in")
|
||||||
|
if in & 4:
|
||||||
|
break
|
||||||
//kdebug_char ('-')
|
//kdebug_char ('-')
|
||||||
|
if len % max_packet_size_bulk != 0 || len < maxlength:
|
||||||
while len < maxlength:
|
while len < maxlength:
|
||||||
UDC_FIFO8 (2) = 0
|
UDC_FIFO8 (2) = 0
|
||||||
++len
|
++len
|
||||||
@ -337,14 +357,14 @@ void Udc::send_padded (char const *data, unsigned length, unsigned maxlength):
|
|||||||
while true:
|
while true:
|
||||||
Iris::register_interrupt (IRQ_UDC)
|
Iris::register_interrupt (IRQ_UDC)
|
||||||
Iris::wait_for_interrupt (IRQ_UDC)
|
Iris::wait_for_interrupt (IRQ_UDC)
|
||||||
//kdebug ("interrupt pad\t")
|
kdebug ("interrupt pad\t")
|
||||||
unsigned usb = UDC_INTRUSB
|
unsigned usb = UDC_INTRUSB
|
||||||
unsigned in = UDC_INTRIN
|
unsigned in = UDC_INTRIN
|
||||||
unsigned out = UDC_INTROUT
|
|
||||||
if usb & 4 || in & 1:
|
if usb & 4 || in & 1:
|
||||||
//kdebug ("general interrupt pad\t")
|
//kdebug ("general interrupt pad\t")
|
||||||
if !handle_interrupt (usb & 4, in & 1):
|
if !handle_interrupt (usb & 4, in & 1):
|
||||||
return
|
return
|
||||||
|
unsigned out = UDC_INTROUT
|
||||||
if out & 2:
|
if out & 2:
|
||||||
Iris::panic (0, "out interrupt while waiting for in")
|
Iris::panic (0, "out interrupt while waiting for in")
|
||||||
if in & 4:
|
if in & 4:
|
||||||
@ -446,22 +466,20 @@ unsigned Udc::handle_setup (Setup *s):
|
|||||||
case ENDPOINT_HALT:
|
case ENDPOINT_HALT:
|
||||||
switch s->index:
|
switch s->index:
|
||||||
case 0x82:
|
case 0x82:
|
||||||
//Iris::debug ("in ep halt reset\n")
|
Iris::debug ("in ep halt reset\n")
|
||||||
UDC_INDEX = 2
|
UDC_INDEX = 2
|
||||||
UDC_INCSR &= ~UDC_INCSR_SENDSTALL
|
UDC_INCSR &= ~UDC_INCSR_SENDSTALL
|
||||||
stalling[2] = false
|
stalling[2] = false
|
||||||
break
|
break
|
||||||
case 1:
|
case 1:
|
||||||
//Iris::debug ("out ep halt reset\n")
|
Iris::debug ("out ep halt reset\n")
|
||||||
UDC_INDEX = 1
|
UDC_INDEX = 1
|
||||||
UDC_OUTCSR &= ~UDC_OUTCSR_SENDSTALL
|
UDC_OUTCSR &= ~UDC_OUTCSR_SENDSTALL
|
||||||
stalling[1] = false
|
stalling[1] = false
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
return ~0
|
return ~0
|
||||||
UDC_INDEX = 0
|
return UDC_CSR0_DATAEND | UDC_CSR0_SVDOUTPKTRDY
|
||||||
UDC_CSR0 = UDC_CSR0_DATAEND | UDC_CSR0_SVDOUTPKTRDY
|
|
||||||
return 0
|
|
||||||
default:
|
default:
|
||||||
return ~0
|
return ~0
|
||||||
default:
|
default:
|
||||||
@ -518,6 +536,11 @@ void Udc::irq_in0 ():
|
|||||||
if !(csr & UDC_CSR0_OUTPKTRDY):
|
if !(csr & UDC_CSR0_OUTPKTRDY):
|
||||||
//Iris::debug ("no packet 0: %x\n", csr)
|
//Iris::debug ("no packet 0: %x\n", csr)
|
||||||
return
|
return
|
||||||
|
UDC_INDEX = 1
|
||||||
|
UDC_OUTCSR |= UDC_OUTCSR_CDT
|
||||||
|
UDC_INDEX = 2
|
||||||
|
UDC_INCSR |= UDC_INCSR_CDT
|
||||||
|
UDC_INDEX = 0
|
||||||
union { unsigned d[2]; Setup s; } packet
|
union { unsigned d[2]; Setup s; } packet
|
||||||
packet.d[0] = UDC_FIFO (0)
|
packet.d[0] = UDC_FIFO (0)
|
||||||
packet.d[1] = UDC_FIFO (0)
|
packet.d[1] = UDC_FIFO (0)
|
||||||
@ -526,10 +549,6 @@ void Udc::irq_in0 ():
|
|||||||
//Iris::debug ("packet on ep0 too long\n")
|
//Iris::debug ("packet on ep0 too long\n")
|
||||||
UDC_CSR0 = UDC_CSR0_SENDSTALL
|
UDC_CSR0 = UDC_CSR0_SENDSTALL
|
||||||
return
|
return
|
||||||
UDC_INDEX = 1
|
|
||||||
UDC_OUTCSR |= UDC_OUTCSR_CDT
|
|
||||||
UDC_INDEX = 2
|
|
||||||
UDC_INCSR |= UDC_INCSR_CDT
|
|
||||||
unsigned ret = handle_setup (&packet.s)
|
unsigned ret = handle_setup (&packet.s)
|
||||||
UDC_INDEX = 0
|
UDC_INDEX = 0
|
||||||
if ret == ~0:
|
if ret == ~0:
|
||||||
@ -552,6 +571,7 @@ void Udc::send_csw ():
|
|||||||
while true:
|
while true:
|
||||||
Iris::register_interrupt (IRQ_UDC)
|
Iris::register_interrupt (IRQ_UDC)
|
||||||
Iris::wait_for_interrupt (IRQ_UDC)
|
Iris::wait_for_interrupt (IRQ_UDC)
|
||||||
|
kdebug ("interrupt csw\n")
|
||||||
unsigned usb = UDC_INTRUSB
|
unsigned usb = UDC_INTRUSB
|
||||||
unsigned in = UDC_INTRIN
|
unsigned in = UDC_INTRIN
|
||||||
if usb & 4 || in & 1:
|
if usb & 4 || in & 1:
|
||||||
@ -562,7 +582,7 @@ void Udc::send_csw ():
|
|||||||
unsigned out = UDC_INTROUT
|
unsigned out = UDC_INTROUT
|
||||||
if out & 2:
|
if out & 2:
|
||||||
Iris::panic (0, "out interrupt while waiting for in after csw")
|
Iris::panic (0, "out interrupt while waiting for in after csw")
|
||||||
//kdebug ("sent csw\n")
|
kdebug ("sent csw\n")
|
||||||
|
|
||||||
void Udc::stall (unsigned error):
|
void Udc::stall (unsigned error):
|
||||||
unsigned index = UDC_INDEX
|
unsigned index = UDC_INDEX
|
||||||
@ -574,14 +594,16 @@ void Udc::stall (unsigned error):
|
|||||||
UDC_INCSR |= UDC_INCSR_SENDSTALL
|
UDC_INCSR |= UDC_INCSR_SENDSTALL
|
||||||
stalling[index] = true
|
stalling[index] = true
|
||||||
while stalling[index]:
|
while stalling[index]:
|
||||||
//kdebug ("stalling\t")
|
//Iris::debug ("stalling %d\n", index)
|
||||||
Iris::register_interrupt (IRQ_UDC)
|
Iris::register_interrupt (IRQ_UDC)
|
||||||
Iris::wait_for_interrupt (IRQ_UDC)
|
Iris::wait_for_interrupt (IRQ_UDC)
|
||||||
//kdebug ("stalling interrupt\n")
|
kdebug ("stalling interrupt\n")
|
||||||
unsigned usb = UDC_INTRUSB
|
unsigned usb = UDC_INTRUSB
|
||||||
unsigned in = UDC_INTRIN
|
unsigned in = UDC_INTRIN
|
||||||
if in & 4:
|
if in & 4:
|
||||||
//kdebug ("stall has been sent to in endpoint\n")
|
if index != 2:
|
||||||
|
Iris::panic (0, "stalling on out, but in responds")
|
||||||
|
kdebug ("stall has been sent to in endpoint\n")
|
||||||
UDC_INDEX = 2
|
UDC_INDEX = 2
|
||||||
UDC_INCSR &= ~UDC_INCSR_SENTSTALL
|
UDC_INCSR &= ~UDC_INCSR_SENTSTALL
|
||||||
//Iris::debug ("csr: %x\n", UDC_INCSR)
|
//Iris::debug ("csr: %x\n", UDC_INCSR)
|
||||||
@ -591,10 +613,12 @@ void Udc::stall (unsigned error):
|
|||||||
return
|
return
|
||||||
unsigned out = UDC_INTROUT
|
unsigned out = UDC_INTROUT
|
||||||
if out & 2:
|
if out & 2:
|
||||||
//kdebug ("stall has been sent to out endpoint\n")
|
if index != 1:
|
||||||
|
Iris::panic (0, "stalling on in, but out responds")
|
||||||
|
kdebug ("stall has been sent to out endpoint\n")
|
||||||
UDC_INDEX = 1
|
UDC_INDEX = 1
|
||||||
UDC_OUTCSR &= ~UDC_OUTCSR_SENTSTALL
|
UDC_OUTCSR &= ~UDC_OUTCSR_SENTSTALL
|
||||||
UDC_INDEX = index
|
//kdebug ("done stalling\n")
|
||||||
if index == 2:
|
if index == 2:
|
||||||
status = error
|
status = error
|
||||||
send_csw ()
|
send_csw ()
|
||||||
@ -608,7 +632,7 @@ void Udc::irq_out ():
|
|||||||
unsigned size = UDC_OUTCOUNT
|
unsigned size = UDC_OUTCOUNT
|
||||||
if !(csr & UDC_OUTCSR_OUTPKTRDY):
|
if !(csr & UDC_OUTCSR_OUTPKTRDY):
|
||||||
// No packet, just a notification.
|
// No packet, just a notification.
|
||||||
//kdebug ("no packet\n")
|
kdebug ("no packet\n")
|
||||||
return
|
return
|
||||||
if csr & UDC_OUTCSR_SENDSTALL:
|
if csr & UDC_OUTCSR_SENDSTALL:
|
||||||
// When stalling, do nothing else.
|
// When stalling, do nothing else.
|
||||||
@ -647,7 +671,7 @@ void Udc::irq_out ():
|
|||||||
send_csw ()
|
send_csw ()
|
||||||
break
|
break
|
||||||
case CBW::REQUEST_SENSE:
|
case CBW::REQUEST_SENSE:
|
||||||
//Iris::debug ("sense requested\t")
|
//Iris::debug ("sense requested\n")
|
||||||
send_padded ("\xf0\x00\x05\x00\x00\x00\x00\x00", 8, cbw.cbw.length)
|
send_padded ("\xf0\x00\x05\x00\x00\x00\x00\x00", 8, cbw.cbw.length)
|
||||||
send_csw ()
|
send_csw ()
|
||||||
break
|
break
|
||||||
@ -682,10 +706,10 @@ void Udc::irq_out ():
|
|||||||
unsigned lba = cbw.cbw.data[2] << 24 | cbw.cbw.data[3] << 16 | cbw.cbw.data[4] << 8 | cbw.cbw.data[5]
|
unsigned lba = cbw.cbw.data[2] << 24 | cbw.cbw.data[3] << 16 | cbw.cbw.data[4] << 8 | cbw.cbw.data[5]
|
||||||
unsigned blocks = cbw.cbw.data[7] << 8 | cbw.cbw.data[8]
|
unsigned blocks = cbw.cbw.data[7] << 8 | cbw.cbw.data[8]
|
||||||
for unsigned i = 0; i < blocks; ++i:
|
for unsigned i = 0; i < blocks; ++i:
|
||||||
//Iris::debug ("reading block %d:", lba + i)
|
//Iris::debug ("reading block %d\n", lba + i)
|
||||||
// read block lba + i.
|
// read block lba + i.
|
||||||
buffer_page.set_flags (Iris::Page::FRAME)
|
buffer_page.set_flags (Iris::Page::FRAME)
|
||||||
block.get_block (lba << block_bits, 1 << block_bits, 0, buffer_page)
|
block.get_block ((lba + i) << block_bits, 1 << block_bits, 0, buffer_page)
|
||||||
for unsigned p = 0; p < 1 << block_bits; p += max_packet_size_bulk:
|
for unsigned p = 0; p < 1 << block_bits; p += max_packet_size_bulk:
|
||||||
//Iris::debug (" %d", p)
|
//Iris::debug (" %d", p)
|
||||||
UDC_INDEX = 2
|
UDC_INDEX = 2
|
||||||
@ -696,7 +720,7 @@ void Udc::irq_out ():
|
|||||||
while true:
|
while true:
|
||||||
Iris::register_interrupt (IRQ_UDC)
|
Iris::register_interrupt (IRQ_UDC)
|
||||||
Iris::wait_for_interrupt (IRQ_UDC)
|
Iris::wait_for_interrupt (IRQ_UDC)
|
||||||
//kdebug ("interrupt read10\t")
|
kdebug ("interrupt read10\n")
|
||||||
unsigned usb = UDC_INTRUSB
|
unsigned usb = UDC_INTRUSB
|
||||||
unsigned in = UDC_INTRIN
|
unsigned in = UDC_INTRIN
|
||||||
unsigned out = UDC_INTROUT
|
unsigned out = UDC_INTROUT
|
||||||
@ -711,7 +735,43 @@ void Udc::irq_out ():
|
|||||||
send_csw ()
|
send_csw ()
|
||||||
break
|
break
|
||||||
case CBW::WRITE10:
|
case CBW::WRITE10:
|
||||||
Iris::panic (0, "WRITE10 isn't implemented")
|
unsigned lba = cbw.cbw.data[2] << 24 | cbw.cbw.data[3] << 16 | cbw.cbw.data[4] << 8 | cbw.cbw.data[5]
|
||||||
|
unsigned blocks = cbw.cbw.data[7] << 8 | cbw.cbw.data[8]
|
||||||
|
for unsigned i = 0; i < blocks; ++i:
|
||||||
|
//Iris::debug ("writing block %d\n", lba + i)
|
||||||
|
// write block lba + i.
|
||||||
|
buffer_page.set_flags (Iris::Page::FRAME)
|
||||||
|
//Iris::debug ("@%x:", (lba + i) << block_bits)
|
||||||
|
for unsigned p = 0; p < 1 << block_bits; p += max_packet_size_bulk:
|
||||||
|
while true:
|
||||||
|
Iris::register_interrupt (IRQ_UDC)
|
||||||
|
Iris::wait_for_interrupt (IRQ_UDC)
|
||||||
|
Iris::debug (".")
|
||||||
|
unsigned usb = UDC_INTRUSB
|
||||||
|
unsigned in = UDC_INTRIN
|
||||||
|
unsigned out = UDC_INTROUT
|
||||||
|
if usb & 4 || in & 1:
|
||||||
|
if !handle_interrupt (usb & 4, in & 1):
|
||||||
|
return
|
||||||
|
if out & 2:
|
||||||
|
break
|
||||||
|
if in & 4:
|
||||||
|
Iris::panic (0, "in interrupt while waiting for out")
|
||||||
|
UDC_INDEX = 1
|
||||||
|
if !(UDC_OUTCSR & UDC_OUTCSR_OUTPKTRDY):
|
||||||
|
Iris::panic (0, "no packet ready after out interrupt in write10")
|
||||||
|
if UDC_OUTCOUNT != max_packet_size_bulk:
|
||||||
|
Iris::panic (UDC_OUTCOUNT, "invalid packet size in write10")
|
||||||
|
for unsigned t = 0; t < max_packet_size_bulk; t += 4:
|
||||||
|
((unsigned *)buffer)[(p + t) >> 2] = UDC_FIFO (1)
|
||||||
|
//kdebug (" ")
|
||||||
|
//kdebug_num (((unsigned *)buffer)[(p + t) >> 2], 8)
|
||||||
|
UDC_OUTCSR &= ~UDC_OUTCSR_OUTPKTRDY
|
||||||
|
//kdebug ("\n")
|
||||||
|
//Iris::debug ("setting block %x@%x+%x\n", lba + i << block_bits, 0, 1 << block_bits)
|
||||||
|
block.set_block ((lba + i) << block_bits, buffer_page, 1 << block_bits)
|
||||||
|
send_csw ()
|
||||||
|
break
|
||||||
case CBW::RESERVE10:
|
case CBW::RESERVE10:
|
||||||
Iris::panic (0, "RESERVE10 isn't implemented")
|
Iris::panic (0, "RESERVE10 isn't implemented")
|
||||||
case CBW::RELEASE10:
|
case CBW::RELEASE10:
|
||||||
@ -725,7 +785,6 @@ void Udc::irq_out ():
|
|||||||
residue = cbw.cbw.length
|
residue = cbw.cbw.length
|
||||||
stall (1)
|
stall (1)
|
||||||
return
|
return
|
||||||
// TODO.
|
|
||||||
|
|
||||||
bool Udc::handle_interrupt (bool usb, bool in):
|
bool Udc::handle_interrupt (bool usb, bool in):
|
||||||
if usb:
|
if usb:
|
||||||
@ -740,7 +799,7 @@ bool Udc::handle_interrupt (bool usb, bool in):
|
|||||||
return true
|
return true
|
||||||
|
|
||||||
void Udc::interrupt ():
|
void Udc::interrupt ():
|
||||||
//Iris::debug ("interrupt\n")
|
Iris::debug ("interrupt\n")
|
||||||
while true:
|
while true:
|
||||||
unsigned usb = UDC_INTRUSB
|
unsigned usb = UDC_INTRUSB
|
||||||
unsigned in = UDC_INTRIN
|
unsigned in = UDC_INTRIN
|
||||||
|
Loading…
Reference in New Issue
Block a user