]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/altera/softdma/softdma.c
Upgrade Unbound to 1.9.2.
[FreeBSD/FreeBSD.git] / sys / dev / altera / softdma / softdma.c
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 uint32_t
194 fifo_fill_level_wait(struct softdma_softc *sc)
195 {
196         uint32_t val;
197
198         do
199                 val = softdma_fill_level(sc);
200         while (val == AVALON_FIFO_TX_BASIC_OPTS_DEPTH);
201
202         return (val);
203 }
204
205 static void
206 softdma_intr(void *arg)
207 {
208         struct softdma_channel *chan;
209         struct softdma_softc *sc;
210         int reg;
211         int err;
212
213         sc = arg;
214
215         chan = &sc->channels[0];
216
217         reg = softdma_memc_read(sc, A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT);
218
219         if (reg & (A_ONCHIP_FIFO_MEM_CORE_EVENT_OVERFLOW | 
220             A_ONCHIP_FIFO_MEM_CORE_EVENT_UNDERFLOW)) {
221                 /* Errors */
222                 err = (((reg & A_ONCHIP_FIFO_MEM_CORE_ERROR_MASK) >> \
223                     A_ONCHIP_FIFO_MEM_CORE_ERROR_SHIFT) & 0xff);
224         }
225
226         if (reg != 0) {
227                 softdma_memc_write(sc,
228                     A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT, reg);
229                 chan->run = 1;
230                 wakeup(chan);
231         }
232 }
233
234 static int
235 softdma_probe(device_t dev)
236 {
237
238         if (!ofw_bus_status_okay(dev))
239                 return (ENXIO);
240
241         if (!ofw_bus_is_compatible(dev, "altr,softdma"))
242                 return (ENXIO);
243
244         device_set_desc(dev, "SoftDMA");
245
246         return (BUS_PROBE_DEFAULT);
247 }
248
249 static int
250 softdma_attach(device_t dev)
251 {
252         struct softdma_softc *sc;
253         phandle_t xref, node;
254         int err;
255
256         sc = device_get_softc(dev);
257         sc->dev = dev;
258
259         if (bus_alloc_resources(dev, softdma_spec, sc->res)) {
260                 device_printf(dev,
261                     "could not allocate resources for device\n");
262                 return (ENXIO);
263         }
264
265         /* FIFO memory interface */
266         sc->bst = rman_get_bustag(sc->res[0]);
267         sc->bsh = rman_get_bushandle(sc->res[0]);
268
269         /* FIFO control memory interface */
270         sc->bst_c = rman_get_bustag(sc->res[1]);
271         sc->bsh_c = rman_get_bushandle(sc->res[1]);
272
273         /* Setup interrupt handler */
274         err = bus_setup_intr(dev, sc->res[2], INTR_TYPE_MISC | INTR_MPSAFE,
275             NULL, softdma_intr, sc, &sc->ih);
276         if (err) {
277                 device_printf(dev, "Unable to alloc interrupt resource.\n");
278                 return (ENXIO);
279         }
280
281         node = ofw_bus_get_node(dev);
282         xref = OF_xref_from_node(node);
283         OF_device_register_xref(xref, dev);
284
285         return (0);
286 }
287
288 static int
289 softdma_detach(device_t dev)
290 {
291         struct softdma_softc *sc;
292
293         sc = device_get_softc(dev);
294
295         return (0);
296 }
297
298 static int
299 softdma_process_tx(struct softdma_channel *chan, struct softdma_desc *desc)
300 {
301         struct softdma_softc *sc;
302         uint64_t addr;
303         uint64_t buf;
304         uint32_t word;
305         uint32_t missing;
306         uint32_t reg;
307         int got_bits;
308         int len;
309
310         sc = chan->sc;
311
312         fifo_fill_level_wait(sc);
313
314         /* Set start of packet. */
315         if (desc->control & CONTROL_GEN_SOP)
316                 softdma_mem_write(sc, A_ONCHIP_FIFO_MEM_CORE_METADATA,
317                     A_ONCHIP_FIFO_MEM_CORE_SOP);
318
319         got_bits = 0;
320         buf = 0;
321
322         addr = desc->src_addr;
323         len = desc->len;
324
325         if (addr & 1) {
326                 buf = (buf << 8) | *(uint8_t *)addr;
327                 got_bits += 8;
328                 addr += 1;
329                 len -= 1;
330         }
331
332         if (len >= 2 && addr & 2) {
333                 buf = (buf << 16) | *(uint16_t *)addr;
334                 got_bits += 16;
335                 addr += 2;
336                 len -= 2;
337         }
338
339         while (len >= 4) {
340                 buf = (buf << 32) | (uint64_t)*(uint32_t *)addr;
341                 addr += 4;
342                 len -= 4;
343                 word = (uint32_t)((buf >> got_bits) & 0xffffffff);
344
345                 fifo_fill_level_wait(sc);
346                 if (len == 0 && got_bits == 0 &&
347                     (desc->control & CONTROL_GEN_EOP) != 0)
348                         softdma_mem_write(sc, A_ONCHIP_FIFO_MEM_CORE_METADATA,
349                             A_ONCHIP_FIFO_MEM_CORE_EOP);
350                 bus_write_4(sc->res[0], A_ONCHIP_FIFO_MEM_CORE_DATA, word);
351         }
352
353         if (len & 2) {
354                 buf = (buf << 16) | *(uint16_t *)addr;
355                 got_bits += 16;
356                 addr += 2;
357                 len -= 2;
358         }
359
360         if (len & 1) {
361                 buf = (buf << 8) | *(uint8_t *)addr;
362                 got_bits += 8;
363                 addr += 1;
364                 len -= 1;
365         }
366
367         if (got_bits >= 32) {
368                 got_bits -= 32;
369                 word = (uint32_t)((buf >> got_bits) & 0xffffffff);
370
371                 fifo_fill_level_wait(sc);
372                 if (len == 0 && got_bits == 0 &&
373                     (desc->control & CONTROL_GEN_EOP) != 0)
374                         softdma_mem_write(sc, A_ONCHIP_FIFO_MEM_CORE_METADATA,
375                             A_ONCHIP_FIFO_MEM_CORE_EOP);
376                 bus_write_4(sc->res[0], A_ONCHIP_FIFO_MEM_CORE_DATA, word);
377         }
378
379         if (got_bits) {
380                 missing = 32 - got_bits;
381                 got_bits /= 8;
382
383                 fifo_fill_level_wait(sc);
384                 reg = A_ONCHIP_FIFO_MEM_CORE_EOP |
385                     ((4 - got_bits) << A_ONCHIP_FIFO_MEM_CORE_EMPTY_SHIFT);
386                 softdma_mem_write(sc, A_ONCHIP_FIFO_MEM_CORE_METADATA, reg);
387                 word = (uint32_t)((buf << missing) & 0xffffffff);
388                 bus_write_4(sc->res[0], A_ONCHIP_FIFO_MEM_CORE_DATA, word);
389         }
390
391         return (desc->len);
392 }
393
394 static int
395 softdma_process_rx(struct softdma_channel *chan, struct softdma_desc *desc)
396 {
397         uint32_t src_offs, dst_offs;
398         struct softdma_softc *sc;
399         uint32_t fill_level;
400         uint32_t empty;
401         uint32_t meta;
402         uint32_t data;
403         int sop_rcvd;
404         int timeout;
405         size_t len;
406         int error;
407
408         sc = chan->sc;
409         empty = 0;
410         src_offs = dst_offs = 0;
411         error = 0;
412
413         fill_level = softdma_fill_level(sc);
414         if (fill_level == 0) {
415                 /* Nothing to receive. */
416                 return (0);
417         }
418
419         len = desc->len;
420
421         sop_rcvd = 0;
422         while (fill_level) {
423                 empty = 0;
424                 data = bus_read_4(sc->res[0], A_ONCHIP_FIFO_MEM_CORE_DATA);
425                 meta = softdma_mem_read(sc, A_ONCHIP_FIFO_MEM_CORE_METADATA);
426
427                 if (meta & A_ONCHIP_FIFO_MEM_CORE_ERROR_MASK) {
428                         error = 1;
429                         break;
430                 }
431
432                 if ((meta & A_ONCHIP_FIFO_MEM_CORE_CHANNEL_MASK) != 0) {
433                         error = 1;
434                         break;
435                 }
436
437                 if (meta & A_ONCHIP_FIFO_MEM_CORE_SOP) {
438                         sop_rcvd = 1;
439                 }
440
441                 if (meta & A_ONCHIP_FIFO_MEM_CORE_EOP) {
442                         empty = (meta & A_ONCHIP_FIFO_MEM_CORE_EMPTY_MASK) >>
443                             A_ONCHIP_FIFO_MEM_CORE_EMPTY_SHIFT;
444                 }
445
446                 if (sop_rcvd == 0) {
447                         error = 1;
448                         break;
449                 }
450
451                 if (empty == 0) {
452                         *(uint32_t *)(desc->dst_addr + dst_offs) = data;
453                         dst_offs += 4;
454                 } else if (empty == 1) {
455                         *(uint16_t *)(desc->dst_addr + dst_offs) =
456                             ((data >> 16) & 0xffff);
457                         dst_offs += 2;
458
459                         *(uint8_t *)(desc->dst_addr + dst_offs) =
460                             ((data >> 8) & 0xff);
461                         dst_offs += 1;
462                 } else {
463                         panic("empty %d\n", empty);
464                 }
465
466                 if (meta & A_ONCHIP_FIFO_MEM_CORE_EOP)
467                         break;
468
469                 fill_level = softdma_fill_level(sc);
470                 timeout = 100;
471                 while (fill_level == 0 && timeout--)
472                         fill_level = softdma_fill_level(sc);
473                 if (timeout == 0) {
474                         /* No EOP received. Broken packet. */
475                         error = 1;
476                         break;
477                 }
478         }
479
480         if (error) {
481                 return (-1);
482         }
483
484         return (dst_offs);
485 }
486
487 static uint32_t
488 softdma_process_descriptors(struct softdma_channel *chan,
489     xdma_transfer_status_t *status)
490 {
491         struct xdma_channel *xchan;
492         struct softdma_desc *desc;
493         struct softdma_softc *sc;
494         xdma_transfer_status_t st;
495         int ret;
496
497         sc = chan->sc;
498
499         xchan = chan->xchan;
500
501         desc = &chan->descs[chan->idx_tail];
502
503         while (desc != NULL) {
504
505                 if ((desc->control & CONTROL_OWN) == 0) {
506                         break;
507                 }
508
509                 if (desc->direction == XDMA_MEM_TO_DEV) {
510                         ret = softdma_process_tx(chan, desc);
511                 } else {
512                         ret = softdma_process_rx(chan, desc);
513                         if (ret == 0) {
514                                 /* No new data available. */
515                                 break;
516                         }
517                 }
518
519                 /* Descriptor processed. */
520                 desc->control = 0;
521
522                 if (ret >= 0) {
523                         st.error = 0;
524                         st.transferred = ret;
525                 } else {
526                         st.error = ret;
527                         st.transferred = 0;
528                 }
529
530                 xchan_seg_done(xchan, &st);
531                 atomic_subtract_int(&chan->descs_used_count, 1);
532
533                 if (ret >= 0) {
534                         status->transferred += ret;
535                 } else {
536                         status->error = 1;
537                         break;
538                 }
539
540                 chan->idx_tail = softdma_next_desc(chan, chan->idx_tail);
541
542                 /* Process next descriptor, if any. */
543                 desc = desc->next;
544         }
545
546         return (0);
547 }
548
549 static void
550 softdma_worker(void *arg)
551 {
552         xdma_transfer_status_t status;
553         struct softdma_channel *chan;
554         struct softdma_softc *sc;
555
556         chan = arg;
557
558         sc = chan->sc;
559
560         while (1) {
561                 mtx_lock(&chan->mtx);
562
563                 do {
564                         mtx_sleep(chan, &chan->mtx, 0, "softdma_wait", hz / 2);
565                 } while (chan->run == 0);
566
567                 status.error = 0;
568                 status.transferred = 0;
569
570                 softdma_process_descriptors(chan, &status);
571
572                 /* Finish operation */
573                 chan->run = 0;
574                 xdma_callback(chan->xchan, &status);
575
576                 mtx_unlock(&chan->mtx);
577         }
578
579 }
580
581 static int
582 softdma_proc_create(struct softdma_channel *chan)
583 {
584         struct softdma_softc *sc;
585
586         sc = chan->sc;
587
588         if (chan->p != NULL) {
589                 /* Already created */
590                 return (0);
591         }
592
593         mtx_init(&chan->mtx, "SoftDMA", NULL, MTX_DEF);
594
595         if (kproc_create(softdma_worker, (void *)chan, &chan->p, 0, 0,
596             "softdma_worker") != 0) {
597                 device_printf(sc->dev,
598                     "%s: Failed to create worker thread.\n", __func__);
599                 return (-1);
600         }
601
602         return (0);
603 }
604
605 static int
606 softdma_channel_alloc(device_t dev, struct xdma_channel *xchan)
607 {
608         struct softdma_channel *chan;
609         struct softdma_softc *sc;
610         int i;
611
612         sc = device_get_softc(dev);
613
614         for (i = 0; i < SOFTDMA_NCHANNELS; i++) {
615                 chan = &sc->channels[i];
616                 if (chan->used == 0) {
617                         chan->xchan = xchan;
618                         xchan->chan = (void *)chan;
619                         xchan->caps |= XCHAN_CAP_NOBUFS;
620                         xchan->caps |= XCHAN_CAP_NOSEG;
621                         chan->index = i;
622                         chan->idx_head = 0;
623                         chan->idx_tail = 0;
624                         chan->descs_used_count = 0;
625                         chan->descs_num = 1024;
626                         chan->sc = sc;
627
628                         if (softdma_proc_create(chan) != 0) {
629                                 return (-1);
630                         }
631
632                         chan->used = 1;
633
634                         return (0);
635                 }
636         }
637
638         return (-1);
639 }
640
641 static int
642 softdma_channel_free(device_t dev, struct xdma_channel *xchan)
643 {
644         struct softdma_channel *chan;
645         struct softdma_softc *sc;
646
647         sc = device_get_softc(dev);
648
649         chan = (struct softdma_channel *)xchan->chan;
650
651         if (chan->descs != NULL) {
652                 free(chan->descs, M_DEVBUF);
653         }
654
655         chan->used = 0;
656
657         return (0);
658 }
659
660 static int
661 softdma_desc_alloc(struct xdma_channel *xchan)
662 {
663         struct softdma_channel *chan;
664         uint32_t nsegments;
665
666         chan = (struct softdma_channel *)xchan->chan;
667
668         nsegments = chan->descs_num;
669
670         chan->descs = malloc(nsegments * sizeof(struct softdma_desc),
671             M_DEVBUF, (M_WAITOK | M_ZERO));
672
673         return (0);
674 }
675
676 static int
677 softdma_channel_prep_sg(device_t dev, struct xdma_channel *xchan)
678 {
679         struct softdma_channel *chan;
680         struct softdma_desc *desc;
681         struct softdma_softc *sc;
682         int ret;
683         int i;
684
685         sc = device_get_softc(dev);
686
687         chan = (struct softdma_channel *)xchan->chan;
688
689         ret = softdma_desc_alloc(xchan);
690         if (ret != 0) {
691                 device_printf(sc->dev,
692                     "%s: Can't allocate descriptors.\n", __func__);
693                 return (-1);
694         }
695
696         for (i = 0; i < chan->descs_num; i++) {
697                 desc = &chan->descs[i];
698
699                 if (i == (chan->descs_num - 1)) {
700                         desc->next = &chan->descs[0];
701                 } else {
702                         desc->next = &chan->descs[i+1];
703                 }
704         }
705
706         return (0);
707 }
708
709 static int
710 softdma_channel_capacity(device_t dev, xdma_channel_t *xchan,
711     uint32_t *capacity)
712 {
713         struct softdma_channel *chan;
714         uint32_t c;
715
716         chan = (struct softdma_channel *)xchan->chan;
717
718         /* At least one descriptor must be left empty. */
719         c = (chan->descs_num - chan->descs_used_count - 1);
720
721         *capacity = c;
722
723         return (0);
724 }
725
726 static int
727 softdma_channel_submit_sg(device_t dev, struct xdma_channel *xchan,
728     struct xdma_sglist *sg, uint32_t sg_n)
729 {
730         struct softdma_channel *chan;
731         struct softdma_desc *desc;
732         struct softdma_softc *sc;
733         uint32_t enqueued;
734         uint32_t saved_dir;
735         uint32_t tmp;
736         uint32_t len;
737         int i;
738
739         sc = device_get_softc(dev);
740
741         chan = (struct softdma_channel *)xchan->chan;
742
743         enqueued = 0;
744
745         for (i = 0; i < sg_n; i++) {
746                 len = (uint32_t)sg[i].len;
747
748                 desc = &chan->descs[chan->idx_head];
749                 desc->src_addr = sg[i].src_addr;
750                 desc->dst_addr = sg[i].dst_addr;
751                 if (sg[i].direction == XDMA_MEM_TO_DEV) {
752                         desc->src_incr = 1;
753                         desc->dst_incr = 0;
754                 } else {
755                         desc->src_incr = 0;
756                         desc->dst_incr = 1;
757                 }
758                 desc->direction = sg[i].direction;
759                 saved_dir = sg[i].direction;
760                 desc->len = len;
761                 desc->transfered = 0;
762                 desc->status = 0;
763                 desc->reserved = 0;
764                 desc->control = 0;
765
766                 if (sg[i].first == 1)
767                         desc->control |= CONTROL_GEN_SOP;
768                 if (sg[i].last == 1)
769                         desc->control |= CONTROL_GEN_EOP;
770
771                 tmp = chan->idx_head;
772                 chan->idx_head = softdma_next_desc(chan, chan->idx_head);
773                 atomic_add_int(&chan->descs_used_count, 1);
774                 desc->control |= CONTROL_OWN;
775                 enqueued += 1;
776         }
777
778         if (enqueued == 0)
779                 return (0);
780
781         if (saved_dir == XDMA_MEM_TO_DEV) {
782                 chan->run = 1;
783                 wakeup(chan);
784         } else
785                 softdma_memc_write(sc,
786                     A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_INT_ENABLE,
787                     SOFTDMA_RX_EVENTS);
788
789         return (0);
790 }
791
792 static int
793 softdma_channel_request(device_t dev, struct xdma_channel *xchan,
794     struct xdma_request *req)
795 {
796         struct softdma_channel *chan;
797         struct softdma_desc *desc;
798         struct softdma_softc *sc;
799         int ret;
800
801         sc = device_get_softc(dev);
802
803         chan = (struct softdma_channel *)xchan->chan;
804
805         ret = softdma_desc_alloc(xchan);
806         if (ret != 0) {
807                 device_printf(sc->dev,
808                     "%s: Can't allocate descriptors.\n", __func__);
809                 return (-1);
810         }
811
812         desc = &chan->descs[0];
813
814         desc->src_addr = req->src_addr;
815         desc->dst_addr = req->dst_addr;
816         desc->len = req->block_len;
817         desc->src_incr = 1;
818         desc->dst_incr = 1;
819         desc->next = NULL;
820
821         return (0);
822 }
823
824 static int
825 softdma_channel_control(device_t dev, xdma_channel_t *xchan, int cmd)
826 {
827         struct softdma_channel *chan;
828         struct softdma_softc *sc;
829
830         sc = device_get_softc(dev);
831
832         chan = (struct softdma_channel *)xchan->chan;
833
834         switch (cmd) {
835         case XDMA_CMD_BEGIN:
836         case XDMA_CMD_TERMINATE:
837         case XDMA_CMD_PAUSE:
838                 /* TODO: implement me */
839                 return (-1);
840         }
841
842         return (0);
843 }
844
845 #ifdef FDT
846 static int
847 softdma_ofw_md_data(device_t dev, pcell_t *cells,
848     int ncells, void **ptr)
849 {
850
851         return (0);
852 }
853 #endif
854
855 static device_method_t softdma_methods[] = {
856         /* Device interface */
857         DEVMETHOD(device_probe,                 softdma_probe),
858         DEVMETHOD(device_attach,                softdma_attach),
859         DEVMETHOD(device_detach,                softdma_detach),
860
861         /* xDMA Interface */
862         DEVMETHOD(xdma_channel_alloc,           softdma_channel_alloc),
863         DEVMETHOD(xdma_channel_free,            softdma_channel_free),
864         DEVMETHOD(xdma_channel_request,         softdma_channel_request),
865         DEVMETHOD(xdma_channel_control,         softdma_channel_control),
866
867         /* xDMA SG Interface */
868         DEVMETHOD(xdma_channel_prep_sg,         softdma_channel_prep_sg),
869         DEVMETHOD(xdma_channel_submit_sg,       softdma_channel_submit_sg),
870         DEVMETHOD(xdma_channel_capacity,        softdma_channel_capacity),
871
872 #ifdef FDT
873         DEVMETHOD(xdma_ofw_md_data,             softdma_ofw_md_data),
874 #endif
875
876         DEVMETHOD_END
877 };
878
879 static driver_t softdma_driver = {
880         "softdma",
881         softdma_methods,
882         sizeof(struct softdma_softc),
883 };
884
885 static devclass_t softdma_devclass;
886
887 EARLY_DRIVER_MODULE(softdma, simplebus, softdma_driver, softdma_devclass, 0, 0,
888     BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);