⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 openpic.c

📁 qemu虚拟机代码
💻 C
📖 第 1 页 / 共 2 页
字号:
    if (addr & 0xF)        return;#if defined OPENPIC_SWAP    val = bswap32(val);#endif    addr &= 0xFF;    switch (addr) {    case 0x00: /* FREP */        break;    case 0x20: /* GLBC */        if (val & 0x80000000)            openpic_reset(opp);        opp->glbc = val & ~0x80000000;	break;    case 0x80: /* VENI */	break;    case 0x90: /* PINT */        /* XXX: Should be able to reset any CPU */        if (val & 1) {            DPRINTF("Reset CPU IRQ\n");            //            cpu_interrupt(first_cpu, CPU_INTERRUPT_RESET);        }	break;#if MAX_IPI > 0    case 0xA0: /* IPI_IPVP */    case 0xB0:    case 0xC0:    case 0xD0:        {            int idx;            idx = (addr - 0xA0) >> 4;            write_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IPVP, val);        }        break;#endif    case 0xE0: /* SPVE */        opp->spve = val & 0x000000FF;        break;    case 0xF0: /* TIFR */        opp->tifr = val;	break;    default:        break;    }}static uint32_t openpic_gbl_read (void *opaque, uint32_t addr){    openpic_t *opp = opaque;    uint32_t retval;    DPRINTF("%s: addr %08x\n", __func__, addr);    retval = 0xFFFFFFFF;    if (addr & 0xF)        return retval;    addr &= 0xFF;    switch (addr) {    case 0x00: /* FREP */        retval = opp->frep;        break;    case 0x20: /* GLBC */        retval = opp->glbc;	break;    case 0x80: /* VENI */        retval = opp->veni;	break;    case 0x90: /* PINT */        retval = 0x00000000;	break;#if MAX_IPI > 0    case 0xA0: /* IPI_IPVP */    case 0xB0:    case 0xC0:    case 0xD0:        {            int idx;            idx = (addr - 0xA0) >> 4;            retval = read_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IPVP);        }	break;#endif    case 0xE0: /* SPVE */        retval = opp->spve;        break;    case 0xF0: /* TIFR */        retval = opp->tifr;	break;    default:        break;    }    DPRINTF("%s: => %08x\n", __func__, retval);#if defined OPENPIC_SWAP    retval = bswap32(retval);#endif    return retval;}static void openpic_timer_write (void *opaque, uint32_t addr, uint32_t val){    openpic_t *opp = opaque;    int idx;    DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);    if (addr & 0xF)        return;#if defined OPENPIC_SWAP    val = bswap32(val);#endif    addr -= 0x1100;    addr &= 0xFFFF;    idx = (addr & 0xFFF0) >> 6;    addr = addr & 0x30;    switch (addr) {    case 0x00: /* TICC */        break;    case 0x10: /* TIBC */	if ((opp->timers[idx].ticc & 0x80000000) != 0 &&	    (val & 0x80000000) == 0 &&            (opp->timers[idx].tibc & 0x80000000) != 0)	    opp->timers[idx].ticc &= ~0x80000000;	opp->timers[idx].tibc = val;	break;    case 0x20: /* TIVP */	write_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IPVP, val);	break;    case 0x30: /* TIDE */	write_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IDE, val);	break;    }}static uint32_t openpic_timer_read (void *opaque, uint32_t addr){    openpic_t *opp = opaque;    uint32_t retval;    int idx;    DPRINTF("%s: addr %08x\n", __func__, addr);    retval = 0xFFFFFFFF;    if (addr & 0xF)        return retval;    addr -= 0x1100;    addr &= 0xFFFF;    idx = (addr & 0xFFF0) >> 6;    addr = addr & 0x30;    switch (addr) {    case 0x00: /* TICC */	retval = opp->timers[idx].ticc;        break;    case 0x10: /* TIBC */	retval = opp->timers[idx].tibc;	break;    case 0x20: /* TIPV */	retval = read_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IPVP);	break;    case 0x30: /* TIDE */	retval = read_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IDE);	break;    }    DPRINTF("%s: => %08x\n", __func__, retval);#if defined OPENPIC_SWAP    retval = bswap32(retval);#endif    return retval;}static void openpic_src_write (void *opaque, uint32_t addr, uint32_t val){    openpic_t *opp = opaque;    int idx;    DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);    if (addr & 0xF)        return;#if defined OPENPIC_SWAP    val = tswap32(val);#endif    addr = addr & 0xFFF0;    idx = addr >> 5;    if (addr & 0x10) {        /* EXDE / IFEDE / IEEDE */        write_IRQreg(opp, idx, IRQ_IDE, val);    } else {        /* EXVP / IFEVP / IEEVP */        write_IRQreg(opp, idx, IRQ_IPVP, val);    }}static uint32_t openpic_src_read (void *opaque, uint32_t addr){    openpic_t *opp = opaque;    uint32_t retval;    int idx;    DPRINTF("%s: addr %08x\n", __func__, addr);    retval = 0xFFFFFFFF;    if (addr & 0xF)        return retval;    addr = addr & 0xFFF0;    idx = addr >> 5;    if (addr & 0x10) {        /* EXDE / IFEDE / IEEDE */        retval = read_IRQreg(opp, idx, IRQ_IDE);    } else {        /* EXVP / IFEVP / IEEVP */        retval = read_IRQreg(opp, idx, IRQ_IPVP);    }    DPRINTF("%s: => %08x\n", __func__, retval);#if defined OPENPIC_SWAP    retval = tswap32(retval);#endif    return retval;}static void openpic_cpu_write (void *opaque, uint32_t addr, uint32_t val){    openpic_t *opp = opaque;    IRQ_src_t *src;    IRQ_dst_t *dst;    int idx, n_IRQ;    DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);    if (addr & 0xF)        return;#if defined OPENPIC_SWAP    val = bswap32(val);#endif    addr &= 0x1FFF0;    idx = addr / 0x1000;    dst = &opp->dst[idx];    addr &= 0xFF0;    switch (addr) {#if MAX_IPI > 0    case 0x40: /* PIPD */    case 0x50:    case 0x60:    case 0x70:        idx = (addr - 0x40) >> 4;        write_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IDE, val);        openpic_set_irq(opp, IRQ_IPI0 + idx, 1);        openpic_set_irq(opp, IRQ_IPI0 + idx, 0);        break;#endif    case 0x80: /* PCTP */	dst->pctp = val & 0x0000000F;	break;    case 0x90: /* WHOAMI */	/* Read-only register */	break;    case 0xA0: /* PIAC */	/* Read-only register */	break;    case 0xB0: /* PEOI */        DPRINTF("PEOI\n");	n_IRQ = IRQ_get_next(opp, &dst->servicing);	IRQ_resetbit(&dst->servicing, n_IRQ);	dst->servicing.next = -1;	src = &opp->src[n_IRQ];	/* Set up next servicing IRQ */	IRQ_get_next(opp, &dst->servicing);	/* Check queued interrupts. */	n_IRQ = IRQ_get_next(opp, &dst->raised);	if (n_IRQ != -1) {	    src = &opp->src[n_IRQ];	    if (IPVP_PRIORITY(src->ipvp) > dst->servicing.priority) {                DPRINTF("Raise CPU IRQ\n");                cpu_interrupt(dst->env, CPU_INTERRUPT_HARD);            }	}	break;    default:        break;    }}static uint32_t openpic_cpu_read (void *opaque, uint32_t addr){    openpic_t *opp = opaque;    IRQ_src_t *src;    IRQ_dst_t *dst;    uint32_t retval;    int idx, n_IRQ;        DPRINTF("%s: addr %08x\n", __func__, addr);    retval = 0xFFFFFFFF;    if (addr & 0xF)        return retval;    addr &= 0x1FFF0;    idx = addr / 0x1000;    dst = &opp->dst[idx];    addr &= 0xFF0;    switch (addr) {    case 0x80: /* PCTP */	retval = dst->pctp;	break;    case 0x90: /* WHOAMI */	retval = idx;	break;    case 0xA0: /* PIAC */	n_IRQ = IRQ_get_next(opp, &dst->raised);        DPRINTF("PIAC: irq=%d\n", n_IRQ);	if (n_IRQ == -1) {	    /* No more interrupt pending */            retval = opp->spve;	} else {	    src = &opp->src[n_IRQ];	    if (!test_bit(&src->ipvp, IPVP_ACTIVITY) ||		!(IPVP_PRIORITY(src->ipvp) > dst->pctp)) {		/* - Spurious level-sensitive IRQ		 * - Priorities has been changed		 *   and the pending IRQ isn't allowed anymore		 */		reset_bit(&src->ipvp, IPVP_ACTIVITY);		retval = IPVP_VECTOR(opp->spve);	    } else {		/* IRQ enter servicing state */		IRQ_setbit(&dst->servicing, n_IRQ);		retval = IPVP_VECTOR(src->ipvp);	    }	    IRQ_resetbit(&dst->raised, n_IRQ);	    dst->raised.next = -1;	    if (!test_bit(&src->ipvp, IPVP_SENSE)) {                /* edge-sensitive IRQ */		reset_bit(&src->ipvp, IPVP_ACTIVITY);                src->pending = 0;            }	}	break;    case 0xB0: /* PEOI */	retval = 0;	break;#if MAX_IPI > 0    case 0x40: /* IDE */    case 0x50:        idx = (addr - 0x40) >> 4;        retval = read_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IDE);        break;#endif    default:        break;    }    DPRINTF("%s: => %08x\n", __func__, retval);#if defined OPENPIC_SWAP    retval= bswap32(retval);#endif    return retval;}static void openpic_buggy_write (void *opaque,                                 target_phys_addr_t addr, uint32_t val){    printf("Invalid OPENPIC write access !\n");}static uint32_t openpic_buggy_read (void *opaque, target_phys_addr_t addr){    printf("Invalid OPENPIC read access !\n");    return -1;}static void openpic_writel (void *opaque,                            target_phys_addr_t addr, uint32_t val){    openpic_t *opp = opaque;    addr &= 0x3FFFF;    DPRINTF("%s: offset %08x val: %08x\n", __func__, (int)addr, val);    if (addr < 0x1100) {        /* Global registers */        openpic_gbl_write(opp, addr, val);    } else if (addr < 0x10000) {        /* Timers registers */        openpic_timer_write(opp, addr, val);    } else if (addr < 0x20000) {        /* Source registers */        openpic_src_write(opp, addr, val);    } else {        /* CPU registers */        openpic_cpu_write(opp, addr, val);    }}static uint32_t openpic_readl (void *opaque,target_phys_addr_t addr){    openpic_t *opp = opaque;    uint32_t retval;    addr &= 0x3FFFF;    DPRINTF("%s: offset %08x\n", __func__, (int)addr);    if (addr < 0x1100) {        /* Global registers */        retval = openpic_gbl_read(opp, addr);    } else if (addr < 0x10000) {        /* Timers registers */        retval = openpic_timer_read(opp, addr);    } else if (addr < 0x20000) {        /* Source registers */        retval = openpic_src_read(opp, addr);    } else {        /* CPU registers */        retval = openpic_cpu_read(opp, addr);    }    return retval;}static CPUWriteMemoryFunc *openpic_write[] = {    &openpic_buggy_write,    &openpic_buggy_write,    &openpic_writel,};static CPUReadMemoryFunc *openpic_read[] = {    &openpic_buggy_read,    &openpic_buggy_read,    &openpic_readl,};static void openpic_map(PCIDevice *pci_dev, int region_num,                         uint32_t addr, uint32_t size, int type){    openpic_t *opp;    DPRINTF("Map OpenPIC\n");    opp = (openpic_t *)pci_dev;    /* Global registers */    DPRINTF("Register OPENPIC gbl   %08x => %08x\n",            addr + 0x1000, addr + 0x1000 + 0x100);    /* Timer registers */    DPRINTF("Register OPENPIC timer %08x => %08x\n",            addr + 0x1100, addr + 0x1100 + 0x40 * MAX_TMR);    /* Interrupt source registers */    DPRINTF("Register OPENPIC src   %08x => %08x\n",            addr + 0x10000, addr + 0x10000 + 0x20 * (EXT_IRQ + 2));    /* Per CPU registers */    DPRINTF("Register OPENPIC dst   %08x => %08x\n",            addr + 0x20000, addr + 0x20000 + 0x1000 * MAX_CPU);    cpu_register_physical_memory(addr, 0x40000, opp->mem_index);#if 0 // Don't implement ISU for now    opp_io_memory = cpu_register_io_memory(0, openpic_src_read,                                           openpic_src_write);    cpu_register_physical_memory(isu_base, 0x20 * (EXT_IRQ + 2),                                 opp_io_memory);#endif}openpic_t *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,                         CPUPPCState **envp){    openpic_t *opp;    uint8_t *pci_conf;    int i, m;        /* XXX: for now, only one CPU is supported */    if (nb_cpus != 1)        return NULL;    if (bus) {        opp = (openpic_t *)pci_register_device(bus, "OpenPIC", sizeof(openpic_t),                                               -1, NULL, NULL);        if (opp == NULL)            return NULL;        pci_conf = opp->pci_dev.config;        pci_conf[0x00] = 0x14; // IBM MPIC2        pci_conf[0x01] = 0x10;        pci_conf[0x02] = 0xFF;        pci_conf[0x03] = 0xFF;        pci_conf[0x0a] = 0x80; // PIC        pci_conf[0x0b] = 0x08;        pci_conf[0x0e] = 0x00; // header_type        pci_conf[0x3d] = 0x00; // no interrupt pin                /* Register I/O spaces */        pci_register_io_region((PCIDevice *)opp, 0, 0x40000,                               PCI_ADDRESS_SPACE_MEM, &openpic_map);    } else {        opp = qemu_mallocz(sizeof(openpic_t));    }    opp->mem_index = cpu_register_io_memory(0, openpic_read,                                            openpic_write, opp);        //    isu_base &= 0xFFFC0000;    opp->nb_cpus = nb_cpus;    /* Set IRQ types */    for (i = 0; i < EXT_IRQ; i++) {        opp->src[i].type = IRQ_EXTERNAL;    }    for (; i < IRQ_TIM0; i++) {        opp->src[i].type = IRQ_SPECIAL;    }#if MAX_IPI > 0    m = IRQ_IPI0;#else    m = IRQ_DBL0;#endif    for (; i < m; i++) {        opp->src[i].type = IRQ_TIMER;    }    for (; i < MAX_IRQ; i++) {        opp->src[i].type = IRQ_INTERNAL;    }    for (i = 0; i < nb_cpus; i++)        opp->dst[i].env = envp[i];    openpic_reset(opp);    if (pmem_index)        *pmem_index = opp->mem_index;    return opp;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -