Index: firmware/usbstack/usb_core.c =================================================================== --- firmware/usbstack/usb_core.c (revision 16230) +++ firmware/usbstack/usb_core.c (working copy) @@ -23,10 +23,10 @@ //#define LOGF_ENABLE #include "logf.h" -//#define USB_STORAGE +#define USB_STORAGE //#define USB_SERIAL //#define USB_BENCHMARK -#define USB_CHARGING_ONLY +//#define USB_CHARGING_ONLY #include "usb_ch9.h" #include "usb_drv.h" @@ -136,7 +136,7 @@ .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = EP_TX | USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = 512, + .wMaxPacketSize = 64, .bInterval = 0 }, { @@ -144,7 +144,7 @@ .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = EP_RX | USB_DIR_OUT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = 512, + .wMaxPacketSize = 64, .bInterval = 0 } #endif Index: firmware/usbstack/usb_storage.c =================================================================== --- firmware/usbstack/usb_storage.c (revision 16230) +++ firmware/usbstack/usb_storage.c (working copy) @@ -46,6 +46,7 @@ #define SCSI_WRITE_10 0x2a #define SCSI_STATUS_GOOD 0x00 +#define SCSI_STATUS_FAIL 0x00 #define SCSI_STATUS_CHECK_CONDITION 0x02 @@ -85,7 +86,7 @@ } __attribute__ ((packed)); /* the ARC USB controller can at most buffer 16KB unaligned data */ -static unsigned char _transfer_buffer[16384]; +static unsigned char _transfer_buffer[16384*8]; static unsigned char* transfer_buffer; static struct inquiry_data _inquiry; static struct inquiry_data* inquiry; @@ -118,6 +119,7 @@ transfer_buffer = (void*)UNCACHED_ADDR(&_transfer_buffer); capacity_data = (void*)UNCACHED_ADDR(&_capacity_data); identify2inquiry(); + state = IDLE; } /* called by usb_core_transfer_complete() */ @@ -128,21 +130,31 @@ switch (endpoint) { case EP_RX: //logf("ums: %d bytes in", length); - switch (state) { - case IDLE: - handle_scsi(cbw); - break; + if(state == RECEIVING) + { + logf("scsi write %d %d", current_cmd.sector, current_cmd.count); - default: - break; + ata_write_sectors(IF_MV2(0,) current_cmd.sector, current_cmd.count, + transfer_buffer); + send_csw(current_cmd.tag, SCSI_STATUS_GOOD); } - - /* re-prime endpoint */ - usb_drv_recv(EP_RX, transfer_buffer, sizeof _transfer_buffer); + else + { + state = SENDING; + handle_scsi(cbw); + } + break; case EP_TX: - //logf("ums: %d bytes out", length); + //logf("ums: out complete"); + if(state != IDLE) + { + /* re-prime endpoint */ + state = IDLE; + usb_drv_recv(EP_RX, transfer_buffer, 16384/*sizeof _transfer_buffer*/); + } + break; } } @@ -156,7 +168,7 @@ switch (req->bRequest) { case USB_BULK_GET_MAX_LUN: { - static char maxlun = 0; + static char maxlun = 0;//NUM_VOLUMES - 1; logf("ums: getmaxlun"); usb_drv_send(EP_CONTROL, UNCACHED_ADDR(&maxlun), 1); usb_drv_recv(EP_CONTROL, NULL, 0); /* ack */ @@ -175,7 +187,8 @@ case USB_REQ_SET_CONFIGURATION: logf("ums: set config"); /* prime rx endpoint */ - usb_drv_recv(EP_RX, transfer_buffer, sizeof _transfer_buffer); + state = IDLE; + usb_drv_recv(EP_RX, transfer_buffer, 16384/*sizeof _transfer_buffer*/); handled = true; break; } @@ -190,7 +203,17 @@ /* USB Mass Storage assumes LBA capability. TODO: support 48-bit LBA */ + unsigned int sectors_per_transfer; unsigned int length = cbw->data_transfer_length; + unsigned int block_size; + unsigned char lun = cbw->lun; +#ifdef HAVE_FLASH_STORAGE + tCardInfo* cinfo = card_get_info(lun); + block_size = cinfo->blocksize; +#else + block_size = SECTOR_SIZE; +#endif + sectors_per_transfer=(sizeof _transfer_buffer/ block_size); switch (cbw->command_block[0]) { case SCSI_TEST_UNIT_READY: @@ -222,13 +245,15 @@ case SCSI_READ_CAPACITY: { logf("scsi read_capacity"); #ifdef HAVE_FLASH_STORAGE - tCardInfo* cinfo = card_get_info(0); - capacity_data->block_count = htobe32(cinfo->numblocks); + // tCardInfo* cinfo = card_get_info(0); + // Careful : "block count" actually means the number of the last block + capacity_data->block_count = htobe32(cinfo->numblocks - 1); capacity_data->block_size = htobe32(cinfo->blocksize); #else unsigned short* identify = ata_get_identify(); - capacity_data->block_count = htobe32(identify[60] << 16 | identify[61]); - capacity_data->block_size = htobe32(SECTOR_SIZE); + // Careful : "block count" actually means the number of the last block + capacity_data->block_count = htobe32((identify[61] << 16 | identify[60]) - 1); + capacity_data->block_size = htobe32(block_size); #endif usb_drv_send(EP_TX, capacity_data, MIN(sizeof _capacity_data, length)); @@ -250,25 +275,41 @@ logf("scsi read %d %d", current_cmd.sector, current_cmd.count); - /* too much? */ - if (current_cmd.count > (sizeof _transfer_buffer / SECTOR_SIZE)) { - send_csw(current_cmd.tag, SCSI_STATUS_CHECK_CONDITION); - break; + logf("Asked for %d sectors",current_cmd.count); + if(current_cmd.count > sectors_per_transfer) + { + current_cmd.count = sectors_per_transfer; } + logf("Sending %d sectors",current_cmd.count); - ata_read_sectors(IF_MV2(0,) current_cmd.sector, current_cmd.count, + ata_read_sectors(IF_MV2(lun,) current_cmd.sector, current_cmd.count, transfer_buffer); - state = SENDING; - usb_drv_send(EP_TX, transfer_buffer, - MIN(current_cmd.count * SECTOR_SIZE, length)); + usb_drv_send(EP_TX, transfer_buffer, current_cmd.count*block_size); + send_csw(current_cmd.tag, SCSI_STATUS_GOOD); break; case SCSI_WRITE_10: logf("scsi write10"); + current_cmd.sector = + cbw->command_block[2] << 24 | + cbw->command_block[3] << 16 | + cbw->command_block[4] << 8 | + cbw->command_block[5] ; + current_cmd.count = + cbw->command_block[7] << 16 | + cbw->command_block[8]; + current_cmd.offset = 0; + current_cmd.tag = cbw->tag; + // expect data + usb_drv_recv(EP_RX, transfer_buffer,current_cmd.count*block_size); + state = RECEIVING; + break; default: logf("scsi unknown cmd %x", cbw->command_block[0]); + usb_drv_stall(EP_TX, true); + send_csw(current_cmd.tag, SCSI_STATUS_FAIL); break; } } Index: firmware/target/arm/usb-fw-pp502x.c =================================================================== --- firmware/target/arm/usb-fw-pp502x.c (revision 16230) +++ firmware/target/arm/usb-fw-pp502x.c (working copy) @@ -57,6 +57,8 @@ void usb_enable(bool on) { if (on) { + usb_core_init(); +#if 0 /* until we have native mass-storage mode, we want to reboot on usb host connect */ #if defined(IRIVER_H10) || defined (IRIVER_H10_5GB) @@ -78,6 +80,7 @@ system_reboot(); /* Reboot */ } +#endif } else usb_core_exit(); Index: firmware/target/arm/usb-drv-pp502x.c =================================================================== --- firmware/target/arm/usb-drv-pp502x.c (revision 16230) +++ firmware/target/arm/usb-drv-pp502x.c (working copy) @@ -295,7 +295,9 @@ } __attribute__ ((packed)); static struct transfer_descriptor _td_array[NUM_ENDPOINTS*2] __attribute((aligned (32))); +static struct transfer_descriptor _extra_td_array[32] __attribute((aligned (32))); static struct transfer_descriptor* td_array; +static struct transfer_descriptor* extra_td_array; /* manual: 32.13.1 Endpoint Queue Head (dQH) */ struct queue_head { @@ -320,6 +322,7 @@ /*-------------------------------------------------------------------------*/ static void transfer_completed(void); static int prime_transfer(int endpoint, void* ptr, int len, bool send); +static void prepare_td(struct transfer_descriptor* td,struct transfer_descriptor* previous_td,void *ptr, int len); static void bus_reset(void); static void init_queue_heads(void); static void init_endpoints(void); @@ -340,7 +343,12 @@ REG_USBMODE = USBMODE_CTRL_MODE_DEVICE; + // Force device to full speed to see if that works better + // See 32.9.5.9.2 + REG_PORTSC1 |= PORTSCX_PORT_FORCE_FULL_SPEED; + td_array = (struct transfer_descriptor*)UNCACHED_ADDR(&_td_array); + extra_td_array = (struct transfer_descriptor*)UNCACHED_ADDR(&_extra_td_array); qh_array = (struct queue_head*)UNCACHED_ADDR(&_qh_array); init_queue_heads(); memset(td_array, 0, sizeof _td_array); @@ -490,24 +498,40 @@ int timeout; int pipe = endpoint * 2 + (send ? 1 : 0); unsigned int mask = pipe2mask[pipe]; - struct transfer_descriptor* td = &td_array[pipe]; + struct transfer_descriptor* first_td; + struct transfer_descriptor* last_td = 0; struct queue_head* qh = &qh_array[pipe]; if (send && endpoint > EP_CONTROL) { logf("usb: sent %d bytes", len); } - memset(td, 0, sizeof(struct transfer_descriptor)); - td->next_td_ptr = DTD_NEXT_TERMINATE; - td->size_ioc_sts = (len << DTD_LENGTH_BIT_POS) | - DTD_STATUS_ACTIVE | DTD_IOC; - td->buff_ptr0 = (unsigned int)ptr; - td->buff_ptr1 = (unsigned int)ptr + 0x1000; - td->buff_ptr2 = (unsigned int)ptr + 0x2000; - td->buff_ptr3 = (unsigned int)ptr + 0x3000; - td->buff_ptr4 = (unsigned int)ptr + 0x4000; - td->reserved = len; - qh->dtd.next_td_ptr = (unsigned int)td; + if(len==0) + { + struct transfer_descriptor* new_td = &extra_td_array[0]; + prepare_td(new_td,0,ptr,0); + + last_td=new_td; + first_td=new_td; + } + else + { + int td_idx=0; + while(len>0) + { + int current_transfer_length = MIN(16384,len); + struct transfer_descriptor* new_td = &extra_td_array[td_idx]; + prepare_td(new_td,last_td,ptr,current_transfer_length); + + last_td=new_td; + len-=current_transfer_length; + td_idx++; + ptr+=current_transfer_length; + } + first_td=&extra_td_array[0]; + } + + qh->dtd.next_td_ptr = (unsigned int)first_td; qh->dtd.size_ioc_sts &= ~(QH_STATUS_HALT | QH_STATUS_ACTIVE); REG_ENDPTPRIME |= mask; @@ -521,7 +545,6 @@ logf("prime timeout"); return -2; } - if (!(REG_ENDPTSTATUS & mask)) { logf("no prime! %d %d %x", endpoint, pipe, qh->dtd.size_ioc_sts & 0xff ); return -3; @@ -530,22 +553,54 @@ if (send) { /* wait for transfer to finish */ timeout = 100000; - while ((td->size_ioc_sts & DTD_STATUS_ACTIVE) && --timeout) { - if (REG_ENDPTCOMPLETE & mask) - REG_ENDPTCOMPLETE |= mask; - if (REG_USBSTS & USBSTS_RESET) - return -4; + struct transfer_descriptor* current_td = first_td; + while(!((unsigned int)current_td & DTD_NEXT_TERMINATE)) + { + while ((current_td->size_ioc_sts & DTD_STATUS_ACTIVE) && --timeout) { + if (REG_ENDPTCOMPLETE & mask) + REG_ENDPTCOMPLETE |= mask; + + if (REG_USBSTS & USBSTS_RESET) + { + logf("td interrupted by reset"); + return -4; + } + } + if (!timeout) { + logf("td never finished"); + logf("status = %X",qh->dtd.size_ioc_sts&0xff); + return -5; + } + logf("td finished : %X",current_td->size_ioc_sts & 0xff); + current_td=(struct transfer_descriptor*)current_td->next_td_ptr; } - if (!timeout) { - logf("td never finished"); - return -5; - } + logf("all tds done"); } return 0; } +static void prepare_td(struct transfer_descriptor* td,struct transfer_descriptor* previous_td,void *ptr, int len) +{ + logf("adding a td : %d",len); + memset(td, 0, sizeof(struct transfer_descriptor)); + td->next_td_ptr = DTD_NEXT_TERMINATE; + td->size_ioc_sts = (len<< DTD_LENGTH_BIT_POS) | + DTD_STATUS_ACTIVE | DTD_IOC; + td->buff_ptr0 = (unsigned int)ptr; + td->buff_ptr1 = ((unsigned int)ptr & 0xfffff000) + 0x1000; + td->buff_ptr2 = ((unsigned int)ptr & 0xfffff000) + 0x2000; + td->buff_ptr3 = ((unsigned int)ptr & 0xfffff000) + 0x3000; + td->buff_ptr4 = ((unsigned int)ptr & 0xfffff000) + 0x4000; + + if(previous_td != 0) + { + previous_td->next_td_ptr=(unsigned int)td; + previous_td->size_ioc_sts&=~DTD_IOC;// Only an interrupt on the last one + } +} + static void transfer_completed(void) { int i; @@ -608,15 +663,15 @@ memset(qh_array, 0, sizeof _qh_array); /*** control ***/ - qh_array[EP_CONTROL].max_pkt_length = 512 << QH_MAX_PKT_LEN_POS | QH_IOS; + qh_array[EP_CONTROL].max_pkt_length = 64 << QH_MAX_PKT_LEN_POS | QH_IOS; qh_array[EP_CONTROL].dtd.next_td_ptr = QH_NEXT_TERMINATE; - qh_array[EP_CONTROL+1].max_pkt_length = 512 << QH_MAX_PKT_LEN_POS; + qh_array[EP_CONTROL+1].max_pkt_length = 64 << QH_MAX_PKT_LEN_POS; qh_array[EP_CONTROL+1].dtd.next_td_ptr = QH_NEXT_TERMINATE; /*** bulk ***/ - qh_array[EP_RX*2].max_pkt_length = 512 << QH_MAX_PKT_LEN_POS; + qh_array[EP_RX*2].max_pkt_length = 64 << QH_MAX_PKT_LEN_POS | QH_ZLT_SEL; qh_array[EP_RX*2].dtd.next_td_ptr = QH_NEXT_TERMINATE; - qh_array[EP_TX*2+1].max_pkt_length = 512 << QH_MAX_PKT_LEN_POS; + qh_array[EP_TX*2+1].max_pkt_length = 64 << QH_MAX_PKT_LEN_POS | QH_ZLT_SEL; qh_array[EP_TX*2+1].dtd.next_td_ptr = QH_NEXT_TERMINATE; }