summary refs log tree commit diff stats
path: root/hw/esp.c
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2005-11-11 00:24:58 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2005-11-11 00:24:58 +0000
commit9e61bde56a65c92ff67559f8ab94887f8aa57a4d (patch)
tree243d5f584c5d9b6066393c4831472ed38f897893 /hw/esp.c
parent4787c71d179ae9b67b0e682a2a95b6ceca4e68c4 (diff)
downloadfocaccia-qemu-9e61bde56a65c92ff67559f8ab94887f8aa57a4d.tar.gz
focaccia-qemu-9e61bde56a65c92ff67559f8ab94887f8aa57a4d.zip
sparc merge (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1620 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'hw/esp.c')
-rw-r--r--hw/esp.c42
1 files changed, 32 insertions, 10 deletions
diff --git a/hw/esp.c b/hw/esp.c
index 6890bd144c..169531ff17 100644
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -29,6 +29,8 @@
 #ifdef DEBUG_ESP
 #define DPRINTF(fmt, args...) \
 do { printf("ESP: " fmt , ##args); } while (0)
+#define pic_set_irq(irq, level) \
+do { printf("ESP: set_irq(%d): %d\n", (irq), (level)); pic_set_irq((irq),(level));} while (0)
 #else
 #define DPRINTF(fmt, args...)
 #endif
@@ -38,6 +40,8 @@ do { printf("ESP: " fmt , ##args); } while (0)
 #define ESP_MAXREG 0x3f
 #define TI_BUFSZ 65536
 #define DMA_VER 0xa0000000
+#define DMA_INTR 1
+#define DMA_INTREN 0x10
 #define DMA_LOADED 0x04000000
 
 typedef struct ESPState {
@@ -66,6 +70,7 @@ typedef struct ESPState {
 #define INTR_FC 0x08
 #define INTR_BS 0x10
 #define INTR_DC 0x20
+#define INTR_RST 0x80
 
 #define SEQ_0 0x0
 #define SEQ_CD 0x4
@@ -98,11 +103,11 @@ static void handle_satn(ESPState *s)
     s->ti_rptr = 0;
     s->ti_wptr = 0;
 
-    if (target > 4 || !s->bd[target]) { // No such drive
+    if (target >= 4 || !s->bd[target]) { // No such drive
 	s->rregs[4] = STAT_IN;
 	s->rregs[5] = INTR_DC;
 	s->rregs[6] = SEQ_0;
-	s->espdmaregs[0] |= 1;
+	s->espdmaregs[0] |= DMA_INTR;
 	pic_set_irq(s->irq, 1);
 	return;
     }
@@ -192,7 +197,7 @@ static void handle_satn(ESPState *s)
     s->rregs[4] = STAT_IN | STAT_TC | STAT_DI;
     s->rregs[5] = INTR_BS | INTR_FC;
     s->rregs[6] = SEQ_CD;
-    s->espdmaregs[0] |= 1;
+    s->espdmaregs[0] |= DMA_INTR;
     pic_set_irq(s->irq, 1);
 }
 
@@ -209,13 +214,14 @@ static void dma_write(ESPState *s, const uint8_t *buf, uint32_t len)
 	s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
 	s->rregs[5] = INTR_BS | INTR_FC;
 	s->rregs[6] = SEQ_CD;
-	s->espdmaregs[0] |= 1;
     } else {
 	memcpy(s->ti_buf, buf, len);
 	s->ti_size = dmalen;
 	s->ti_rptr = 0;
 	s->ti_wptr = 0;
+	s->rregs[7] = dmalen;
     }
+    s->espdmaregs[0] |= DMA_INTR;
     pic_set_irq(s->irq, 1);
 
 }
@@ -242,11 +248,12 @@ static void handle_ti(ESPState *s)
 	s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
 	s->rregs[5] = INTR_BS;
 	s->rregs[6] = 0;
-	s->espdmaregs[0] |= 1;
+	s->espdmaregs[0] |= DMA_INTR;
     } else {
 	s->ti_size = dmalen;
 	s->ti_rptr = 0;
 	s->ti_wptr = 0;
+	s->rregs[7] = dmalen;
     }	
     pic_set_irq(s->irq, 1);
 }
@@ -265,6 +272,7 @@ static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
     uint32_t saddr;
 
     saddr = (addr & ESP_MAXREG) >> 2;
+    DPRINTF("read reg[%d]: 0x%2.2x\n", saddr, s->rregs[saddr]);
     switch (saddr) {
     case 2:
 	// FIFO
@@ -278,11 +286,16 @@ static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
             s->ti_wptr = 0;
         }
 	break;
+    case 5:
+        // interrupt
+        // Clear status bits except TC
+        s->rregs[4] &= STAT_TC;
+        pic_set_irq(s->irq, 0);
+	s->espdmaregs[0] &= ~DMA_INTR;
+        break;
     default:
 	break;
     }
-    DPRINTF("read reg[%d]: 0x%2.2x\n", saddr, s->rregs[saddr]);
-
     return s->rregs[saddr];
 }
 
@@ -317,8 +330,9 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
 	    break;
 	case 1:
 	    DPRINTF("Flush FIFO (%2.2x)\n", val);
-	    s->rregs[6] = 0;
+            //s->ti_size = 0;
 	    s->rregs[5] = INTR_FC;
+	    s->rregs[6] = 0;
 	    break;
 	case 2:
 	    DPRINTF("Chip reset (%2.2x)\n", val);
@@ -326,6 +340,11 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
 	    break;
 	case 3:
 	    DPRINTF("Bus reset (%2.2x)\n", val);
+	    s->rregs[5] = INTR_RST;
+            if (!(s->wregs[8] & 0x40)) {
+                s->espdmaregs[0] |= DMA_INTR;
+                pic_set_irq(s->irq, 1);
+            }
 	    break;
 	case 0x10:
 	    handle_ti(s);
@@ -362,7 +381,10 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
         break;
     case 9 ... 10:
         break;
-    case 11 ... 15:
+    case 11:
+        s->rregs[saddr] = val & 0x15;
+        break;
+    case 12 ... 15:
         s->rregs[saddr] = val;
         break;
     default:
@@ -403,7 +425,7 @@ static void espdma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t va
     DPRINTF("write dmareg[%d]: 0x%8.8x -> 0x%8.8x\n", saddr, s->espdmaregs[saddr], val);
     switch (saddr) {
     case 0:
-	if (!(val & 0x10))
+	if (!(val & DMA_INTREN))
 	    pic_set_irq(s->irq, 0);
 	if (val & 0x80) {
             esp_reset(s);