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) @@ -103,6 +103,7 @@ void handle_scsi(struct command_block_wrapper* cbw); void send_csw(unsigned int tag, int status); + void send_csw_residue(unsigned int tag, int status,unsigned int residue); static void identify2inquiry(void); static enum { @@ -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,22 +130,17 @@ switch (endpoint) { case EP_RX: //logf("ums: %d bytes in", length); - switch (state) { - case IDLE: - handle_scsi(cbw); - break; + state = SENDING; + handle_scsi(cbw); - default: - break; - } + break; + case EP_TX: + //logf("ums: out complete"); + state = IDLE; /* re-prime endpoint */ usb_drv_recv(EP_RX, transfer_buffer, sizeof _transfer_buffer); break; - - case EP_TX: - //logf("ums: %d bytes out", length); - break; } } @@ -190,7 +187,16 @@ /* 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; +#ifdef HAVE_FLASH_STORAGE + tCardInfo* cinfo = card_get_info(0); + block_size = cinfo->blocksize; +#else + block_size = blocksize; +#endif + sectors_per_transfer=(sizeof _transfer_buffer/ block_size); switch (cbw->command_block[0]) { case SCSI_TEST_UNIT_READY: @@ -222,12 +228,14 @@ 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]); + // Careful : "block count" actually means the number of the last block + capacity_data->block_count = htobe32((identify[60] << 16 | identify[61]) - 1); capacity_data->block_size = htobe32(SECTOR_SIZE); #endif usb_drv_send(EP_TX, capacity_data, @@ -250,17 +258,17 @@ 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, 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_residue(current_cmd.tag, SCSI_STATUS_GOOD,length-current_cmd.count*block_size); break; case SCSI_WRITE_10: @@ -273,6 +281,19 @@ } } +void send_csw_residue(unsigned int tag, int status,unsigned int residue) +{ + static struct command_status_wrapper _csw; + struct command_status_wrapper* csw = UNCACHED_ADDR(&_csw); + csw->signature = CSW_SIGNATURE; + csw->tag = tag; + csw->data_residue = residue; + csw->status = status; + + //logf("csw %x %x", csw->tag, csw->signature); + usb_drv_send(EP_TX, csw, sizeof _csw); +} + void send_csw(unsigned int tag, int status) { static struct command_status_wrapper _csw; 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) @@ -340,6 +340,10 @@ 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); qh_array = (struct queue_head*)UNCACHED_ADDR(&_qh_array); init_queue_heads(); @@ -502,11 +506,11 @@ 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; + 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; + //td->reserved = len; qh->dtd.next_td_ptr = (unsigned int)td; qh->dtd.size_ioc_sts &= ~(QH_STATUS_HALT | QH_STATUS_ACTIVE); @@ -608,15 +612,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_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_array[EP_TX*2+1].dtd.next_td_ptr = QH_NEXT_TERMINATE; }