Browse Source

waterHeterogeneousDataSynchronization memoryOperation.c 姚强 commit at 2020-09-27

姚强 4 years ago
parent
commit
52e20c4cb1

+ 101 - 0
waterHeterogeneousDataSynchronization/dataSharedMemory/memoryOperation.c

@@ -372,3 +372,104 @@ static int s3c2410_dma_start(struct s3c2410_dma_chan *chan)
 	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;
+}
+
+/* s3c2410_dma_canload
+ *
+ * work out if we can queue another buffer into the DMA engine
+*/
+
+static int
+s3c2410_dma_canload(struct s3c2410_dma_chan *chan)
+{
+	if (chan->load_state == S3C2410_DMALOAD_NONE ||
+	    chan->load_state == S3C2410_DMALOAD_1RUNNING)
+		return 1;
+
+	return 0;
+}
+
+/* s3c2410_dma_enqueue
+ *
+ * queue an given buffer for dma transfer.
+ *
+ * id         the device driver's id information for this buffer
+ * data       the physical address of the buffer data
+ * size       the size of the buffer in bytes
+ *
+ * If the channel is not running, then the flag S3C2410_DMAF_AUTOSTART
+ * is checked, and if set, the channel is started. If this flag isn't set,
+ * then an error will be returned.
+ *
+ * It is possible to queue more than one DMA buffer onto a channel at
+ * once, and the code will deal with the re-loading of the next buffer
+ * when necessary.
+*/
+
+int s3c2410_dma_enqueue(enum dma_ch channel, void *id,
+			dma_addr_t data, int size)
+{
+	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
+	struct s3c2410_dma_buf *buf;
+	unsigned long flags;
+
+	if (chan == NULL)
+		return -EINVAL;
+
+	pr_debug("%s: id=%p, data=%08x, size=%d\n",
+		 __func__, id, (unsigned int)data, size);
+
+	buf = kmem_cache_alloc(dma_kmem, GFP_ATOMIC);
+	if (buf == NULL) {
+		pr_debug("%s: out of memory (%ld alloc)\n",
+			 __func__, (long)sizeof(*buf));
+		return -ENOMEM;
+	}
+
+	//pr_debug("%s: new buffer %p\n", __func__, buf);
+	//dbg_showchan(chan);
+
+	buf->next  = NULL;
+	buf->data  = buf->ptr = data;
+	buf->size  = size;
+	buf->id    = id;
+	buf->magic = BUF_MAGIC;
+
+	local_irq_save(flags);
+
+	if (chan->curr == NULL) {
+		/* we've got nothing loaded... */
+		pr_debug("%s: buffer %p queued onto empty channel\n",
+			 __func__, buf);
+
+		chan->curr = buf;
+		chan->end  = buf;
+		chan->next = NULL;
+	} else {
+		pr_debug("dma%d: %s: buffer %p queued onto non-empty channel\n",
+			 chan->number, __func__, buf);
+