etraxfs_dma.c

来自「xen虚拟机源代码安装包」· C语言 代码 · 共 695 行 · 第 1/2 页

C
695
字号
		channel_load_c(ctrl, c);	}}static void channel_update_irq(struct fs_dma_ctrl *ctrl, int c){	D(printf("%s %d\n", __func__, c));        ctrl->channels[c].regs[R_INTR] &=		~(ctrl->channels[c].regs[RW_ACK_INTR]);        ctrl->channels[c].regs[R_MASKED_INTR] =		ctrl->channels[c].regs[R_INTR]		& ctrl->channels[c].regs[RW_INTR_MASK];	D(printf("%s: chan=%d masked_intr=%x\n", __func__, 		 c,		 ctrl->channels[c].regs[R_MASKED_INTR]));        if (ctrl->channels[c].regs[R_MASKED_INTR])                qemu_irq_raise(ctrl->channels[c].irq[0]);        else                qemu_irq_lower(ctrl->channels[c].irq[0]);}static void channel_out_run(struct fs_dma_ctrl *ctrl, int c){	uint32_t len;	uint32_t saved_data_buf;	unsigned char buf[2 * 1024];	if (ctrl->channels[c].eol == 1)		return;	saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF);	D(printf("buf=%x after=%x saved_data_buf=%x\n",		 (uint32_t)ctrl->channels[c].current_d.buf,		 (uint32_t)ctrl->channels[c].current_d.after,		 saved_data_buf));	if (saved_data_buf == (uint32_t)ctrl->channels[c].current_d.after) {		/* Done. Step to next.  */		if (ctrl->channels[c].current_d.out_eop) {			/* TODO: signal eop to the client.  */			D(printf("signal eop\n"));		}		if (ctrl->channels[c].current_d.intr) {			/* TODO: signal eop to the client.  */			/* data intr.  */			D(printf("signal intr\n"));			ctrl->channels[c].regs[R_INTR] |= (1 << 2);			channel_update_irq(ctrl, c);		}		if (ctrl->channels[c].current_d.eol) {			D(printf("channel %d EOL\n", c));			ctrl->channels[c].eol = 1;			channel_stop(ctrl, c);		} else {			ctrl->channels[c].regs[RW_SAVED_DATA] =				(uint32_t) ctrl->channels[c].current_d.next;			/* Load new descriptor.  */			channel_load_d(ctrl, c);		}		channel_store_d(ctrl, c);		D(dump_d(c, &ctrl->channels[c].current_d));		return;	}	len = (uint32_t) ctrl->channels[c].current_d.after;	len -= saved_data_buf;	if (len > sizeof buf)		len = sizeof buf;	cpu_physical_memory_read (saved_data_buf, buf, len);	D(printf("channel %d pushes %x %u bytes\n", c, 		 saved_data_buf, len));	/* TODO: Push content.  */	if (ctrl->channels[c].client->client.push)		ctrl->channels[c].client->client.push(			ctrl->channels[c].client->client.opaque, buf, len);	else		printf("WARNING: DMA ch%d dataloss, no attached client.\n", c);	ctrl->channels[c].regs[RW_SAVED_DATA_BUF] += len;}static int channel_in_process(struct fs_dma_ctrl *ctrl, int c, 			      unsigned char *buf, int buflen, int eop){	uint32_t len;	uint32_t saved_data_buf;	if (ctrl->channels[c].eol == 1)		return 0;	saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF);	len = (uint32_t) ctrl->channels[c].current_d.after;	len -= saved_data_buf;		if (len > buflen)		len = buflen;	cpu_physical_memory_write (saved_data_buf, buf, len);	saved_data_buf += len;	if (saved_data_buf == (uint32_t)ctrl->channels[c].current_d.after	    || eop) {		uint32_t r_intr = ctrl->channels[c].regs[R_INTR];		D(printf("in dscr end len=%d\n", 			 ctrl->channels[c].current_d.after			 - ctrl->channels[c].current_d.buf));		ctrl->channels[c].current_d.after = 			(void *) saved_data_buf;		/* Done. Step to next.  */		if (ctrl->channels[c].current_d.intr) {			/* TODO: signal eop to the client.  */			/* data intr.  */			ctrl->channels[c].regs[R_INTR] |= 3;		}		if (eop) {			ctrl->channels[c].current_d.in_eop = 1;			ctrl->channels[c].regs[R_INTR] |= 8;		}		if (r_intr != ctrl->channels[c].regs[R_INTR])			channel_update_irq(ctrl, c);		channel_store_d(ctrl, c);		D(dump_d(c, &ctrl->channels[c].current_d));		if (ctrl->channels[c].current_d.eol) {			D(printf("channel %d EOL\n", c));			ctrl->channels[c].eol = 1;			channel_stop(ctrl, c);		} else {			ctrl->channels[c].regs[RW_SAVED_DATA] =				(uint32_t) ctrl->channels[c].current_d.next;			/* Load new descriptor.  */			channel_load_d(ctrl, c);			saved_data_buf =				ctrl->channels[c].regs[RW_SAVED_DATA_BUF];		}	}	ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = saved_data_buf;	return len;}static inline void channel_in_run(struct fs_dma_ctrl *ctrl, int c){	if (ctrl->channels[c].client->client.pull)		ctrl->channels[c].client->client.pull(			ctrl->channels[c].client->client.opaque);}static uint32_t dma_rinvalid (void *opaque, target_phys_addr_t addr){        struct fs_dma_ctrl *ctrl = opaque;        CPUState *env = ctrl->env;        cpu_abort(env, "Unsupported short access. reg=%x pc=%x.\n",                   addr, env->pc);        return 0;}static uint32_tdma_readl (void *opaque, target_phys_addr_t addr){        struct fs_dma_ctrl *ctrl = opaque;	int c;	uint32_t r = 0;	/* Make addr relative to this instances base.  */	c = fs_channel(ctrl->base, addr);        addr &= 0x1fff;	switch (addr)        {		case RW_STAT:			r = ctrl->channels[c].state & 7;			r |= ctrl->channels[c].eol << 5;			r |= ctrl->channels[c].stream_cmd_src << 8;			break;                default:			r = ctrl->channels[c].regs[addr];			D(printf ("%s c=%d addr=%x pc=%x\n",				 __func__, c, addr, env->pc));                        break;        }	return r;}static voiddma_winvalid (void *opaque, target_phys_addr_t addr, uint32_t value){        struct fs_dma_ctrl *ctrl = opaque;        CPUState *env = ctrl->env;        cpu_abort(env, "Unsupported short access. reg=%x pc=%x.\n",                   addr, env->pc);}static voiddma_writel (void *opaque, target_phys_addr_t addr, uint32_t value){        struct fs_dma_ctrl *ctrl = opaque;	int c;        /* Make addr relative to this instances base.  */	c = fs_channel(ctrl->base, addr);        addr &= 0x1fff;        switch (addr)        {		case RW_DATA:			printf("RW_DATA=%x\n", value);						break;		case RW_CFG:			ctrl->channels[c].regs[addr] = value;			break;		case RW_CMD:			/* continue.  */			ctrl->channels[c].regs[addr] = value;			channel_continue(ctrl, c);			break;		case RW_SAVED_DATA:		case RW_SAVED_DATA_BUF:		case RW_GROUP:		case RW_GROUP_DOWN:			ctrl->channels[c].regs[addr] = value;			break;		case RW_ACK_INTR:		case RW_INTR_MASK:			ctrl->channels[c].regs[addr] = value;			channel_update_irq(ctrl, c);			if (addr == RW_ACK_INTR)				ctrl->channels[c].regs[RW_ACK_INTR] = 0;			break;		case RW_STREAM_CMD:			ctrl->channels[c].regs[addr] = value;			channel_stream_cmd(ctrl, c, value);			break;                default:                        D(printf ("%s c=%d %x %x pc=%x\n",				  __func__, c, addr, value, env->pc));                        break;        }}static CPUReadMemoryFunc *dma_read[] = {	&dma_rinvalid,	&dma_rinvalid,	&dma_readl,};static CPUWriteMemoryFunc *dma_write[] = {	&dma_winvalid,	&dma_winvalid,	&dma_writel,};void etraxfs_dmac_run(void *opaque){	struct fs_dma_ctrl *ctrl = opaque;	int i;	int p = 0;	for (i = 0; 	     i < ctrl->nr_channels;	     i++)	{		if (ctrl->channels[i].state == RUNNING)		{			p++;			if (ctrl->channels[i].input)				channel_in_run(ctrl, i);			else				channel_out_run(ctrl, i);		}	}}int etraxfs_dmac_input(struct etraxfs_dma_client *client, 		       void *buf, int len, int eop){	return channel_in_process(client->ctrl, client->channel, 				  buf, len, eop);}/* Connect an IRQ line with a channel.  */void etraxfs_dmac_connect(void *opaque, int c, qemu_irq *line, int input){	struct fs_dma_ctrl *ctrl = opaque;	ctrl->channels[c].irq = line;	ctrl->channels[c].input = input;}void etraxfs_dmac_connect_client(void *opaque, int c, 				 struct etraxfs_dma_client *cl){	struct fs_dma_ctrl *ctrl = opaque;	cl->ctrl = ctrl;	cl->channel = c;	ctrl->channels[c].client = cl;}void *etraxfs_dmac_init(CPUState *env, 			target_phys_addr_t base, int nr_channels){	struct fs_dma_ctrl *ctrl = NULL;	int i;	ctrl = qemu_mallocz(sizeof *ctrl);	if (!ctrl)		return NULL;	ctrl->base = base;	ctrl->env = env;	ctrl->nr_channels = nr_channels;	ctrl->channels = qemu_mallocz(sizeof ctrl->channels[0] * nr_channels);	if (!ctrl->channels)		goto err;	for (i = 0; i < nr_channels; i++)	{		ctrl->channels[i].regmap = cpu_register_io_memory(0,								  dma_read, 								  dma_write, 								  ctrl);		cpu_register_physical_memory (base + i * 0x2000,					      sizeof ctrl->channels[i].regs, 					      ctrl->channels[i].regmap);	}	return ctrl;  err:	qemu_free(ctrl->channels);	qemu_free(ctrl);	return NULL;}

⌨️ 快捷键说明

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