diff --git a/firmware/export/config/rk27generic.h b/firmware/export/config/rk27generic.h
index 69c3330..cb0e825 100644
--- a/firmware/export/config/rk27generic.h
+++ b/firmware/export/config/rk27generic.h
@@ -54,7 +54,7 @@
/* define this if you have a flash memory storage */
#define HAVE_FLASH_STORAGE
-#define CONFIG_STORAGE (STORAGE_SD | STORAGE_NAND)
+#define CONFIG_STORAGE (STORAGE_SD /*| STORAGE_NAND*/)
#define CONFIG_NAND NAND_RK27XX
#define HAVE_SW_TONE_CONTROLS
diff --git a/firmware/export/logf.h b/firmware/export/logf.h
index b57ae91..48cfae8 100644
--- a/firmware/export/logf.h
+++ b/firmware/export/logf.h
@@ -29,7 +29,7 @@
#ifndef __PCTOOL__
-#define MAX_LOGF_SIZE 16384
+#define MAX_LOGF_SIZE 163840
extern unsigned char logfbuffer[MAX_LOGF_SIZE];
extern int logfindex;
diff --git a/firmware/export/rk27xx.h b/firmware/export/rk27xx.h
index 3ca2bc0..0a56536 100644
--- a/firmware/export/rk27xx.h
+++ b/firmware/export/rk27xx.h
@@ -8,7 +8,8 @@
#define FLASH_BANK1 0x11000000
#define USB_NUM_ENDPOINTS 16
-#define USB_DEVBSS_ATTR
+/* cache aligned */
+#define USB_DEVBSS_ATTR __attribute__((aligned(32)))
/* Timers */
#define APB0_TIMER (ARM_BUS0_BASE + 0x00000000)
@@ -731,6 +732,7 @@
#define RXVOIDINTEN (1<<5)
#define RXERRINTEN (1<<6)
#define RXACKINTEN (1<<7)
+#define RXCFINTE (1<<12)
/* bits 31:8 reserved for EP0 */
/* bits 31:14 reserved for others */
@@ -753,6 +755,7 @@
#define TXERRINTEN (1<<5)
#define TXACKINTEN (1<<6)
#define TXDMADNEN (1<<7) /* reserved for EP0 */
+#define TXCFINTE (1<<12)
/* bits 31:8 reserved */
/* TXnBUF bits */
diff --git a/firmware/target/arm/rk27xx/usb-drv-rk27xx.c b/firmware/target/arm/rk27xx/usb-drv-rk27xx.c
index 810c793..7058612 100644
--- a/firmware/target/arm/rk27xx/usb-drv-rk27xx.c
+++ b/firmware/target/arm/rk27xx/usb-drv-rk27xx.c
@@ -170,48 +170,112 @@ static void ctr_read(void)
RX0DMACTLO = DMA_START; /* start DMA */
}
-static void blk_write(int ep)
+static void blk_write(int ep_num)
{
- int ep_num = EP_NUM(ep);
- int max = usb_drv_port_speed() ? 512 : 64;
- int xfer_size = (endpoints[ep_num].cnt > max) ? max : endpoints[ep_num].cnt;
unsigned int timeout = current_tick + HZ/10;
-
+ int max = usb_drv_port_speed() ? 512 : 64;
+ int xfer_size = (endpoints[ep_num].cnt > max) ? max : endpoints[ep_num].cnt;
+
while (BIN_TXBUF(ep_num) & TXFULL) /* TXFULL flag */
{
if(TIME_AFTER(current_tick, timeout))
break;
}
-
+
BIN_TXSTAT(ep_num) = xfer_size; /* size */
BIN_DMAINLMADDR(ep_num) = (uint32_t)endpoints[ep_num].buf; /* buf address */
BIN_DMAINCTL(ep_num) = DMA_START; /* start DMA */
BIN_TXCON(ep_num) &= ~TXNAK; /* clear NAK */
-
+
/* Decrement by max packet size is intentional.
- * This way if we have final packet short one we will get negative len
- * after transfer, which in turn indicates we *don't* need to send
- * zero length packet. If the final packet is max sized packet we will
- * get zero len after transfer which indicates we need to send
- * zero length packet to signal host end of the transfer.
- */
+ * This way if we have final packet short one we will get negative len
+ * after transfer, which in turn indicates we *don't* need to send
+ * zero length packet. If the final packet is max sized packet we will
+ * get zero len after transfer which indicates we need to send
+ * zero length packet to signal host end of the transfer.
+ */
endpoints[ep_num].cnt -= max;
endpoints[ep_num].buf += xfer_size;
}
-static void blk_read(int ep)
+static void blk_write_int(int ep_num)
{
- int ep_num = EP_NUM(ep);
- int xfer_size = BOUT_RXSTAT(ep_num) & 0xffff;
-
- /* clear NAK bit */
- BOUT_RXCON(ep_num) &= ~RXNAK;
-
- endpoints[ep_num].cnt -= xfer_size;
- endpoints[ep_num].buf += xfer_size;
-
- BOUT_DMAOUTLMADDR(ep_num) = (uint32_t)endpoints[ep_num].buf;
- BOUT_DMAOUTCTL(ep_num) = DMA_START;
+ uint32_t txstat = BIN_TXSTAT(ep_num);
+ struct endpoint_t *endp = &endpoints[ep_num];
+
+ if(txstat & TXCFINT)
+ {
+ logf("blk_write:cf(0x%x), %ld", ep_num, current_tick);
+ /* bit cleared by read */
+ usb_drv_stall(ep_num, false, true);
+ }
+
+ if (txstat & TXACK) /* check TxACK flag */
+ {
+ if (endp->cnt > 0)
+ {
+ logf("blk_write:ack(0x%x), %ld", ep_num, current_tick);
+ /* we still have data to send (or ZLP) */
+ blk_write(ep_num);
+ }
+ else
+ {
+ logf("udc_intr: usb_core_transfer_complete(0x%x, USB_DIR_IN, 0, 0x%x), %ld", ep_num, endp->len, current_tick);
+ /* final ack received */
+ usb_core_transfer_complete(ep_num, /* ep */
+ USB_DIR_IN, /* dir */
+ 0, /* status */
+ endp->len); /* length */
+
+ /* release semaphore for blocking transfer */
+ if (endp->block)
+ {
+ logf("udc_intr: ep=0x%x, semaphore_release(), %ld", ep_num, current_tick);
+ semaphore_release(&endp->complete);
+ }
+ }
+ }
+}
+
+static void blk_read_int(int ep_num)
+{
+ uint32_t rxstat = BOUT_RXSTAT(ep_num);
+ int xfer_size = rxstat & 0xffff;
+ int max = usb_drv_port_speed() ? 512 : 64;
+ struct endpoint_t *endp = &endpoints[ep_num];
+
+ if(rxstat & RXCFINT)
+ {
+ logf("blk_read:cf(0x%x), %ld", ep_num, current_tick);
+ /* bit cleared by read */
+ usb_drv_stall(ep_num, false, false);
+ }
+
+ if((rxstat & RXACK) && endp->cnt > 0)
+ {
+ logf("blk_read:ack(0x%x,0x%x), %ld", ep_num, xfer_size, current_tick);
+ /* clear NAK bit */
+ BOUT_RXCON(ep_num) &= ~RXNAK;
+
+ endp->cnt -= xfer_size;
+ endp->buf += xfer_size;
+
+ /* if the transfer was short or if the total count is zero, transfer is complete */
+ if (endp->cnt == 0 || xfer_size < max)
+ {
+ logf("udc_intr: usb_core_transfer_complete(0x%x, USB_DIR_OUT, 0, 0x%x), %ld", ep_num, endp->len, current_tick);
+ usb_core_transfer_complete(ep_num, /* ep */
+ USB_DIR_OUT, /* dir */
+ 0, /* status */
+ endp->len - endp->cnt); /* length */
+ endp->cnt = 0;
+ }
+ else
+ {
+ BOUT_DMAOUTLMADDR(ep_num) = (uint32_t)endp->buf;
+ BOUT_DMAOUTCTL(ep_num) = DMA_START;
+ }
+ }
}
static void int_write(int ep)
@@ -387,17 +451,20 @@ void INT_UDC(void)
if (intsrc & CONN_INTR) /* usb connect */
{
-// if (DEV_INFO & VBUS_STS)
-// {
+ if (DEV_INFO & VBUS_STS)
+ {
udc_phy_reset();
udelay(10000);
udc_soft_connect();
udc_conn = 1;
usb_status_event(USB_INSERTED);
-// }
-// else
-// udc_conn = 0;
+ }
+ else
+ {
+ udc_conn = 0;
+ usb_status_event(USB_EXTRACTED);
+ }
}
/* TODO this needs rework */
@@ -414,60 +481,10 @@ void INT_UDC(void)
{
case USB_ENDPOINT_XFER_BULK:
if (ep->dir == DIR_OUT)
- {
/* bulk out */
- rxstat = BOUT_RXSTAT(ep_num);
-
- /* TODO handle errors */
- if (rxstat & RXACK) /* RxACK */
- {
- if (ep->cnt > 0)
- {
- logf("udc_intr: blk_read(0x%x), %ld", ep_num, current_tick);
- blk_read(ep_num);
- }
- else
- {
- logf("udc_intr: usb_core_transfer_complete(0x%x, USB_DIR_OUT, 0, 0x%x), %ld", ep_num, ep->len, current_tick);
- usb_core_transfer_complete(ep_num, /* ep */
- USB_DIR_OUT, /* dir */
- 0, /* status */
- ep->len); /* length */
- }
- }
- }
+ blk_read_int(ep_num);
else
- {
- /* bulk in */
- txstat = BIN_TXSTAT(ep_num);
-
- /* TODO handle errors */
- if (txstat & TXACK) /* check TxACK flag */
- {
- if (ep->cnt >= 0)
- {
- logf("udc_intr: blk_write(0x%x), %ld", ep_num, current_tick);
- /* we still have data to send (or ZLP) */
- blk_write(ep_num);
- }
- else
- {
- logf("udc_intr: usb_core_transfer_complete(0x%x, USB_DIR_IN, 0, 0x%x), %ld", ep_num, ep->len, current_tick);
- /* final ack received */
- usb_core_transfer_complete(ep_num, /* ep */
- USB_DIR_IN, /* dir */
- 0, /* status */
- ep->len); /* length */
-
- /* release semaphore for blocking transfer */
- if (ep->block)
- {
- logf("udc_intr: ep=0x%x, semaphore_release(), %ld", ep_num, current_tick);
- semaphore_release(&ep->complete);
- }
- }
- }
- }
+ blk_write_int(ep_num);
break;
case USB_ENDPOINT_XFER_INT:
@@ -534,15 +551,15 @@ int usb_drv_request_endpoint(int type, int dir)
if (ep_num%3 == 0) /* IIN 3, 6, 9, 12, 15 */
{
- IIN_TXCON(ep_num) = (ep_num<<8)|TXEPEN|TXNAK; /* ep_num, enable, NAK */
+ IIN_TXCON(ep_num) = (ep_num<<8)|TXEPEN|TXNAK|TXACKINTEN|TXCFINTE;
}
else if (ep_num%3 == 1) /* BOUT 1, 4, 7, 10, 13 */
{
- BOUT_RXCON(ep_num) = (ep_num<<8)|RXEPEN|RXNAK; /* ep_num, NAK, enable */
+ BOUT_RXCON(ep_num) = (ep_num<<8)|RXEPEN|RXNAK|RXACKINTEN|RXCFINTE;
}
else if (ep_num%3 == 2) /* BIN 2, 5, 8, 11, 14 */
{
- BIN_TXCON(ep_num) = (ep_num<<8)|TXEPEN|TXNAK; /* ep_num, enable, NAK */
+ BIN_TXCON(ep_num) = (ep_num<<8)|TXEPEN|TXNAK|TXACKINTEN|TXCFINTE;
}
/* enable interrupt from this endpoint */
@@ -586,6 +603,12 @@ static int _usb_drv_send(int endpoint, void *ptr, int length, bool block)
struct endpoint_t *ep;
int ep_num = EP_NUM(endpoint);
+ /* for send transfers, make sure the data is committed
+ * for recv, I don't know how to simply discard the cache so commit and
+ * pray that no-one will read it in between */
+ //commit_discard_dcache_range(ptr, length);
+ commit_discard_idcache();
+
logf("_usb_drv_send: endpt=0x%x, len=0x%x, block=%d", endpoint, length, block);
if (ep_num == 0)
ep = &ctrlep[DIR_IN];
@@ -602,7 +625,7 @@ static int _usb_drv_send(int endpoint, void *ptr, int length, bool block)
switch (ep->type)
{
- case USB_ENDPOINT_XFER_CONTROL:
+ case USB_ENDPOINT_XFER_CONTROL:
ctr_write();
break;
@@ -724,6 +747,7 @@ bool usb_drv_stalled(int endpoint, bool in)
void usb_drv_stall(int endpoint, bool stall, bool in)
{
int ep_num = EP_NUM(endpoint);
+ logf("usb_drv: %sstall EP%d %s", stall ? "": "un", ep_num, in ? "IN" : "OUT");
switch (endpoints[ep_num].type)
{
diff --git a/firmware/usbstack/usb_core.c b/firmware/usbstack/usb_core.c
index 8dc5969..0703036 100644
--- a/firmware/usbstack/usb_core.c
+++ b/firmware/usbstack/usb_core.c
@@ -686,6 +686,16 @@ static void usb_core_do_set_config(uint8_t config)
#endif
}
+static void usb_core_do_clear_feature(int recip, int recip_nr, int feature)
+{
+ logf("usb_core: CLEAR FEATURE (%d,%d,%d)", recip, recip_nr, feature);
+ if(recip == USB_RECIP_ENDPOINT)
+ {
+ if(feature == USB_ENDPOINT_HALT)
+ usb_drv_stall(EP_NUM(recip_nr), false, EP_DIR(recip_nr));
+ }
+}
+
static void request_handler_device(struct usb_ctrlrequest* req)
{
switch(req->bRequest) {
@@ -808,12 +818,11 @@ static void request_handler_endpoint_standard(struct usb_ctrlrequest* req)
{
switch (req->bRequest) {
case USB_REQ_CLEAR_FEATURE:
- if(req->wValue == USB_ENDPOINT_HALT)
- usb_drv_stall(EP_NUM(req->wIndex), false, EP_DIR(req->wIndex));
-
+ usb_core_do_clear_feature(USB_RECIP_ENDPOINT, req->wIndex, req->wValue);
usb_drv_send(EP_CONTROL, NULL, 0);
break;
case USB_REQ_SET_FEATURE:
+ logf("usb_core: SET FEATURE (%d)", req->wValue);
if(req->wValue == USB_ENDPOINT_HALT)
usb_drv_stall(EP_NUM(req->wIndex), true, EP_DIR(req->wIndex));
diff --git a/firmware/usbstack/usb_storage.c b/firmware/usbstack/usb_storage.c
index dbcf4a2..d2b2a5e 100644
--- a/firmware/usbstack/usb_storage.c
+++ b/firmware/usbstack/usb_storage.c
@@ -753,6 +753,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
unsigned int block_size_mult = 1;
if(letoh32(cbw->signature) != CBW_SIGNATURE) {
+ logf("ums: bad cbw signature (%x)", cbw->signature);
usb_drv_stall(ep_in, true,true);
usb_drv_stall(ep_out, true,false);
return;
@@ -1151,6 +1152,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
default:
logf("scsi unknown cmd %x",cbw->command_block[0x0]);
+ usb_drv_stall(ep_in, true,true);
send_csw(UMS_STATUS_FAIL);
cur_sense_data.sense_key=SENSE_ILLEGAL_REQUEST;
cur_sense_data.asc=ASC_INVALID_COMMAND;