Index: firmware/usbstack/usb_storage.c =================================================================== --- firmware/usbstack/usb_storage.c (revision 20305) +++ firmware/usbstack/usb_storage.c (working copy) @@ -50,7 +50,7 @@ * transfer chaining in the driver. Tests on sansa c200 show that the 16k * limitation causes no more than 2% slowdown. */ -#define BUFFER_SIZE 16384 +#define BUFFER_SIZE 16384*4 /* bulk-only class specific requests */ #define USB_BULK_RESET_REQUEST 0xff Index: firmware/target/arm/usb-drv-arc.c =================================================================== --- firmware/target/arm/usb-drv-arc.c (revision 20305) +++ firmware/target/arm/usb-drv-arc.c (working copy) @@ -308,6 +308,10 @@ #define DTD_RESERVED_PIPE_OFFSET 20 /*-------------------------------------------------------------------------*/ +/* 4 transfer descriptors per endpoint allow 64k transfers, which is the usual MSC + transfer size, so it seems like a good size */ +#define NUM_TDS_PER_EP 4 + /* manual: 32.13.2 Endpoint Transfer Descriptor (dTD) */ struct transfer_descriptor { unsigned int next_td_ptr; /* Next TD pointer(31-5), T(0) set @@ -322,7 +326,7 @@ unsigned int reserved; } __attribute__ ((packed)); -static struct transfer_descriptor td_array[USB_NUM_ENDPOINTS*2] +static struct transfer_descriptor td_array[USB_NUM_ENDPOINTS*2*NUM_TDS_PER_EP] USB_DEVBSS_ATTR __attribute__((aligned(32))); /* manual: 32.13.1 Endpoint Queue Head (dQH) */ @@ -665,7 +669,7 @@ unsigned int mask = pipe2mask[pipe]; struct queue_head* qh = &qh_array[pipe]; static long last_tick; - struct transfer_descriptor* new_td; + struct transfer_descriptor* new_td,*cur_td,*prev_td; int oldlevel = disable_irq_save(); /* @@ -677,8 +681,21 @@ qh->length = 0; qh->wait = wait; - new_td=&td_array[pipe]; - prepare_td(new_td, 0, ptr, len,pipe); + new_td=&td_array[pipe*NUM_TDS_PER_EP]; + cur_td=new_td; + prev_td=0; + int tdlen; + + do + { + tdlen=MIN(len,16384); + prepare_td(cur_td, prev_td, ptr, tdlen,pipe); + ptr+=tdlen; + prev_td=cur_td; + cur_td++; + len-=tdlen; + } + while(len>0 ); //logf("starting ep %d %s",endpoint,send?"send":"receive"); qh->dtd.next_td_ptr = (unsigned int)new_td; @@ -807,6 +824,7 @@ if (previous_td != 0) { previous_td->next_td_ptr=(unsigned int)td; + previous_td->size_ioc_sts&=~DTD_IOC; } } @@ -845,22 +863,27 @@ int pipe = ep * 2 + dir; if (mask & pipe2mask[pipe]) { struct queue_head* qh = &qh_array[pipe]; - struct transfer_descriptor *td = &td_array[pipe]; + struct transfer_descriptor *td = &td_array[pipe*NUM_TDS_PER_EP]; - if(td->size_ioc_sts & DTD_STATUS_ACTIVE) { - /* TODO this shouldn't happen, but...*/ - break; + qh->length = 0; + while(td!=0) + { + if(td->size_ioc_sts & DTD_STATUS_ACTIVE) { + /* TODO this shouldn't happen, but...*/ + break; + } + if((td->size_ioc_sts & DTD_PACKET_SIZE) >> DTD_LENGTH_BIT_POS != 0 && dir==0) { + /* We got less data than we asked for. */ + } + qh->length += (td->reserved & DTD_RESERVED_LENGTH_MASK) - + ((td->size_ioc_sts & DTD_PACKET_SIZE) >> DTD_LENGTH_BIT_POS); + if(td->size_ioc_sts & DTD_ERROR_MASK) { + logf("pipe %d err %x", pipe, td->size_ioc_sts & DTD_ERROR_MASK); + qh->status |= td->size_ioc_sts & DTD_ERROR_MASK; + /* TODO we need to handle this somehow. Flush the endpoint ? */ + } + td=td->next_td_ptr; } - if((td->size_ioc_sts & DTD_PACKET_SIZE) >> DTD_LENGTH_BIT_POS != 0 && dir==0) { - /* We got less data than we asked for. */ - } - qh->length = (td->reserved & DTD_RESERVED_LENGTH_MASK) - - ((td->size_ioc_sts & DTD_PACKET_SIZE) >> DTD_LENGTH_BIT_POS); - if(td->size_ioc_sts & DTD_ERROR_MASK) { - logf("pipe %d err %x", pipe, td->size_ioc_sts & DTD_ERROR_MASK); - qh->status |= td->size_ioc_sts & DTD_ERROR_MASK; - /* TODO we need to handle this somehow. Flush the endpoint ? */ - } if(qh->wait) { qh->wait=0; wakeup_signal(&transfer_completion_signal[pipe]);