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