1
0
mirror of git://projects.qi-hardware.com/iris.git synced 2024-07-01 00:44:31 +03:00

mass storage nand almost working

This commit is contained in:
Bas Wijnen 2010-09-09 21:48:35 +02:00
parent 3a38ea2944
commit 87acc47fd9
4 changed files with 211 additions and 106 deletions

View File

@ -220,11 +220,13 @@ bool kMemory_arch_map (kMemory *mem, kPage *page, unsigned address):
mem->unmap (table->page[idx]) mem->unmap (table->page[idx])
table->entrylo[idx] = make_entry_lo (page) table->entrylo[idx] = make_entry_lo (page)
table->page[idx] = page table->page[idx] = page
//kdebug ("mapped ") #if 0
//kdebug_num (page->frame) kdebug ("mapped ")
//kdebug (" at address ") kdebug_num (page->frame)
//kdebug_num (address) kdebug (" at address ")
//kdebug ('\n') kdebug_num (address)
kdebug ('\n')
#endif
page->mapping = address page->mapping = address
page->arch.next_mapped = mem->arch.shadow[address >> 21] page->arch.next_mapped = mem->arch.shadow[address >> 21]
if page->arch.next_mapped: if page->arch.next_mapped:

View File

@ -80,6 +80,9 @@ static unsigned rdata ():
static void reset (): static void reset ():
// Set up. // Set up.
gpio_as_nand () gpio_as_nand ()
gpio_as_gpio (2, 1 << 30)
gpio_as_input (2, 1 << 30)
gpio_enable_pull (2, 1 << 30)
EMC_NFCSR = EMC_NFCSR_NFE1 | EMC_NFCSR_NFCE1 EMC_NFCSR = EMC_NFCSR_NFE1 | EMC_NFCSR_NFCE1
// Reset nand. // Reset nand.
@ -149,11 +152,11 @@ static bool read (unsigned a, char *buffer):
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)
@ -165,8 +168,10 @@ 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)

View File

@ -20,7 +20,7 @@
#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"
@ -74,7 +74,7 @@ Iris::Num start ():
for unsigned p = 0; p < 1 << (block_bits - PAGE_BITS); ++p: for unsigned p = 0; p < 1 << (block_bits - PAGE_BITS); ++p:
Iris::Page page = Iris::my_memory.create_page () Iris::Page page = Iris::my_memory.create_page ()
page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME) page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME)
Iris::my_memory.map (page, (unsigned)cache + p << PAGE_BITS) Iris::my_memory.map (page, (unsigned)cache + (p << PAGE_BITS))
Iris::free_cap (page) Iris::free_cap (page)
Iris::Page tmp = Iris::my_memory.create_page () Iris::Page tmp = Iris::my_memory.create_page ()
tmp.set_flags (Iris::Page::PAYING) tmp.set_flags (Iris::Page::PAYING)

View File

@ -146,10 +146,18 @@ class Udc:
u8 size; u8 size;
u8 data[16]; u8 data[16];
enum Code { enum Code {
INQUIRY = 0x12,
TEST_UNIT_READY = 0x00, TEST_UNIT_READY = 0x00,
REQUEST_SENSE = 0x03,
FORMAT_UNIT = 0x04,
INQUIRY = 0x12,
RESERVE6 = 0x16,
RELEASE6 = 0x17,
SEND_DIAGNOSTIC = 0x1d,
READ_CAPACITY = 0x25, READ_CAPACITY = 0x25,
REQUEST_SENSE = 0x03 READ10 = 0x28,
WRITE10 = 0x2a,
RESERVE10 = 0x56,
RELEASE10 = 0x57
}; };
} __attribute__ ((packed)) } __attribute__ ((packed))
static unsigned const max_packet_size0 = 64 static unsigned const max_packet_size0 = 64
@ -223,6 +231,9 @@ class Udc:
unsigned tag unsigned tag
unsigned block_bits unsigned block_bits
Iris::WBlock block Iris::WBlock block
Iris::Page buffer_page
// A random address to map the buffer.
static unsigned const buffer = 0x15000
public: public:
void init (Iris::WBlock b) void init (Iris::WBlock b)
void log (unsigned c) void log (unsigned c)
@ -240,6 +251,10 @@ Udc::String <12> Udc::s_serial
void Udc::init (Iris::WBlock b): void Udc::init (Iris::WBlock b):
block = b block = b
block_bits = block.get_align_bits () block_bits = block.get_align_bits ()
// Set up the buffer page.
buffer_page = Iris::my_memory.create_page ()
buffer_page.set_flags (Iris::Page::PAYING)
Iris::my_memory.map (buffer_page, buffer)
// Initialize the globals. My method of compiling doesn't handle global constructors. // Initialize the globals. My method of compiling doesn't handle global constructors.
device_descriptor = (Device){ sizeof (Device), Device::Type, 0x200, 0, 0, 0, max_packet_size0, 0xfffe, 0x0002, 0x100, 1, 2, 3, 1 } device_descriptor = (Device){ sizeof (Device), Device::Type, 0x200, 0, 0, 0, max_packet_size0, 0xfffe, 0x0002, 0x100, 1, 2, 3, 1 }
config_descriptor = (my_config){ config_descriptor = (my_config){
@ -259,6 +274,16 @@ void Udc::init (Iris::WBlock b):
UDC_POWER = 0 UDC_POWER = 0
UDC_TESTMODE = 0 UDC_TESTMODE = 0
configuration = 0 configuration = 0
// Set max packet sizes.
UDC_INDEX = 1
UDC_OUTMAXP = max_packet_size_bulk
UDC_OUTCSR = UDC_OUTCSR_CDT | UDC_OUTCSR_FF
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
// 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.
@ -266,13 +291,10 @@ void Udc::init (Iris::WBlock b):
i = UDC_INTROUT i = UDC_INTROUT
// enable interrupt on bus reset. // enable interrupt on bus reset.
UDC_INTRUSBE = UDC_INTR_RESET UDC_INTRUSBE = UDC_INTR_RESET
// enable interrupt on control endpoint. // enable interrupts on endpoint 0 and in endpoint 2
UDC_INTRINE = 1 << 0 UDC_INTRINE = 1 << 0 | 1 << 2
// Set max packet sizes. // and on out endpoint 1.
UDC_INDEX = 1 UDC_INTROUTE = 1 << 1
UDC_OUTMAXP = max_packet_size_bulk
UDC_INDEX = 2
UDC_INMAXP = max_packet_size_bulk
// Wait a while. // Wait a while.
Iris::sleep (HZ / 10) Iris::sleep (HZ / 10)
// Connect to the host. // Connect to the host.
@ -288,14 +310,17 @@ void Udc::send (unsigned ep, char const *data, unsigned length, unsigned maxleng
unsigned i unsigned i
for i = 0; (length - i & ~3) > 0 && i < length; i += 4: for i = 0; (length - i & ~3) > 0 && i < length; i += 4:
UDC_FIFO (ep) = ((unsigned *)data)[i / 4] UDC_FIFO (ep) = ((unsigned *)data)[i / 4]
kdebug_num (((unsigned *)data)[i / 4], 8) //kdebug_num (((unsigned *)data)[i / 4], 8)
kdebug (" ") //kdebug (" ")
for ; i < length; ++i: for ; i < length; ++i:
UDC_FIFO8 (ep) = data[i] UDC_FIFO8 (ep) = data[i]
kdebug_num (data[i], 2) //kdebug_num (data[i], 2)
kdebug (" ") //kdebug (" ")
void Udc::send_padded (char const *data, unsigned length, unsigned maxlength): void Udc::send_padded (char const *data, unsigned length, unsigned maxlength):
UDC_INDEX = 2
if UDC_INCSR & UDC_INCSR_INPKTRDY:
Iris::panic (0, "sending padded not possible because a packet is already waiting.\n")
unsigned len = length < maxlength ? length : maxlength unsigned len = length < maxlength ? length : maxlength
residue = maxlength - len residue = maxlength - len
len = (len + 3) & ~3 len = (len + 3) & ~3
@ -303,42 +328,41 @@ void Udc::send_padded (char const *data, unsigned length, unsigned maxlength):
while len + 3 < maxlength: while len + 3 < maxlength:
UDC_FIFO (2) = 0 UDC_FIFO (2) = 0
len += 4 len += 4
kdebug_char ('-') //kdebug_char ('-')
while len < maxlength: while len < maxlength:
UDC_FIFO8 (2) = 0 UDC_FIFO8 (2) = 0
++len ++len
kdebug_char ('.') //kdebug_char ('.')
UDC_INDEX = 2
UDC_INCSR |= UDC_INCSR_INPKTRDY UDC_INCSR |= UDC_INCSR_INPKTRDY
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\n") //kdebug ("interrupt pad\t")
unsigned usb = UDC_INTRUSB unsigned usb = UDC_INTRUSB
unsigned in = UDC_INTRIN unsigned in = UDC_INTRIN
unsigned out = UDC_INTROUT unsigned out = UDC_INTROUT
if usb & 4 || in & 1: if usb & 4 || in & 1:
kdebug ("general interrupt pad\n") //kdebug ("general interrupt pad\t")
if !handle_interrupt (usb & 4, in & 1): if !handle_interrupt (usb & 4, in & 1):
return return
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:
break break
kdebug ("done interrupt pad\n") //kdebug ("done interrupt pad\n")
unsigned Udc::get_descriptor (unsigned type, unsigned idx, unsigned len): unsigned Udc::get_descriptor (unsigned type, unsigned idx, unsigned len):
switch type: switch type:
case Configuration::Type: case Configuration::Type:
if idx != 0: if idx != 0:
return false return false
Iris::debug ("get config descriptor\n") //Iris::debug ("get config descriptor\n")
send (0, reinterpret_cast <char const *> (&config_descriptor), sizeof (config_descriptor), len) send (0, reinterpret_cast <char const *> (&config_descriptor), sizeof (config_descriptor), len)
return UDC_CSR0_INPKTRDY | UDC_CSR0_DATAEND return UDC_CSR0_INPKTRDY | UDC_CSR0_DATAEND
case Device::Type: case Device::Type:
if idx != 0: if idx != 0:
return false return false
Iris::debug ("get device descriptor\n") //Iris::debug ("get device descriptor\n")
send (0, reinterpret_cast <char const *> (&device_descriptor), sizeof (device_descriptor), len) send (0, reinterpret_cast <char const *> (&device_descriptor), sizeof (device_descriptor), len)
return UDC_CSR0_INPKTRDY | UDC_CSR0_DATAEND return UDC_CSR0_INPKTRDY | UDC_CSR0_DATAEND
case Device_Qualifier::Type: case Device_Qualifier::Type:
@ -352,19 +376,19 @@ unsigned Udc::get_descriptor (unsigned type, unsigned idx, unsigned len):
case String <6>::Type: case String <6>::Type:
switch idx: switch idx:
case 0: case 0:
Iris::debug ("get language descriptor\n") //Iris::debug ("get language descriptor\n")
send (0, reinterpret_cast <char const *> (&s_langs), sizeof (s_langs), len) send (0, reinterpret_cast <char const *> (&s_langs), sizeof (s_langs), len)
return UDC_CSR0_INPKTRDY | UDC_CSR0_DATAEND return UDC_CSR0_INPKTRDY | UDC_CSR0_DATAEND
case 1: case 1:
Iris::debug ("get manufacturer descriptor\n") //Iris::debug ("get manufacturer descriptor\n")
send (0, reinterpret_cast <char const *> (&s_manufacturer), sizeof (s_manufacturer), len) send (0, reinterpret_cast <char const *> (&s_manufacturer), sizeof (s_manufacturer), len)
return UDC_CSR0_INPKTRDY | UDC_CSR0_DATAEND return UDC_CSR0_INPKTRDY | UDC_CSR0_DATAEND
case 2: case 2:
Iris::debug ("get product descriptor\n") //Iris::debug ("get product descriptor\n")
send (0, reinterpret_cast <char const *> (&s_product), sizeof (s_product), len) send (0, reinterpret_cast <char const *> (&s_product), sizeof (s_product), len)
return UDC_CSR0_INPKTRDY | UDC_CSR0_DATAEND return UDC_CSR0_INPKTRDY | UDC_CSR0_DATAEND
case 3: case 3:
Iris::debug ("get serial descriptor\n") //Iris::debug ("get serial descriptor\n")
send (0, reinterpret_cast <char const *> (&s_serial), sizeof (s_serial), len) send (0, reinterpret_cast <char const *> (&s_serial), sizeof (s_serial), len)
return UDC_CSR0_INPKTRDY | UDC_CSR0_DATAEND return UDC_CSR0_INPKTRDY | UDC_CSR0_DATAEND
default: default:
@ -375,38 +399,42 @@ unsigned Udc::get_descriptor (unsigned type, unsigned idx, unsigned len):
unsigned Udc::handle_setup (Setup *s): unsigned Udc::handle_setup (Setup *s):
switch s->request_type: switch s->request_type:
case STANDARD_TO_DEVICE: case STANDARD_TO_DEVICE:
UDC_INDEX = 0
UDC_CSR0 = UDC_CSR0_DATAEND | UDC_CSR0_SVDOUTPKTRDY
switch s->request: switch s->request:
case SET_ADDRESS: case SET_ADDRESS:
UDC_FADDR = s->value UDC_FADDR = s->value
Iris::debug ("set address %x\n", s->value) //Iris::debug ("set address %x\n", s->value)
return 0 return 0
case SET_CONFIGURATION: case SET_CONFIGURATION:
if s->value >= 2: if s->value >= 2:
return ~0 return ~0
configuration = s->value configuration = s->value
Iris::debug ("set configuration %x\n", s->value) //Iris::debug ("set configuration %x\n", s->value)
return 0 return 0
case SET_INTERFACE: case SET_INTERFACE:
if s->value != 0: if s->value != 0:
return ~0 return ~0
Iris::debug ("set interface %x\n", s->value) //Iris::debug ("set interface %x\n", s->value)
return 0 return 0
default: default:
return ~0 return ~0
case STANDARD_FROM_DEVICE: case STANDARD_FROM_DEVICE:
UDC_INDEX = 0
UDC_CSR0 = UDC_CSR0_DATAEND | UDC_CSR0_SVDOUTPKTRDY
switch s->request: switch s->request:
case GET_STATUS: case GET_STATUS:
Iris::debug ("get status\n") //Iris::debug ("get status\t")
send (0, "\0\0", 2, s->length) send (0, "\0\0", 2, s->length)
return UDC_CSR0_INPKTRDY | UDC_CSR0_DATAEND return UDC_CSR0_INPKTRDY | UDC_CSR0_DATAEND
case GET_DESCRIPTOR: case GET_DESCRIPTOR:
return get_descriptor ((s->value >> 8) & 0xff, s->value & 0xff, s->length) return get_descriptor ((s->value >> 8) & 0xff, s->value & 0xff, s->length)
case GET_CONFIGURATION: case GET_CONFIGURATION:
Iris::debug ("get configuration\n") //Iris::debug ("get configuration\t")
send (0, &configuration, 1, s->length) send (0, &configuration, 1, s->length)
return UDC_CSR0_INPKTRDY | UDC_CSR0_DATAEND return UDC_CSR0_INPKTRDY | UDC_CSR0_DATAEND
case GET_INTERFACE: case GET_INTERFACE:
Iris::debug ("get interface\n") //Iris::debug ("get interface\t")
send (0, "\0", 1, s->length) send (0, "\0", 1, s->length)
return UDC_CSR0_INPKTRDY | UDC_CSR0_DATAEND return UDC_CSR0_INPKTRDY | UDC_CSR0_DATAEND
default: default:
@ -418,35 +446,42 @@ 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_SENTSTALL) UDC_INCSR &= ~UDC_INCSR_SENDSTALL
stalling[2] = false stalling[2] = false
return 0 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_SENTSTALL) UDC_OUTCSR &= ~UDC_OUTCSR_SENDSTALL
stalling[1] = false stalling[1] = false
return 0 break
default: default:
return ~0 return ~0
UDC_INDEX = 0
UDC_CSR0 = UDC_CSR0_DATAEND | UDC_CSR0_SVDOUTPKTRDY
return 0
default: default:
return ~0 return ~0
default: default:
return ~0 return ~0
case CLASS_FROM_INTERFACE: case CLASS_FROM_INTERFACE:
UDC_INDEX = 0
UDC_CSR0 = UDC_CSR0_DATAEND | UDC_CSR0_SVDOUTPKTRDY
switch s->request: switch s->request:
case GET_MAX_LUN: case GET_MAX_LUN:
Iris::debug ("get max lun\n") //Iris::debug ("get max lun\t")
send (0, "\0", 1, s->length) send (0, "\0", 1, s->length)
return UDC_CSR0_INPKTRDY | UDC_CSR0_DATAEND return UDC_CSR0_INPKTRDY | UDC_CSR0_DATAEND
default: default:
return ~0 return ~0
case CLASS_TO_INTERFACE: case CLASS_TO_INTERFACE:
UDC_INDEX = 0
UDC_CSR0 = UDC_CSR0_DATAEND | UDC_CSR0_SVDOUTPKTRDY
switch s->request: switch s->request:
case BULK_ONLY_RESET: case BULK_ONLY_RESET:
Iris::debug ("bulk reset\n") //Iris::debug ("bulk reset\n")
return 0 return 0
default: default:
return ~0 return ~0
@ -462,45 +497,48 @@ void Udc::irq_usb ():
UDC_INTROUTE = 1 << 1 UDC_INTROUTE = 1 << 1
UDC_INDEX = 1 UDC_INDEX = 1
// Do this twice to flush a double-buffered fifo completely. // Do this twice to flush a double-buffered fifo completely.
UDC_OUTMAXP = max_packet_size_bulk
UDC_OUTCSR |= UDC_OUTCSR_CDT | UDC_OUTCSR_FF UDC_OUTCSR |= UDC_OUTCSR_CDT | UDC_OUTCSR_FF
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_INCSR |= UDC_INCSR_CDT UDC_INCSR |= UDC_INCSR_CDT
Iris::debug ("usb reset\n") //Iris::debug ("usb reset\n")
void Udc::irq_in0 (): void Udc::irq_in0 ():
// Interrupt on endpoint 0. // Interrupt on endpoint 0.
UDC_INDEX = 0 UDC_INDEX = 0
unsigned csr = UDC_CSR0 unsigned csr = UDC_CSR0
if csr & UDC_CSR0_SENTSTALL: if csr & UDC_CSR0_SENTSTALL:
csr &= ~(UDC_CSR0_SENTSTALL | UDC_CSR0_SENDSTALL) UDC_CSR0 = 0
//Iris::debug ("stall done\t")
if csr & UDC_CSR0_SETUPEND: if csr & UDC_CSR0_SETUPEND:
csr |= UDC_CSR0_SVDSETUPEND UDC_CSR0 = UDC_CSR0_SVDSETUPEND
//Iris::debug ("setup aborted\t")
if !(csr & UDC_CSR0_OUTPKTRDY): if !(csr & UDC_CSR0_OUTPKTRDY):
kdebug ("packet sent 0\n") //Iris::debug ("no packet 0: %x\n", csr)
return return
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)
if !(packet.s.request_type & 0x80) && packet.s.length > 0: if !(packet.s.request_type & 0x80) && packet.s.length > 0:
// More data will follow; unsupported. // More data will follow; unsupported.
Iris::debug ("packet on ep0 too long\n") //Iris::debug ("packet on ep0 too long\n")
UDC_CSR0 = csr | UDC_CSR0_SENDSTALL UDC_CSR0 = UDC_CSR0_SENDSTALL
return return
UDC_CSR0 = csr | UDC_CSR0_DATAEND | UDC_CSR0_SVDOUTPKTRDY
csr &= ~(UDC_CSR0_SETUPEND | UDC_CSR0_SENDSTALL | UDC_CSR0_SENTSTALL)
unsigned ret = handle_setup (&packet.s)
UDC_INDEX = 1 UDC_INDEX = 1
UDC_OUTCSR |= UDC_OUTCSR_CDT UDC_OUTCSR |= UDC_OUTCSR_CDT
UDC_INDEX = 2 UDC_INDEX = 2
UDC_INCSR |= UDC_INCSR_CDT UDC_INCSR |= UDC_INCSR_CDT
unsigned ret = handle_setup (&packet.s)
UDC_INDEX = 0 UDC_INDEX = 0
if ret == ~0: if ret == ~0:
Iris::debug ("failed setup: %x %x %x %x %x\n", packet.s.request_type, packet.s.request, packet.s.index, packet.s.length, packet.s.value) Iris::debug ("failed setup: %x %x %x %x %x\n", packet.s.request_type, packet.s.request, packet.s.index, packet.s.length, packet.s.value)
UDC_CSR0 = csr | UDC_CSR0_SENDSTALL UDC_CSR0 = UDC_CSR0_SENDSTALL
return return
UDC_CSR0 = csr | ret if ret:
kdebug ("done in0\n") UDC_CSR0 = ret
//kdebug ("done in0\n")
void Udc::send_csw (): void Udc::send_csw ():
UDC_INDEX = 2 UDC_INDEX = 2
@ -524,32 +562,38 @@ 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
if stalling[index]:
Iris::debug ("already stalling!\n")
if index == 1: if index == 1:
UDC_OUTCSR |= UDC_OUTCSR_SENDSTALL UDC_OUTCSR |= UDC_OUTCSR_SENDSTALL
else: else:
UDC_INCSR |= UDC_INCSR_SENDSTALL UDC_INCSR |= UDC_INCSR_SENDSTALL
stalling[index] = true stalling[index] = true
kdebug ("stalling\n")
while stalling[index]: while stalling[index]:
//kdebug ("stalling\t")
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:
//kdebug ("stall has been sent to in endpoint\n")
UDC_INDEX = 2
UDC_INCSR &= ~UDC_INCSR_SENTSTALL
//Iris::debug ("csr: %x\n", UDC_INCSR)
if usb & 4 || in & 1: if usb & 4 || in & 1:
kdebug ("stuff\n") //kdebug ("stuff\n")
if !handle_interrupt (usb & 4, in & 1): if !handle_interrupt (usb & 4, in & 1):
return return
if in & 4:
kdebug ("in interrupt ignored while waiting for stall reset\n")
unsigned out = UDC_INTROUT unsigned out = UDC_INTROUT
if out & 2: if out & 2:
Iris::panic (0, "out interrupt while waiting for stall reset") //kdebug ("stall has been sent to out endpoint\n")
kdebug ("no stuff\n") UDC_INDEX = 1
UDC_OUTCSR &= ~UDC_OUTCSR_SENTSTALL
UDC_INDEX = index UDC_INDEX = index
if index == 2: if index == 2:
status = error status = error
@ -564,12 +608,12 @@ 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.
kdebug ("not responding to out during stall\n") //kdebug ("not responding to out during stall\n")
UDC_OUTCSR &= ~UDC_OUTCSR_SENTSTALL UDC_OUTCSR = csr & ~UDC_OUTCSR_SENTSTALL
return return
// expect a new cbw. // expect a new cbw.
if size != 31: if size != 31:
@ -578,51 +622,100 @@ void Udc::irq_out ():
return return
union Cbw: union Cbw:
unsigned u[8] unsigned u[8]
char b[32]
CBW cbw CBW cbw
Cbw cbw Cbw cbw
for unsigned i = 0; i < 8; ++i: for unsigned i = 0; i < 7; ++i:
cbw.u[i] = UDC_FIFO (1) cbw.u[i] = UDC_FIFO (1)
for unsigned i = 28; i < 31; ++i:
cbw.b[i] = UDC_FIFO8 (1)
UDC_OUTCSR = csr & ~UDC_OUTCSR_OUTPKTRDY
tag = cbw.cbw.tag tag = cbw.cbw.tag
if cbw.cbw.sig != 0x43425355 || cbw.cbw.lun != 0 || cbw.cbw.size == 0 || cbw.cbw.size > 16: if cbw.cbw.sig != 0x43425355 || cbw.cbw.lun != 0 || cbw.cbw.size == 0 || cbw.cbw.size > 16:
Iris::debug ("sig %x lun %d size %d\n", cbw.cbw.sig, cbw.cbw.lun, cbw.cbw.size) Iris::debug ("sig %x lun %d size %d\n", cbw.cbw.sig, cbw.cbw.lun, cbw.cbw.size)
stall (2) stall (2)
return return
UDC_OUTCSR = csr & ~UDC_OUTCSR_OUTPKTRDY //kdebug ("bulk cbw\t")
kdebug ("bulk cbw\n")
UDC_INDEX = 2 UDC_INDEX = 2
bool to_host = cbw.cbw.flags & 0x80 bool to_host = cbw.cbw.flags & 0x80
switch cbw.cbw.data[0]: switch cbw.cbw.data[0]:
case CBW::INQUIRY:
if !to_host:
stall (2)
break
Iris::debug ("sending inquiry response\n")
send_padded ("\x00\x00\x04\x02\x1f\x00\x00\x00shevek iris usb stick 0 ", 36, cbw.cbw.length)
send_csw ()
break
case CBW::TEST_UNIT_READY: case CBW::TEST_UNIT_READY:
if to_host || cbw.cbw.length != 0: if to_host || cbw.cbw.length != 0:
stall (2) stall (2)
return return
Iris::debug ("sending ready response\n") //Iris::debug ("sending ready response\t")
send_csw ()
break
case CBW::READ_CAPACITY:
if !to_host:
stall (2)
break
unsigned capacity[2]
capacity[0] = big_endian ((block.get_size ().value () >> block_bits) - 1)
capacity[1] = big_endian (1 << block_bits)
Iris::debug ("sending capacity: %x * %x\n", capacity[0], capacity[1])
send_padded ((char *)capacity, 8, cbw.cbw.length)
send_csw () send_csw ()
break break
case CBW::REQUEST_SENSE: case CBW::REQUEST_SENSE:
Iris::debug ("sense requested\n") //Iris::debug ("sense requested\t")
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
case CBW::FORMAT_UNIT:
Iris::panic (0, "FORMAT_UNIT isn't implemented")
case CBW::INQUIRY:
if !to_host:
stall (2)
return
//Iris::debug ("sending inquiry response\t")
send_padded ("\x00\x00\x04\x02\x1f\x00\x00\x00shevek iris usb stick \x00\x00\x04\x02", 36, cbw.cbw.length)
send_csw ()
break
case CBW::RESERVE6:
Iris::panic (0, "RESERVE6 isn't implemented")
case CBW::RELEASE6:
Iris::panic (0, "RELEASE6 isn't implemented")
case CBW::SEND_DIAGNOSTIC:
Iris::panic (0, "SEND_DIAGNOSTIC isn't implemented")
case CBW::READ_CAPACITY:
if !to_host:
stall (2)
return
unsigned capacity[2]
capacity[0] = big_endian ((block.get_size ().value () >> block_bits) - 1)
capacity[1] = big_endian (1 << block_bits)
//Iris::debug ("sending capacity: %x * %x\t", capacity[0], capacity[1])
send_padded ((char *)capacity, 8, cbw.cbw.length)
send_csw ()
break
case CBW::READ10:
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)
// read block lba + i.
buffer_page.set_flags (Iris::Page::FRAME)
block.get_block (lba << 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
for unsigned t = 0; t < max_packet_size_bulk; t += 4:
UDC_FIFO (2) = ((unsigned *)buffer)[(p + t) >> 2]
UDC_INCSR |= UDC_INCSR_INPKTRDY
//Iris::debug ("\n")
while true:
Iris::register_interrupt (IRQ_UDC)
Iris::wait_for_interrupt (IRQ_UDC)
//kdebug ("interrupt read10\t")
unsigned usb = UDC_INTRUSB
unsigned in = UDC_INTRIN
unsigned out = UDC_INTROUT
if usb & 4 || in & 1:
//kdebug ("general interrupt read10\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
send_csw ()
break
case CBW::WRITE10:
Iris::panic (0, "WRITE10 isn't implemented")
case CBW::RESERVE10:
Iris::panic (0, "RESERVE10 isn't implemented")
case CBW::RELEASE10:
Iris::panic (0, "RELEASE10 isn't implemented")
default: default:
Iris::debug ("cbw:") Iris::debug ("cbw:")
for unsigned i = 0; i < cbw.cbw.size; ++i: for unsigned i = 0; i < cbw.cbw.size; ++i:
@ -631,35 +724,40 @@ void Udc::irq_out ():
Iris::debug ("\n") Iris::debug ("\n")
residue = cbw.cbw.length residue = cbw.cbw.length
stall (1) stall (1)
break return
// TODO. // TODO.
bool Udc::handle_interrupt (bool usb, bool in): bool Udc::handle_interrupt (bool usb, bool in):
if usb: if usb:
Iris::debug ("usb\t") //Iris::debug ("usb\t")
// reset. // reset.
irq_usb () irq_usb ()
return false return false
if in: if in:
Iris::debug ("control\t") //Iris::debug ("control\t")
// control request // control request
irq_in0 () irq_in0 ()
return true return true
void Udc::interrupt (): void Udc::interrupt ():
//Iris::debug ("interrupt\n")
while true: while true:
unsigned usb = UDC_INTRUSB unsigned usb = UDC_INTRUSB
unsigned in = UDC_INTRIN unsigned in = UDC_INTRIN
unsigned out = UDC_INTROUT bool action = false
if !(usb & 4) && !(in & 5) && !(out & 2):
// No more interrupts to handle; this is normal, because we're looping until this happens.
Iris::debug ("irq done\n")
return
if in & 4: if in & 4:
Iris::debug ("ignoring data request during idle\n") Iris::panic (0, "data request during idle\n")
handle_interrupt (usb & 4, in & 1) if usb & 4 || in & 1:
handle_interrupt (usb & 4, in & 1)
action = true
unsigned out = UDC_INTROUT
if out & 2: if out & 2:
irq_out () irq_out ()
action = true
if !action:
// No more interrupts to handle; this is normal, because we're looping until this happens.
//Iris::debug ("irq done\n")
return
Iris::Num start (): Iris::Num start ():
map_udc () map_udc ()