185debf7fSRuslan Bukin /*- 2101869a8SRuslan Bukin * SPDX-License-Identifier: BSD-2-Clause 3101869a8SRuslan Bukin * 4101869a8SRuslan Bukin * Copyright (c) 2016-2019 Ruslan Bukin <br@bsdpad.com> 585debf7fSRuslan Bukin * 685debf7fSRuslan Bukin * This software was developed by SRI International and the University of 785debf7fSRuslan Bukin * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237 885debf7fSRuslan Bukin * ("CTSRD"), as part of the DARPA CRASH research programme. 985debf7fSRuslan Bukin * 1085debf7fSRuslan Bukin * Redistribution and use in source and binary forms, with or without 1185debf7fSRuslan Bukin * modification, are permitted provided that the following conditions 1285debf7fSRuslan Bukin * are met: 1385debf7fSRuslan Bukin * 1. Redistributions of source code must retain the above copyright 1485debf7fSRuslan Bukin * notice, this list of conditions and the following disclaimer. 1585debf7fSRuslan Bukin * 2. Redistributions in binary form must reproduce the above copyright 1685debf7fSRuslan Bukin * notice, this list of conditions and the following disclaimer in the 1785debf7fSRuslan Bukin * documentation and/or other materials provided with the distribution. 1885debf7fSRuslan Bukin * 1985debf7fSRuslan Bukin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2085debf7fSRuslan Bukin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2185debf7fSRuslan Bukin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2285debf7fSRuslan Bukin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2385debf7fSRuslan Bukin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2485debf7fSRuslan Bukin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2585debf7fSRuslan Bukin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2685debf7fSRuslan Bukin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2785debf7fSRuslan Bukin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2885debf7fSRuslan Bukin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2985debf7fSRuslan Bukin * SUCH DAMAGE. 3085debf7fSRuslan Bukin */ 3185debf7fSRuslan Bukin 323d5b3b0aSRuslan Bukin #ifndef _DEV_XDMA_XDMA_H_ 333d5b3b0aSRuslan Bukin #define _DEV_XDMA_XDMA_H_ 343d5b3b0aSRuslan Bukin 353d5b3b0aSRuslan Bukin #include <sys/proc.h> 36101869a8SRuslan Bukin #include <sys/vmem.h> 3785debf7fSRuslan Bukin 38951e0584SRuslan Bukin #ifdef FDT 39951e0584SRuslan Bukin #include <dev/fdt/fdt_common.h> 40951e0584SRuslan Bukin #include <dev/ofw/openfirm.h> 41951e0584SRuslan Bukin #endif 42951e0584SRuslan Bukin 43951e0584SRuslan Bukin #include <vm/vm.h> 44951e0584SRuslan Bukin #include <vm/pmap.h> 45951e0584SRuslan Bukin 4685debf7fSRuslan Bukin enum xdma_direction { 4785debf7fSRuslan Bukin XDMA_MEM_TO_MEM, 4885debf7fSRuslan Bukin XDMA_MEM_TO_DEV, 4985debf7fSRuslan Bukin XDMA_DEV_TO_MEM, 5085debf7fSRuslan Bukin XDMA_DEV_TO_DEV, 5185debf7fSRuslan Bukin }; 5285debf7fSRuslan Bukin 5385debf7fSRuslan Bukin enum xdma_operation_type { 5485debf7fSRuslan Bukin XDMA_MEMCPY, 5585debf7fSRuslan Bukin XDMA_CYCLIC, 563d5b3b0aSRuslan Bukin XDMA_FIFO, 573d5b3b0aSRuslan Bukin XDMA_SG, 583d5b3b0aSRuslan Bukin }; 593d5b3b0aSRuslan Bukin 603d5b3b0aSRuslan Bukin enum xdma_request_type { 613d5b3b0aSRuslan Bukin XR_TYPE_PHYS, 623d5b3b0aSRuslan Bukin XR_TYPE_VIRT, 633d5b3b0aSRuslan Bukin XR_TYPE_MBUF, 643d5b3b0aSRuslan Bukin XR_TYPE_BIO, 6585debf7fSRuslan Bukin }; 6685debf7fSRuslan Bukin 6785debf7fSRuslan Bukin enum xdma_command { 6885debf7fSRuslan Bukin XDMA_CMD_BEGIN, 6985debf7fSRuslan Bukin XDMA_CMD_PAUSE, 7085debf7fSRuslan Bukin XDMA_CMD_TERMINATE, 7185debf7fSRuslan Bukin }; 7285debf7fSRuslan Bukin 733d5b3b0aSRuslan Bukin struct xdma_transfer_status { 743d5b3b0aSRuslan Bukin uint32_t transferred; 753d5b3b0aSRuslan Bukin int error; 763d5b3b0aSRuslan Bukin }; 773d5b3b0aSRuslan Bukin 783d5b3b0aSRuslan Bukin typedef struct xdma_transfer_status xdma_transfer_status_t; 793d5b3b0aSRuslan Bukin 8085debf7fSRuslan Bukin struct xdma_controller { 8185debf7fSRuslan Bukin device_t dev; /* DMA consumer device_t. */ 8285debf7fSRuslan Bukin device_t dma_dev; /* A real DMA device_t. */ 8385debf7fSRuslan Bukin void *data; /* OFW MD part. */ 84101869a8SRuslan Bukin vmem_t *vmem; /* Bounce memory. */ 8585debf7fSRuslan Bukin 8685debf7fSRuslan Bukin /* List of virtual channels allocated. */ 8785debf7fSRuslan Bukin TAILQ_HEAD(xdma_channel_list, xdma_channel) channels; 8885debf7fSRuslan Bukin }; 8985debf7fSRuslan Bukin 9085debf7fSRuslan Bukin typedef struct xdma_controller xdma_controller_t; 9185debf7fSRuslan Bukin 923d5b3b0aSRuslan Bukin struct xchan_buf { 933d5b3b0aSRuslan Bukin bus_dmamap_t map; 943d5b3b0aSRuslan Bukin uint32_t nsegs; 953d5b3b0aSRuslan Bukin uint32_t nsegs_left; 96101869a8SRuslan Bukin vm_offset_t vaddr; 97101869a8SRuslan Bukin vm_offset_t paddr; 98101869a8SRuslan Bukin vm_size_t size; 993d5b3b0aSRuslan Bukin }; 1003d5b3b0aSRuslan Bukin 1013d5b3b0aSRuslan Bukin struct xdma_request { 1023d5b3b0aSRuslan Bukin struct mbuf *m; 1033d5b3b0aSRuslan Bukin struct bio *bp; 1043d5b3b0aSRuslan Bukin enum xdma_operation_type operation; 1053d5b3b0aSRuslan Bukin enum xdma_request_type req_type; 10685debf7fSRuslan Bukin enum xdma_direction direction; 1073d5b3b0aSRuslan Bukin bus_addr_t src_addr; 1083d5b3b0aSRuslan Bukin bus_addr_t dst_addr; 1093d5b3b0aSRuslan Bukin uint8_t src_width; 1103d5b3b0aSRuslan Bukin uint8_t dst_width; 1113d5b3b0aSRuslan Bukin bus_size_t block_num; 1123d5b3b0aSRuslan Bukin bus_size_t block_len; 1133d5b3b0aSRuslan Bukin xdma_transfer_status_t status; 1143d5b3b0aSRuslan Bukin void *user; 1153d5b3b0aSRuslan Bukin TAILQ_ENTRY(xdma_request) xr_next; 1163d5b3b0aSRuslan Bukin struct xchan_buf buf; 11785debf7fSRuslan Bukin }; 11885debf7fSRuslan Bukin 1193d5b3b0aSRuslan Bukin struct xdma_sglist { 1203d5b3b0aSRuslan Bukin bus_addr_t src_addr; 1213d5b3b0aSRuslan Bukin bus_addr_t dst_addr; 1223d5b3b0aSRuslan Bukin size_t len; 1233d5b3b0aSRuslan Bukin uint8_t src_width; 1243d5b3b0aSRuslan Bukin uint8_t dst_width; 1253d5b3b0aSRuslan Bukin enum xdma_direction direction; 1263d5b3b0aSRuslan Bukin bool first; 1273d5b3b0aSRuslan Bukin bool last; 12885debf7fSRuslan Bukin }; 12985debf7fSRuslan Bukin 130951e0584SRuslan Bukin struct xdma_iommu { 131951e0584SRuslan Bukin struct pmap p; 132951e0584SRuslan Bukin vmem_t *vmem; /* VA space */ 133951e0584SRuslan Bukin device_t dev; /* IOMMU device */ 134951e0584SRuslan Bukin }; 135951e0584SRuslan Bukin 13685debf7fSRuslan Bukin struct xdma_channel { 13785debf7fSRuslan Bukin xdma_controller_t *xdma; 138101869a8SRuslan Bukin vmem_t *vmem; 13985debf7fSRuslan Bukin 1403d5b3b0aSRuslan Bukin uint32_t flags; 1413d5b3b0aSRuslan Bukin #define XCHAN_BUFS_ALLOCATED (1 << 0) 1423d5b3b0aSRuslan Bukin #define XCHAN_SGLIST_ALLOCATED (1 << 1) 1433d5b3b0aSRuslan Bukin #define XCHAN_CONFIGURED (1 << 2) 1443d5b3b0aSRuslan Bukin #define XCHAN_TYPE_CYCLIC (1 << 3) 1453d5b3b0aSRuslan Bukin #define XCHAN_TYPE_MEMCPY (1 << 4) 1463d5b3b0aSRuslan Bukin #define XCHAN_TYPE_FIFO (1 << 5) 1473d5b3b0aSRuslan Bukin #define XCHAN_TYPE_SG (1 << 6) 1483d5b3b0aSRuslan Bukin 1493d5b3b0aSRuslan Bukin uint32_t caps; 1503d5b3b0aSRuslan Bukin #define XCHAN_CAP_BUSDMA (1 << 0) 1515a51e5e4SRuslan Bukin #define XCHAN_CAP_NOSEG (1 << 1) 1520c340d7eSRuslan Bukin #define XCHAN_CAP_BOUNCE (1 << 2) 153951e0584SRuslan Bukin #define XCHAN_CAP_IOMMU (1 << 3) 15485debf7fSRuslan Bukin 15585debf7fSRuslan Bukin /* A real hardware driver channel. */ 15685debf7fSRuslan Bukin void *chan; 15785debf7fSRuslan Bukin 15885debf7fSRuslan Bukin /* Interrupt handlers. */ 15985debf7fSRuslan Bukin TAILQ_HEAD(, xdma_intr_handler) ie_handlers; 16085debf7fSRuslan Bukin TAILQ_ENTRY(xdma_channel) xchan_next; 1613d5b3b0aSRuslan Bukin 162101869a8SRuslan Bukin struct mtx mtx_lock; 163101869a8SRuslan Bukin struct mtx mtx_qin_lock; 164101869a8SRuslan Bukin struct mtx mtx_qout_lock; 165101869a8SRuslan Bukin struct mtx mtx_bank_lock; 166101869a8SRuslan Bukin struct mtx mtx_proc_lock; 1673d5b3b0aSRuslan Bukin 1683d5b3b0aSRuslan Bukin /* Request queue. */ 1693d5b3b0aSRuslan Bukin bus_dma_tag_t dma_tag_bufs; 1703d5b3b0aSRuslan Bukin struct xdma_request *xr_mem; 1713d5b3b0aSRuslan Bukin uint32_t xr_num; 1723d5b3b0aSRuslan Bukin 1733d5b3b0aSRuslan Bukin /* Bus dma tag options. */ 1743d5b3b0aSRuslan Bukin bus_size_t maxsegsize; 1753d5b3b0aSRuslan Bukin bus_size_t maxnsegs; 1763d5b3b0aSRuslan Bukin bus_size_t alignment; 1773d5b3b0aSRuslan Bukin bus_addr_t boundary; 1783d5b3b0aSRuslan Bukin bus_addr_t lowaddr; 1793d5b3b0aSRuslan Bukin bus_addr_t highaddr; 1803d5b3b0aSRuslan Bukin 1813d5b3b0aSRuslan Bukin struct xdma_sglist *sg; 1823d5b3b0aSRuslan Bukin 1833d5b3b0aSRuslan Bukin TAILQ_HEAD(, xdma_request) bank; 1843d5b3b0aSRuslan Bukin TAILQ_HEAD(, xdma_request) queue_in; 1853d5b3b0aSRuslan Bukin TAILQ_HEAD(, xdma_request) queue_out; 1863d5b3b0aSRuslan Bukin TAILQ_HEAD(, xdma_request) processing; 187951e0584SRuslan Bukin 188951e0584SRuslan Bukin /* iommu */ 189951e0584SRuslan Bukin struct xdma_iommu xio; 19085debf7fSRuslan Bukin }; 19185debf7fSRuslan Bukin 19285debf7fSRuslan Bukin typedef struct xdma_channel xdma_channel_t; 19385debf7fSRuslan Bukin 19485debf7fSRuslan Bukin struct xdma_intr_handler { 1953d5b3b0aSRuslan Bukin int (*cb)(void *cb_user, xdma_transfer_status_t *status); 196*d987842dSRuslan Bukin int flags; 197*d987842dSRuslan Bukin #define XDMA_INTR_NET (1 << 0) 19885debf7fSRuslan Bukin void *cb_user; 19985debf7fSRuslan Bukin TAILQ_ENTRY(xdma_intr_handler) ih_next; 20085debf7fSRuslan Bukin }; 20185debf7fSRuslan Bukin 2023d5b3b0aSRuslan Bukin static MALLOC_DEFINE(M_XDMA, "xdma", "xDMA framework"); 2033d5b3b0aSRuslan Bukin 204101869a8SRuslan Bukin #define XCHAN_LOCK(xchan) mtx_lock(&(xchan)->mtx_lock) 205101869a8SRuslan Bukin #define XCHAN_UNLOCK(xchan) mtx_unlock(&(xchan)->mtx_lock) 2063d5b3b0aSRuslan Bukin #define XCHAN_ASSERT_LOCKED(xchan) \ 207101869a8SRuslan Bukin mtx_assert(&(xchan)->mtx_lock, MA_OWNED) 2083d5b3b0aSRuslan Bukin 209101869a8SRuslan Bukin #define QUEUE_IN_LOCK(xchan) mtx_lock(&(xchan)->mtx_qin_lock) 210101869a8SRuslan Bukin #define QUEUE_IN_UNLOCK(xchan) mtx_unlock(&(xchan)->mtx_qin_lock) 2113d5b3b0aSRuslan Bukin #define QUEUE_IN_ASSERT_LOCKED(xchan) \ 212101869a8SRuslan Bukin mtx_assert(&(xchan)->mtx_qin_lock, MA_OWNED) 2133d5b3b0aSRuslan Bukin 214101869a8SRuslan Bukin #define QUEUE_OUT_LOCK(xchan) mtx_lock(&(xchan)->mtx_qout_lock) 215101869a8SRuslan Bukin #define QUEUE_OUT_UNLOCK(xchan) mtx_unlock(&(xchan)->mtx_qout_lock) 2163d5b3b0aSRuslan Bukin #define QUEUE_OUT_ASSERT_LOCKED(xchan) \ 217101869a8SRuslan Bukin mtx_assert(&(xchan)->mtx_qout_lock, MA_OWNED) 2183d5b3b0aSRuslan Bukin 219101869a8SRuslan Bukin #define QUEUE_BANK_LOCK(xchan) mtx_lock(&(xchan)->mtx_bank_lock) 220101869a8SRuslan Bukin #define QUEUE_BANK_UNLOCK(xchan) mtx_unlock(&(xchan)->mtx_bank_lock) 2213d5b3b0aSRuslan Bukin #define QUEUE_BANK_ASSERT_LOCKED(xchan) \ 222101869a8SRuslan Bukin mtx_assert(&(xchan)->mtx_bank_lock, MA_OWNED) 2233d5b3b0aSRuslan Bukin 224101869a8SRuslan Bukin #define QUEUE_PROC_LOCK(xchan) mtx_lock(&(xchan)->mtx_proc_lock) 225101869a8SRuslan Bukin #define QUEUE_PROC_UNLOCK(xchan) mtx_unlock(&(xchan)->mtx_proc_lock) 2263d5b3b0aSRuslan Bukin #define QUEUE_PROC_ASSERT_LOCKED(xchan) \ 227101869a8SRuslan Bukin mtx_assert(&(xchan)->mtx_proc_lock, MA_OWNED) 2283d5b3b0aSRuslan Bukin 2293d5b3b0aSRuslan Bukin #define XDMA_SGLIST_MAXLEN 2048 2303d5b3b0aSRuslan Bukin #define XDMA_MAX_SEG 128 2313d5b3b0aSRuslan Bukin 2323d5b3b0aSRuslan Bukin /* xDMA controller ops */ 2333d5b3b0aSRuslan Bukin xdma_controller_t *xdma_ofw_get(device_t dev, const char *prop); 234a8692c16SRuslan Bukin xdma_controller_t *xdma_get(device_t dev, device_t dma_dev); 2353d5b3b0aSRuslan Bukin int xdma_put(xdma_controller_t *xdma); 236101869a8SRuslan Bukin vmem_t * xdma_get_memory(device_t dev); 237101869a8SRuslan Bukin void xdma_put_memory(vmem_t *vmem); 238951e0584SRuslan Bukin #ifdef FDT 239951e0584SRuslan Bukin int xdma_handle_mem_node(vmem_t *vmem, phandle_t memory); 240951e0584SRuslan Bukin #endif 2413d5b3b0aSRuslan Bukin 2423d5b3b0aSRuslan Bukin /* xDMA channel ops */ 2433d5b3b0aSRuslan Bukin xdma_channel_t * xdma_channel_alloc(xdma_controller_t *, uint32_t caps); 2443d5b3b0aSRuslan Bukin int xdma_channel_free(xdma_channel_t *); 2453d5b3b0aSRuslan Bukin int xdma_request(xdma_channel_t *xchan, struct xdma_request *r); 246101869a8SRuslan Bukin void xchan_set_memory(xdma_channel_t *xchan, vmem_t *vmem); 2473d5b3b0aSRuslan Bukin 2483d5b3b0aSRuslan Bukin /* SG interface */ 2493d5b3b0aSRuslan Bukin int xdma_prep_sg(xdma_channel_t *, uint32_t, 2503d5b3b0aSRuslan Bukin bus_size_t, bus_size_t, bus_size_t, bus_addr_t, bus_addr_t, bus_addr_t); 2513d5b3b0aSRuslan Bukin void xdma_channel_free_sg(xdma_channel_t *xchan); 2523d5b3b0aSRuslan Bukin int xdma_queue_submit_sg(xdma_channel_t *xchan); 2533d5b3b0aSRuslan Bukin void xchan_seg_done(xdma_channel_t *xchan, xdma_transfer_status_t *); 2543d5b3b0aSRuslan Bukin 2553d5b3b0aSRuslan Bukin /* Queue operations */ 2563d5b3b0aSRuslan Bukin int xdma_dequeue_mbuf(xdma_channel_t *xchan, struct mbuf **m, 2573d5b3b0aSRuslan Bukin xdma_transfer_status_t *); 2583d5b3b0aSRuslan Bukin int xdma_enqueue_mbuf(xdma_channel_t *xchan, struct mbuf **m, uintptr_t addr, 2593d5b3b0aSRuslan Bukin uint8_t, uint8_t, enum xdma_direction dir); 2603d5b3b0aSRuslan Bukin int xdma_dequeue_bio(xdma_channel_t *xchan, struct bio **bp, 2613d5b3b0aSRuslan Bukin xdma_transfer_status_t *status); 2623d5b3b0aSRuslan Bukin int xdma_enqueue_bio(xdma_channel_t *xchan, struct bio **bp, bus_addr_t addr, 2633d5b3b0aSRuslan Bukin uint8_t, uint8_t, enum xdma_direction dir); 2643d5b3b0aSRuslan Bukin int xdma_dequeue(xdma_channel_t *xchan, void **user, 2653d5b3b0aSRuslan Bukin xdma_transfer_status_t *status); 2663d5b3b0aSRuslan Bukin int xdma_enqueue(xdma_channel_t *xchan, uintptr_t src, uintptr_t dst, 2673d5b3b0aSRuslan Bukin uint8_t, uint8_t, bus_size_t, enum xdma_direction dir, void *); 2683d5b3b0aSRuslan Bukin int xdma_queue_submit(xdma_channel_t *xchan); 2693d5b3b0aSRuslan Bukin 2703d5b3b0aSRuslan Bukin /* Mbuf operations */ 2713d5b3b0aSRuslan Bukin uint32_t xdma_mbuf_defrag(xdma_channel_t *xchan, struct xdma_request *xr); 2723d5b3b0aSRuslan Bukin uint32_t xdma_mbuf_chain_count(struct mbuf *m0); 2733d5b3b0aSRuslan Bukin 2743d5b3b0aSRuslan Bukin /* Channel Control */ 2753d5b3b0aSRuslan Bukin int xdma_control(xdma_channel_t *xchan, enum xdma_command cmd); 2763d5b3b0aSRuslan Bukin 2773d5b3b0aSRuslan Bukin /* Interrupt callback */ 278*d987842dSRuslan Bukin int xdma_setup_intr(xdma_channel_t *xchan, int flags, int (*cb)(void *, 2793d5b3b0aSRuslan Bukin xdma_transfer_status_t *), void *arg, void **); 2803d5b3b0aSRuslan Bukin int xdma_teardown_intr(xdma_channel_t *xchan, struct xdma_intr_handler *ih); 2813d5b3b0aSRuslan Bukin int xdma_teardown_all_intr(xdma_channel_t *xchan); 2823d5b3b0aSRuslan Bukin void xdma_callback(struct xdma_channel *xchan, xdma_transfer_status_t *status); 2833d5b3b0aSRuslan Bukin 2843d5b3b0aSRuslan Bukin /* Sglist */ 2853d5b3b0aSRuslan Bukin int xchan_sglist_alloc(xdma_channel_t *xchan); 2863d5b3b0aSRuslan Bukin void xchan_sglist_free(xdma_channel_t *xchan); 2873d5b3b0aSRuslan Bukin int xdma_sglist_add(struct xdma_sglist *sg, struct bus_dma_segment *seg, 2883d5b3b0aSRuslan Bukin uint32_t nsegs, struct xdma_request *xr); 2893d5b3b0aSRuslan Bukin 2903d5b3b0aSRuslan Bukin /* Requests bank */ 2913d5b3b0aSRuslan Bukin void xchan_bank_init(xdma_channel_t *xchan); 2923d5b3b0aSRuslan Bukin int xchan_bank_free(xdma_channel_t *xchan); 2933d5b3b0aSRuslan Bukin struct xdma_request * xchan_bank_get(xdma_channel_t *xchan); 2943d5b3b0aSRuslan Bukin int xchan_bank_put(xdma_channel_t *xchan, struct xdma_request *xr); 2953d5b3b0aSRuslan Bukin 296951e0584SRuslan Bukin /* IOMMU */ 297951e0584SRuslan Bukin void xdma_iommu_add_entry(xdma_channel_t *xchan, vm_offset_t *va, 298951e0584SRuslan Bukin vm_paddr_t pa, vm_size_t size, vm_prot_t prot); 299951e0584SRuslan Bukin void xdma_iommu_remove_entry(xdma_channel_t *xchan, vm_offset_t va); 300951e0584SRuslan Bukin int xdma_iommu_init(struct xdma_iommu *xio); 301951e0584SRuslan Bukin int xdma_iommu_release(struct xdma_iommu *xio); 302951e0584SRuslan Bukin 3033d5b3b0aSRuslan Bukin #endif /* !_DEV_XDMA_XDMA_H_ */ 304