mirror of
git://projects.qi-hardware.com/iris.git
synced 2025-04-21 12:27:27 +03:00
mass storage sort of working, but not nice
This commit is contained in:
@@ -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]):
|
||||
++name_len
|
||||
name = new char[name_len]
|
||||
kdebug ("name: ")
|
||||
//kdebug ("name: ")
|
||||
for unsigned i = 0; i < name_len; ++i:
|
||||
name[i] = line[i]
|
||||
kdebug_char (name[i])
|
||||
kdebug_char ('\n')
|
||||
//kdebug_char (name[i])
|
||||
//kdebug_char ('\n')
|
||||
line += name_len
|
||||
len -= name_len
|
||||
delspace (line, len)
|
||||
|
||||
@@ -20,22 +20,30 @@
|
||||
#define ARCH
|
||||
#include "arch.hh"
|
||||
|
||||
#define debug //Iris::debug
|
||||
#define debug Iris::debug
|
||||
#define DELAY Iris::schedule
|
||||
#include "nand.hh"
|
||||
#undef debug
|
||||
|
||||
static unsigned *cache
|
||||
static bool dirty
|
||||
static unsigned current_block
|
||||
|
||||
static void sync ():
|
||||
debug ("erasing %x\n", current_block << block_bits)
|
||||
//erase (current_block << block_bits)
|
||||
for unsigned p = 0; p < 1 << (block_bits - 9); ++p:
|
||||
debug ("writing %x\n", (current_block << block_bits) + (p << 9))
|
||||
//write ((current_block << block_bits) + (p << 9), &cache[p << (9 - 2)])
|
||||
Iris::debug ("erasing %x\n", current_block << block_bits)
|
||||
erase (current_block << block_bits)
|
||||
for unsigned p = 0; p < 1 << (block_bits - page_bits); ++p:
|
||||
write ((current_block << block_bits) + (p << page_bits), (char *)&cache[p << (page_bits - 2)])
|
||||
|
||||
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:
|
||||
read ((b << block_bits) + (p << 9), (char *)&cache[p << (9 - 2)])
|
||||
dirty = false
|
||||
@@ -103,21 +111,28 @@ Iris::Num start ():
|
||||
unsigned row = Iris::recv.data[1].value () >> 9
|
||||
unsigned block = row >> (block_bits - 9)
|
||||
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 size = Iris::recv.data[0].h >> 16
|
||||
if size + offset >= 0x1000:
|
||||
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::Page page = Iris::get_arg ()
|
||||
page.share (tmp)
|
||||
tmp.set_flags (Iris::Page::FRAME)
|
||||
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)
|
||||
reply.invoke ()
|
||||
Iris::free_cap (reply)
|
||||
@@ -126,26 +141,38 @@ Iris::Num start ():
|
||||
case Iris::WBlock::SET_BLOCK:
|
||||
unsigned row = Iris::recv.data[1].value () >> 9
|
||||
unsigned block = row >> (block_bits - 9)
|
||||
if block != current_block:
|
||||
if current_block != ~0 && dirty:
|
||||
sync ()
|
||||
current_block = block
|
||||
read_block (block)
|
||||
row &= (1 << (block_bits - 9)) - 1
|
||||
unsigned offset = Iris::recv.data[0].h & 0xe00
|
||||
unsigned size = Iris::recv.data[0].h >> 16
|
||||
if size + offset >= 0x1000:
|
||||
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::Page page = Iris::get_arg ()
|
||||
page.share (tmp)
|
||||
tmp.set_flags (Iris::Page::FRAME)
|
||||
for unsigned t = 0; t < size >> 2; ++t:
|
||||
cache[(offset >> 2) + t + (row << 9)] = tmp_addr[(offset >> 2) + t]
|
||||
for unsigned t = 0; t < size; t += 4:
|
||||
cache[(offset + t + (row << 9)) >> 2] = tmp_addr[(offset + t) >> 2]
|
||||
tmp.set_flags (0, Iris::Page::FRAME)
|
||||
reply.invoke ()
|
||||
Iris::free_cap (reply)
|
||||
Iris::free_cap (page)
|
||||
dirty = true
|
||||
//kdebug_num (current_block)
|
||||
//kdebug ("!")
|
||||
break
|
||||
case Iris::WBlock::TRUNCATE:
|
||||
default:
|
||||
|
||||
@@ -281,9 +281,8 @@ void Udc::init (Iris::WBlock b):
|
||||
UDC_OUTCSR = UDC_OUTCSR_CDT | UDC_OUTCSR_FF
|
||||
UDC_INDEX = 2
|
||||
UDC_INMAXP = max_packet_size_bulk
|
||||
UDC_INCSRH = UDC_INCSRH_MODE
|
||||
UDC_INCSR = 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_INCSRH_MODE << 8) | UDC_INCSR_CDT | UDC_INCSR_FF
|
||||
// exit suspend mode by reading the interrupt register.
|
||||
unsigned i = UDC_INTRUSB
|
||||
// reset all pending endpoint interrupts.
|
||||
@@ -325,31 +324,52 @@ void Udc::send_padded (char const *data, unsigned length, unsigned maxlength):
|
||||
residue = maxlength - len
|
||||
len = (len + 3) & ~3
|
||||
send (2, data, len, maxlength)
|
||||
//Iris::debug ("sending %x, valid %x\n", maxlength, len)
|
||||
while len + 3 < maxlength:
|
||||
UDC_FIFO (2) = 0
|
||||
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 ('-')
|
||||
while len < maxlength:
|
||||
UDC_FIFO8 (2) = 0
|
||||
++len
|
||||
//kdebug_char ('.')
|
||||
UDC_INCSR |= UDC_INCSR_INPKTRDY
|
||||
while true:
|
||||
Iris::register_interrupt (IRQ_UDC)
|
||||
Iris::wait_for_interrupt (IRQ_UDC)
|
||||
//kdebug ("interrupt pad\t")
|
||||
unsigned usb = UDC_INTRUSB
|
||||
unsigned in = UDC_INTRIN
|
||||
unsigned out = UDC_INTROUT
|
||||
if usb & 4 || in & 1:
|
||||
//kdebug ("general interrupt pad\t")
|
||||
if !handle_interrupt (usb & 4, in & 1):
|
||||
return
|
||||
if out & 2:
|
||||
Iris::panic (0, "out interrupt while waiting for in")
|
||||
if in & 4:
|
||||
break
|
||||
//kdebug ("done interrupt pad\n")
|
||||
if len % max_packet_size_bulk != 0 || len < maxlength:
|
||||
while len < maxlength:
|
||||
UDC_FIFO8 (2) = 0
|
||||
++len
|
||||
//kdebug_char ('.')
|
||||
UDC_INCSR |= UDC_INCSR_INPKTRDY
|
||||
while true:
|
||||
Iris::register_interrupt (IRQ_UDC)
|
||||
Iris::wait_for_interrupt (IRQ_UDC)
|
||||
kdebug ("interrupt pad\t")
|
||||
unsigned usb = UDC_INTRUSB
|
||||
unsigned in = UDC_INTRIN
|
||||
if usb & 4 || in & 1:
|
||||
//kdebug ("general interrupt pad\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 ("done interrupt pad\n")
|
||||
|
||||
unsigned Udc::get_descriptor (unsigned type, unsigned idx, unsigned len):
|
||||
switch type:
|
||||
@@ -446,22 +466,20 @@ unsigned Udc::handle_setup (Setup *s):
|
||||
case ENDPOINT_HALT:
|
||||
switch s->index:
|
||||
case 0x82:
|
||||
//Iris::debug ("in ep halt reset\n")
|
||||
Iris::debug ("in ep halt reset\n")
|
||||
UDC_INDEX = 2
|
||||
UDC_INCSR &= ~UDC_INCSR_SENDSTALL
|
||||
stalling[2] = false
|
||||
break
|
||||
case 1:
|
||||
//Iris::debug ("out ep halt reset\n")
|
||||
Iris::debug ("out ep halt reset\n")
|
||||
UDC_INDEX = 1
|
||||
UDC_OUTCSR &= ~UDC_OUTCSR_SENDSTALL
|
||||
stalling[1] = false
|
||||
break
|
||||
default:
|
||||
return ~0
|
||||
UDC_INDEX = 0
|
||||
UDC_CSR0 = UDC_CSR0_DATAEND | UDC_CSR0_SVDOUTPKTRDY
|
||||
return 0
|
||||
return UDC_CSR0_DATAEND | UDC_CSR0_SVDOUTPKTRDY
|
||||
default:
|
||||
return ~0
|
||||
default:
|
||||
@@ -518,6 +536,11 @@ void Udc::irq_in0 ():
|
||||
if !(csr & UDC_CSR0_OUTPKTRDY):
|
||||
//Iris::debug ("no packet 0: %x\n", csr)
|
||||
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
|
||||
packet.d[0] = 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")
|
||||
UDC_CSR0 = UDC_CSR0_SENDSTALL
|
||||
return
|
||||
UDC_INDEX = 1
|
||||
UDC_OUTCSR |= UDC_OUTCSR_CDT
|
||||
UDC_INDEX = 2
|
||||
UDC_INCSR |= UDC_INCSR_CDT
|
||||
unsigned ret = handle_setup (&packet.s)
|
||||
UDC_INDEX = 0
|
||||
if ret == ~0:
|
||||
@@ -552,6 +571,7 @@ void Udc::send_csw ():
|
||||
while true:
|
||||
Iris::register_interrupt (IRQ_UDC)
|
||||
Iris::wait_for_interrupt (IRQ_UDC)
|
||||
kdebug ("interrupt csw\n")
|
||||
unsigned usb = UDC_INTRUSB
|
||||
unsigned in = UDC_INTRIN
|
||||
if usb & 4 || in & 1:
|
||||
@@ -562,7 +582,7 @@ void Udc::send_csw ():
|
||||
unsigned out = UDC_INTROUT
|
||||
if out & 2:
|
||||
Iris::panic (0, "out interrupt while waiting for in after csw")
|
||||
//kdebug ("sent csw\n")
|
||||
kdebug ("sent csw\n")
|
||||
|
||||
void Udc::stall (unsigned error):
|
||||
unsigned index = UDC_INDEX
|
||||
@@ -574,14 +594,16 @@ void Udc::stall (unsigned error):
|
||||
UDC_INCSR |= UDC_INCSR_SENDSTALL
|
||||
stalling[index] = true
|
||||
while stalling[index]:
|
||||
//kdebug ("stalling\t")
|
||||
//Iris::debug ("stalling %d\n", index)
|
||||
Iris::register_interrupt (IRQ_UDC)
|
||||
Iris::wait_for_interrupt (IRQ_UDC)
|
||||
//kdebug ("stalling interrupt\n")
|
||||
kdebug ("stalling interrupt\n")
|
||||
unsigned usb = UDC_INTRUSB
|
||||
unsigned in = UDC_INTRIN
|
||||
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_INCSR &= ~UDC_INCSR_SENTSTALL
|
||||
//Iris::debug ("csr: %x\n", UDC_INCSR)
|
||||
@@ -591,10 +613,12 @@ void Udc::stall (unsigned error):
|
||||
return
|
||||
unsigned out = UDC_INTROUT
|
||||
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_OUTCSR &= ~UDC_OUTCSR_SENTSTALL
|
||||
UDC_INDEX = index
|
||||
//kdebug ("done stalling\n")
|
||||
if index == 2:
|
||||
status = error
|
||||
send_csw ()
|
||||
@@ -608,7 +632,7 @@ void Udc::irq_out ():
|
||||
unsigned size = UDC_OUTCOUNT
|
||||
if !(csr & UDC_OUTCSR_OUTPKTRDY):
|
||||
// No packet, just a notification.
|
||||
//kdebug ("no packet\n")
|
||||
kdebug ("no packet\n")
|
||||
return
|
||||
if csr & UDC_OUTCSR_SENDSTALL:
|
||||
// When stalling, do nothing else.
|
||||
@@ -647,7 +671,7 @@ void Udc::irq_out ():
|
||||
send_csw ()
|
||||
break
|
||||
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_csw ()
|
||||
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 blocks = cbw.cbw.data[7] << 8 | cbw.cbw.data[8]
|
||||
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.
|
||||
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:
|
||||
//Iris::debug (" %d", p)
|
||||
UDC_INDEX = 2
|
||||
@@ -696,7 +720,7 @@ void Udc::irq_out ():
|
||||
while true:
|
||||
Iris::register_interrupt (IRQ_UDC)
|
||||
Iris::wait_for_interrupt (IRQ_UDC)
|
||||
//kdebug ("interrupt read10\t")
|
||||
kdebug ("interrupt read10\n")
|
||||
unsigned usb = UDC_INTRUSB
|
||||
unsigned in = UDC_INTRIN
|
||||
unsigned out = UDC_INTROUT
|
||||
@@ -711,7 +735,43 @@ void Udc::irq_out ():
|
||||
send_csw ()
|
||||
break
|
||||
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:
|
||||
Iris::panic (0, "RESERVE10 isn't implemented")
|
||||
case CBW::RELEASE10:
|
||||
@@ -725,7 +785,6 @@ void Udc::irq_out ():
|
||||
residue = cbw.cbw.length
|
||||
stall (1)
|
||||
return
|
||||
// TODO.
|
||||
|
||||
bool Udc::handle_interrupt (bool usb, bool in):
|
||||
if usb:
|
||||
@@ -740,7 +799,7 @@ bool Udc::handle_interrupt (bool usb, bool in):
|
||||
return true
|
||||
|
||||
void Udc::interrupt ():
|
||||
//Iris::debug ("interrupt\n")
|
||||
Iris::debug ("interrupt\n")
|
||||
while true:
|
||||
unsigned usb = UDC_INTRUSB
|
||||
unsigned in = UDC_INTRIN
|
||||
|
||||
Reference in New Issue
Block a user