Browse Source

waterHeterogeneousDataSynchronization memoryOperation.c 姚强 commit at 2020-11-23

姚强 4 years ago
parent
commit
6aa414a34c

+ 143 - 0
waterHeterogeneousDataSynchronization/dataSharedMemory/memoryOperation.c

@@ -829,3 +829,146 @@ EXPORT_SYMBOL(s3c2410_dma_free);
 static int s3c2410_dma_dostop(struct s3c2410_dma_chan *chan)
 {
 	unsigned long flags;
+	unsigned long tmp;
+
+	pr_debug("%s:\n", __func__);
+
+	dbg_showchan(chan);
+
+	local_irq_save(flags);
+
+	s3c2410_dma_call_op(chan,  S3C2410_DMAOP_STOP);
+
+	tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
+	tmp |= S3C2410_DMASKTRIG_STOP;
+	//tmp &= ~S3C2410_DMASKTRIG_ON;
+	dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp);
+
+#if 0
+	/* should also clear interrupts, according to WinCE BSP */
+	tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
+	tmp |= S3C2410_DCON_NORELOAD;
+	dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
+#endif
+
+	/* should stop do this, or should we wait for flush? */
+	chan->state      = S3C2410_DMA_IDLE;
+	chan->load_state = S3C2410_DMALOAD_NONE;
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+static void s3c2410_dma_waitforstop(struct s3c2410_dma_chan *chan)
+{
+	unsigned long tmp;
+	unsigned int timeout = 0x10000;
+
+	while (timeout-- > 0) {
+		tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
+
+		if (!(tmp & S3C2410_DMASKTRIG_ON))
+			return;
+	}
+
+	pr_debug("dma%d: failed to stop?\n", chan->number);
+}
+
+
+/* s3c2410_dma_flush
+ *
+ * stop the channel, and remove all current and pending transfers
+*/
+
+static int s3c2410_dma_flush(struct s3c2410_dma_chan *chan)
+{
+	struct s3c2410_dma_buf *buf, *next;
+	unsigned long flags;
+
+	pr_debug("%s: chan %p (%d)\n", __func__, chan, chan->number);
+
+	dbg_showchan(chan);
+
+	local_irq_save(flags);
+
+	if (chan->state != S3C2410_DMA_IDLE) {
+		pr_debug("%s: stopping channel...\n", __func__ );
+		s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_STOP);
+	}
+
+	buf = chan->curr;
+	if (buf == NULL)
+		buf = chan->next;
+
+	chan->curr = chan->next = chan->end = NULL;
+
+	if (buf != NULL) {
+		for ( ; buf != NULL; buf = next) {
+			next = buf->next;
+
+			pr_debug("%s: free buffer %p, next %p\n",
+			       __func__, buf, buf->next);
+
+			s3c2410_dma_buffdone(chan, buf, S3C2410_RES_ABORT);
+			s3c2410_dma_freebuf(buf);
+		}
+	}
+
+	dbg_showregs(chan);
+
+	s3c2410_dma_waitforstop(chan);
+
+#if 0
+	/* should also clear interrupts, according to WinCE BSP */
+	{
+		unsigned long tmp;
+
+		tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
+		tmp |= S3C2410_DCON_NORELOAD;
+		dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
+	}
+#endif
+
+	dbg_showregs(chan);
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+static int s3c2410_dma_started(struct s3c2410_dma_chan *chan)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	dbg_showchan(chan);
+
+	/* if we've only loaded one buffer onto the channel, then chec
+	 * to see if we have another, and if so, try and load it so when
+	 * the first buffer is finished, the new one will be loaded onto
+	 * the channel */
+
+	if (chan->next != NULL) {
+		if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
+
+			if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
+				pr_debug("%s: buff not yet loaded, no more todo\n",
+					 __func__);
+			} else {
+				chan->load_state = S3C2410_DMALOAD_1RUNNING;
+				s3c2410_dma_loadbuffer(chan, chan->next);
+			}
+
+		} else if (chan->load_state == S3C2410_DMALOAD_1RUNNING) {
+			s3c2410_dma_loadbuffer(chan, chan->next);
+		}
+	}
+
+
+	local_irq_restore(flags);
+
+	return 0;
+
+}