Am Freitag, 7. April 2006 17:44 schrieb Blue Swirl:
Hi!

The attached patch is an updated version of my previous patch. Now it applies 
cleanly to cvs head and the read and write performance is increased.

regards,
Jörg
--- esp.c	2006-04-10 14:51:37.000000000 +0200
+++ esp.c.new	2006-04-10 14:54:44.000000000 +0200
@@ -63,6 +63,8 @@
     ESPDMAFunc *dma_cb;
     int64_t offset, len;
     int target;
+    int blocksize;
+    int ti_bufstart;
 };
 
 #define STAT_DO 0x00
@@ -229,12 +231,12 @@
                             target_phys_addr_t phys_addr, 
                             int transfer_size1)
 {
+    int len = transfer_size1/s->blocksize;
     DPRINTF("Write callback (offset %lld len %lld size %d trans_size %d)\n",
             s->offset, s->len, s->ti_size, transfer_size1);
-    bdrv_write(s->bd[s->target], s->offset, s->ti_buf, s->len);
-    s->offset = 0;
-    s->len = 0;
-    s->target = 0;
+
+    bdrv_write(s->bd[s->target], s->offset, s->ti_buf+s->ti_bufstart, len);
+    s->offset+=len;
     return 0;
 }
 
@@ -265,6 +267,7 @@
     s->ti_size = 0;
     s->ti_rptr = 0;
     s->ti_wptr = 0;
+    s->ti_bufstart = 0;
 
     if (target >= 4 || !s->bd[target]) { // No such drive
 	s->rregs[4] = STAT_IN;
@@ -293,6 +296,7 @@
 	s->ti_buf[3] = 2;
 	s->ti_buf[4] = 32;
 	s->ti_dir = 1;
+	s->ti_bufstart = 0;
 	s->ti_size = 36;
 	break;
     case 0x1a:
@@ -314,6 +318,7 @@
 	    s->ti_buf[6] = 2; // sector size 512
 	s->ti_buf[7] = 0;
 	s->ti_dir = 1;
+	s->ti_bufstart = 0;
 	s->ti_size = 8;
 	break;
     case 0x28:
@@ -336,6 +341,7 @@
 	    bdrv_read(s->bd[target], offset, s->ti_buf, len);
 	    // XXX error handling
 	    s->ti_dir = 1;
+	    s->ti_bufstart = 0;
 	    break;
 	}
     case 0x2a:
@@ -346,10 +352,12 @@
 		offset = ((buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6]) * 4;
 		len = ((buf[8] << 8) | buf[9]) * 4;
 		s->ti_size = len * 2048;
+		s->blocksize=2048;
 	    } else {
 		offset = (buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6];
 		len = (buf[8] << 8) | buf[9];
 		s->ti_size = len * 512;
+		s->blocksize=512;
 	    }
 	    DPRINTF("Write (10) (offset %lld len %lld)\n", offset, len);
             if (s->ti_size > TI_BUFSZ) {
@@ -359,6 +367,7 @@
             s->offset = offset;
             s->len = len;
             s->target = target;
+            s->ti_bufstart = 0;
 	    // XXX error handling
 	    s->ti_dir = 0;
 	    break;
@@ -400,6 +409,7 @@
                 break;
             }
 	    s->ti_dir = 1;
+	    s->ti_bufstart = 0;
             break;
         }
     default:
@@ -415,10 +425,9 @@
 
 static void dma_write(ESPState *s, const uint8_t *buf, uint32_t len)
 {
-    uint32_t dmaptr, dmalen;
+    uint32_t dmaptr;
 
-    dmalen = s->wregs[0] | (s->wregs[1] << 8);
-    DPRINTF("Transfer status len %d\n", dmalen);
+    DPRINTF("Transfer status len %d\n", len);
     if (s->dma) {
 	dmaptr = iommu_translate(s->espdmaregs[1]);
 	DPRINTF("DMA Direction: %c\n", s->espdmaregs[0] & 0x100? 'w': 'r');
@@ -428,10 +437,10 @@
 	s->rregs[6] = SEQ_CD;
     } else {
 	memcpy(s->ti_buf, buf, len);
-	s->ti_size = dmalen;
+	s->ti_size = len;
 	s->ti_rptr = 0;
 	s->ti_wptr = 0;
-	s->rregs[7] = dmalen;
+	s->rregs[7] = len;
     }
     s->espdmaregs[0] |= DMA_INTR;
     pic_set_irq(s->irq, 1);
@@ -442,34 +451,58 @@
 
 static void handle_ti(ESPState *s)
 {
-    uint32_t dmaptr, dmalen;
+    uint32_t dmaptr, dmalen, minlen, len, from, to;
     unsigned int i;
 
     dmalen = s->wregs[0] | (s->wregs[1] << 8);
-    DPRINTF("Transfer Information len %d\n", dmalen);
+    if (dmalen==0) {
+      dmalen=0x10000;
+    }
+
+    minlen = (dmalen < s->ti_size) ? dmalen : s->ti_size;
+    DPRINTF("Transfer Information len %d\n", minlen);
     if (s->dma) {
 	dmaptr = iommu_translate(s->espdmaregs[1]);
-	DPRINTF("DMA Direction: %c, addr 0x%8.8x\n", s->espdmaregs[0] & 0x100? 'w': 'r', dmaptr);
-	for (i = 0; i < s->ti_size; i++) {
+	DPRINTF("DMA Direction: %c, addr 0x%8.8x %08x %d %d\n", s->espdmaregs[0] & 0x100? 'w': 'r', dmaptr, s->ti_size, s->ti_bufstart, s->ti_dir);
+	from=s->espdmaregs[1];
+	to=from+minlen;
+	for (i = 0; i < minlen; i+=len, from+=len) {
 	    dmaptr = iommu_translate(s->espdmaregs[1] + i);
+	    if ((from&TARGET_PAGE_MASK)!=(to&TARGET_PAGE_MASK)) {
+               len=TARGET_PAGE_SIZE-(from&~TARGET_PAGE_MASK);
+            } else {
+	       len=to-from;
+            }
+            DPRINTF("DMA address p %08x v %08x len %08x, from %08x, to %08x\n", dmaptr, s->espdmaregs[1] + i, len, from, to);
 	    if (s->ti_dir)
-		cpu_physical_memory_write(dmaptr, &s->ti_buf[i], 1);
+		cpu_physical_memory_write(dmaptr, &s->ti_buf[s->ti_bufstart+i], len);
 	    else
-		cpu_physical_memory_read(dmaptr, &s->ti_buf[i], 1);
+		cpu_physical_memory_read(dmaptr, &s->ti_buf[s->ti_bufstart+i], len);
 	}
         if (s->dma_cb) {
-            s->dma_cb(s, s->espdmaregs[1], dmalen);
+            s->dma_cb(s, s->espdmaregs[1], minlen);
+        }
+        if (minlen<s->ti_size) {
+	    s->rregs[4] = STAT_IN | STAT_TC | (s->ti_dir?STAT_DO:STAT_DI);
+	    s->ti_size-=minlen;
+	    s->ti_bufstart+=minlen;
+        } else {
+	    s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
             s->dma_cb = NULL;
+            s->offset = 0;
+            s->len = 0;
+            s->target = 0;
+            s->ti_bufstart = 0;
         }
-	s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
-	s->rregs[5] = INTR_BS;
+        s->rregs[5] = INTR_BS;
 	s->rregs[6] = 0;
+	s->rregs[7] = 0;
 	s->espdmaregs[0] |= DMA_INTR;
     } else {
-	s->ti_size = dmalen;
+	s->ti_size = minlen;
 	s->ti_rptr = 0;
 	s->ti_wptr = 0;
-	s->rregs[7] = dmalen;
+	s->rregs[7] = minlen;
     }	
     pic_set_irq(s->irq, 1);
 }
@@ -485,8 +518,10 @@
     s->ti_rptr = 0;
     s->ti_wptr = 0;
     s->ti_dir = 0;
+    s->ti_bufstart = 0;
     s->dma = 0;
     s->dma_cb = NULL;
+    s->blocksize = 0;
 }
 
 static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
_______________________________________________
Qemu-devel mailing list
Qemu-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/qemu-devel

Reply via email to