Esempio n. 1
0
static void channel_continue(struct fs_dma_ctrl *ctrl, int c)
{
	if (!channel_en(ctrl, c) 
	    || channel_stopped(ctrl, c)
	    || ctrl->channels[c].state != RUNNING
	    /* Only reload the current data descriptor if it has eol set.  */
	    || !ctrl->channels[c].current_d.eol) {
		D(printf("continue failed ch=%d state=%d stopped=%d en=%d eol=%d\n", 
			 c, ctrl->channels[c].state,
			 channel_stopped(ctrl, c),
			 channel_en(ctrl,c),
			 ctrl->channels[c].eol));
		D(dump_d(c, &ctrl->channels[c].current_d));
		return;
	}

	/* Reload the current descriptor.  */
	channel_load_d(ctrl, c);

	/* If the current descriptor cleared the eol flag and we had already
	   reached eol state, do the continue.  */
	if (!ctrl->channels[c].current_d.eol && ctrl->channels[c].eol) {
		D(printf("continue %d ok %x\n", c,
			 ctrl->channels[c].current_d.next));
		ctrl->channels[c].regs[RW_SAVED_DATA] =
			(uint32_t) ctrl->channels[c].current_d.next;
		channel_load_d(ctrl, c);
		channel_start(ctrl, c);
	}
}
Esempio n. 2
0
static void channel_stream_cmd(struct fs_dma_ctrl *ctrl, int c, uint32_t v)
{
	unsigned int cmd = v & ((1 << 10) - 1);

	D(printf("%s cmd=%x\n", __func__, cmd));
	if (cmd & regk_dma_load_d) {
		channel_load_d(ctrl, c);
		if (cmd & regk_dma_burst)
			channel_start(ctrl, c);
	}

	if (cmd & regk_dma_load_c) {
		channel_load_c(ctrl, c);
	}
}
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;
}