1*3d5b3b0aSRuslan Bukin /*- 2*3d5b3b0aSRuslan Bukin * Copyright (c) 2018 Ruslan Bukin <br@bsdpad.com> 3*3d5b3b0aSRuslan Bukin * All rights reserved. 4*3d5b3b0aSRuslan Bukin * 5*3d5b3b0aSRuslan Bukin * This software was developed by SRI International and the University of 6*3d5b3b0aSRuslan Bukin * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237 7*3d5b3b0aSRuslan Bukin * ("CTSRD"), as part of the DARPA CRASH research programme. 8*3d5b3b0aSRuslan Bukin * 9*3d5b3b0aSRuslan Bukin * Redistribution and use in source and binary forms, with or without 10*3d5b3b0aSRuslan Bukin * modification, are permitted provided that the following conditions 11*3d5b3b0aSRuslan Bukin * are met: 12*3d5b3b0aSRuslan Bukin * 1. Redistributions of source code must retain the above copyright 13*3d5b3b0aSRuslan Bukin * notice, this list of conditions and the following disclaimer. 14*3d5b3b0aSRuslan Bukin * 2. Redistributions in binary form must reproduce the above copyright 15*3d5b3b0aSRuslan Bukin * notice, this list of conditions and the following disclaimer in the 16*3d5b3b0aSRuslan Bukin * documentation and/or other materials provided with the distribution. 17*3d5b3b0aSRuslan Bukin * 18*3d5b3b0aSRuslan Bukin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19*3d5b3b0aSRuslan Bukin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20*3d5b3b0aSRuslan Bukin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21*3d5b3b0aSRuslan Bukin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22*3d5b3b0aSRuslan Bukin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23*3d5b3b0aSRuslan Bukin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24*3d5b3b0aSRuslan Bukin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25*3d5b3b0aSRuslan Bukin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26*3d5b3b0aSRuslan Bukin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27*3d5b3b0aSRuslan Bukin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28*3d5b3b0aSRuslan Bukin * SUCH DAMAGE. 29*3d5b3b0aSRuslan Bukin */ 30*3d5b3b0aSRuslan Bukin 31*3d5b3b0aSRuslan Bukin #include <sys/cdefs.h> 32*3d5b3b0aSRuslan Bukin __FBSDID("$FreeBSD$"); 33*3d5b3b0aSRuslan Bukin 34*3d5b3b0aSRuslan Bukin #include "opt_platform.h" 35*3d5b3b0aSRuslan Bukin #include <sys/param.h> 36*3d5b3b0aSRuslan Bukin #include <sys/conf.h> 37*3d5b3b0aSRuslan Bukin #include <sys/bus.h> 38*3d5b3b0aSRuslan Bukin #include <sys/kernel.h> 39*3d5b3b0aSRuslan Bukin #include <sys/malloc.h> 40*3d5b3b0aSRuslan Bukin #include <sys/bus_dma.h> 41*3d5b3b0aSRuslan Bukin #include <sys/sx.h> 42*3d5b3b0aSRuslan Bukin 43*3d5b3b0aSRuslan Bukin #include <dev/xdma/xdma.h> 44*3d5b3b0aSRuslan Bukin 45*3d5b3b0aSRuslan Bukin int 46*3d5b3b0aSRuslan Bukin xdma_dequeue(xdma_channel_t *xchan, void **user, 47*3d5b3b0aSRuslan Bukin xdma_transfer_status_t *status) 48*3d5b3b0aSRuslan Bukin { 49*3d5b3b0aSRuslan Bukin struct xdma_request *xr_tmp; 50*3d5b3b0aSRuslan Bukin struct xdma_request *xr; 51*3d5b3b0aSRuslan Bukin 52*3d5b3b0aSRuslan Bukin QUEUE_OUT_LOCK(xchan); 53*3d5b3b0aSRuslan Bukin TAILQ_FOREACH_SAFE(xr, &xchan->queue_out, xr_next, xr_tmp) { 54*3d5b3b0aSRuslan Bukin TAILQ_REMOVE(&xchan->queue_out, xr, xr_next); 55*3d5b3b0aSRuslan Bukin break; 56*3d5b3b0aSRuslan Bukin } 57*3d5b3b0aSRuslan Bukin QUEUE_OUT_UNLOCK(xchan); 58*3d5b3b0aSRuslan Bukin 59*3d5b3b0aSRuslan Bukin if (xr == NULL) 60*3d5b3b0aSRuslan Bukin return (-1); 61*3d5b3b0aSRuslan Bukin 62*3d5b3b0aSRuslan Bukin *user = xr->user; 63*3d5b3b0aSRuslan Bukin status->error = xr->status.error; 64*3d5b3b0aSRuslan Bukin status->transferred = xr->status.transferred; 65*3d5b3b0aSRuslan Bukin 66*3d5b3b0aSRuslan Bukin xchan_bank_put(xchan, xr); 67*3d5b3b0aSRuslan Bukin 68*3d5b3b0aSRuslan Bukin return (0); 69*3d5b3b0aSRuslan Bukin } 70*3d5b3b0aSRuslan Bukin 71*3d5b3b0aSRuslan Bukin int 72*3d5b3b0aSRuslan Bukin xdma_enqueue(xdma_channel_t *xchan, uintptr_t src, uintptr_t dst, 73*3d5b3b0aSRuslan Bukin uint8_t src_width, uint8_t dst_width, bus_size_t len, 74*3d5b3b0aSRuslan Bukin enum xdma_direction dir, void *user) 75*3d5b3b0aSRuslan Bukin { 76*3d5b3b0aSRuslan Bukin struct xdma_request *xr; 77*3d5b3b0aSRuslan Bukin xdma_controller_t *xdma; 78*3d5b3b0aSRuslan Bukin 79*3d5b3b0aSRuslan Bukin xdma = xchan->xdma; 80*3d5b3b0aSRuslan Bukin KASSERT(xdma != NULL, ("xdma is NULL")); 81*3d5b3b0aSRuslan Bukin 82*3d5b3b0aSRuslan Bukin xr = xchan_bank_get(xchan); 83*3d5b3b0aSRuslan Bukin if (xr == NULL) 84*3d5b3b0aSRuslan Bukin return (-1); /* No space is available. */ 85*3d5b3b0aSRuslan Bukin 86*3d5b3b0aSRuslan Bukin xr->user = user; 87*3d5b3b0aSRuslan Bukin xr->direction = dir; 88*3d5b3b0aSRuslan Bukin xr->m = NULL; 89*3d5b3b0aSRuslan Bukin xr->bp = NULL; 90*3d5b3b0aSRuslan Bukin xr->block_num = 1; 91*3d5b3b0aSRuslan Bukin xr->block_len = len; 92*3d5b3b0aSRuslan Bukin xr->req_type = XR_TYPE_VIRT; 93*3d5b3b0aSRuslan Bukin xr->src_addr = src; 94*3d5b3b0aSRuslan Bukin xr->dst_addr = dst; 95*3d5b3b0aSRuslan Bukin xr->src_width = src_width; 96*3d5b3b0aSRuslan Bukin xr->dst_width = dst_width; 97*3d5b3b0aSRuslan Bukin 98*3d5b3b0aSRuslan Bukin QUEUE_IN_LOCK(xchan); 99*3d5b3b0aSRuslan Bukin TAILQ_INSERT_TAIL(&xchan->queue_in, xr, xr_next); 100*3d5b3b0aSRuslan Bukin QUEUE_IN_UNLOCK(xchan); 101*3d5b3b0aSRuslan Bukin 102*3d5b3b0aSRuslan Bukin return (0); 103*3d5b3b0aSRuslan Bukin } 104*3d5b3b0aSRuslan Bukin 105*3d5b3b0aSRuslan Bukin int 106*3d5b3b0aSRuslan Bukin xdma_queue_submit(xdma_channel_t *xchan) 107*3d5b3b0aSRuslan Bukin { 108*3d5b3b0aSRuslan Bukin xdma_controller_t *xdma; 109*3d5b3b0aSRuslan Bukin int ret; 110*3d5b3b0aSRuslan Bukin 111*3d5b3b0aSRuslan Bukin xdma = xchan->xdma; 112*3d5b3b0aSRuslan Bukin KASSERT(xdma != NULL, ("xdma is NULL")); 113*3d5b3b0aSRuslan Bukin 114*3d5b3b0aSRuslan Bukin ret = 0; 115*3d5b3b0aSRuslan Bukin 116*3d5b3b0aSRuslan Bukin XCHAN_LOCK(xchan); 117*3d5b3b0aSRuslan Bukin 118*3d5b3b0aSRuslan Bukin if (xchan->flags & XCHAN_TYPE_SG) 119*3d5b3b0aSRuslan Bukin ret = xdma_queue_submit_sg(xchan); 120*3d5b3b0aSRuslan Bukin 121*3d5b3b0aSRuslan Bukin XCHAN_UNLOCK(xchan); 122*3d5b3b0aSRuslan Bukin 123*3d5b3b0aSRuslan Bukin return (ret); 124*3d5b3b0aSRuslan Bukin } 125