⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pxa2xx_dma.c.svn-base

📁 我们自己开发的一个OSEK操作系统!不知道可不可以?
💻 SVN-BASE
📖 第 1 页 / 共 2 页
字号:
/* * Intel XScale PXA255/270 DMA controller. * * Copyright (c) 2006 Openedhand Ltd. * Copyright (c) 2006 Thorsten Zitterell * Written by Andrzej Zaborowski <balrog@zabor.org> * * This code is licenced under the GPL. */#include "hw.h"#include "pxa.h"struct pxa2xx_dma_channel_s {    target_phys_addr_t descr;    target_phys_addr_t src;    target_phys_addr_t dest;    uint32_t cmd;    uint32_t state;    int request;};/* Allow the DMA to be used as a PIC.  */typedef void (*pxa2xx_dma_handler_t)(void *opaque, int irq, int level);struct pxa2xx_dma_state_s {    pxa2xx_dma_handler_t handler;    target_phys_addr_t base;    qemu_irq irq;    uint32_t stopintr;    uint32_t eorintr;    uint32_t rasintr;    uint32_t startintr;    uint32_t endintr;    uint32_t align;    uint32_t pio;    int channels;    struct pxa2xx_dma_channel_s *chan;    uint8_t *req;    /* Flag to avoid recursive DMA invocations.  */    int running;};#define PXA255_DMA_NUM_CHANNELS	16#define PXA27X_DMA_NUM_CHANNELS	32#define PXA2XX_DMA_NUM_REQUESTS	75#define DCSR0	0x0000	/* DMA Control / Status register for Channel 0 */#define DCSR31	0x007c	/* DMA Control / Status register for Channel 31 */#define DALGN	0x00a0	/* DMA Alignment register */#define DPCSR	0x00a4	/* DMA Programmed I/O Control Status register */#define DRQSR0	0x00e0	/* DMA DREQ<0> Status register */#define DRQSR1	0x00e4	/* DMA DREQ<1> Status register */#define DRQSR2	0x00e8	/* DMA DREQ<2> Status register */#define DINT	0x00f0	/* DMA Interrupt register */#define DRCMR0	0x0100	/* Request to Channel Map register 0 */#define DRCMR63	0x01fc	/* Request to Channel Map register 63 */#define D_CH0	0x0200	/* Channel 0 Descriptor start */#define DRCMR64	0x1100	/* Request to Channel Map register 64 */#define DRCMR74	0x1128	/* Request to Channel Map register 74 *//* Per-channel register */#define DDADR	0x00#define DSADR	0x01#define DTADR	0x02#define DCMD	0x03/* Bit-field masks */#define DRCMR_CHLNUM		0x1f#define DRCMR_MAPVLD		(1 << 7)#define DDADR_STOP		(1 << 0)#define DDADR_BREN		(1 << 1)#define DCMD_LEN		0x1fff#define DCMD_WIDTH(x)		(1 << ((((x) >> 14) & 3) - 1))#define DCMD_SIZE(x)		(4 << (((x) >> 16) & 3))#define DCMD_FLYBYT		(1 << 19)#define DCMD_FLYBYS		(1 << 20)#define DCMD_ENDIRQEN		(1 << 21)#define DCMD_STARTIRQEN		(1 << 22)#define DCMD_CMPEN		(1 << 25)#define DCMD_FLOWTRG		(1 << 28)#define DCMD_FLOWSRC		(1 << 29)#define DCMD_INCTRGADDR		(1 << 30)#define DCMD_INCSRCADDR		(1 << 31)#define DCSR_BUSERRINTR		(1 << 0)#define DCSR_STARTINTR		(1 << 1)#define DCSR_ENDINTR		(1 << 2)#define DCSR_STOPINTR		(1 << 3)#define DCSR_RASINTR		(1 << 4)#define DCSR_REQPEND		(1 << 8)#define DCSR_EORINT		(1 << 9)#define DCSR_CMPST		(1 << 10)#define DCSR_MASKRUN		(1 << 22)#define DCSR_RASIRQEN		(1 << 23)#define DCSR_CLRCMPST		(1 << 24)#define DCSR_SETCMPST		(1 << 25)#define DCSR_EORSTOPEN		(1 << 26)#define DCSR_EORJMPEN		(1 << 27)#define DCSR_EORIRQEN		(1 << 28)#define DCSR_STOPIRQEN		(1 << 29)#define DCSR_NODESCFETCH	(1 << 30)#define DCSR_RUN		(1 << 31)static inline void pxa2xx_dma_update(struct pxa2xx_dma_state_s *s, int ch){    if (ch >= 0) {        if ((s->chan[ch].state & DCSR_STOPIRQEN) &&                (s->chan[ch].state & DCSR_STOPINTR))            s->stopintr |= 1 << ch;        else            s->stopintr &= ~(1 << ch);        if ((s->chan[ch].state & DCSR_EORIRQEN) &&                (s->chan[ch].state & DCSR_EORINT))            s->eorintr |= 1 << ch;        else            s->eorintr &= ~(1 << ch);        if ((s->chan[ch].state & DCSR_RASIRQEN) &&                (s->chan[ch].state & DCSR_RASINTR))            s->rasintr |= 1 << ch;        else            s->rasintr &= ~(1 << ch);        if (s->chan[ch].state & DCSR_STARTINTR)            s->startintr |= 1 << ch;        else            s->startintr &= ~(1 << ch);        if (s->chan[ch].state & DCSR_ENDINTR)            s->endintr |= 1 << ch;        else            s->endintr &= ~(1 << ch);    }    if (s->stopintr | s->eorintr | s->rasintr | s->startintr | s->endintr)        qemu_irq_raise(s->irq);    else        qemu_irq_lower(s->irq);}static inline void pxa2xx_dma_descriptor_fetch(                struct pxa2xx_dma_state_s *s, int ch){    uint32_t desc[4];    target_phys_addr_t daddr = s->chan[ch].descr & ~0xf;    if ((s->chan[ch].descr & DDADR_BREN) && (s->chan[ch].state & DCSR_CMPST))        daddr += 32;    cpu_physical_memory_read(daddr, (uint8_t *) desc, 16);    s->chan[ch].descr = desc[DDADR];    s->chan[ch].src = desc[DSADR];    s->chan[ch].dest = desc[DTADR];    s->chan[ch].cmd = desc[DCMD];    if (s->chan[ch].cmd & DCMD_FLOWSRC)        s->chan[ch].src &= ~3;    if (s->chan[ch].cmd & DCMD_FLOWTRG)        s->chan[ch].dest &= ~3;    if (s->chan[ch].cmd & (DCMD_CMPEN | DCMD_FLYBYS | DCMD_FLYBYT))        printf("%s: unsupported mode in channel %i\n", __FUNCTION__, ch);    if (s->chan[ch].cmd & DCMD_STARTIRQEN)        s->chan[ch].state |= DCSR_STARTINTR;}static void pxa2xx_dma_run(struct pxa2xx_dma_state_s *s){    int c, srcinc, destinc;    uint32_t n, size;    uint32_t width;    uint32_t length;    char buffer[32];    struct pxa2xx_dma_channel_s *ch;    if (s->running ++)        return;    while (s->running) {        s->running = 1;        for (c = 0; c < s->channels; c ++) {            ch = &s->chan[c];            while ((ch->state & DCSR_RUN) && !(ch->state & DCSR_STOPINTR)) {                /* Test for pending requests */                if ((ch->cmd & (DCMD_FLOWSRC | DCMD_FLOWTRG)) && !ch->request)                    break;                length = ch->cmd & DCMD_LEN;                size = DCMD_SIZE(ch->cmd);                width = DCMD_WIDTH(ch->cmd);                srcinc = (ch->cmd & DCMD_INCSRCADDR) ? width : 0;                destinc = (ch->cmd & DCMD_INCTRGADDR) ? width : 0;                while (length) {                    size = MIN(length, size);                    for (n = 0; n < size; n += width) {                        cpu_physical_memory_read(ch->src, buffer + n, width);                        ch->src += srcinc;                    }                    for (n = 0; n < size; n += width) {                        cpu_physical_memory_write(ch->dest, buffer + n, width);                        ch->dest += destinc;                    }                    length -= size;                    if ((ch->cmd & (DCMD_FLOWSRC | DCMD_FLOWTRG)) &&                            !ch->request) {                        ch->state |= DCSR_EORINT;                        if (ch->state & DCSR_EORSTOPEN)                            ch->state |= DCSR_STOPINTR;                        if ((ch->state & DCSR_EORJMPEN) &&                                        !(ch->state & DCSR_NODESCFETCH))                            pxa2xx_dma_descriptor_fetch(s, c);                        break;		    }                }                ch->cmd = (ch->cmd & ~DCMD_LEN) | length;                /* Is the transfer complete now? */                if (!length) {                    if (ch->cmd & DCMD_ENDIRQEN)                        ch->state |= DCSR_ENDINTR;                    if ((ch->state & DCSR_NODESCFETCH) ||                                (ch->descr & DDADR_STOP) ||                                (ch->state & DCSR_EORSTOPEN)) {                        ch->state |= DCSR_STOPINTR;                        ch->state &= ~DCSR_RUN;                        break;                    }                    ch->state |= DCSR_STOPINTR;                    break;                }            }        }        s->running --;    }}static uint32_t pxa2xx_dma_read(void *opaque, target_phys_addr_t offset){    struct pxa2xx_dma_state_s *s = (struct pxa2xx_dma_state_s *) opaque;    unsigned int channel;    offset -= s->base;    switch (offset) {    case DRCMR64 ... DRCMR74:        offset -= DRCMR64 - DRCMR0 - (64 << 2);        /* Fall through */    case DRCMR0 ... DRCMR63:        channel = (offset - DRCMR0) >> 2;        return s->req[channel];    case DRQSR0:    case DRQSR1:    case DRQSR2:        return 0;    case DCSR0 ... DCSR31:        channel = offset >> 2;	if (s->chan[channel].request)            return s->chan[channel].state | DCSR_REQPEND;        return s->chan[channel].state;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -