aboutsummaryrefslogtreecommitdiffstats
path: root/hw/sparc32_dma.c
diff options
context:
space:
mode:
authorArtyom Tarasenko <atar4qemu@googlemail.com>2010-05-22 10:38:56 +0200
committerBlue Swirl <blauwirbel@gmail.com>2010-05-22 09:07:46 +0000
commit65899fe34b09ab4af4b045977460b531ec5c1f73 (patch)
tree8443a4b3fdb801a2d4d437baef401e910384daa7 /hw/sparc32_dma.c
parentae6b2c4ed956c17456e70efefe13ad0ab7db31de (diff)
sparc32 protect read-only bits in DMA CSR registers
On a real hardware changing read-only bits has no effect Use a mask common for SCSI and Ethernet registers. The crucial bit is DMA_INTR, because setting or clearing it may produce spurious interrupts. This patch allows booting Solaris 2.3 Signed-off-by: Artyom Tarasenko <atar4qemu@gmail.com> Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Diffstat (limited to 'hw/sparc32_dma.c')
-rw-r--r--hw/sparc32_dma.c12
1 files changed, 8 insertions, 4 deletions
diff --git a/hw/sparc32_dma.c b/hw/sparc32_dma.c
index 3ceb851e9..b52170787 100644
--- a/hw/sparc32_dma.c
+++ b/hw/sparc32_dma.c
@@ -62,6 +62,9 @@
#define DMA_DRAIN_FIFO 0x40
#define DMA_RESET 0x80
+/* XXX SCSI and ethernet should have different read-only bit masks */
+#define DMA_CSR_RO_MASK 0xfe000007
+
typedef struct DMAState DMAState;
struct DMAState {
@@ -187,7 +190,7 @@ static void dma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
switch (saddr) {
case 0:
if (val & DMA_INTREN) {
- if (val & DMA_INTR) {
+ if (s->dmaregs[0] & DMA_INTR) {
DPRINTF("Raise IRQ\n");
qemu_irq_raise(s->irq);
}
@@ -204,16 +207,17 @@ static void dma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
val &= ~DMA_DRAIN_FIFO;
} else if (val == 0)
val = DMA_DRAIN_FIFO;
- val &= 0x0fffffff;
+ val &= ~DMA_CSR_RO_MASK;
val |= DMA_VER;
+ s->dmaregs[0] = (s->dmaregs[0] & DMA_CSR_RO_MASK) | val;
break;
case 1:
s->dmaregs[0] |= DMA_LOADED;
- break;
+ /* fall through */
default:
+ s->dmaregs[saddr] = val;
break;
}
- s->dmaregs[saddr] = val;
}
static CPUReadMemoryFunc * const dma_mem_read[3] = {