omap1.c
来自「xen虚拟机源代码安装包」· C语言 代码 · 共 2,284 行 · 第 1/5 页
C
2,284 行
case 0x14: /* INTC_SYSSTATUS */ return 1; /* RESETDONE */ case 0x40: /* INTC_SIR_IRQ */ return s->sir_intr[0]; case 0x44: /* INTC_SIR_FIQ */ return s->sir_intr[1]; case 0x48: /* INTC_CONTROL */ return (!s->mask) << 2; /* GLOBALMASK */ case 0x4c: /* INTC_PROTECTION */ return 0; case 0x50: /* INTC_IDLE */ return s->autoidle & 3; /* Per-bank registers */ case 0x80: /* INTC_ITR */ return bank->inputs; case 0x84: /* INTC_MIR */ return bank->mask; case 0x88: /* INTC_MIR_CLEAR */ case 0x8c: /* INTC_MIR_SET */ return 0; case 0x90: /* INTC_ISR_SET */ return bank->swi; case 0x94: /* INTC_ISR_CLEAR */ return 0; case 0x98: /* INTC_PENDING_IRQ */ return bank->irqs & ~bank->mask & ~bank->fiq; case 0x9c: /* INTC_PENDING_FIQ */ return bank->irqs & ~bank->mask & bank->fiq; /* Per-line registers */ case 0x100 ... 0x300: /* INTC_ILR */ bank_no = (offset - 0x100) >> 7; if (bank_no > s->nbanks) break; bank = &s->bank[bank_no]; line_no = (offset & 0x7f) >> 2; return (bank->priority[line_no] << 2) | ((bank->fiq >> line_no) & 1); } OMAP_BAD_REG(addr); return 0;}static void omap2_inth_write(void *opaque, target_phys_addr_t addr, uint32_t value){ struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque; int offset = addr - s->base; int bank_no, line_no; struct omap_intr_handler_bank_s *bank = 0; if ((offset & 0xf80) == 0x80) { bank_no = (offset & 0x60) >> 5; if (bank_no < s->nbanks) { offset &= ~0x60; bank = &s->bank[bank_no]; } } switch (offset) { case 0x10: /* INTC_SYSCONFIG */ s->autoidle &= 4; s->autoidle |= (value & 1) << 2; if (value & 2) /* SOFTRESET */ omap_inth_reset(s); return; case 0x48: /* INTC_CONTROL */ s->mask = (value & 4) ? 0 : ~0; /* GLOBALMASK */ if (value & 2) { /* NEWFIQAGR */ qemu_set_irq(s->parent_intr[1], 0); s->new_agr[1] = ~0; omap_inth_update(s, 1); } if (value & 1) { /* NEWIRQAGR */ qemu_set_irq(s->parent_intr[0], 0); s->new_agr[0] = ~0; omap_inth_update(s, 0); } return; case 0x4c: /* INTC_PROTECTION */ /* TODO: Make a bitmap (or sizeof(char)map) of access privileges * for every register, see Chapter 3 and 4 for privileged mode. */ if (value & 1) fprintf(stderr, "%s: protection mode enable attempt\n", __FUNCTION__); return; case 0x50: /* INTC_IDLE */ s->autoidle &= ~3; s->autoidle |= value & 3; return; /* Per-bank registers */ case 0x84: /* INTC_MIR */ bank->mask = value; omap_inth_update(s, 0); omap_inth_update(s, 1); return; case 0x88: /* INTC_MIR_CLEAR */ bank->mask &= ~value; omap_inth_update(s, 0); omap_inth_update(s, 1); return; case 0x8c: /* INTC_MIR_SET */ bank->mask |= value; return; case 0x90: /* INTC_ISR_SET */ bank->irqs |= bank->swi |= value; omap_inth_update(s, 0); omap_inth_update(s, 1); return; case 0x94: /* INTC_ISR_CLEAR */ bank->swi &= ~value; bank->irqs = bank->swi & bank->inputs; return; /* Per-line registers */ case 0x100 ... 0x300: /* INTC_ILR */ bank_no = (offset - 0x100) >> 7; if (bank_no > s->nbanks) break; bank = &s->bank[bank_no]; line_no = (offset & 0x7f) >> 2; bank->priority[line_no] = (value >> 2) & 0x3f; bank->fiq &= ~(1 << line_no); bank->fiq |= (value & 1) << line_no; return; case 0x00: /* INTC_REVISION */ case 0x14: /* INTC_SYSSTATUS */ case 0x40: /* INTC_SIR_IRQ */ case 0x44: /* INTC_SIR_FIQ */ case 0x80: /* INTC_ITR */ case 0x98: /* INTC_PENDING_IRQ */ case 0x9c: /* INTC_PENDING_FIQ */ OMAP_RO_REG(addr); return; } OMAP_BAD_REG(addr);}static CPUReadMemoryFunc *omap2_inth_readfn[] = { omap_badwidth_read32, omap_badwidth_read32, omap2_inth_read,};static CPUWriteMemoryFunc *omap2_inth_writefn[] = { omap2_inth_write, omap2_inth_write, omap2_inth_write,};struct omap_intr_handler_s *omap2_inth_init(target_phys_addr_t base, int size, int nbanks, qemu_irq **pins, qemu_irq parent_irq, qemu_irq parent_fiq, omap_clk fclk, omap_clk iclk){ int iomemtype; struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) qemu_mallocz(sizeof(struct omap_intr_handler_s) + sizeof(struct omap_intr_handler_bank_s) * nbanks); s->parent_intr[0] = parent_irq; s->parent_intr[1] = parent_fiq; s->base = base; s->nbanks = nbanks; s->level_only = 1; s->pins = qemu_allocate_irqs(omap_set_intr_noedge, s, nbanks * 32); if (pins) *pins = s->pins; omap_inth_reset(s); iomemtype = cpu_register_io_memory(0, omap2_inth_readfn, omap2_inth_writefn, s); cpu_register_physical_memory(s->base, size, iomemtype); return s;}/* MPU OS timers */struct omap_mpu_timer_s { qemu_irq irq; omap_clk clk; target_phys_addr_t base; uint32_t val; int64_t time; QEMUTimer *timer; int64_t rate; int it_ena; int enable; int ptv; int ar; int st; uint32_t reset_val;};static inline uint32_t omap_timer_read(struct omap_mpu_timer_s *timer){ uint64_t distance = qemu_get_clock(vm_clock) - timer->time; if (timer->st && timer->enable && timer->rate) return timer->val - muldiv64(distance >> (timer->ptv + 1), timer->rate, ticks_per_sec); else return timer->val;}static inline void omap_timer_sync(struct omap_mpu_timer_s *timer){ timer->val = omap_timer_read(timer); timer->time = qemu_get_clock(vm_clock);}static inline void omap_timer_update(struct omap_mpu_timer_s *timer){ int64_t expires; if (timer->enable && timer->st && timer->rate) { timer->val = timer->reset_val; /* Should skip this on clk enable */ expires = muldiv64((uint64_t) timer->val << (timer->ptv + 1), ticks_per_sec, timer->rate); /* If timer expiry would be sooner than in about 1 ms and * auto-reload isn't set, then fire immediately. This is a hack * to make systems like PalmOS run in acceptable time. PalmOS * sets the interval to a very low value and polls the status bit * in a busy loop when it wants to sleep just a couple of CPU * ticks. */ if (expires > (ticks_per_sec >> 10) || timer->ar) qemu_mod_timer(timer->timer, timer->time + expires); else { timer->val = 0; timer->st = 0; if (timer->it_ena) /* Edge-triggered irq */ qemu_irq_pulse(timer->irq); } } else qemu_del_timer(timer->timer);}static void omap_timer_tick(void *opaque){ struct omap_mpu_timer_s *timer = (struct omap_mpu_timer_s *) opaque; omap_timer_sync(timer); if (!timer->ar) { timer->val = 0; timer->st = 0; } if (timer->it_ena) /* Edge-triggered irq */ qemu_irq_pulse(timer->irq); omap_timer_update(timer);}static void omap_timer_clk_update(void *opaque, int line, int on){ struct omap_mpu_timer_s *timer = (struct omap_mpu_timer_s *) opaque; omap_timer_sync(timer); timer->rate = on ? omap_clk_getrate(timer->clk) : 0; omap_timer_update(timer);}static void omap_timer_clk_setup(struct omap_mpu_timer_s *timer){ omap_clk_adduser(timer->clk, qemu_allocate_irqs(omap_timer_clk_update, timer, 1)[0]); timer->rate = omap_clk_getrate(timer->clk);}static uint32_t omap_mpu_timer_read(void *opaque, target_phys_addr_t addr){ struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *) opaque; int offset = addr - s->base; switch (offset) { case 0x00: /* CNTL_TIMER */ return (s->enable << 5) | (s->ptv << 2) | (s->ar << 1) | s->st; case 0x04: /* LOAD_TIM */ break; case 0x08: /* READ_TIM */ return omap_timer_read(s); } OMAP_BAD_REG(addr); return 0;}static void omap_mpu_timer_write(void *opaque, target_phys_addr_t addr, uint32_t value){ struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *) opaque; int offset = addr - s->base; switch (offset) { case 0x00: /* CNTL_TIMER */ omap_timer_sync(s); s->enable = (value >> 5) & 1; s->ptv = (value >> 2) & 7; s->ar = (value >> 1) & 1; s->st = value & 1; omap_timer_update(s); return; case 0x04: /* LOAD_TIM */ s->reset_val = value; return; case 0x08: /* READ_TIM */ OMAP_RO_REG(addr); break; default: OMAP_BAD_REG(addr); }}static CPUReadMemoryFunc *omap_mpu_timer_readfn[] = { omap_badwidth_read32, omap_badwidth_read32, omap_mpu_timer_read,};static CPUWriteMemoryFunc *omap_mpu_timer_writefn[] = { omap_badwidth_write32, omap_badwidth_write32, omap_mpu_timer_write,};static void omap_mpu_timer_reset(struct omap_mpu_timer_s *s){ qemu_del_timer(s->timer); s->enable = 0; s->reset_val = 31337; s->val = 0; s->ptv = 0; s->ar = 0; s->st = 0; s->it_ena = 1;}struct omap_mpu_timer_s *omap_mpu_timer_init(target_phys_addr_t base, qemu_irq irq, omap_clk clk){ int iomemtype; struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *) qemu_mallocz(sizeof(struct omap_mpu_timer_s)); s->irq = irq; s->clk = clk; s->base = base; s->timer = qemu_new_timer(vm_clock, omap_timer_tick, s); omap_mpu_timer_reset(s); omap_timer_clk_setup(s); iomemtype = cpu_register_io_memory(0, omap_mpu_timer_readfn, omap_mpu_timer_writefn, s); cpu_register_physical_memory(s->base, 0x100, iomemtype); return s;}/* Watchdog timer */struct omap_watchdog_timer_s { struct omap_mpu_timer_s timer; uint8_t last_wr; int mode; int free; int reset;};static uint32_t omap_wd_timer_read(void *opaque, target_phys_addr_t addr){ struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *) opaque; int offset = addr - s->timer.base; switch (offset) { case 0x00: /* CNTL_TIMER */ return (s->timer.ptv << 9) | (s->timer.ar << 8) | (s->timer.st << 7) | (s->free << 1); case 0x04: /* READ_TIMER */ return omap_timer_read(&s->timer); case 0x08: /* TIMER_MODE */ return s->mode << 15; } OMAP_BAD_REG(addr); return 0;}static void omap_wd_timer_write(void *opaque, target_phys_addr_t addr, uint32_t value){ struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *) opaque; int offset = addr - s->timer.base; switch (offset) { case 0x00: /* CNTL_TIMER */ omap_timer_sync(&s->timer); s->timer.ptv = (value >> 9) & 7; s->timer.ar = (value >> 8) & 1; s->timer.st = (value >> 7) & 1; s->free = (value >> 1) & 1; omap_timer_update(&s->timer); break; case 0x04: /* LOAD_TIMER */ s->timer.reset_val = value & 0xffff; break; case 0x08: /* TIMER_MODE */ if (!s->mode && ((value >> 15) & 1)) omap_clk_get(s->timer.clk); s->mode |= (value >> 15) & 1; if (s->last_wr == 0xf5) { if ((value & 0xff) == 0xa0) { if (s->mode) { s->mode = 0; omap_clk_put(s->timer.clk); } } else { /* XXX: on T|E hardware somehow this has no effect, * on Zire 71 it works as specified. */ s->reset = 1; qemu_system_reset_request(); } } s->last_wr = value & 0xff;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?