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

📄 arm_gic.c.svn-base

📁 我们自己开发的一个OSEK操作系统!不知道可不可以?
💻 SVN-BASE
📖 第 1 页 / 共 2 页
字号:
#endif    } else if (offset < 0xfe0) {        goto bad_reg;    } else /* offset >= 0xfe0 */ {        if (offset & 3) {            res = 0;        } else {            res = gic_id[(offset - 0xfe0) >> 2];        }    }    return res;bad_reg:    cpu_abort(cpu_single_env, "gic_dist_readb: Bad offset %x\n", (int)offset);    return 0;}static uint32_t gic_dist_readw(void *opaque, target_phys_addr_t offset){    uint32_t val;    val = gic_dist_readb(opaque, offset);    val |= gic_dist_readb(opaque, offset + 1) << 8;    return val;}static uint32_t gic_dist_readl(void *opaque, target_phys_addr_t offset){    uint32_t val;#ifdef NVIC    gic_state *s = (gic_state *)opaque;    uint32_t addr;    addr = offset - s->base;    if (addr < 0x100 || addr > 0xd00)        return nvic_readl(s->nvic, addr);#endif    val = gic_dist_readw(opaque, offset);    val |= gic_dist_readw(opaque, offset + 2) << 16;    return val;}static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,                            uint32_t value){    gic_state *s = (gic_state *)opaque;    int irq;    int i;    int cpu;    cpu = gic_get_current_cpu();    offset -= s->base + GIC_DIST_OFFSET;    if (offset < 0x100) {#ifdef NVIC        goto bad_reg;#else        if (offset == 0) {            s->enabled = (value & 1);            DPRINTF("Distribution %sabled\n", s->enabled ? "En" : "Dis");        } else if (offset < 4) {            /* ignored.  */        } else {            goto bad_reg;        }#endif    } else if (offset < 0x180) {        /* Interrupt Set Enable.  */        irq = (offset - 0x100) * 8 + GIC_BASE_IRQ;        if (irq >= GIC_NIRQ)            goto bad_reg;        if (irq < 16)          value = 0xff;        for (i = 0; i < 8; i++) {            if (value & (1 << i)) {                int mask = (irq < 32) ? (1 << cpu) : GIC_TARGET(irq);                if (!GIC_TEST_ENABLED(irq + i))                    DPRINTF("Enabled IRQ %d\n", irq + i);                GIC_SET_ENABLED(irq + i);                /* If a raised level triggered IRQ enabled then mark                   is as pending.  */                if (GIC_TEST_LEVEL(irq + i, mask)                        && !GIC_TEST_TRIGGER(irq + i)) {                    DPRINTF("Set %d pending mask %x\n", irq + i, mask);                    GIC_SET_PENDING(irq + i, mask);                }            }        }    } else if (offset < 0x200) {        /* Interrupt Clear Enable.  */        irq = (offset - 0x180) * 8 + GIC_BASE_IRQ;        if (irq >= GIC_NIRQ)            goto bad_reg;        if (irq < 16)          value = 0;        for (i = 0; i < 8; i++) {            if (value & (1 << i)) {                if (GIC_TEST_ENABLED(irq + i))                    DPRINTF("Disabled IRQ %d\n", irq + i);                GIC_CLEAR_ENABLED(irq + i);            }        }    } else if (offset < 0x280) {        /* Interrupt Set Pending.  */        irq = (offset - 0x200) * 8 + GIC_BASE_IRQ;        if (irq >= GIC_NIRQ)            goto bad_reg;        if (irq < 16)          irq = 0;        for (i = 0; i < 8; i++) {            if (value & (1 << i)) {                GIC_SET_PENDING(irq + i, GIC_TARGET(irq));            }        }    } else if (offset < 0x300) {        /* Interrupt Clear Pending.  */        irq = (offset - 0x280) * 8 + GIC_BASE_IRQ;        if (irq >= GIC_NIRQ)            goto bad_reg;        for (i = 0; i < 8; i++) {            /* ??? This currently clears the pending bit for all CPUs, even               for per-CPU interrupts.  It's unclear whether this is the               corect behavior.  */            if (value & (1 << i)) {                GIC_CLEAR_PENDING(irq + i, ALL_CPU_MASK);            }        }    } else if (offset < 0x400) {        /* Interrupt Active.  */        goto bad_reg;    } else if (offset < 0x800) {        /* Interrupt Priority.  */        irq = (offset - 0x400) + GIC_BASE_IRQ;        if (irq >= GIC_NIRQ)            goto bad_reg;        if (irq < 32) {            s->priority1[irq][cpu] = value;        } else {            s->priority2[irq - 32] = value;        }#ifndef NVIC    } else if (offset < 0xc00) {        /* Interrupt CPU Target.  */        irq = (offset - 0x800) + GIC_BASE_IRQ;        if (irq >= GIC_NIRQ)            goto bad_reg;        if (irq < 29)            value = 0;        else if (irq < 32)            value = ALL_CPU_MASK;        s->irq_target[irq] = value & ALL_CPU_MASK;    } else if (offset < 0xf00) {        /* Interrupt Configuration.  */        irq = (offset - 0xc00) * 4 + GIC_BASE_IRQ;        if (irq >= GIC_NIRQ)            goto bad_reg;        if (irq < 32)            value |= 0xaa;        for (i = 0; i < 4; i++) {            if (value & (1 << (i * 2))) {                GIC_SET_MODEL(irq + i);            } else {                GIC_CLEAR_MODEL(irq + i);            }            if (value & (2 << (i * 2))) {                GIC_SET_TRIGGER(irq + i);            } else {                GIC_CLEAR_TRIGGER(irq + i);            }        }#endif    } else {        /* 0xf00 is only handled for 32-bit writes.  */        goto bad_reg;    }    gic_update(s);    return;bad_reg:    cpu_abort(cpu_single_env, "gic_dist_writeb: Bad offset %x\n", (int)offset);}static void gic_dist_writew(void *opaque, target_phys_addr_t offset,                            uint32_t value){    gic_dist_writeb(opaque, offset, value & 0xff);    gic_dist_writeb(opaque, offset + 1, value >> 8);}static void gic_dist_writel(void *opaque, target_phys_addr_t offset,                            uint32_t value){    gic_state *s = (gic_state *)opaque;#ifdef NVIC    uint32_t addr;    addr = offset - s->base;    if (addr < 0x100 || (addr > 0xd00 && addr != 0xf00)) {        nvic_writel(s->nvic, addr, value);        return;    }#endif    if (offset - s->base == GIC_DIST_OFFSET + 0xf00) {        int cpu;        int irq;        int mask;        cpu = gic_get_current_cpu();        irq = value & 0x3ff;        switch ((value >> 24) & 3) {        case 0:            mask = (value >> 16) & ALL_CPU_MASK;            break;        case 1:            mask = 1 << cpu;            break;        case 2:            mask = ALL_CPU_MASK ^ (1 << cpu);            break;        default:            DPRINTF("Bad Soft Int target filter\n");            mask = ALL_CPU_MASK;            break;        }        GIC_SET_PENDING(irq, mask);        gic_update(s);        return;    }    gic_dist_writew(opaque, offset, value & 0xffff);    gic_dist_writew(opaque, offset + 2, value >> 16);}static CPUReadMemoryFunc *gic_dist_readfn[] = {   gic_dist_readb,   gic_dist_readw,   gic_dist_readl};static CPUWriteMemoryFunc *gic_dist_writefn[] = {   gic_dist_writeb,   gic_dist_writew,   gic_dist_writel};#ifndef NVICstatic uint32_t gic_cpu_read(gic_state *s, int cpu, int offset){    switch (offset) {    case 0x00: /* Control */        return s->cpu_enabled[cpu];    case 0x04: /* Priority mask */        return s->priority_mask[cpu];    case 0x08: /* Binary Point */        /* ??? Not implemented.  */        return 0;    case 0x0c: /* Acknowledge */        return gic_acknowledge_irq(s, cpu);    case 0x14: /* Runing Priority */        return s->running_priority[cpu];    case 0x18: /* Highest Pending Interrupt */        return s->current_pending[cpu];    default:        cpu_abort(cpu_single_env, "gic_cpu_read: Bad offset %x\n",                  (int)offset);        return 0;    }}static void gic_cpu_write(gic_state *s, int cpu, int offset, uint32_t value){    switch (offset) {    case 0x00: /* Control */        s->cpu_enabled[cpu] = (value & 1);        DPRINTF("CPU %sabled\n", s->cpu_enabled ? "En" : "Dis");        break;    case 0x04: /* Priority mask */        s->priority_mask[cpu] = (value & 0xff);        break;    case 0x08: /* Binary Point */        /* ??? Not implemented.  */        break;    case 0x10: /* End Of Interrupt */        return gic_complete_irq(s, cpu, value & 0x3ff);    default:        cpu_abort(cpu_single_env, "gic_cpu_write: Bad offset %x\n",                  (int)offset);        return;    }    gic_update(s);}#endifstatic void gic_reset(gic_state *s){    int i;    memset(s->irq_state, 0, GIC_NIRQ * sizeof(gic_irq_state));    for (i = 0 ; i < NCPU; i++) {        s->priority_mask[i] = 0xf0;        s->current_pending[i] = 1023;        s->running_irq[i] = 1023;        s->running_priority[i] = 0x100;#ifdef NVIC        /* The NVIC doesn't have per-cpu interfaces, so enable by default.  */        s->cpu_enabled[i] = 1;#else        s->cpu_enabled[i] = 0;#endif    }    for (i = 0; i < 16; i++) {        GIC_SET_ENABLED(i);        GIC_SET_TRIGGER(i);    }#ifdef NVIC    /* The NVIC is always enabled.  */    s->enabled = 1;#else    s->enabled = 0;#endif}static gic_state *gic_init(uint32_t base, qemu_irq *parent_irq){    gic_state *s;    int iomemtype;    int i;    s = (gic_state *)qemu_mallocz(sizeof(gic_state));    if (!s)        return NULL;    s->in = qemu_allocate_irqs(gic_set_irq, s, GIC_NIRQ);    for (i = 0; i < NCPU; i++) {        s->parent_irq[i] = parent_irq[i];    }    iomemtype = cpu_register_io_memory(0, gic_dist_readfn,                                       gic_dist_writefn, s);    cpu_register_physical_memory(base + GIC_DIST_OFFSET, 0x00001000,                                 iomemtype);    s->base = base;    gic_reset(s);    return s;}

⌨️ 快捷键说明

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