diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2005-04-06 20:47:48 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2005-04-06 20:47:48 +0000 |
commit | 66321a11a4ef45942b3bee7377a36bb94831365a (patch) | |
tree | f038f1aef344fa93923d874d348d09542d4c5b68 /hw | |
parent | c44644bb966bd0cf7e09d94b043814ea0740fe8f (diff) |
sparc update (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1350 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'hw')
-rw-r--r-- | hw/iommu.c | 97 | ||||
-rw-r--r-- | hw/lance.c | 134 | ||||
-rw-r--r-- | hw/slavio_intctl.c | 60 | ||||
-rw-r--r-- | hw/slavio_timer.c | 14 |
4 files changed, 140 insertions, 165 deletions
diff --git a/hw/iommu.c b/hw/iommu.c index 62927acd54..d0b16ea88a 100644 --- a/hw/iommu.c +++ b/hw/iommu.c @@ -1,7 +1,7 @@ /* * QEMU SPARC iommu emulation * - * Copyright (c) 2003 Fabrice Bellard + * Copyright (c) 2003-2005 Fabrice Bellard * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,30 +26,14 @@ /* debug iommu */ //#define DEBUG_IOMMU -/* The IOMMU registers occupy three pages in IO space. */ -struct iommu_regs { - /* First page */ - volatile unsigned long control; /* IOMMU control */ - volatile unsigned long base; /* Physical base of iopte page table */ - volatile unsigned long _unused1[3]; - volatile unsigned long tlbflush; /* write only */ - volatile unsigned long pageflush; /* write only */ - volatile unsigned long _unused2[1017]; - /* Second page */ - volatile unsigned long afsr; /* Async-fault status register */ - volatile unsigned long afar; /* Async-fault physical address */ - volatile unsigned long _unused3[2]; - volatile unsigned long sbuscfg0; /* SBUS configuration registers, per-slot */ - volatile unsigned long sbuscfg1; - volatile unsigned long sbuscfg2; - volatile unsigned long sbuscfg3; - volatile unsigned long mfsr; /* Memory-fault status register */ - volatile unsigned long mfar; /* Memory-fault physical address */ - volatile unsigned long _unused4[1014]; - /* Third page */ - volatile unsigned long mid; /* IOMMU module-id */ -}; +#ifdef DEBUG_IOMMU +#define DPRINTF(fmt, args...) \ +do { printf("IOMMU: " fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) +#endif +#define IOMMU_NREGS (3*4096) #define IOMMU_CTRL_IMPL 0xf0000000 /* Implementation */ #define IOMMU_CTRL_VERS 0x0f000000 /* Version */ #define IOMMU_CTRL_RNGE 0x0000001c /* Mapping RANGE */ @@ -63,43 +47,6 @@ struct iommu_regs { #define IOMMU_RNGE_2GB 0x0000001c /* 0x80000000 -> 0xffffffff */ #define IOMMU_CTRL_ENAB 0x00000001 /* IOMMU Enable */ -#define IOMMU_AFSR_ERR 0x80000000 /* LE, TO, or BE asserted */ -#define IOMMU_AFSR_LE 0x40000000 /* SBUS reports error after transaction */ -#define IOMMU_AFSR_TO 0x20000000 /* Write access took more than 12.8 us. */ -#define IOMMU_AFSR_BE 0x10000000 /* Write access received error acknowledge */ -#define IOMMU_AFSR_SIZE 0x0e000000 /* Size of transaction causing error */ -#define IOMMU_AFSR_S 0x01000000 /* Sparc was in supervisor mode */ -#define IOMMU_AFSR_RESV 0x00f00000 /* Reserver, forced to 0x8 by hardware */ -#define IOMMU_AFSR_ME 0x00080000 /* Multiple errors occurred */ -#define IOMMU_AFSR_RD 0x00040000 /* A read operation was in progress */ -#define IOMMU_AFSR_FAV 0x00020000 /* IOMMU afar has valid contents */ - -#define IOMMU_SBCFG_SAB30 0x00010000 /* Phys-address bit 30 when bypass enabled */ -#define IOMMU_SBCFG_BA16 0x00000004 /* Slave supports 16 byte bursts */ -#define IOMMU_SBCFG_BA8 0x00000002 /* Slave supports 8 byte bursts */ -#define IOMMU_SBCFG_BYPASS 0x00000001 /* Bypass IOMMU, treat all addresses - produced by this device as pure - physical. */ - -#define IOMMU_MFSR_ERR 0x80000000 /* One or more of PERR1 or PERR0 */ -#define IOMMU_MFSR_S 0x01000000 /* Sparc was in supervisor mode */ -#define IOMMU_MFSR_CPU 0x00800000 /* CPU transaction caused parity error */ -#define IOMMU_MFSR_ME 0x00080000 /* Multiple parity errors occurred */ -#define IOMMU_MFSR_PERR 0x00006000 /* high bit indicates parity error occurred - on the even word of the access, low bit - indicated odd word caused the parity error */ -#define IOMMU_MFSR_BM 0x00001000 /* Error occurred while in boot mode */ -#define IOMMU_MFSR_C 0x00000800 /* Address causing error was marked cacheable */ -#define IOMMU_MFSR_RTYP 0x000000f0 /* Memory request transaction type */ - -#define IOMMU_MID_SBAE 0x001f0000 /* SBus arbitration enable */ -#define IOMMU_MID_SE 0x00100000 /* Enables SCSI/ETHERNET arbitration */ -#define IOMMU_MID_SB3 0x00080000 /* Enable SBUS device 3 arbitration */ -#define IOMMU_MID_SB2 0x00040000 /* Enable SBUS device 2 arbitration */ -#define IOMMU_MID_SB1 0x00020000 /* Enable SBUS device 1 arbitration */ -#define IOMMU_MID_SB0 0x00010000 /* Enable SBUS device 0 arbitration */ -#define IOMMU_MID_MID 0x0000000f /* Module-id, hardcoded to 0x8 */ - /* The format of an iopte in the page tables */ #define IOPTE_PAGE 0x07ffff00 /* Physical page number (PA[30:12]) */ #define IOPTE_CACHE 0x00000080 /* Cached (in vme IOCACHE or Viking/MXCC) */ @@ -113,7 +60,7 @@ struct iommu_regs { typedef struct IOMMUState { uint32_t addr; - uint32_t regs[sizeof(struct iommu_regs)]; + uint32_t regs[IOMMU_NREGS]; uint32_t iostart; } IOMMUState; @@ -125,6 +72,7 @@ static uint32_t iommu_mem_readw(void *opaque, target_phys_addr_t addr) saddr = (addr - s->addr) >> 2; switch (saddr) { default: + DPRINTF("read reg[%d] = %x\n", saddr, s->regs[saddr]); return s->regs[saddr]; break; } @@ -137,6 +85,7 @@ static void iommu_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val uint32_t saddr; saddr = (addr - s->addr) >> 2; + DPRINTF("write reg[%d] = %x\n", saddr, val); switch (saddr) { case 0: switch (val & IOMMU_CTRL_RNGE) { @@ -166,6 +115,7 @@ static void iommu_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val s->iostart = 0x80000000; break; } + DPRINTF("iostart = %x\n", s->iostart); /* Fall through */ default: s->regs[saddr] = val; @@ -188,13 +138,17 @@ static CPUWriteMemoryFunc *iommu_mem_write[3] = { uint32_t iommu_translate_local(void *opaque, uint32_t addr) { IOMMUState *s = opaque; - uint32_t *iopte = (void *)(s->regs[1] << 4), pa; + uint32_t iopte, pa, tmppte; - iopte += ((addr - s->iostart) >> PAGE_SHIFT); - cpu_physical_memory_read((uint32_t)iopte, (void *) &pa, 4); + iopte = s->regs[1] << 4; + addr &= ~s->iostart; + iopte += (addr >> (PAGE_SHIFT - 2)) & ~3; + cpu_physical_memory_read(iopte, (void *) &pa, 4); bswap32s(&pa); - pa = (pa & IOPTE_PAGE) << 4; /* Loose higher bits of 36 */ - return pa + (addr & PAGE_MASK); + tmppte = pa; + pa = ((pa & IOPTE_PAGE) << 4) + (addr & PAGE_MASK); + DPRINTF("xlate dva %x => pa %x (iopte[%x] = %x)\n", addr, pa, iopte, tmppte); + return pa; } static void iommu_save(QEMUFile *f, void *opaque) @@ -203,7 +157,7 @@ static void iommu_save(QEMUFile *f, void *opaque) int i; qemu_put_be32s(f, &s->addr); - for (i = 0; i < sizeof(struct iommu_regs); i += 4) + for (i = 0; i < IOMMU_NREGS; i++) qemu_put_be32s(f, &s->regs[i]); qemu_put_be32s(f, &s->iostart); } @@ -217,7 +171,7 @@ static int iommu_load(QEMUFile *f, void *opaque, int version_id) return -EINVAL; qemu_get_be32s(f, &s->addr); - for (i = 0; i < sizeof(struct iommu_regs); i += 4) + for (i = 0; i < IOMMU_NREGS; i++) qemu_put_be32s(f, &s->regs[i]); qemu_get_be32s(f, &s->iostart); @@ -228,7 +182,7 @@ static void iommu_reset(void *opaque) { IOMMUState *s = opaque; - memset(s->regs, 0, sizeof(struct iommu_regs)); + memset(s->regs, 0, IOMMU_NREGS * 4); s->iostart = 0; } @@ -244,8 +198,7 @@ void *iommu_init(uint32_t addr) s->addr = addr; iommu_io_memory = cpu_register_io_memory(0, iommu_mem_read, iommu_mem_write, s); - cpu_register_physical_memory(addr, sizeof(struct iommu_regs), - iommu_io_memory); + cpu_register_physical_memory(addr, IOMMU_NREGS * 4, iommu_io_memory); register_savevm("iommu", addr, 1, iommu_save, iommu_load, s); qemu_register_reset(iommu_reset, s); diff --git a/hw/lance.c b/hw/lance.c index c594c52e83..3a8a7d0b28 100644 --- a/hw/lance.c +++ b/hw/lance.c @@ -1,7 +1,7 @@ /* * QEMU Lance emulation * - * Copyright (c) 2003-2004 Fabrice Bellard + * Copyright (c) 2003-2005 Fabrice Bellard * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,20 +26,24 @@ /* debug LANCE card */ //#define DEBUG_LANCE +#ifdef DEBUG_LANCE +#define DPRINTF(fmt, args...) \ +do { printf("LANCE: " fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) +#endif + #ifndef LANCE_LOG_TX_BUFFERS #define LANCE_LOG_TX_BUFFERS 4 #define LANCE_LOG_RX_BUFFERS 4 #endif -#define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */ -#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */ - - #define LE_CSR0 0 #define LE_CSR1 1 #define LE_CSR2 2 #define LE_CSR3 3 -#define LE_MAXREG (LE_CSR3 + 1) +#define LE_NREGS (LE_CSR3 + 1) +#define LE_MAXREG LE_CSR3 #define LE_RDP 0 #define LE_RAP 1 @@ -148,21 +152,12 @@ struct lance_init_block { #define LEDMA_REGS 4 #define LEDMA_MAXADDR (LEDMA_REGS * 4 - 1) -#if 0 -/* Structure to describe the current status of DMA registers on the Sparc */ -struct sparc_dma_registers { - uint32_t cond_reg; /* DMA condition register */ - uint32_t st_addr; /* Start address of this transfer */ - uint32_t cnt; /* How many bytes to transfer */ - uint32_t dma_test; /* DMA test register */ -}; -#endif typedef struct LANCEState { NetDriverState *nd; uint32_t leptr; uint16_t addr; - uint16_t regs[LE_MAXREG]; + uint16_t regs[LE_NREGS]; uint8_t phys[6]; /* mac address */ int irq; unsigned int rxptr, txptr; @@ -177,7 +172,7 @@ static void lance_reset(void *opaque) memcpy(s->phys, s->nd->macaddr, 6); s->rxptr = 0; s->txptr = 0; - memset(s->regs, 0, LE_MAXREG * 2); + memset(s->regs, 0, LE_NREGS * 2); s->regs[LE_CSR0] = LE_C0_STOP; memset(s->ledmaregs, 0, LEDMA_REGS * 4); } @@ -190,10 +185,13 @@ static uint32_t lance_mem_readw(void *opaque, target_phys_addr_t addr) saddr = addr & LE_MAXREG; switch (saddr >> 1) { case LE_RDP: + DPRINTF("read dreg[%d] = %4.4x\n", s->addr, s->regs[s->addr]); return s->regs[s->addr]; case LE_RAP: + DPRINTF("read areg = %4.4x\n", s->addr); return s->addr; default: + DPRINTF("read unknown(%d)\n", saddr>>1); break; } return 0; @@ -208,6 +206,7 @@ static void lance_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val saddr = addr & LE_MAXREG; switch (saddr >> 1) { case LE_RDP: + DPRINTF("write dreg[%d] = %4.4x\n", s->addr, val); switch(s->addr) { case LE_CSR0: if (val & LE_C0_STOP) { @@ -242,12 +241,6 @@ static void lance_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val } s->regs[LE_CSR0] = reg; - - // trigger bits - //if (val & LE_C0_TDMD) - - if ((s->regs[LE_CSR0] & LE_C0_INTR) && (s->regs[LE_CSR0] & LE_C0_INEA)) - pic_set_irq(s->irq, 1); break; case LE_CSR1: s->leptr = (s->leptr & 0xffff0000) | (val & 0xffff); @@ -263,10 +256,12 @@ static void lance_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val } break; case LE_RAP: - if (val < LE_MAXREG) + DPRINTF("write areg = %4.4x\n", val); + if (val < LE_NREGS) s->addr = val; break; default: + DPRINTF("write unknown(%d) = %4.4x\n", saddr>>1, val); break; } lance_send(s); @@ -292,7 +287,7 @@ static int lance_can_receive(void *opaque) uint32_t dmaptr = s->leptr + s->ledmaregs[3]; struct lance_init_block *ib; int i; - uint16_t temp; + uint8_t temp8; if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP) return 0; @@ -300,18 +295,13 @@ static int lance_can_receive(void *opaque) ib = (void *) iommu_translate(dmaptr); for (i = 0; i < RX_RING_SIZE; i++) { - cpu_physical_memory_read((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1); - temp &= 0xff; - if (temp == (LE_R1_OWN)) { -#ifdef DEBUG_LANCE - fprintf(stderr, "lance: can receive %d\n", RX_BUFF_SIZE); -#endif + cpu_physical_memory_read((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp8, 1); + if (temp8 == (LE_R1_OWN)) { + DPRINTF("can receive %d\n", RX_BUFF_SIZE); return RX_BUFF_SIZE; } } -#ifdef DEBUG_LANCE - fprintf(stderr, "lance: cannot receive\n"); -#endif + DPRINTF("cannot receive\n"); return 0; } @@ -322,9 +312,11 @@ static void lance_receive(void *opaque, const uint8_t *buf, int size) LANCEState *s = opaque; uint32_t dmaptr = s->leptr + s->ledmaregs[3]; struct lance_init_block *ib; - unsigned int i, old_rxptr, j; - uint16_t temp; + unsigned int i, old_rxptr; + uint16_t temp16; + uint8_t temp8; + DPRINTF("receive size %d\n", size); if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP) return; @@ -332,27 +324,19 @@ static void lance_receive(void *opaque, const uint8_t *buf, int size) old_rxptr = s->rxptr; for (i = s->rxptr; i != ((old_rxptr - 1) & RX_RING_MOD_MASK); i = (i + 1) & RX_RING_MOD_MASK) { - cpu_physical_memory_read((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1); - if (temp == (LE_R1_OWN)) { + cpu_physical_memory_read((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp8, 1); + if (temp8 == (LE_R1_OWN)) { s->rxptr = (s->rxptr + 1) & RX_RING_MOD_MASK; - temp = size; - bswap16s(&temp); - cpu_physical_memory_write((uint32_t)&ib->brx_ring[i].mblength, (void *) &temp, 2); -#if 0 + temp16 = size + 4; + bswap16s(&temp16); + cpu_physical_memory_write((uint32_t)&ib->brx_ring[i].mblength, (void *) &temp16, 2); cpu_physical_memory_write((uint32_t)&ib->rx_buf[i], buf, size); -#else - for (j = 0; j < size; j++) { - cpu_physical_memory_write(((uint32_t)&ib->rx_buf[i]) + j, &buf[j], 1); - } -#endif - temp = LE_R1_POK; - cpu_physical_memory_write((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1); + temp8 = LE_R1_POK; + cpu_physical_memory_write((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp8, 1); s->regs[LE_CSR0] |= LE_C0_RINT | LE_C0_INTR; - if ((s->regs[LE_CSR0] & LE_C0_INTR) && (s->regs[LE_CSR0] & LE_C0_INEA)) + if (s->regs[LE_CSR0] & LE_C0_INEA) pic_set_irq(s->irq, 1); -#ifdef DEBUG_LANCE - fprintf(stderr, "lance: got packet, len %d\n", size); -#endif + DPRINTF("got packet, len %d\n", size); return; } } @@ -363,40 +347,36 @@ static void lance_send(void *opaque) LANCEState *s = opaque; uint32_t dmaptr = s->leptr + s->ledmaregs[3]; struct lance_init_block *ib; - unsigned int i, old_txptr, j; - uint16_t temp; + unsigned int i, old_txptr; + uint16_t temp16; + uint8_t temp8; char pkt_buf[PKT_BUF_SZ]; + DPRINTF("sending packet? (csr0 %4.4x)\n", s->regs[LE_CSR0]); if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP) return; ib = (void *) iommu_translate(dmaptr); + DPRINTF("sending packet? (dmaptr %8.8x) (ib %p) (btx_ring %p)\n", dmaptr, ib, &ib->btx_ring); old_txptr = s->txptr; for (i = s->txptr; i != ((old_txptr - 1) & TX_RING_MOD_MASK); i = (i + 1) & TX_RING_MOD_MASK) { - cpu_physical_memory_read((uint32_t)&ib->btx_ring[i].tmd1_bits, (void *) &temp, 1); - if (temp == (LE_T1_POK|LE_T1_OWN)) { - cpu_physical_memory_read((uint32_t)&ib->btx_ring[i].length, (void *) &temp, 2); - bswap16s(&temp); - temp = (~temp) + 1; -#if 0 - cpu_physical_memory_read((uint32_t)&ib->tx_buf[i], pkt_buf, temp); -#else - for (j = 0; j < temp; j++) { - cpu_physical_memory_read((uint32_t)&ib->tx_buf[i] + j, &pkt_buf[j], 1); - } -#endif - -#ifdef DEBUG_LANCE - fprintf(stderr, "lance: sending packet, len %d\n", temp); -#endif - qemu_send_packet(s->nd, pkt_buf, temp); - temp = LE_T1_POK; - cpu_physical_memory_write((uint32_t)&ib->btx_ring[i].tmd1_bits, (void *) &temp, 1); + cpu_physical_memory_read((uint32_t)&ib->btx_ring[i].tmd1_bits, (void *) &temp8, 1); + if (temp8 == (LE_T1_POK|LE_T1_OWN)) { + cpu_physical_memory_read((uint32_t)&ib->btx_ring[i].length, (void *) &temp16, 2); + bswap16s(&temp16); + temp16 = (~temp16) + 1; + cpu_physical_memory_read((uint32_t)&ib->tx_buf[i], pkt_buf, temp16); + DPRINTF("sending packet, len %d\n", temp16); + qemu_send_packet(s->nd, pkt_buf, temp16); + temp8 = LE_T1_POK; + cpu_physical_memory_write((uint32_t)&ib->btx_ring[i].tmd1_bits, (void *) &temp8, 1); s->txptr = (s->txptr + 1) & TX_RING_MOD_MASK; s->regs[LE_CSR0] |= LE_C0_TINT | LE_C0_INTR; } } + if ((s->regs[LE_CSR0] & LE_C0_INTR) && (s->regs[LE_CSR0] & LE_C0_INEA)) + pic_set_irq(s->irq, 1); } static uint32_t ledma_mem_readl(void *opaque, target_phys_addr_t addr) @@ -436,7 +416,7 @@ static void lance_save(QEMUFile *f, void *opaque) qemu_put_be32s(f, &s->leptr); qemu_put_be16s(f, &s->addr); - for (i = 0; i < LE_MAXREG; i ++) + for (i = 0; i < LE_NREGS; i ++) qemu_put_be16s(f, &s->regs[i]); qemu_put_buffer(f, s->phys, 6); qemu_put_be32s(f, &s->irq); @@ -454,7 +434,7 @@ static int lance_load(QEMUFile *f, void *opaque, int version_id) qemu_get_be32s(f, &s->leptr); qemu_get_be16s(f, &s->addr); - for (i = 0; i < LE_MAXREG; i ++) + for (i = 0; i < LE_NREGS; i ++) qemu_get_be16s(f, &s->regs[i]); qemu_get_buffer(f, s->phys, 6); qemu_get_be32s(f, &s->irq); @@ -476,7 +456,7 @@ void lance_init(NetDriverState *nd, int irq, uint32_t leaddr, uint32_t ledaddr) s->irq = irq; lance_io_memory = cpu_register_io_memory(0, lance_mem_read, lance_mem_write, s); - cpu_register_physical_memory(leaddr, 8, lance_io_memory); + cpu_register_physical_memory(leaddr, 4, lance_io_memory); ledma_io_memory = cpu_register_io_memory(0, ledma_mem_read, ledma_mem_write, s); cpu_register_physical_memory(ledaddr, 16, ledma_io_memory); diff --git a/hw/slavio_intctl.c b/hw/slavio_intctl.c index 352ae1f0f0..9c8ddd0d0c 100644 --- a/hw/slavio_intctl.c +++ b/hw/slavio_intctl.c @@ -1,7 +1,7 @@ /* * QEMU Sparc SLAVIO interrupt controller emulation * - * Copyright (c) 2003-2004 Fabrice Bellard + * Copyright (c) 2003-2005 Fabrice Bellard * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,6 +23,14 @@ */ #include "vl.h" //#define DEBUG_IRQ_COUNT +//#define DEBUG_IRQ + +#ifdef DEBUG_IRQ +#define DPRINTF(fmt, args...) \ +do { printf("IRQ: " fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) +#endif /* * Registers of interrupt controller in sun4m. @@ -49,6 +57,7 @@ typedef struct SLAVIO_INTCTLState { #define INTCTL_MAXADDR 0xf #define INTCTLM_MAXADDR 0xf +static void slavio_check_interrupts(void *opaque); // per-cpu interrupt controller static uint32_t slavio_intctl_mem_readl(void *opaque, target_phys_addr_t addr) @@ -82,10 +91,12 @@ static void slavio_intctl_mem_writel(void *opaque, target_phys_addr_t addr, uint val |= 80000000; val &= 0xfffe0000; s->intreg_pending[cpu] &= ~val; + DPRINTF("Cleared cpu %d irq mask %x, curmask %x\n", cpu, val, s->intreg_pending[cpu]); break; case 2: // set softint val &= 0xfffe0000; s->intreg_pending[cpu] |= val; + DPRINTF("Set cpu %d irq mask %x, curmask %x\n", cpu, val, s->intreg_pending[cpu]); break; default: break; @@ -135,15 +146,19 @@ static void slavio_intctlm_mem_writel(void *opaque, target_phys_addr_t addr, uin // Force clear unused bits val &= ~0x7fb2007f; s->intregm_disabled &= ~val; + DPRINTF("Enabled master irq mask %x, curmask %x\n", val, s->intregm_disabled); + slavio_check_interrupts(s); break; case 3: // set (disable, clear pending) // Force clear unused bits val &= ~0x7fb2007f; s->intregm_disabled |= val; s->intregm_pending &= ~val; + DPRINTF("Disabled master irq mask %x, curmask %x\n", val, s->intregm_disabled); break; case 4: s->target_cpu = val & (MAX_CPUS - 1); + DPRINTF("Set master irq cpu %d\n", s->target_cpu); break; default: break; @@ -196,6 +211,36 @@ static const uint32_t intbit_to_level[32] = { 6, 0, 4, 10, 8, 0, 11, 0, 0, 0, 0, 0, 15, 0, 0, 0, }; +static void slavio_check_interrupts(void *opaque) +{ + SLAVIO_INTCTLState *s = opaque; + uint32_t pending = s->intregm_pending; + unsigned int i, max = 0; + + pending &= ~s->intregm_disabled; + + if (pending && !(s->intregm_disabled & 0x80000000)) { + for (i = 0; i < 32; i++) { + if (pending & (1 << i)) { + if (max < intbit_to_level[i]) + max = intbit_to_level[i]; + } + } + if (cpu_single_env->interrupt_index == 0) { + DPRINTF("Triggered pil %d\n", max); +#ifdef DEBUG_IRQ_COUNT + s->irq_count[max]++; +#endif + cpu_single_env->interrupt_index = TT_EXTINT | max; + cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HARD); + } + else + DPRINTF("Not triggered (pending %x), pending exception %x\n", pending, cpu_single_env->interrupt_index); + } + else + DPRINTF("Not triggered (pending %x), disabled %x\n", pending, s->intregm_disabled); +} + /* * "irq" here is the bit number in the system interrupt register to * separate serial and keyboard interrupts sharing a level. @@ -204,6 +249,7 @@ void slavio_pic_set_irq(void *opaque, int irq, int level) { SLAVIO_INTCTLState *s = opaque; + DPRINTF("Set irq %d level %d\n", irq, level); if (irq < 32) { uint32_t mask = 1 << irq; uint32_t pil = intbit_to_level[irq]; @@ -216,19 +262,9 @@ void slavio_pic_set_irq(void *opaque, int irq, int level) s->intregm_pending &= ~mask; s->intreg_pending[s->target_cpu] &= ~(1 << pil); } - if (level && - !(s->intregm_disabled & mask) && - !(s->intregm_disabled & 0x80000000) && - (pil == 15 || (pil > cpu_single_env->psrpil && cpu_single_env->psret == 1))) { -#ifdef DEBUG_IRQ_COUNT - if (level == 1) - s->irq_count[pil]++; -#endif - cpu_single_env->interrupt_index = TT_EXTINT | pil; - cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HARD); - } } } + slavio_check_interrupts(s); } static void slavio_intctl_save(QEMUFile *f, void *opaque) diff --git a/hw/slavio_timer.c b/hw/slavio_timer.c index 43f59d2750..47d538529e 100644 --- a/hw/slavio_timer.c +++ b/hw/slavio_timer.c @@ -1,7 +1,7 @@ /* * QEMU Sparc SLAVIO timer controller emulation * - * Copyright (c) 2003-2004 Fabrice Bellard + * Copyright (c) 2003-2005 Fabrice Bellard * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,6 +25,13 @@ //#define DEBUG_TIMER +#ifdef DEBUG_TIMER +#define DPRINTF(fmt, args...) \ +do { printf("TIMER: " fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) +#endif + /* * Registers of hardware timer in sun4m. * @@ -90,9 +97,8 @@ static void slavio_timer_get_out(SLAVIO_TIMERState *s) // Convert remaining counter ticks to CPU ticks s->expire_time = ticks + muldiv64(limit - count, ticks_per_sec, CNT_FREQ); -#ifdef DEBUG_TIMER - term_printf("timer: irq %d limit %d reached %d d %lld count %d s->c %x diff %lld stopped %d mode %d\n", s->irq, limit, s->reached?1:0, (ticks-s->count_load_time), count, s->count, s->expire_time - ticks, s->stopped, s->mode); -#endif + DPRINTF("irq %d limit %d reached %d d %lld count %d s->c %x diff %lld stopped %d mode %d\n", s->irq, limit, s->reached?1:0, (ticks-s->count_load_time), count, s->count, s->expire_time - ticks, s->stopped, s->mode); + if (s->mode != 1) pic_set_irq(s->irq, out); } |