]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/altera/softdma/softdma.c
Update libdialog to 1.3-20180621
[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 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);