omap_dma.c
来自「xen虚拟机源代码安装包」· C语言 代码 · 共 1,842 行 · 第 1/4 页
C
1,842 行
(1 << 3) | /* SRC_DOUBLE_INDEX_ADRS_CPBLTY */ (1 << 2) | /* SRC_SINGLE_INDEX_ADRS_CPBLTY */ (1 << 1) | /* SRC_POST_INCRMNT_ADRS_CPBLTY */ (1 << 0); /* SRC_CONST_ADRS_CPBLTY */ s->caps[3] = (1 << 6) | /* BLOCK_SYNCHR_CPBLTY (DMA 4 only) */ (1 << 7) | /* PKT_SYNCHR_CPBLTY (DMA 4 only) */ (1 << 5) | /* CHANNEL_CHAINING_CPBLTY */ (1 << 4) | /* LCh_INTERLEAVE_CPBLTY */ (1 << 3) | /* AUTOINIT_REPEAT_CPBLTY (DMA 3.2 only) */ (1 << 2) | /* AUTOINIT_ENDPROG_CPBLTY (DMA 3.2 only) */ (1 << 1) | /* FRAME_SYNCHR_CPBLTY */ (1 << 0); /* ELMNT_SYNCHR_CPBLTY */ s->caps[4] = (1 << 7) | /* PKT_INTERRUPT_CPBLTY (DMA 4 only) */ (1 << 6) | /* SYNC_STATUS_CPBLTY */ (1 << 5) | /* BLOCK_INTERRUPT_CPBLTY */ (1 << 4) | /* LAST_FRAME_INTERRUPT_CPBLTY */ (1 << 3) | /* FRAME_INTERRUPT_CPBLTY */ (1 << 2) | /* HALF_FRAME_INTERRUPT_CPBLTY */ (1 << 1) | /* EVENT_DROP_INTERRUPT_CPBLTY */ (1 << 0); /* TIMEOUT_INTERRUPT_CPBLTY (DMA 3.2 only) */ break; }}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; omap_dma_setcaps(s); 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;}static void omap_dma_interrupts_4_update(struct omap_dma_s *s){ struct omap_dma_channel_s *ch = s->ch; uint32_t bmp, bit; for (bmp = 0, bit = 1; bit; ch ++, bit <<= 1) if (ch->status) { bmp |= bit; ch->cstatus |= ch->status; ch->status = 0; } if ((s->irqstat[0] |= s->irqen[0] & bmp)) qemu_irq_raise(s->irq[0]); if ((s->irqstat[1] |= s->irqen[1] & bmp)) qemu_irq_raise(s->irq[1]); if ((s->irqstat[2] |= s->irqen[2] & bmp)) qemu_irq_raise(s->irq[2]); if ((s->irqstat[3] |= s->irqen[3] & bmp)) qemu_irq_raise(s->irq[3]);}static uint32_t omap_dma4_read(void *opaque, target_phys_addr_t addr){ struct omap_dma_s *s = (struct omap_dma_s *) opaque; int irqn = 0, chnum, offset = addr - s->base; struct omap_dma_channel_s *ch; switch (offset) { case 0x00: /* DMA4_REVISION */ return 0x40; case 0x14: /* DMA4_IRQSTATUS_L3 */ irqn ++; case 0x10: /* DMA4_IRQSTATUS_L2 */ irqn ++; case 0x0c: /* DMA4_IRQSTATUS_L1 */ irqn ++; case 0x08: /* DMA4_IRQSTATUS_L0 */ return s->irqstat[irqn]; case 0x24: /* DMA4_IRQENABLE_L3 */ irqn ++; case 0x20: /* DMA4_IRQENABLE_L2 */ irqn ++; case 0x1c: /* DMA4_IRQENABLE_L1 */ irqn ++; case 0x18: /* DMA4_IRQENABLE_L0 */ return s->irqen[irqn]; case 0x28: /* DMA4_SYSSTATUS */ return 1; /* RESETDONE */ case 0x2c: /* DMA4_OCP_SYSCONFIG */ return s->ocp; case 0x64: /* DMA4_CAPS_0 */ return s->caps[0]; case 0x6c: /* DMA4_CAPS_2 */ return s->caps[2]; case 0x70: /* DMA4_CAPS_3 */ return s->caps[3]; case 0x74: /* DMA4_CAPS_4 */ return s->caps[4]; case 0x78: /* DMA4_GCR */ return s->gcr; case 0x80 ... 0xfff: offset -= 0x80; chnum = offset / 0x60; ch = s->ch + chnum; offset -= chnum * 0x60; break; default: OMAP_BAD_REG(addr); return 0; } /* Per-channel registers */ switch (offset) { case 0x00: /* DMA4_CCR */ return (ch->buf_disable << 25) | (ch->src_sync << 24) | (ch->prefetch << 23) | ((ch->sync & 0x60) << 14) | (ch->bs << 18) | (ch->transparent_copy << 17) | (ch->constant_fill << 16) | (ch->mode[1] << 14) | (ch->mode[0] << 12) | (0 << 10) | (0 << 9) | (ch->suspend << 8) | (ch->enable << 7) | (ch->priority << 6) | (ch->fs << 5) | (ch->sync & 0x1f); case 0x04: /* DMA4_CLNK_CTRL */ return (ch->link_enabled << 15) | ch->link_next_ch; case 0x08: /* DMA4_CICR */ return ch->interrupts; case 0x0c: /* DMA4_CSR */ return ch->cstatus; case 0x10: /* DMA4_CSDP */ return (ch->endian[0] << 21) | (ch->endian_lock[0] << 20) | (ch->endian[1] << 19) | (ch->endian_lock[1] << 18) | (ch->write_mode << 16) | (ch->burst[1] << 14) | (ch->pack[1] << 13) | (ch->translate[1] << 9) | (ch->burst[0] << 7) | (ch->pack[0] << 6) | (ch->translate[0] << 2) | (ch->data_type >> 1); case 0x14: /* DMA4_CEN */ return ch->elements; case 0x18: /* DMA4_CFN */ return ch->frames; case 0x1c: /* DMA4_CSSA */ return ch->addr[0]; case 0x20: /* DMA4_CDSA */ return ch->addr[1]; case 0x24: /* DMA4_CSEI */ return ch->element_index[0]; case 0x28: /* DMA4_CSFI */ return ch->frame_index[0]; case 0x2c: /* DMA4_CDEI */ return ch->element_index[1]; case 0x30: /* DMA4_CDFI */ return ch->frame_index[1]; case 0x34: /* DMA4_CSAC */ return ch->active_set.src & 0xffff; case 0x38: /* DMA4_CDAC */ return ch->active_set.dest & 0xffff; case 0x3c: /* DMA4_CCEN */ return ch->active_set.element; case 0x40: /* DMA4_CCFN */ return ch->active_set.frame; case 0x44: /* DMA4_COLOR */ /* XXX only in sDMA */ return ch->color; default: OMAP_BAD_REG(addr); return 0; }}static void omap_dma4_write(void *opaque, target_phys_addr_t addr, uint32_t value){ struct omap_dma_s *s = (struct omap_dma_s *) opaque; int chnum, irqn = 0, offset = addr - s->base; struct omap_dma_channel_s *ch; switch (offset) { case 0x14: /* DMA4_IRQSTATUS_L3 */ irqn ++; case 0x10: /* DMA4_IRQSTATUS_L2 */ irqn ++; case 0x0c: /* DMA4_IRQSTATUS_L1 */ irqn ++; case 0x08: /* DMA4_IRQSTATUS_L0 */ s->irqstat[irqn] &= ~value; if (!s->irqstat[irqn]) qemu_irq_lower(s->irq[irqn]); return; case 0x24: /* DMA4_IRQENABLE_L3 */ irqn ++; case 0x20: /* DMA4_IRQENABLE_L2 */ irqn ++; case 0x1c: /* DMA4_IRQENABLE_L1 */ irqn ++; case 0x18: /* DMA4_IRQENABLE_L0 */ s->irqen[irqn] = value; return; case 0x2c: /* DMA4_OCP_SYSCONFIG */ if (value & 2) /* SOFTRESET */ omap_dma_reset(s); s->ocp = value & 0x3321; if (((s->ocp >> 12) & 3) == 3) /* MIDLEMODE */ fprintf(stderr, "%s: invalid DMA power mode\n", __FUNCTION__); return; case 0x78: /* DMA4_GCR */ s->gcr = value & 0x00ff00ff; if ((value & 0xff) == 0x00) /* MAX_CHANNEL_FIFO_DEPTH */ fprintf(stderr, "%s: wrong FIFO depth in GCR\n", __FUNCTION__); return; case 0x80 ... 0xfff: offset -= 0x80; chnum = offset / 0x60; ch = s->ch + chnum; offset -= chnum * 0x60; break; case 0x00: /* DMA4_REVISION */ case 0x28: /* DMA4_SYSSTATUS */ case 0x64: /* DMA4_CAPS_0 */ case 0x6c: /* DMA4_CAPS_2 */ case 0x70: /* DMA4_CAPS_3 */ case 0x74: /* DMA4_CAPS_4 */ OMAP_RO_REG(addr); return; default: OMAP_BAD_REG(addr); return; } /* Per-channel registers */ switch (offset) { case 0x00: /* DMA4_CCR */ ch->buf_disable = (value >> 25) & 1; ch->src_sync = (value >> 24) & 1; /* XXX For CamDMA must be 1 */ if (ch->buf_disable && !ch->src_sync) fprintf(stderr, "%s: Buffering disable is not allowed in " "destination synchronised mode\n", __FUNCTION__); ch->prefetch = (value >> 23) & 1; ch->bs = (value >> 18) & 1; ch->transparent_copy = (value >> 17) & 1; ch->constant_fill = (value >> 16) & 1; ch->mode[1] = (omap_dma_addressing_t) ((value & 0xc000) >> 14); ch->mode[0] = (omap_dma_addressing_t) ((value & 0x3000) >> 12); ch->suspend = (value & 0x0100) >> 8; ch->priority = (value & 0x0040) >> 6; ch->fs = (value & 0x0020) >> 5; if (ch->fs && ch->bs && ch->mode[0] && ch->mode[1]) fprintf(stderr, "%s: For a packet transfer at least one port " "must be constant-addressed\n", __FUNCTION__); ch->sync = (value & 0x001f) | ((value >> 14) & 0x0060); /* XXX must be 0x01 for CamDMA */ if (value & 0x0080) omap_dma_enable_channel(s, ch); else omap_dma_disable_channel(s, ch); break; case 0x04: /* DMA4_CLNK_CTRL */ ch->link_enabled = (value >> 15) & 0x1; ch->link_next_ch = value & 0x1f; break; case 0x08: /* DMA4_CICR */ ch->interrupts = value & 0x09be; break; case 0x0c: /* DMA4_CSR */ ch->cstatus &= ~value; break; case 0x10: /* DMA4_CSDP */ ch->endian[0] =(value >> 21) & 1; ch->endian_lock[0] =(value >> 20) & 1; ch->endian[1] =(value >> 19) & 1; ch->endian_lock[1] =(value >> 18) & 1; if (ch->endian[0] != ch->endian[1]) fprintf(stderr, "%s: DMA endianned conversion enable attempt\n", __FUNCTION__); ch->write_mode = (value >> 16) & 3; ch->burst[1] = (value & 0xc000) >> 14; ch->pack[1] = (value & 0x2000) >> 13; ch->translate[1] = (value & 0x1e00) >> 9; ch->burst[0] = (value & 0x0180) >> 7; ch->pack[0] = (value & 0x0040) >> 6; ch->translate[0] = (value & 0x003c) >> 2; if (ch->translate[0] | ch->translate[1]) fprintf(stderr, "%s: bad MReqAddressTranslate sideband signal\n", __FUNCTION__); ch->data_type = 1 << (value & 3); if ((value & 3) == 3) printf("%s: bad data_type for DMA channel\n", __FUNCTION__); break; case 0x14: /* DMA4_CEN */ ch->elements = value & 0xffffff; break; case 0x18: /* DMA4_CFN */ ch->frames = value & 0xffff; break; case 0x1c: /* DMA4_CSSA */ ch->addr[0] = (target_phys_addr_t) (uint32_t) value; break; case 0x20: /* DMA4_CDSA */ ch->addr[1] = (target_phys_addr_t) (uint32_t) value; break; case 0x24: /* DMA4_CSEI */ ch->element_index[0] = (int16_t) value; break; case 0x28: /* DMA4_CSFI */ ch->frame_index[0] = (int32_t) value; break; case 0x2c: /* DMA4_CDEI */ ch->element_index[1] = (int16_t) value; break; case 0x30: /* DMA4_CDFI */ ch->frame_index[1] = (int32_t) value; break; case 0x44: /* DMA4_COLOR */ /* XXX only in sDMA */ ch->color = value; break; case 0x34: /* DMA4_CSAC */ case 0x38: /* DMA4_CDAC */ case 0x3c: /* DMA4_CCEN */ case 0x40: /* DMA4_CCFN */ OMAP_RO_REG(addr); break; default: OMAP_BAD_REG(addr); }}static CPUReadMemoryFunc *omap_dma4_readfn[] = { omap_badwidth_read16, omap_dma4_read, omap_dma4_read,};static CPUWriteMemoryFunc *omap_dma4_writefn[] = { omap_badwidth_write16, omap_dma4_write, omap_dma4_write,};struct omap_dma_s *omap_dma4_init(target_phys_addr_t base, qemu_irq *irqs, struct omap_mpu_state_s *mpu, int fifo, int chans, omap_clk iclk, omap_clk fclk){ int iomemtype; struct omap_dma_s *s = (struct omap_dma_s *) qemu_mallocz(sizeof(struct omap_dma_s)); s->base = base; s->model = omap_dma_4; s->chans = chans; s->mpu = mpu; s->clk = fclk; memcpy(&s->irq, irqs, sizeof(s->irq)); s->intr_update = omap_dma_interrupts_4_update; omap_dma_setcaps(s); 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, 64); omap_dma_reset(s); omap_dma_clk_update(s, 0, 1); iomemtype = cpu_register_io_memory(0, omap_dma4_readfn, omap_dma4_writefn, s); cpu_register_physical_memory(s->base, 0x1000, iomemtype); return s;}struct omap_dma_lcd_channel_s *omap_dma_get_lcdch(struct omap_dma_s *s){ return &s->lcd_ch;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?