1/*
2 * Copyright (c) 2014 ETH Zurich.
3 * All rights reserved.
4 *
5 * This file is distributed under the terms in the attached LICENSE file.
6 * If you do not find this file, copies can be found by writing to:
7 * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
8 */
9
10#include <string.h>
11
12#include <barrelfish/barrelfish.h>
13
14#include <dma_internal.h>
15#include <dma_mem_utils.h>
16
17/**
18 * \brief allocates and maps a memory region to be used for DMA purposes
19 *
20 * \param bytes minimum size of the memory region in bytes
21 * \param flags VREGION flags how the region gets mapped
22 * \param mem   returns the mapping information
23 *
24 * \returns SYS_ERR_OK on success
25 *          errval on error
26 */
27errval_t dma_mem_alloc(size_t bytes,
28                       vregion_flags_t flags,
29                       struct dma_mem *mem)
30{
31    errval_t err;
32
33    if (mem == NULL) {
34        return DMA_ERR_ARG_INVALID;
35    }
36
37    err = frame_alloc(&mem->frame, bytes, &mem->bytes);
38    if (err_is_fail(err)) {
39        return err;
40    }
41
42    struct frame_identity id;
43    err = frame_identify(mem->frame, &id);
44    if (err_is_fail(err)) {
45        dma_mem_free(mem);
46        return err;
47    }
48
49    mem->paddr = id.base;
50
51    void *addr;
52    err = vspace_map_one_frame_attr(&addr, mem->bytes, mem->frame, flags, NULL,
53                                    NULL);
54    if (err_is_fail(err)) {
55        dma_mem_free(mem);
56        return err;
57    }
58
59    mem->vaddr = (lvaddr_t)addr;
60
61    return SYS_ERR_OK;
62}
63
64/**
65 * \brief tries to free the allocated memory region
66 *
67 * \returns SYS_ERR_OK on success
68 *          errval on error
69 */
70errval_t dma_mem_free(struct dma_mem *mem)
71{
72    errval_t err;
73
74    if (mem->vaddr) {
75        err = vspace_unmap((void*)mem->vaddr);
76        if (err_is_fail(err)) {
77            /* todo: error handling ignoring for now */
78        }
79    }
80
81    if (!capref_is_null(mem->frame)) {
82        err = cap_destroy(mem->frame);
83        if (err_is_fail(err)) {
84            /* todo: error handling ignoring for now */
85
86        }
87    }
88
89    memset(mem, 0, sizeof(*mem));
90
91    return SYS_ERR_OK;
92}
93