Esempio n. 1
0
static void
dma_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
{
        struct fs_dma_ctrl *ctrl = opaque;
	int c;

        /* Make addr relative to this channel and bounded to nr regs.  */
	c = fs_channel(addr);
        addr &= 0xff;
        addr >>= 2;
        switch (addr)
	{
		case RW_DATA:
			ctrl->channels[c].regs[addr] = value;
			break;

		case RW_CFG:
			ctrl->channels[c].regs[addr] = value;
			dma_update_state(ctrl, c);
			break;
		case RW_CMD:
			/* continue.  */
			if (value & ~1)
				printf("Invalid store to ch=%d RW_CMD %x\n",
				       c, value);
			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:
			if (value & ~1023)
				printf("Invalid store to ch=%d "
				       "RW_STREAMCMD %x\n",
				       c, value);
			ctrl->channels[c].regs[addr] = value;
			D(printf("stream_cmd ch=%d\n", c));
			channel_stream_cmd(ctrl, c, value);
			break;

	        default:
			D(printf ("%s c=%d " TARGET_FMT_plx "\n",
				__func__, c, addr));
			break;
        }
}
Esempio n. 2
0
static void
dma_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;
        }
}
Esempio n. 3
0
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;
}
Esempio n. 4
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;
}
Esempio n. 5
0
static int channel_out_run(struct fs_dma_ctrl *ctrl, int c)
{
	uint32_t len;
	uint32_t saved_data_buf;
	unsigned char buf[2 * 1024];

	struct dma_context_metadata meta;
	bool send_context = true;

	if (ctrl->channels[c].eol)
		return 0;

	do {
		bool out_eop;
		D(printf("ch=%d buf=%x after=%x\n",
			 c,
			 (uint32_t)ctrl->channels[c].current_d.buf,
			 (uint32_t)ctrl->channels[c].current_d.after));

		if (send_context) {
			if (ctrl->channels[c].client->client.metadata_push) {
				meta.metadata = ctrl->channels[c].current_d.md;
				ctrl->channels[c].client->client.metadata_push(
					ctrl->channels[c].client->client.opaque,
					&meta);
			}
			send_context = false;
		}

		channel_load_d(ctrl, c);
		saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF);
		len = (uint32_t)(unsigned long)
			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);

		out_eop = ((saved_data_buf + len) ==
		           ctrl->channels[c].current_d.after) &&
			ctrl->channels[c].current_d.out_eop;

		D(printf("channel %d pushes %x %u bytes eop=%u\n", c,
		         saved_data_buf, len, out_eop));

		if (ctrl->channels[c].client->client.push)
			ctrl->channels[c].client->client.push(
				ctrl->channels[c].client->client.opaque,
				buf, len, out_eop);
		else
			printf("WARNING: DMA ch%d dataloss,"
			       " no attached client.\n", c);

		saved_data_buf += len;

		if (saved_data_buf == (uint32_t)(unsigned long)
				ctrl->channels[c].current_d.after) {
			/* Done. Step to next.  */
			if (ctrl->channels[c].current_d.out_eop) {
				send_context = true;
			}
			if (ctrl->channels[c].current_d.intr) {
				/* data intr.  */
				D(printf("signal intr %d eol=%d\n",
					len, ctrl->channels[c].current_d.eol));
				ctrl->channels[c].regs[R_INTR] |= (1 << 2);
				channel_update_irq(ctrl, c);
			}
			channel_store_d(ctrl, c);
			if (ctrl->channels[c].current_d.eol) {
				D(printf("channel %d EOL\n", c));
				ctrl->channels[c].eol = 1;

				/* Mark the context as disabled.  */
				ctrl->channels[c].current_c.dis = 1;
				channel_store_c(ctrl, c);

				channel_stop(ctrl, c);
			} else {
				ctrl->channels[c].regs[RW_SAVED_DATA] =
					(uint32_t)(unsigned long)ctrl->
						channels[c].current_d.next;
				/* Load new descriptor.  */
				channel_load_d(ctrl, c);
				saved_data_buf = (uint32_t)(unsigned long)
					ctrl->channels[c].current_d.buf;
			}

			ctrl->channels[c].regs[RW_SAVED_DATA_BUF] =
							saved_data_buf;
			D(dump_d(c, &ctrl->channels[c].current_d));
		}
		ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = saved_data_buf;
	} while (!ctrl->channels[c].eol);
	return 1;
}