xref: /freebsd/sys/dev/altera/softdma/softdma.c (revision 780fb4a2)
1 /*-
2  * Copyright (c) 2017-2018 Ruslan Bukin <br@bsdpad.com>
3  * All rights reserved.
4  *
5  * This software was developed by SRI International and the University of
6  * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237
7  * ("CTSRD"), as part of the DARPA CRASH research programme.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 
31 /* This is driver for SoftDMA device built using Altera FIFO component. */
32 
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35 
36 #include "opt_platform.h"
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/conf.h>
40 #include <sys/bus.h>
41 #include <sys/endian.h>
42 #include <sys/kernel.h>
43 #include <sys/kthread.h>
44 #include <sys/module.h>
45 #include <sys/lock.h>
46 #include <sys/mutex.h>
47 #include <sys/resource.h>
48 #include <sys/rman.h>
49 
50 #include <machine/bus.h>
51 
52 #ifdef FDT
53 #include <dev/fdt/fdt_common.h>
54 #include <dev/ofw/ofw_bus.h>
55 #include <dev/ofw/ofw_bus_subr.h>
56 #endif
57 
58 #include <dev/altera/softdma/a_api.h>
59 
60 #include <dev/xdma/xdma.h>
61 #include "xdma_if.h"
62 
63 #define SOFTDMA_DEBUG
64 #undef SOFTDMA_DEBUG
65 
66 #ifdef SOFTDMA_DEBUG
67 #define dprintf(fmt, ...)  printf(fmt, ##__VA_ARGS__)
68 #else
69 #define dprintf(fmt, ...)
70 #endif
71 
72 #define	AVALON_FIFO_TX_BASIC_OPTS_DEPTH		16
73 #define	SOFTDMA_NCHANNELS			1
74 #define	CONTROL_GEN_SOP				(1 << 0)
75 #define	CONTROL_GEN_EOP				(1 << 1)
76 #define	CONTROL_OWN				(1 << 31)
77 
78 #define	SOFTDMA_RX_EVENTS	\
79 	(A_ONCHIP_FIFO_MEM_CORE_INTR_FULL	| \
80 	 A_ONCHIP_FIFO_MEM_CORE_INTR_OVERFLOW	| \
81 	 A_ONCHIP_FIFO_MEM_CORE_INTR_UNDERFLOW)
82 #define	SOFTDMA_TX_EVENTS	\
83 	(A_ONCHIP_FIFO_MEM_CORE_INTR_EMPTY	| \
84  	A_ONCHIP_FIFO_MEM_CORE_INTR_OVERFLOW	| \
85  	A_ONCHIP_FIFO_MEM_CORE_INTR_UNDERFLOW)
86 
87 struct softdma_channel {
88 	struct softdma_softc	*sc;
89 	struct mtx		mtx;
90 	xdma_channel_t		*xchan;
91 	struct proc		*p;
92 	int			used;
93 	int			index;
94 	int			run;
95 	uint32_t		idx_tail;
96 	uint32_t		idx_head;
97 	struct softdma_desc	*descs;
98 
99 	uint32_t		descs_num;
100 	uint32_t		descs_used_count;
101 };
102 
103 struct softdma_desc {
104 	uint64_t		src_addr;
105 	uint64_t		dst_addr;
106 	uint32_t		len;
107 	uint32_t		access_width;
108 	uint32_t		count;
109 	uint16_t		src_incr;
110 	uint16_t		dst_incr;
111 	uint32_t		direction;
112 	struct softdma_desc	*next;
113 	uint32_t		transfered;
114 	uint32_t		status;
115 	uint32_t		reserved;
116 	uint32_t		control;
117 };
118 
119 struct softdma_softc {
120 	device_t		dev;
121 	struct resource		*res[3];
122 	bus_space_tag_t		bst;
123 	bus_space_handle_t	bsh;
124 	bus_space_tag_t		bst_c;
125 	bus_space_handle_t	bsh_c;
126 	void			*ih;
127 	struct softdma_channel	channels[SOFTDMA_NCHANNELS];
128 };
129 
130 static struct resource_spec softdma_spec[] = {
131 	{ SYS_RES_MEMORY,	0,	RF_ACTIVE },	/* fifo */
132 	{ SYS_RES_MEMORY,	1,	RF_ACTIVE },	/* core */
133 	{ SYS_RES_IRQ,		0,	RF_ACTIVE },
134 	{ -1, 0 }
135 };
136 
137 static int softdma_probe(device_t dev);
138 static int softdma_attach(device_t dev);
139 static int softdma_detach(device_t dev);
140 
141 static inline uint32_t
142 softdma_next_desc(struct softdma_channel *chan, uint32_t curidx)
143 {
144 
145 	return ((curidx + 1) % chan->descs_num);
146 }
147 
148 static void
149 softdma_mem_write(struct softdma_softc *sc, uint32_t reg, uint32_t val)
150 {
151 
152 	bus_write_4(sc->res[0], reg, htole32(val));
153 }
154 
155 static uint32_t
156 softdma_mem_read(struct softdma_softc *sc, uint32_t reg)
157 {
158 	uint32_t val;
159 
160 	val = bus_read_4(sc->res[0], reg);
161 
162 	return (le32toh(val));
163 }
164 
165 static void
166 softdma_memc_write(struct softdma_softc *sc, uint32_t reg, uint32_t val)
167 {
168 
169 	bus_write_4(sc->res[1], reg, htole32(val));
170 }
171 
172 static uint32_t
173 softdma_memc_read(struct softdma_softc *sc, uint32_t reg)
174 {
175 	uint32_t val;
176 
177 	val = bus_read_4(sc->res[1], reg);
178 
179 	return (le32toh(val));
180 }
181 
182 static uint32_t
183 softdma_fill_level(struct softdma_softc *sc)
184 {
185 	uint32_t val;
186 
187 	val = softdma_memc_read(sc,
188 	    A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_FILL_LEVEL);
189 
190 	return (val);
191 }
192 
193 static void
194 softdma_intr(void *arg)
195 {
196 	struct softdma_channel *chan;
197 	struct softdma_softc *sc;
198 	int reg;
199 	int err;
200 
201 	sc = arg;
202 
203 	chan = &sc->channels[0];
204 
205 	reg = softdma_memc_read(sc, A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT);
206 
207 	if (reg & (A_ONCHIP_FIFO_MEM_CORE_EVENT_OVERFLOW |
208 	    A_ONCHIP_FIFO_MEM_CORE_EVENT_UNDERFLOW)) {
209 		/* Errors */
210 		err = (((reg & A_ONCHIP_FIFO_MEM_CORE_ERROR_MASK) >> \
211 		    A_ONCHIP_FIFO_MEM_CORE_ERROR_SHIFT) & 0xff);
212 	}
213 
214 	if (reg != 0) {
215 		softdma_memc_write(sc,
216 		    A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT, reg);
217 		chan->run = 1;
218 		wakeup(chan);
219 	}
220 }
221 
222 static int
223 softdma_probe(device_t dev)
224 {
225 
226 	if (!ofw_bus_status_okay(dev))
227 		return (ENXIO);
228 
229 	if (!ofw_bus_is_compatible(dev, "altr,softdma"))
230 		return (ENXIO);
231 
232 	device_set_desc(dev, "SoftDMA");
233 
234 	return (BUS_PROBE_DEFAULT);
235 }
236 
237 static int
238 softdma_attach(device_t dev)
239 {
240 	struct softdma_softc *sc;
241 	phandle_t xref, node;
242 	int err;
243 
244 	sc = device_get_softc(dev);
245 	sc->dev = dev;
246 
247 	if (bus_alloc_resources(dev, softdma_spec, sc->res)) {
248 		device_printf(dev,
249 		    "could not allocate resources for device\n");
250 		return (ENXIO);
251 	}
252 
253 	/* FIFO memory interface */
254 	sc->bst = rman_get_bustag(sc->res[0]);
255 	sc->bsh = rman_get_bushandle(sc->res[0]);
256 
257 	/* FIFO control memory interface */
258 	sc->bst_c = rman_get_bustag(sc->res[1]);
259 	sc->bsh_c = rman_get_bushandle(sc->res[1]);
260 
261 	/* Setup interrupt handler */
262 	err = bus_setup_intr(dev, sc->res[2], INTR_TYPE_MISC | INTR_MPSAFE,
263 	    NULL, softdma_intr, sc, &sc->ih);
264 	if (err) {
265 		device_printf(dev, "Unable to alloc interrupt resource.\n");
266 		return (ENXIO);
267 	}
268 
269 	node = ofw_bus_get_node(dev);
270 	xref = OF_xref_from_node(node);
271 	OF_device_register_xref(xref, dev);
272 
273 	return (0);
274 }
275 
276 static int
277 softdma_detach(device_t dev)
278 {
279 	struct softdma_softc *sc;
280 
281 	sc = device_get_softc(dev);
282 
283 	return (0);
284 }
285 
286 static int
287 softdma_process_tx(struct softdma_channel *chan, struct softdma_desc *desc)
288 {
289 	struct softdma_softc *sc;
290 	uint32_t src_offs, dst_offs;
291 	uint32_t reg;
292 	uint32_t fill_level;
293 	uint32_t leftm;
294 	uint32_t tmp;
295 	uint32_t val;
296 	uint32_t c;
297 
298 	sc = chan->sc;
299 
300 	fill_level = softdma_fill_level(sc);
301 	while (fill_level == AVALON_FIFO_TX_BASIC_OPTS_DEPTH)
302 		fill_level = softdma_fill_level(sc);
303 
304 	/* Set start of packet. */
305 	if (desc->control & CONTROL_GEN_SOP) {
306 		reg = 0;
307 		reg |= A_ONCHIP_FIFO_MEM_CORE_SOP;
308 		softdma_mem_write(sc, A_ONCHIP_FIFO_MEM_CORE_METADATA, reg);
309 	}
310 
311 	src_offs = dst_offs = 0;
312 	c = 0;
313 	while ((desc->len - c) >= 4) {
314 		val = *(uint32_t *)(desc->src_addr + src_offs);
315 		bus_write_4(sc->res[0], A_ONCHIP_FIFO_MEM_CORE_DATA, val);
316 		if (desc->src_incr)
317 			src_offs += 4;
318 		if (desc->dst_incr)
319 			dst_offs += 4;
320 		fill_level += 1;
321 
322 		while (fill_level == AVALON_FIFO_TX_BASIC_OPTS_DEPTH) {
323 			fill_level = softdma_fill_level(sc);
324 		}
325 		c += 4;
326 	}
327 
328 	val = 0;
329 	leftm = (desc->len - c);
330 
331 	switch (leftm) {
332 	case 1:
333 		val = *(uint8_t *)(desc->src_addr + src_offs);
334 		val <<= 24;
335 		src_offs += 1;
336 		break;
337 	case 2:
338 	case 3:
339 		val = *(uint16_t *)(desc->src_addr + src_offs);
340 		val <<= 16;
341 		src_offs += 2;
342 
343 		if (leftm == 3) {
344 			tmp = *(uint8_t *)(desc->src_addr + src_offs);
345 			val |= (tmp << 8);
346 			src_offs += 1;
347 		}
348 		break;
349 	case 0:
350 	default:
351 		break;
352 	}
353 
354 	/* Set end of packet. */
355 	reg = 0;
356 	if (desc->control & CONTROL_GEN_EOP)
357 		reg |= A_ONCHIP_FIFO_MEM_CORE_EOP;
358 	reg |= ((4 - leftm) << A_ONCHIP_FIFO_MEM_CORE_EMPTY_SHIFT);
359 	softdma_mem_write(sc, A_ONCHIP_FIFO_MEM_CORE_METADATA, reg);
360 
361 	/* Ensure there is a FIFO entry available. */
362 	fill_level = softdma_fill_level(sc);
363 	while (fill_level == AVALON_FIFO_TX_BASIC_OPTS_DEPTH)
364 		fill_level = softdma_fill_level(sc);
365 
366 	/* Final write */
367 	bus_write_4(sc->res[0], A_ONCHIP_FIFO_MEM_CORE_DATA, val);
368 
369 	return (dst_offs);
370 }
371 
372 static int
373 softdma_process_rx(struct softdma_channel *chan, struct softdma_desc *desc)
374 {
375 	uint32_t src_offs, dst_offs;
376 	struct softdma_softc *sc;
377 	uint32_t fill_level;
378 	uint32_t empty;
379 	uint32_t meta;
380 	uint32_t data;
381 	int sop_rcvd;
382 	int timeout;
383 	size_t len;
384 	int error;
385 
386 	sc = chan->sc;
387 	empty = 0;
388 	src_offs = dst_offs = 0;
389 	error = 0;
390 
391 	fill_level = softdma_fill_level(sc);
392 	if (fill_level == 0) {
393 		/* Nothing to receive. */
394 		return (0);
395 	}
396 
397 	len = desc->len;
398 
399 	sop_rcvd = 0;
400 	while (fill_level) {
401 		empty = 0;
402 		data = bus_read_4(sc->res[0], A_ONCHIP_FIFO_MEM_CORE_DATA);
403 		meta = softdma_mem_read(sc, A_ONCHIP_FIFO_MEM_CORE_METADATA);
404 
405 		if (meta & A_ONCHIP_FIFO_MEM_CORE_ERROR_MASK) {
406 			error = 1;
407 			break;
408 		}
409 
410 		if ((meta & A_ONCHIP_FIFO_MEM_CORE_CHANNEL_MASK) != 0) {
411 			error = 1;
412 			break;
413 		}
414 
415 		if (meta & A_ONCHIP_FIFO_MEM_CORE_SOP) {
416 			sop_rcvd = 1;
417 		}
418 
419 		if (meta & A_ONCHIP_FIFO_MEM_CORE_EOP) {
420 			empty = (meta & A_ONCHIP_FIFO_MEM_CORE_EMPTY_MASK) >>
421 			    A_ONCHIP_FIFO_MEM_CORE_EMPTY_SHIFT;
422 		}
423 
424 		if (sop_rcvd == 0) {
425 			error = 1;
426 			break;
427 		}
428 
429 		if (empty == 0) {
430 			*(uint32_t *)(desc->dst_addr + dst_offs) = data;
431 			dst_offs += 4;
432 		} else if (empty == 1) {
433 			*(uint16_t *)(desc->dst_addr + dst_offs) =
434 			    ((data >> 16) & 0xffff);
435 			dst_offs += 2;
436 
437 			*(uint8_t *)(desc->dst_addr + dst_offs) =
438 			    ((data >> 8) & 0xff);
439 			dst_offs += 1;
440 		} else {
441 			panic("empty %d\n", empty);
442 		}
443 
444 		if (meta & A_ONCHIP_FIFO_MEM_CORE_EOP)
445 			break;
446 
447 		fill_level = softdma_fill_level(sc);
448 		timeout = 100;
449 		while (fill_level == 0 && timeout--)
450 			fill_level = softdma_fill_level(sc);
451 		if (timeout == 0) {
452 			/* No EOP received. Broken packet. */
453 			error = 1;
454 			break;
455 		}
456 	}
457 
458 	if (error) {
459 		return (-1);
460 	}
461 
462 	return (dst_offs);
463 }
464 
465 static uint32_t
466 softdma_process_descriptors(struct softdma_channel *chan,
467     xdma_transfer_status_t *status)
468 {
469 	struct xdma_channel *xchan;
470 	struct softdma_desc *desc;
471 	struct softdma_softc *sc;
472 	xdma_transfer_status_t st;
473 	int ret;
474 
475 	sc = chan->sc;
476 
477 	xchan = chan->xchan;
478 
479 	desc = &chan->descs[chan->idx_tail];
480 
481 	while (desc != NULL) {
482 
483 		if ((desc->control & CONTROL_OWN) == 0) {
484 			break;
485 		}
486 
487 		if (desc->direction == XDMA_MEM_TO_DEV) {
488 			ret = softdma_process_tx(chan, desc);
489 		} else {
490 			ret = softdma_process_rx(chan, desc);
491 			if (ret == 0) {
492 				/* No new data available. */
493 				break;
494 			}
495 		}
496 
497 		/* Descriptor processed. */
498 		desc->control = 0;
499 
500 		if (ret >= 0) {
501 			st.error = 0;
502 			st.transferred = ret;
503 		} else {
504 			st.error = ret;
505 			st.transferred = 0;
506 		}
507 
508 		xchan_seg_done(xchan, &st);
509 		atomic_subtract_int(&chan->descs_used_count, 1);
510 
511 		if (ret >= 0) {
512 			status->transferred += ret;
513 		} else {
514 			status->error = 1;
515 			break;
516 		}
517 
518 		chan->idx_tail = softdma_next_desc(chan, chan->idx_tail);
519 
520 		/* Process next descriptor, if any. */
521 		desc = desc->next;
522 	}
523 
524 	return (0);
525 }
526 
527 static void
528 softdma_worker(void *arg)
529 {
530 	xdma_transfer_status_t status;
531 	struct softdma_channel *chan;
532 	struct softdma_softc *sc;
533 
534 	chan = arg;
535 
536 	sc = chan->sc;
537 
538 	while (1) {
539 		mtx_lock(&chan->mtx);
540 
541 		do {
542 			mtx_sleep(chan, &chan->mtx, 0, "softdma_wait", hz / 2);
543 		} while (chan->run == 0);
544 
545 		status.error = 0;
546 		status.transferred = 0;
547 
548 		softdma_process_descriptors(chan, &status);
549 
550 		/* Finish operation */
551 		chan->run = 0;
552 		xdma_callback(chan->xchan, &status);
553 
554 		mtx_unlock(&chan->mtx);
555 	}
556 
557 }
558 
559 static int
560 softdma_proc_create(struct softdma_channel *chan)
561 {
562 	struct softdma_softc *sc;
563 
564 	sc = chan->sc;
565 
566 	if (chan->p != NULL) {
567 		/* Already created */
568 		return (0);
569 	}
570 
571 	mtx_init(&chan->mtx, "SoftDMA", NULL, MTX_DEF);
572 
573 	if (kproc_create(softdma_worker, (void *)chan, &chan->p, 0, 0,
574 	    "softdma_worker") != 0) {
575 		device_printf(sc->dev,
576 		    "%s: Failed to create worker thread.\n", __func__);
577 		return (-1);
578 	}
579 
580 	return (0);
581 }
582 
583 static int
584 softdma_channel_alloc(device_t dev, struct xdma_channel *xchan)
585 {
586 	struct softdma_channel *chan;
587 	struct softdma_softc *sc;
588 	int i;
589 
590 	sc = device_get_softc(dev);
591 
592 	for (i = 0; i < SOFTDMA_NCHANNELS; i++) {
593 		chan = &sc->channels[i];
594 		if (chan->used == 0) {
595 			chan->xchan = xchan;
596 			xchan->chan = (void *)chan;
597 			chan->index = i;
598 			chan->idx_head = 0;
599 			chan->idx_tail = 0;
600 			chan->descs_used_count = 0;
601 			chan->descs_num = 1024;
602 			chan->sc = sc;
603 
604 			if (softdma_proc_create(chan) != 0) {
605 				return (-1);
606 			}
607 
608 			chan->used = 1;
609 
610 			return (0);
611 		}
612 	}
613 
614 	return (-1);
615 }
616 
617 static int
618 softdma_channel_free(device_t dev, struct xdma_channel *xchan)
619 {
620 	struct softdma_channel *chan;
621 	struct softdma_softc *sc;
622 
623 	sc = device_get_softc(dev);
624 
625 	chan = (struct softdma_channel *)xchan->chan;
626 
627 	if (chan->descs != NULL) {
628 		free(chan->descs, M_DEVBUF);
629 	}
630 
631 	chan->used = 0;
632 
633 	return (0);
634 }
635 
636 static int
637 softdma_desc_alloc(struct xdma_channel *xchan)
638 {
639 	struct softdma_channel *chan;
640 	uint32_t nsegments;
641 
642 	chan = (struct softdma_channel *)xchan->chan;
643 
644 	nsegments = chan->descs_num;
645 
646 	chan->descs = malloc(nsegments * sizeof(struct softdma_desc),
647 	    M_DEVBUF, (M_WAITOK | M_ZERO));
648 
649 	return (0);
650 }
651 
652 static int
653 softdma_channel_prep_sg(device_t dev, struct xdma_channel *xchan)
654 {
655 	struct softdma_channel *chan;
656 	struct softdma_desc *desc;
657 	struct softdma_softc *sc;
658 	int ret;
659 	int i;
660 
661 	sc = device_get_softc(dev);
662 
663 	chan = (struct softdma_channel *)xchan->chan;
664 
665 	ret = softdma_desc_alloc(xchan);
666 	if (ret != 0) {
667 		device_printf(sc->dev,
668 		    "%s: Can't allocate descriptors.\n", __func__);
669 		return (-1);
670 	}
671 
672 	for (i = 0; i < chan->descs_num; i++) {
673 		desc = &chan->descs[i];
674 
675 		if (i == (chan->descs_num - 1)) {
676 			desc->next = &chan->descs[0];
677 		} else {
678 			desc->next = &chan->descs[i+1];
679 		}
680 	}
681 
682 	return (0);
683 }
684 
685 static int
686 softdma_channel_capacity(device_t dev, xdma_channel_t *xchan,
687     uint32_t *capacity)
688 {
689 	struct softdma_channel *chan;
690 	uint32_t c;
691 
692 	chan = (struct softdma_channel *)xchan->chan;
693 
694 	/* At least one descriptor must be left empty. */
695 	c = (chan->descs_num - chan->descs_used_count - 1);
696 
697 	*capacity = c;
698 
699 	return (0);
700 }
701 
702 static int
703 softdma_channel_submit_sg(device_t dev, struct xdma_channel *xchan,
704     struct xdma_sglist *sg, uint32_t sg_n)
705 {
706 	struct softdma_channel *chan;
707 	struct softdma_desc *desc;
708 	struct softdma_softc *sc;
709 	uint32_t enqueued;
710 	uint32_t saved_dir;
711 	uint32_t tmp;
712 	uint32_t len;
713 	int i;
714 
715 	sc = device_get_softc(dev);
716 
717 	chan = (struct softdma_channel *)xchan->chan;
718 
719 	enqueued = 0;
720 
721 	for (i = 0; i < sg_n; i++) {
722 		len = (uint32_t)sg[i].len;
723 
724 		desc = &chan->descs[chan->idx_head];
725 		desc->src_addr = sg[i].src_addr;
726 		desc->dst_addr = sg[i].dst_addr;
727 		if (sg[i].direction == XDMA_MEM_TO_DEV) {
728 			desc->src_incr = 1;
729 			desc->dst_incr = 0;
730 		} else {
731 			desc->src_incr = 0;
732 			desc->dst_incr = 1;
733 		}
734 		desc->direction = sg[i].direction;
735 		saved_dir = sg[i].direction;
736 		desc->len = len;
737 		desc->transfered = 0;
738 		desc->status = 0;
739 		desc->reserved = 0;
740 		desc->control = 0;
741 
742 		if (sg[i].first == 1)
743 			desc->control |= CONTROL_GEN_SOP;
744 		if (sg[i].last == 1)
745 			desc->control |= CONTROL_GEN_EOP;
746 
747 		tmp = chan->idx_head;
748 		chan->idx_head = softdma_next_desc(chan, chan->idx_head);
749 		atomic_add_int(&chan->descs_used_count, 1);
750 		desc->control |= CONTROL_OWN;
751 		enqueued += 1;
752 	}
753 
754 	if (enqueued == 0)
755 		return (0);
756 
757 	if (saved_dir == XDMA_MEM_TO_DEV) {
758 		chan->run = 1;
759 		wakeup(chan);
760 	} else
761 		softdma_memc_write(sc,
762 		    A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_INT_ENABLE,
763 		    SOFTDMA_RX_EVENTS);
764 
765 	return (0);
766 }
767 
768 static int
769 softdma_channel_request(device_t dev, struct xdma_channel *xchan,
770     struct xdma_request *req)
771 {
772 	struct softdma_channel *chan;
773 	struct softdma_desc *desc;
774 	struct softdma_softc *sc;
775 	int ret;
776 
777 	sc = device_get_softc(dev);
778 
779 	chan = (struct softdma_channel *)xchan->chan;
780 
781 	ret = softdma_desc_alloc(xchan);
782 	if (ret != 0) {
783 		device_printf(sc->dev,
784 		    "%s: Can't allocate descriptors.\n", __func__);
785 		return (-1);
786 	}
787 
788 	desc = &chan->descs[0];
789 
790 	desc->src_addr = req->src_addr;
791 	desc->dst_addr = req->dst_addr;
792 	desc->len = req->block_len;
793 	desc->src_incr = 1;
794 	desc->dst_incr = 1;
795 	desc->next = NULL;
796 
797 	return (0);
798 }
799 
800 static int
801 softdma_channel_control(device_t dev, xdma_channel_t *xchan, int cmd)
802 {
803 	struct softdma_channel *chan;
804 	struct softdma_softc *sc;
805 
806 	sc = device_get_softc(dev);
807 
808 	chan = (struct softdma_channel *)xchan->chan;
809 
810 	switch (cmd) {
811 	case XDMA_CMD_BEGIN:
812 	case XDMA_CMD_TERMINATE:
813 	case XDMA_CMD_PAUSE:
814 		/* TODO: implement me */
815 		return (-1);
816 	}
817 
818 	return (0);
819 }
820 
821 #ifdef FDT
822 static int
823 softdma_ofw_md_data(device_t dev, pcell_t *cells,
824     int ncells, void **ptr)
825 {
826 
827 	return (0);
828 }
829 #endif
830 
831 static device_method_t softdma_methods[] = {
832 	/* Device interface */
833 	DEVMETHOD(device_probe,			softdma_probe),
834 	DEVMETHOD(device_attach,		softdma_attach),
835 	DEVMETHOD(device_detach,		softdma_detach),
836 
837 	/* xDMA Interface */
838 	DEVMETHOD(xdma_channel_alloc,		softdma_channel_alloc),
839 	DEVMETHOD(xdma_channel_free,		softdma_channel_free),
840 	DEVMETHOD(xdma_channel_request,		softdma_channel_request),
841 	DEVMETHOD(xdma_channel_control,		softdma_channel_control),
842 
843 	/* xDMA SG Interface */
844 	DEVMETHOD(xdma_channel_prep_sg,		softdma_channel_prep_sg),
845 	DEVMETHOD(xdma_channel_submit_sg,	softdma_channel_submit_sg),
846 	DEVMETHOD(xdma_channel_capacity,	softdma_channel_capacity),
847 
848 #ifdef FDT
849 	DEVMETHOD(xdma_ofw_md_data,		softdma_ofw_md_data),
850 #endif
851 
852 	DEVMETHOD_END
853 };
854 
855 static driver_t softdma_driver = {
856 	"softdma",
857 	softdma_methods,
858 	sizeof(struct softdma_softc),
859 };
860 
861 static devclass_t softdma_devclass;
862 
863 EARLY_DRIVER_MODULE(softdma, simplebus, softdma_driver, softdma_devclass, 0, 0,
864     BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
865