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 + -
显示快捷键?