diff --git a/firmware/src/os/pcd_enumerate.c b/firmware/src/os/pcd_enumerate.c
index 3a7397f..fc27737 100644
--- a/firmware/src/os/pcd_enumerate.c
+++ b/firmware/src/os/pcd_enumerate.c
@@ -137,12 +137,13 @@ void udp_unthrottle(void)
 	pUDP->UDP_IER = AT91C_UDP_EPINT1;
 }
 
-static int __udp_refill_ep(int ep)
+int udp_refill_ep(int ep)
 {
 	u_int16_t i;
 	AT91PS_UDP pUDP = upcd.pUdp;
 	struct req_ctx *rctx;
 	unsigned int start, end;
+	unsigned long flags;
 
 	/* If we're not configured by the host yet, there is no point
 	 * in trying to send data to it... */
@@ -156,6 +157,8 @@ static int __udp_refill_ep(int ep)
 		return -EBUSY;
 	}
 
+	pUDP->UDP_IDR |= 1 << ep;
+
 	/* If we have an incompletely-transmitted req_ctx (>EP size),
 	 * we need to transmit the rest and finish the transaction */
 	if (upcd.ep[ep].incomplete.rctx) {
@@ -163,33 +166,45 @@ static int __udp_refill_ep(int ep)
 		start = upcd.ep[ep].incomplete.bytes_sent;
 	} else {
 		/* get pending rctx and start transmitting from zero */
+	local_irq_save(flags);
 		rctx = req_ctx_find_get(0, epstate[ep].state_pending, 
 					epstate[ep].state_busy);
-		if (!rctx)
-			return 0;
+	local_irq_restore(flags);
+	if (!rctx) {
+	  pUDP->UDP_IER |= 1 << ep;
+		  return 0;
+	}
+		if (rctx->tot_len == 0) {
+		  pUDP->UDP_IER |= 1 << ep;
+		  req_ctx_put(rctx);
+		  return 0;
+		}
+
 		start = 0;
 
 		upcd.ep[ep].incomplete.bytes_sent = 0;
 	}
 
-	if (rctx->tot_len - start <= AT91C_EP_IN_SIZE)
+	if (rctx->tot_len - start <= AT91C_EP_IN_SIZE) {
 		end = rctx->tot_len;
-	else
+	} else {
 		end = start + AT91C_EP_IN_SIZE;
+	}
 
 	/* fill FIFO/DPR */
 	DEBUGII("RCTX_tx(ep=%u,ctx=%u):%u ", ep, req_ctx_num(rctx),
 		end - start);
 	for (i = start; i < end; i++) 
-		pUDP->UDP_FDR[ep] = rctx->data[i];
+	  pUDP->UDP_FDR[ep] = rctx->data[i];
 
 	if (atomic_inc_return(&upcd.ep[ep].pkts_in_transit) == 1) {
 		/* not been transmitting before, start transmit */
 		pUDP->UDP_CSR[ep] |= AT91C_UDP_TXPKTRDY;
 	}
-
-	if ((end - start < AT91C_EP_OUT_SIZE) ||
-	    (((end - start) == 0) && end && (rctx->tot_len % AT91C_EP_OUT_SIZE) == 0)) {
+	
+	if (end == rctx->tot_len) {
+	//	if ((end == rctx->tot_len && end - start <= AT91C_EP_OUT_SIZE) ||
+	//	    (((end - start) == 0) && end && (rctx->tot_len % AT91C_EP_OUT_SIZE) == 0)) {
 		/* CASE 1: return context to pool, if
 		 * - packet transfer < AT91C_EP_OUT_SIZE
 		 * - after ZLP of transfer == AT91C_EP_OUT_SIZE
@@ -209,10 +224,10 @@ static int __udp_refill_ep(int ep)
 		upcd.ep[ep].incomplete.bytes_sent += end - start;
 		DEBUGII("RCTX(ep=%u)_tx_cont ", ep);
 	}
-
+	pUDP->UDP_IER |= 1 << ep;
 	return 1;
 }
-
+/*
 int udp_refill_ep(int ep)
 {
 	unsigned long flags;
@@ -223,7 +238,7 @@ int udp_refill_ep(int ep)
 	local_irq_restore(flags);
 
 	return ret;
-}
+} */
 
 static void udp_irq(void)
 {
@@ -359,7 +374,7 @@ cont_ep2:
 			if (atomic_dec_return(&upcd.ep[2].pkts_in_transit) == 1)
 				pUDP->UDP_CSR[2] |= AT91C_UDP_TXPKTRDY;
 
-			__udp_refill_ep(2);
+			udp_refill_ep(2);
 		}
 	}
 	if (isr & AT91C_UDP_EPINT3) {
@@ -374,7 +389,7 @@ cont_ep2:
 			if (atomic_dec_return(&upcd.ep[3].pkts_in_transit) == 1)
 				pUDP->UDP_CSR[3] |= AT91C_UDP_TXPKTRDY;
 
-			__udp_refill_ep(3);
+			udp_refill_ep(3);
 		}
 	}
 	if (isr & AT91C_UDP_RXSUSP) {
diff --git a/firmware/src/os/req_ctx.c b/firmware/src/os/req_ctx.c
index cc8d57b..62dc847 100644
--- a/firmware/src/os/req_ctx.c
+++ b/firmware/src/os/req_ctx.c
@@ -27,7 +27,11 @@
 #include "../openpcd.h"
 
 /* FIXME: locking, FIFO order processing */
+#define NUM_RCTX_SMALL 18
+#define NUM_RCTX_LARGE 2
 
+// 8 * 128 + 4 * 2048 =>   18 * 270 + 2 * 2048
+/*
 #if defined(__AT91SAM7S64__) || defined(RUN_FROM_RAM)
 #define NUM_RCTX_SMALL 16
 #define NUM_RCTX_LARGE 1
@@ -35,7 +39,7 @@
 #define NUM_RCTX_SMALL 8
 #define NUM_RCTX_LARGE 4
 #endif
-
+*/
 #define NUM_REQ_CTX	(NUM_RCTX_SMALL+NUM_RCTX_LARGE)
 
 static u_int8_t rctx_data[NUM_RCTX_SMALL][RCTX_SIZE_SMALL];
diff --git a/firmware/src/os/req_ctx.h b/firmware/src/os/req_ctx.h
index 94b5c5a..dc3e8d4 100644
--- a/firmware/src/os/req_ctx.h
+++ b/firmware/src/os/req_ctx.h
@@ -1,8 +1,11 @@
 #ifndef _REQ_CTX_H
 #define _REQ_CTX_H
 
-#define RCTX_SIZE_LARGE	2048
-#define RCTX_SIZE_SMALL	128
+//#define RCTX_SIZE_LARGE	2048
+//#define RCTX_SIZE_SMALL	128
+
+#define RCTX_SIZE_LARGE       2048
+#define RCTX_SIZE_SMALL       270
 
 #define MAX_HDRSIZE	sizeof(struct openpcd_hdr)
 #define MAX_REQSIZE	(64-MAX_HDRSIZE)
diff --git a/firmware/src/simtrace/iso7816_uart.c b/firmware/src/simtrace/iso7816_uart.c
index 52522c0..a9db063 100644
--- a/firmware/src/simtrace/iso7816_uart.c
+++ b/firmware/src/simtrace/iso7816_uart.c
@@ -124,7 +124,13 @@ static const u_int8_t di_table[] = {
 	0, 1, 2, 4, 8, 16, 32, 64,
 	12, 20, 2, 4, 8, 16, 32, 64,
 };
+void iso_uart_report_overrun(void) {
+  static unsigned lastOverrun = 0;
+  if (isoh.stats.overrun != lastOverrun) {
+    DEBUGPCRF("overrun: %u", lastOverrun = isoh.stats.overrun);
+  }
 
+}
 void iso_uart_stats_dump(void)
 {
 	DEBUGPCRF("no_rctx: %u, rctx_sent: %u, rst: %u, pps: %u, bytes: %u, "
diff --git a/firmware/src/simtrace/main_simtrace.c b/firmware/src/simtrace/main_simtrace.c
index 6f82d96..8e9bf34 100644
--- a/firmware/src/simtrace/main_simtrace.c
+++ b/firmware/src/simtrace/main_simtrace.c
@@ -225,4 +225,5 @@ void _main_func(void)
 	usb_in_process();
 
 	udp_unthrottle();
+	iso_uart_report_overrun();
 }
