1/* 2 * Copyright (c) 2014, ETH Zurich. All rights reserved. 3 * 4 * This file is distributed under the terms in the attached LICENSE file. 5 * If you do not find this file, copies can be found by writing to: 6 * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group. 7 */ 8#include <barrelfish/barrelfish.h> 9 10#include <dma/dma.h> 11#include <dma/dma_service.h> 12#include <dma/dma_mem_mgr.h> 13#include <dma/ioat/ioat_dma_request.h> 14 15#include "device.h" 16#include "dma_service.h" 17 18#include "debug.h" 19 20struct user_st 21{ 22 struct dma_mem_mgr *mem_mgr; 23 uint64_t num_req; 24}; 25 26/* 27 * --------------------------------------------------------------------------- 28 * Request done callbacks 29 * --------------------------------------------------------------------------- 30 */ 31 32static void memcpy_req_cb(errval_t err, dma_req_id_t id, void *st) 33{ 34 DMA_DEBUG("memcpy_req_cb %lx, %s\n", id, err_getstring(err)); 35 dma_service_send_done(st, err, id); 36} 37 38/* 39 * --------------------------------------------------------------------------- 40 * 41 * --------------------------------------------------------------------------- 42 */ 43 44 45/* 46 * \brief callback handler for new connect requests 47 * 48 * \param user_st pointer to store the user state 49 * 50 * \returns SYS_ERR_OK if the connection is accepted 51 * errval if connection is rejected 52 */ 53errval_t dma_svc_connect_cb(void *arg, void **user_st) 54{ 55 errval_t err; 56 57 struct user_st *st = calloc(1, sizeof(*st)); 58 if (st == NULL) { 59 return LIB_ERR_MALLOC_FAIL; 60 } 61 62 DMA_DEBUG("dma_svc_connect_cb user_st = %p\n", st); 63 64 err = dma_mem_mgr_init(&st->mem_mgr, 0x0, (1UL << 48) - 1); 65 if (err_is_fail(err)) { 66 free(st); 67 return err; 68 } 69 70 *user_st = st; 71 72 return SYS_ERR_OK; 73} 74 75/** 76 * \brief registers a memory region with the client such that it can be used later 77 * 78 * \param user_st pointer to stored user state 79 * \param cap the capability to register 80 * 81 * \returns SYS_ERR_OK if the memory region was accepted 82 * errval if the memory region was rejected 83 */ 84errval_t dma_svc_addregion_cb(dma_svc_handle_t svc_handle, 85 struct capref cap) 86{ 87 struct user_st *user_st = dma_service_get_user_state(svc_handle); 88 89 DMA_DEBUG("dma_svc_addregion_cb user_st = %p\n", user_st); 90 91 return dma_mem_register(user_st->mem_mgr, cap, NULL); 92} 93 94/** 95 * \brief deregisters a memory region with the client 96 * 97 * \param user_st pointer to stored user state 98 * \param cap the capability to deregister 99 * 100 * \returns SYS_ERR_OK if the memory region was removed 101 * errval if the memory region removal was rejected 102 */ 103errval_t dma_svc_removeregion_cb(dma_svc_handle_t svc_handle, 104 struct capref cap) 105{ 106 struct user_st *user_st = dma_service_get_user_state(svc_handle); 107 108 DMA_DEBUG("dma_svc_removeregion_cb user_st = %p\n", user_st); 109 110 return dma_mem_deregister(user_st->mem_mgr, cap); 111} 112 113/** 114 * \brief executes a DMA memcpy 115 * 116 * \param user_st pointer to stored user state 117 * \param dst the physical destination address 118 * \param src the physical source address 119 * \param bytes size of the transfer in bytes 120 * \param id returns the DMA request ID of the transfer 121 * 122 * \returns SYS_ERR_OK if the memory region was removed 123 * errval if the memory region removal was rejected 124 */ 125errval_t dma_svc_memcpy_cb(dma_svc_handle_t svc_handle, 126 lpaddr_t dst, 127 lpaddr_t src, 128 size_t bytes, 129 dma_req_id_t *id) 130{ 131 errval_t err; 132 133 struct user_st *st = dma_service_get_user_state(svc_handle); 134 135 DMA_DEBUG("dma_svc_memcpy_cb user_st = %p\n", st); 136 137 lpaddr_t dma_dst, dma_src; 138 err = dma_mem_verify(st->mem_mgr, dst, bytes, &dma_dst); 139 if (err_is_fail(err)) { 140 return err; 141 } 142 err = dma_mem_verify(st->mem_mgr, src, bytes, &dma_src); 143 if (err_is_fail(err)) { 144 return err; 145 } 146 147 DMA_DEBUG("[%016lx]->[%016lx] of %lu bytes\n", dma_src, dma_dst, bytes); 148 149 150 /* both addresses are valid and have been translated now */ 151 struct ioat_dma_device *dev = ioat_device_get_next(); 152 assert(dev); 153 154 struct dma_req_setup setup = { 155 .type = DMA_REQ_TYPE_MEMCPY, 156 .done_cb = memcpy_req_cb, 157 .cb_arg = svc_handle, 158 .args = { 159 .memcpy = { 160 .src = dma_src, 161 .dst = dma_dst, 162 .bytes = bytes 163 } 164 } 165 }; 166 167 return ioat_dma_request_memcpy((struct dma_device *)dev, &setup, id); 168} 169