From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1LoIcZ-0000Dr-9I for qemu-devel@nongnu.org; Mon, 30 Mar 2009 10:37:51 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1LoIcU-00007t-53 for qemu-devel@nongnu.org; Mon, 30 Mar 2009 10:37:50 -0400 Received: from [199.232.76.173] (port=54240 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LoIcT-00007g-VX for qemu-devel@nongnu.org; Mon, 30 Mar 2009 10:37:46 -0400 Received: from mx20.gnu.org ([199.232.41.8]:3106) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1LoIcT-0001Dh-Ab for qemu-devel@nongnu.org; Mon, 30 Mar 2009 10:37:45 -0400 Received: from mel.act-europe.fr ([212.99.106.210]) by mx20.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1LoIcR-0007R5-Of for qemu-devel@nongnu.org; Mon, 30 Mar 2009 10:37:44 -0400 Received: from localhost (localhost [127.0.0.1]) by filtered-smtp.eu.adacore.com (Postfix) with ESMTP id D0E3C29003E for ; Mon, 30 Mar 2009 16:36:40 +0200 (CEST) Received: from mel.act-europe.fr ([127.0.0.1]) by localhost (smtp.eu.adacore.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 2j9DJVc3120O for ; Mon, 30 Mar 2009 16:36:36 +0200 (CEST) Received: from ulanbator.act-europe.fr (ulanbator.act-europe.fr [10.10.1.67]) by mel.act-europe.fr (Postfix) with ESMTP id 24842290049 for ; Mon, 30 Mar 2009 16:36:35 +0200 (CEST) From: Tristan Gingold Date: Mon, 30 Mar 2009 16:36:26 +0200 Message-Id: <1238423794-25455-12-git-send-email-gingold@adacore.com> In-Reply-To: <1238423794-25455-11-git-send-email-gingold@adacore.com> References: <1238423794-25455-1-git-send-email-gingold@adacore.com> <1238423794-25455-2-git-send-email-gingold@adacore.com> <1238423794-25455-3-git-send-email-gingold@adacore.com> <1238423794-25455-4-git-send-email-gingold@adacore.com> <1238423794-25455-5-git-send-email-gingold@adacore.com> <1238423794-25455-6-git-send-email-gingold@adacore.com> <1238423794-25455-7-git-send-email-gingold@adacore.com> <1238423794-25455-8-git-send-email-gingold@adacore.com> <1238423794-25455-9-git-send-email-gingold@adacore.com> <1238423794-25455-10-git-send-email-gingold@adacore.com> <1238423794-25455-11-git-send-email-gingold@adacore.com> Subject: [Qemu-devel] [PATCH 11/19] Add 21272 chipset (memory and pci controller for alpha) Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Signed-off-by: Tristan Gingold --- hw/21272.c | 869 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ hw/pci.h | 8 + 2 files changed, 877 insertions(+), 0 deletions(-) create mode 100644 hw/21272.c diff --git a/hw/21272.c b/hw/21272.c new file mode 100644 index 0000000..a54dd59 --- /dev/null +++ b/hw/21272.c @@ -0,0 +1,869 @@ +/* + * Qemu 21272 (Tsunami/Typhoon) chipset emulation. + * + * Copyright (c) 2009 AdaCore + * + * Written by Tristan Gingold. + * + * This work is licensed under the GNU GPL license version 2 or later. + */ +#include "hw.h" +#include "devices.h" +#include "pci.h" + +//#define DEBUG_CCHIP +//#define DEBUG_PCHIP +//#define DEBUG_DCHIP +//#define DEBUG_PCICFG + +typedef struct PchipState PchipState; +struct PchipState { + /* IntAck handler. */ + int (*iack_handler)(void *); + void *iack_handler_param; + + PCIBus *pci; + + /* Pchip id. */ + int num; + + /* Used to reconstruct 64bits accesses. Low long word first. */ + uint32_t data; + + uint32_t wsba[3]; + uint64_t wsba3; + uint32_t wsm[3]; + uint32_t wsm3; + uint64_t tba[3]; + uint64_t tba3; + uint32_t perrmask; + uint32_t plat; + /* pctl */ + unsigned char ptevrfy; + unsigned char mwin; + unsigned char hole; + unsigned char chaindis; +}; + +struct TyphoonState { + qemu_irq *irqs; + qemu_irq *intim_irq; + CPUState *cpu[4]; + + /* Used to reconstruct 64bits accesses. Low long word first. */ + uint32_t data; + + unsigned char misc_rev; + unsigned char misc_abw; + unsigned char misc_abt; + + int b_irq[4]; + + uint64_t dim[4]; + uint64_t dir[4]; + uint64_t drir; + uint64_t aar[4]; + + /* dchip */ + uint64_t csc; + uint64_t str; + + PchipState pchip[2]; +}; + +static void illegal_write (void *opaque, + target_phys_addr_t addr, uint32_t value) +{ + qemu_log("illegal_write at addr="TARGET_FMT_lx"\n", addr); +} + +static uint32_t illegal_read (void *opaque, target_phys_addr_t addr) +{ + qemu_log("illegal_read at addr="TARGET_FMT_lx"\n", addr); + return 0; +} + +static uint32_t typhoon_cchip_readl (void *opaque, target_phys_addr_t addr) +{ + TyphoonState *s = opaque; + uint64_t val; + int reg; + + /* Handle 64-bits accesses; */ + if (addr & 0x04) + return s->data; + + reg = addr >> 6; + switch (reg) { + case 0x00: /* CSC */ + val = s->csc; + break; + case 0x02: /* MISC */ + val = ((uint64_t)s->misc_rev << 32) + | ((uint64_t)s->misc_abt << 20) + | ((uint64_t)s->misc_abw << 16) + | ((s->b_irq[0] & 4) << 2) + | ((s->b_irq[1] & 4) << 3) + | ((s->b_irq[2] & 4) << 4) + | ((s->b_irq[3] & 4) << 5) + | ((s->b_irq[0] & 8) << 5) + | ((s->b_irq[1] & 8) << 6) + | ((s->b_irq[2] & 8) << 7) + | ((s->b_irq[3] & 8) << 8); + break; + case 0x04: + case 0x05: + case 0x06: + case 0x07: + val = s->aar[reg - 4]; + break; + case 0x08: + case 0x09: + case 0x18: + case 0x19: + val = s->dim[(reg & 1) | ((reg & 0x10) >> 3)]; + break; + case 0x0a: + case 0x0b: + case 0x1a: + case 0x1b: + val = s->dir[(reg & 1) | ((reg & 0x10) >> 3)]; + break; + case 0x0c: + val = s->drir; + break; + default: + qemu_log("21272: unhandled cchip read reg=%x\n", reg); + val = 0; + break; + } + +#ifdef DEBUG_CCHIP + fprintf(stderr,"typhoon cchip read reg=%x, val=%016"PRIx64"\n", reg, val); +#endif + s->data = val >> 32; + return (uint32_t)val; +} + +static void typhoon_cchip_writel (void *opaque, + target_phys_addr_t addr, uint32_t value) +{ + TyphoonState *s = opaque; + int reg; + uint64_t val; + +#if 0 + fprintf(stderr,"typhoon write addr="TARGET_FMT_lx", val=%08x\n", + addr, value); +#endif + + /* Handle 64-bits accesses. LSB first. */ + if (!(addr & 0x04)) { + s->data = value; + return; + } + else + val = ((uint64_t)value << 32) | s->data; + + reg = addr >> 6; + +#ifdef DEBUG_CCHIP + fprintf(stderr,"typhoon cchip write reg=%x, val=%016"PRIx64"\n", reg, val); +#endif + + switch (reg) { + case 0x00: /* CSC */ + s->csc = (s->csc & 0xffffU) | (val & 0x0777777fff3f0000ULL); + break; + case 0x02: /* MISC */ + if (val & (1 << 24)) { + /* ACL: arbitration clear. */ + s->misc_abt = 0; + s->misc_abw = 0; + } + if (val & (0xf << 12)) { + int i; + for (i = 0; i < 4 && s->cpu[i]; i++) + if ((val & (0x1000 << i))) { + s->b_irq[i] &= ~(1 << 3); + cpu_alpha_update_irq(s->cpu[i], s->b_irq[i]); + } + } + if ((val & (0xf << 16)) && s->misc_abw == 0) { + /* ABW: arbitration won. */ + s->misc_abw = (val >> 16) & 0x0f; + } + if ((val & (0x0f << 20)) && s->misc_abt == 0) { + /* ABT: arbitration try. */ + s->misc_abt = (val >> 20) & 0x0f; + } + if (val & (1ULL << 28)) { + /* NXM - not handled. */ + } + if (val & (0x0fULL << 40)) { + /* DEVUP - not handled. */ + } + if (val & (0x0f << 4)) { + /* ITINTR */ + int i; + for (i = 0; i < 4 && s->cpu[i]; i++) + if ((val & (0x10 << i))) { + s->b_irq[i] &= ~(1 << 2); + cpu_alpha_update_irq(s->cpu[i], s->b_irq[i]); + } + } + if (val & ~((0xfULL << 40) | (0xffULL << 32) | (1 << 28) | (1ULL << 24) + | (0x0f << 12) | (0xf << 16) + | (0x0f << 20) | (0x0f << 4))) { + qemu_log("21272: unhandled value %016"PRIx64" written in MISC\n", + val); + } + break; + case 0x08: + case 0x09: + case 0x18: + case 0x19: + s->dim[(reg & 1) | ((reg & 0x10) >> 3)] = val; + break; + default: + qemu_log("21272: unhandled cchip write reg %x (%016"PRIx64")\n", + reg, val); + break; + } +} + +static CPUReadMemoryFunc *typhoon_cchip_read[] = { + &illegal_read, + &illegal_read, + &typhoon_cchip_readl, +}; + +static CPUWriteMemoryFunc *typhoon_cchip_write[] = { + &illegal_write, + &illegal_write, + &typhoon_cchip_writel, +}; + +static uint32_t typhoon_dchip_readl (void *opaque, target_phys_addr_t addr) +{ + TyphoonState *s = opaque; + uint64_t val; + int reg; + + /* Handle 64-bits accesses; */ + if (addr & 0x04) + return s->data; + + reg = addr >> 6; + switch (reg) { + case 0x20: /* DSC */ + val = (s->csc & 0x3f) | ((s->csc >> (14 - 6)) & 0x40); + val = (val << 8) | val; + val = (val << 16) | val; + val = (val << 32) | val; + break; + case 0x21: /* STR */ + val = s->str; + break; + case 0x22: /* DREV */ + val = 0x01 * 0x0101010101010101ULL; + break; + case 0x23: /* DSC2 */ + val = 0; + default: + qemu_log("21272: unhandled dchip read reg=%x\n", reg); + val = 0; + break; + } + +#ifdef DEBUG_DCHIP + fprintf(stderr,"typhoon dchip read reg=%x, val=%016"PRIx64"\n", reg, val); +#endif + s->data = val >> 32; + return (uint32_t)val; +} + +static void typhoon_dchip_writel (void *opaque, + target_phys_addr_t addr, uint32_t value) +{ + TyphoonState *s = opaque; + int reg; + uint64_t val; + +#if 0 + fprintf(stderr,"typhoon write addr="TARGET_FMT_lx", val=%08x\n", + addr, value); +#endif + + /* Handle 64-bits accesses. LSB first. */ + if (!(addr & 0x04)) { + s->data = value; + return; + } + else + val = ((uint64_t)value << 32) | s->data; + + reg = addr >> 6; + +#ifdef DEBUG_DCHIP + fprintf(stderr,"typhoon dchip write reg=%x, val=%016"PRIx64"\n", reg, val); +#endif + + switch (reg) { + default: + qemu_log("21272: unhandled dchip write reg %x (%016"PRIx64")\n", + reg, val); + break; + } +} + +static CPUReadMemoryFunc *typhoon_dchip_read[] = { + &illegal_read, + &illegal_read, + &typhoon_dchip_readl, +}; + +static CPUWriteMemoryFunc *typhoon_dchip_write[] = { + &illegal_write, + &illegal_write, + &typhoon_dchip_writel, +}; + +static uint32_t typhoon_pchip_readl (void *opaque, target_phys_addr_t addr) +{ + PchipState *s = opaque; + uint64_t val; + int reg; + + /* Handle 64-bits accesses; */ + if (addr & 0x04) + return s->data; + + reg = addr >> 6; + switch (reg) { + case 0x00: + case 0x01: + case 0x02: + val = s->wsba[reg]; + break; + case 0x03: + val = s->wsba3; + break; + case 0x04: + case 0x05: + case 0x06: + val = s->wsm[reg - 4]; + break; + case 0x07: + val = s->wsm3; + break; + case 0x08: + case 0x09: + case 0x0a: + val = s->tba[reg - 0x8]; + break; + case 0x0b: + val = s->tba3; + break; + case 0x0c: /* pctl */ + val = (((uint64_t)(s->num & 3)) << 46) + | (((uint64_t)s->ptevrfy) << 44) + | (1ULL << 40) /* PCLKX */ + | (1 << 24) /* Rev */ + | (s->mwin << 6) + | (s->hole << 5) + | (s->chaindis << 3); + break; + case 0x0d: /* plat */ + val = s->plat; + break; + case 0x0f: /* PERROR */ + val = 0; /* Not emulated. */ + break; + case 0x10: /* PERRMASK */ + val = s->perrmask; + break; + case 0x20: /* WO. */ + val = 0; + break; + default: + qemu_log("21272: unhandled pchip read reg=%x\n", reg); + val = 0; + break; + } + +#ifdef DEBUG_PCHIP + fprintf(stderr,"typhoon pchip%d read reg=%x, val=%016"PRIx64"\n", + s->num, reg, val); +#endif + s->data = val >> 32; + return (uint32_t)val; +} + +static void typhoon_pchip_writel (void *opaque, + target_phys_addr_t addr, uint32_t value) +{ + PchipState *s = opaque; + int reg; + uint64_t val; + + /* Handle 64-bits accesses. LSB first. */ + if (!(addr & 0x04)) { + s->data = value; + return; + } + else + val = ((uint64_t)value << 32) | s->data; + + reg = addr >> 6; + +#ifdef DEBUG_PCHIP + fprintf(stderr,"typhoon pchip%d write reg=%x, val=%016"PRIx64"\n", + s->num, reg, val); +#endif + + switch (reg) { + case 0: + case 1: + case 2: + s->wsba[reg] = val & 0xfff00003; + if (val & 1) + qemu_log("21272: enabling wsba%d!\n", reg); /* Not yet emulated */ + break; + case 3: + s->wsba3 = val & 0xffffff80fff00003ULL; + if (val & 1) + qemu_log("21272: enabling wsba3!\n"); /* Not yet emulated */ + break; + case 0x4: + case 0x5: + case 0x6: + s->wsm[reg - 4] = val & 0xfff00000; + break; + case 0x7: + s->wsm3 = val & 0xfff00000; + break; + case 0x8: + case 0x9: + case 0xa: + s->tba[reg - 0x8] = val & 0x7fffffc00; + break; + case 0xb: + s->tba3 = val & 0x7fffffc00; + break; + case 0x0c: /* pctl */ + s->ptevrfy = (val >> 44) & 1; + s->mwin = (val >> 6) & 1; + s->hole = (val >> 5) & 1; + s->chaindis = (val >> 3) & 1; + if (val & ((1ULL << 43) | (1ULL << 42) | (3ULL << 36) | (0x0fULL << 32) + | (0x0f << 20) | (1 << 19) | (0x3f << 8) + | (1 << 2) | (1 << 1))) + qemu_log("21272: pchip pctl: unhandled value %016"PRIx64"\n", + val); + break; + case 0x0d: /* plat */ + s->plat = val & 0xff00; + break; + case 0x0f: /* PERROR */ + break; /* Not emulated. */ + case 0x10: /* PERRMASK */ + s->perrmask = val & 0xfff; + break; + case 0x13: /* tlbia */ + /* FIXME: todo */ + break; + case 0x20: /* SPRST */ + /* Software pci-reset. FIXME: disable bus? */ + break; + default: + qemu_log("21272: unhandled pchip write reg=%x (%016"PRIx64")\n", + reg, val); + break; + } +} + +static CPUReadMemoryFunc *typhoon_pchip_read[] = { + &illegal_read, + &illegal_read, + &typhoon_pchip_readl, +}; + +static CPUWriteMemoryFunc *typhoon_pchip_write[] = { + &illegal_write, + &illegal_write, + &typhoon_pchip_writel, +}; + + +static void pchip_pci_io_writeb (void *opaque, target_phys_addr_t addr, + uint32_t value) +{ + cpu_outb(NULL, addr, value); +} + +static uint32_t pchip_pci_io_readb (void *opaque, target_phys_addr_t addr) +{ + return cpu_inb(NULL, addr); +} + +static void pchip_pci_io_writew (void *opaque, target_phys_addr_t addr, + uint32_t value) +{ +#ifdef TARGET_WORDS_BIGENDIAN + value = bswap16(value); +#endif + cpu_outw(NULL, addr, value); +} + +static uint32_t pchip_pci_io_readw (void *opaque, target_phys_addr_t addr) +{ + uint32_t ret; + + ret = cpu_inw(NULL, addr); +#ifdef TARGET_WORDS_BIGENDIAN + ret = bswap16(ret); +#endif + return ret; +} + +static void pchip_pci_io_writel (void *opaque, target_phys_addr_t addr, + uint32_t value) +{ +#ifdef TARGET_WORDS_BIGENDIAN + value = bswap32(value); +#endif + cpu_outl(NULL, addr, value); +} + +static uint32_t pchip_pci_io_readl (void *opaque, target_phys_addr_t addr) +{ + uint32_t ret; + + ret = cpu_inl(NULL, addr); +#ifdef TARGET_WORDS_BIGENDIAN + ret = bswap32(ret); +#endif + return ret; +} + +static CPUWriteMemoryFunc *pchip_pci_io_write[] = { + &pchip_pci_io_writeb, + &pchip_pci_io_writew, + &pchip_pci_io_writel, +}; + +static CPUReadMemoryFunc *pchip_pci_io_read[] = { + &pchip_pci_io_readb, + &pchip_pci_io_readw, + &pchip_pci_io_readl, +}; + +static void pchip_pci_cfg_writex (void *opaque, target_phys_addr_t addr, + uint32_t value, int sz) +{ + uint32_t a = addr & 0xffffffU; + PchipState *s = opaque; + +#ifdef DEBUG_PCICFG + fprintf(stderr, "pci_cfg write: addr=%06x, sz=%d %u:%u:%02x, val=%08x\n", + a, sz, + (a >> 11) & 0x1f, (a >> 8) & 0x7, a & 0xff, value); +#endif + + pci_data_write(s->pci, a, value, 1 << sz); +} + +static void pchip_pci_cfg_writel (void *opaque, target_phys_addr_t addr, + uint32_t value) +{ +#ifdef TARGET_WORDS_BIGENDIAN + value = bswap32(value); +#endif + pchip_pci_cfg_writex(opaque, addr, value, 2); +} + +static void pchip_pci_cfg_writew (void *opaque, target_phys_addr_t addr, + uint32_t value) +{ +#ifdef TARGET_WORDS_BIGENDIAN + value = bswap16(value); +#endif + pchip_pci_cfg_writex(opaque, addr, value, 1); +} + +static void pchip_pci_cfg_writeb (void *opaque, target_phys_addr_t addr, + uint32_t value) +{ + pchip_pci_cfg_writex(opaque, addr, value, 0); +} + +static uint32_t pchip_pci_cfg_readx (void *opaque, target_phys_addr_t addr, + int sz) +{ + uint32_t a = addr & 0xffffffU; + PchipState *s = opaque; + uint32_t val; + + if (s->num == 0) + val = pci_data_read(s->pci, a, 1 << sz); + else { + switch (sz) { + case 0: + val = 0xff; + break; + case 1: + val = 0xffff; + break; + default: + case 2: + val = 0xffffffff; + break; + } + } + +#ifdef DEBUG_PCICFG + fprintf(stderr, "pci_cfg read: addr=%06x, sz=%d %u:%u:%02x, val=%08x\n", + a, sz, + (a >> 11) & 0x1f, (a >> 8) & 0x7, a & 0xff, + val); +#endif + + return val; +} + +static uint32_t pchip_pci_cfg_readb (void *opaque, target_phys_addr_t addr) +{ + return pchip_pci_cfg_readx(opaque, addr, 0); +} + +static uint32_t pchip_pci_cfg_readw (void *opaque, target_phys_addr_t addr) +{ + return pchip_pci_cfg_readx(opaque, addr, 1); +} + +static uint32_t pchip_pci_cfg_readl (void *opaque, target_phys_addr_t addr) +{ + return pchip_pci_cfg_readx(opaque, addr, 2); +} + +static CPUWriteMemoryFunc *pchip_pci_cfg_write[] = { + &pchip_pci_cfg_writeb, + &pchip_pci_cfg_writew, + &pchip_pci_cfg_writel, +}; + +static CPUReadMemoryFunc *pchip_pci_cfg_read[] = { + &pchip_pci_cfg_readb, + &pchip_pci_cfg_readw, + &pchip_pci_cfg_readl, +}; + +static void pchip_pci_iack_writex (void *opaque, + target_phys_addr_t addr, uint32_t value) +{ + qemu_log("21272: pci iack addr=%08x, val=%08x\n", (uint32_t)addr, value); +} + +static uint32_t pchip_pci_iack_readx (void *opaque, target_phys_addr_t addr) +{ + PchipState *s = opaque; + uint32_t res; + + /* Ideally we should have a PCIBus interface. */ + res = (*s->iack_handler)(s->iack_handler_param); + //fprintf(stderr, "21272 iack: addr=%016"PRIx64", res=%d\n", addr, res); + return res; +} + +static CPUWriteMemoryFunc *pchip_pci_iack_write[] = { + &pchip_pci_iack_writex, + &pchip_pci_iack_writex, + &pchip_pci_iack_writex, +}; + +static CPUReadMemoryFunc *pchip_pci_iack_read[] = { + &pchip_pci_iack_readx, + &pchip_pci_iack_readx, + &pchip_pci_iack_readx, +}; + +static void typhoon_reset (void *opaque) +{ + TyphoonState *s = opaque; + + s->misc_rev = 8; + s->misc_abw = 0; +} + +static void cchip_set_irq(void *opaque, int irq, int level) +{ + TyphoonState *s = opaque; + uint64_t mask; + int i; + +#if 0 + qemu_log("cchip_set_irq: irq=%d level=%d\n", irq, level); +#endif + mask = 1ULL << irq; + if (level) + s->drir |= mask; + else + s->drir &= ~mask; + + for (i = 0; i < 4 && s->cpu[i]; i++) { + int old = s->b_irq[i]; + s->dir[i] = s->drir & s->dim[i]; + if (s->dir[i] >> 58) + s->b_irq[i] |= (1 << 0); + else + s->b_irq[i] &= ~(1 << 0); + + if (s->dir[i] << 8) + s->b_irq[i] |= (1 << 1); + else + s->b_irq[i] &= ~(1 << 1); + +#if 0 + qemu_log("cchip_set_irq: cpu[%d]: drir=%016"PRIx64" dim=%016"PRIx64" " + " dir=%016"PRIx64" birq=%02x\n", + i, s->drir, s->dim[i], s->dir[i], s->b_irq[i]); +#endif + if (s->b_irq[i] != old) + cpu_alpha_update_irq(s->cpu[i], s->b_irq[i]); + } +} + +static void intim_set_irq(void *opaque, int irq, int level) +{ + int i; + TyphoonState *s = opaque; + unsigned char old; + +#if 0 + { + static int cnt; + cnt++; + if ((cnt % 1024) == 1023) + fprintf(stderr, "Clock!\n"); + } +#endif + + if (0 && (s->b_irq[0] & 0x04)) + fprintf(stderr, "!!Interrupt missed\n"); + + for (i = 0; i < 4 && s->cpu[i]; i++) { + old = s->b_irq[i]; + if (!(old & (1 << 2))) { + s->b_irq[i] |= (1 << 2); + cpu_alpha_update_irq(s->cpu[i], s->b_irq[i]); + } + } +} + + +static int typhoon_map_irq(PCIDevice *pci_dev, int irq_num) +{ + return irq_num; +} + +static void typhoon_set_irq(qemu_irq *pic, int irq_num, int level) +{ + /* Never called (yet). */ + fprintf(stderr, "typhoon_set_irq: irq_num=%d, level=%d\n", irq_num, level); + exit(4); +} + +TyphoonState *typhoon_21272_init (uint64_t *arr, qemu_irq **irqs, + qemu_irq *intim_irq, void *cpu0) +{ + TyphoonState *s; + int cchip; + int dchip; + int pchip; + int pci_io; + int pci_cfg; + int pci_iack; + int i; + + s = qemu_mallocz(sizeof(TyphoonState)); + + /* Cchip registers. */ + cchip = cpu_register_io_memory(0, typhoon_cchip_read, + typhoon_cchip_write, s); + cpu_register_physical_memory(0x801a0000000ULL, 0x0002000, cchip); + + /* Dchip registers. */ + dchip = cpu_register_io_memory(0, typhoon_dchip_read, + typhoon_dchip_write, s); + cpu_register_physical_memory(0x801b0000000ULL, 0x0002000, dchip); + + /* Pchip0 registers. */ + pchip = cpu_register_io_memory(0, typhoon_pchip_read, + typhoon_pchip_write, &s->pchip[0]); + cpu_register_physical_memory(0x80180000000ULL, 0x0002000, pchip); + + /* Pchip1 registers. */ + pchip = cpu_register_io_memory(0, typhoon_pchip_read, + typhoon_pchip_write, &s->pchip[1]); + cpu_register_physical_memory(0x80380000000ULL, 0x0002000, pchip); + + /* Pchip0 PCI I/O */ + pci_io = cpu_register_io_memory(0, pchip_pci_io_read, + pchip_pci_io_write, &s->pchip[0]); + cpu_register_physical_memory(0x801fc000000ULL, 0x0010000, pci_io); + + /* Pchip0 PCI cfg */ + pci_cfg = cpu_register_io_memory(0, pchip_pci_cfg_read, + pchip_pci_cfg_write, &s->pchip[0]); + cpu_register_physical_memory(0x801fe000000ULL, 0x0010000, pci_cfg); + + /* Pchip0 PCI IntAck */ + pci_iack = cpu_register_io_memory(0, pchip_pci_iack_read, + pchip_pci_iack_write, &s->pchip[0]); + cpu_register_physical_memory(0x801f8000000ULL, 0x002000, pci_iack); + + /* Pchip0 PCI cfg */ + pci_cfg = cpu_register_io_memory(0, pchip_pci_cfg_read, + pchip_pci_cfg_write, &s->pchip[1]); + cpu_register_physical_memory(0x803fe000000ULL, 0x0010000, pci_cfg); + + s->pchip[0].pci = pci_register_bus(typhoon_set_irq, + typhoon_map_irq, + (void *)&s->pchip[0], 0, 64); + + pci_mem_base = 0x80000000000ULL; + isa_mem_base = 0x80000000000ULL; + + typhoon_reset(s); + + /* P1 chip present, 8 dchips, 2 memory buses. */ + s->csc = (1 << 14) | (3 << 0); + + /* Configure cchip array address. */ + for (i = 0; i < 4; i++) + s->aar[i] = arr[i]; + + s->cpu[0] = cpu0; + s->irqs = qemu_allocate_irqs(cchip_set_irq, s, 64); + *irqs = s->irqs; + + s->intim_irq = qemu_allocate_irqs(intim_set_irq, s, 1); + *intim_irq = s->intim_irq[0]; + + qemu_register_reset(&typhoon_reset, s); + + return s; +} + +void typhoon_set_iack_handler(TyphoonState *c, int num, + int (*handler)(void *), void *param) +{ + c->pchip[num].iack_handler = handler; + c->pchip[num].iack_handler_param = param; +} + +PCIBus *typhoon_get_pci_bus(TyphoonState *c, int num) +{ + return c->pchip[num].pci; +} diff --git a/hw/pci.h b/hw/pci.h index e4e0738..4f2496f 100644 --- a/hw/pci.h +++ b/hw/pci.h @@ -261,6 +261,14 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base, PCIBus *sh_pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, qemu_irq *pic, int devfn_min, int nirq); +/* 21272.c */ +typedef struct TyphoonState TyphoonState; +TyphoonState *typhoon_21272_init (uint64_t *arr, qemu_irq **irqs, + qemu_irq *intim_irq, void *cpu0); +void typhoon_set_iack_handler(TyphoonState *c, int num, + int (*handler)(void *), void *param); +PCIBus *typhoon_get_pci_bus(TyphoonState *c, int num); + /* ali1543.c */ typedef struct ALI1543State ALI1543State; ALI1543State *ali1543_init (PCIBus *bus, int devfn, qemu_irq irq); -- 1.6.2