📄 omap.c.svn-base
字号:
{ int i; switch (offset) { case 0x300: /* SYS_DMA_LCD_CTRL */ i = s->condition; s->condition = 0; qemu_irq_lower(s->irq); *ret = ((s->src == imif) << 6) | (i << 3) | (s->interrupts << 1) | s->dual; break; case 0x302: /* SYS_DMA_LCD_TOP_F1_L */ *ret = s->src_f1_top & 0xffff; break; case 0x304: /* SYS_DMA_LCD_TOP_F1_U */ *ret = s->src_f1_top >> 16; break; case 0x306: /* SYS_DMA_LCD_BOT_F1_L */ *ret = s->src_f1_bottom & 0xffff; break; case 0x308: /* SYS_DMA_LCD_BOT_F1_U */ *ret = s->src_f1_bottom >> 16; break; case 0x30a: /* SYS_DMA_LCD_TOP_F2_L */ *ret = s->src_f2_top & 0xffff; break; case 0x30c: /* SYS_DMA_LCD_TOP_F2_U */ *ret = s->src_f2_top >> 16; break; case 0x30e: /* SYS_DMA_LCD_BOT_F2_L */ *ret = s->src_f2_bottom & 0xffff; break; case 0x310: /* SYS_DMA_LCD_BOT_F2_U */ *ret = s->src_f2_bottom >> 16; break; default: return 1; } return 0;}static int omap_dma_sys_write(struct omap_dma_s *s, int offset, uint16_t value){ switch (offset) { case 0x400: /* SYS_DMA_GCR */ s->gcr = value; break; case 0x404: /* DMA_GSCR */ if (value & 0x8) omap_dma_disable_3_1_mapping(s); else omap_dma_enable_3_1_mapping(s); break; case 0x408: /* DMA_GRST */ if (value & 0x1) omap_dma_reset(s); break; default: return 1; } return 0;}static int omap_dma_sys_read(struct omap_dma_s *s, int offset, uint16_t *ret){ switch (offset) { case 0x400: /* SYS_DMA_GCR */ *ret = s->gcr; break; case 0x404: /* DMA_GSCR */ *ret = s->omap_3_1_mapping_disabled << 3; break; case 0x408: /* DMA_GRST */ *ret = 0; break; case 0x442: /* DMA_HW_ID */ case 0x444: /* DMA_PCh2_ID */ case 0x446: /* DMA_PCh0_ID */ case 0x448: /* DMA_PCh1_ID */ case 0x44a: /* DMA_PChG_ID */ case 0x44c: /* DMA_PChD_ID */ *ret = 1; break; case 0x44e: /* DMA_CAPS_0_U */ *ret = (1 << 3) | /* Constant Fill Capacity */ (1 << 2); /* Transparent BLT Capacity */ break; case 0x450: /* DMA_CAPS_0_L */ case 0x452: /* DMA_CAPS_1_U */ *ret = 0; break; case 0x454: /* DMA_CAPS_1_L */ *ret = (1 << 1); /* 1-bit palletized capability */ break; case 0x456: /* DMA_CAPS_2 */ *ret = (1 << 8) | /* SSDIC */ (1 << 7) | /* DDIAC */ (1 << 6) | /* DSIAC */ (1 << 5) | /* DPIAC */ (1 << 4) | /* DCAC */ (1 << 3) | /* SDIAC */ (1 << 2) | /* SSIAC */ (1 << 1) | /* SPIAC */ 1; /* SCAC */ break; case 0x458: /* DMA_CAPS_3 */ *ret = (1 << 5) | /* CCC */ (1 << 4) | /* IC */ (1 << 3) | /* ARC */ (1 << 2) | /* AEC */ (1 << 1) | /* FSC */ 1; /* ESC */ break; case 0x45a: /* DMA_CAPS_4 */ *ret = (1 << 6) | /* SSC */ (1 << 5) | /* BIC */ (1 << 4) | /* LFIC */ (1 << 3) | /* FIC */ (1 << 2) | /* HFIC */ (1 << 1) | /* EDIC */ 1; /* TOIC */ break; case 0x460: /* DMA_PCh2_SR */ case 0x480: /* DMA_PCh0_SR */ case 0x482: /* DMA_PCh1_SR */ case 0x4c0: /* DMA_PChD_SR_0 */ printf("%s: Physical Channel Status Registers not implemented.\n", __FUNCTION__); *ret = 0xff; break; default: return 1; } return 0;}static uint32_t omap_dma_read(void *opaque, target_phys_addr_t addr){ struct omap_dma_s *s = (struct omap_dma_s *) opaque; int reg, ch, offset = addr - s->base; uint16_t ret; switch (offset) { case 0x300 ... 0x3fe: if (s->model == omap_dma_3_1 || !s->omap_3_1_mapping_disabled) { if (omap_dma_3_1_lcd_read(&s->lcd_ch, offset, &ret)) break; return ret; } /* Fall through. */ case 0x000 ... 0x2fe: reg = offset & 0x3f; ch = (offset >> 6) & 0x0f; if (omap_dma_ch_reg_read(s, &s->ch[ch], reg, &ret)) break; return ret; case 0x404 ... 0x4fe: if (s->model == omap_dma_3_1) break; /* Fall through. */ case 0x400: if (omap_dma_sys_read(s, offset, &ret)) break; return ret; case 0xb00 ... 0xbfe: if (s->model == omap_dma_3_2 && s->omap_3_1_mapping_disabled) { if (omap_dma_3_2_lcd_read(&s->lcd_ch, offset, &ret)) break; return ret; } break; } OMAP_BAD_REG(addr); return 0;}static void omap_dma_write(void *opaque, target_phys_addr_t addr, uint32_t value){ struct omap_dma_s *s = (struct omap_dma_s *) opaque; int reg, ch, offset = addr - s->base; switch (offset) { case 0x300 ... 0x3fe: if (s->model == omap_dma_3_1 || !s->omap_3_1_mapping_disabled) { if (omap_dma_3_1_lcd_write(&s->lcd_ch, offset, value)) break; return; } /* Fall through. */ case 0x000 ... 0x2fe: reg = offset & 0x3f; ch = (offset >> 6) & 0x0f; if (omap_dma_ch_reg_write(s, &s->ch[ch], reg, value)) break; return; case 0x404 ... 0x4fe: if (s->model == omap_dma_3_1) break; case 0x400: /* Fall through. */ if (omap_dma_sys_write(s, offset, value)) break; return; case 0xb00 ... 0xbfe: if (s->model == omap_dma_3_2 && s->omap_3_1_mapping_disabled) { if (omap_dma_3_2_lcd_write(&s->lcd_ch, offset, value)) break; return; } break; } OMAP_BAD_REG(addr);}static CPUReadMemoryFunc *omap_dma_readfn[] = { omap_badwidth_read16, omap_dma_read, omap_badwidth_read16,};static CPUWriteMemoryFunc *omap_dma_writefn[] = { omap_badwidth_write16, omap_dma_write, omap_badwidth_write16,};static void omap_dma_request(void *opaque, int drq, int req){ struct omap_dma_s *s = (struct omap_dma_s *) opaque; /* The request pins are level triggered. */ if (req) { if (~s->drq & (1 << drq)) { s->drq |= 1 << drq; omap_dma_process_request(s, drq); } } else s->drq &= ~(1 << drq);}static void omap_dma_clk_update(void *opaque, int line, int on){ struct omap_dma_s *s = (struct omap_dma_s *) opaque; if (on) { /* TODO: make a clever calculation */ s->delay = ticks_per_sec >> 8; if (s->run_count) qemu_mod_timer(s->tm, qemu_get_clock(vm_clock) + s->delay); } else { s->delay = 0; qemu_del_timer(s->tm); }}struct omap_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs, qemu_irq lcd_irq, struct omap_mpu_state_s *mpu, omap_clk clk, enum omap_dma_model model){ int iomemtype, num_irqs, memsize, i; struct omap_dma_s *s = (struct omap_dma_s *) qemu_mallocz(sizeof(struct omap_dma_s)); if (model == omap_dma_3_1) { num_irqs = 6; memsize = 0x800; } else { num_irqs = 16; memsize = 0xc00; } s->base = base; s->model = model; s->mpu = mpu; s->clk = clk; s->lcd_ch.irq = lcd_irq; s->lcd_ch.mpu = mpu; while (num_irqs --) s->ch[num_irqs].irq = irqs[num_irqs]; for (i = 0; i < 3; i ++) { s->ch[i].sibling = &s->ch[i + 6]; s->ch[i + 6].sibling = &s->ch[i]; } s->tm = qemu_new_timer(vm_clock, (QEMUTimerCB *) omap_dma_channel_run, s); omap_clk_adduser(s->clk, qemu_allocate_irqs(omap_dma_clk_update, s, 1)[0]); mpu->drq = qemu_allocate_irqs(omap_dma_request, s, 32); omap_dma_reset(s); omap_dma_clk_update(s, 0, 1); iomemtype = cpu_register_io_memory(0, omap_dma_readfn, omap_dma_writefn, s); cpu_register_physical_memory(s->base, memsize, iomemtype); return s;}/* DMA ports */static int omap_validate_emiff_addr(struct omap_mpu_state_s *s, target_phys_addr_t addr){ return addr >= OMAP_EMIFF_BASE && addr < OMAP_EMIFF_BASE + s->sdram_size;}static int omap_validate_emifs_addr(struct omap_mpu_state_s *s, target_phys_addr_t addr){ return addr >= OMAP_EMIFS_BASE && addr < OMAP_EMIFF_BASE;}static int omap_validate_imif_addr(struct omap_mpu_state_s *s, target_phys_addr_t addr){ return addr >= OMAP_IMIF_BASE && addr < OMAP_IMIF_BASE + s->sram_size;}static int omap_validate_tipb_addr(struct omap_mpu_state_s *s, target_phys_addr_t addr){ return addr >= 0xfffb0000 && addr < 0xffff0000;}static int omap_validate_local_addr(struct omap_mpu_state_s *s, target_phys_addr_t addr){ return addr >= OMAP_LOCALBUS_BASE && addr < OMAP_LOCALBUS_BASE + 0x1000000;}static int omap_validate_tipb_mpui_addr(struct omap_mpu_state_s *s, target_phys_addr_t addr){ return addr >= 0xe1010000 && addr < 0xe1020004;}/* 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(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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -