1 /*
2 * Copyright (C) 2016 Google, Inc.
3 *
4 * This software is licensed under the terms of the GNU General Public
5 * License version 2, as published by the Free Software Foundation, and
6 * may be copied, distributed, and modified under those terms.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 */
14
15 #include "goldfish_dma.h"
16 #include "qemu_pipe.h"
17
18 #include <cutils/log.h>
19 #include <sys/mman.h>
20 #include <stdlib.h>
21 #include <string.h>
22
goldfish_dma_lock(struct goldfish_dma_context * cxt)23 int goldfish_dma_lock(struct goldfish_dma_context* cxt) {
24 struct goldfish_dma_ioctl_info info;
25
26 return ioctl(cxt->fd, GOLDFISH_DMA_IOC_LOCK, &info);
27 }
28
goldfish_dma_unlock(struct goldfish_dma_context * cxt)29 int goldfish_dma_unlock(struct goldfish_dma_context* cxt) {
30 struct goldfish_dma_ioctl_info info;
31
32 return ioctl(cxt->fd, GOLDFISH_DMA_IOC_UNLOCK, &info);
33 }
34
goldfish_dma_create_region(uint32_t sz,struct goldfish_dma_context * res)35 int goldfish_dma_create_region(uint32_t sz, struct goldfish_dma_context* res) {
36
37 res->fd = qemu_pipe_open("opengles");
38 res->mapped = NULL;
39 res->sz = 0;
40
41 if (res->fd > 0) {
42 // now alloc
43 struct goldfish_dma_ioctl_info info;
44 info.size = sz;
45 int alloc_res = ioctl(res->fd, GOLDFISH_DMA_IOC_CREATE_REGION, &info);
46
47 if (alloc_res) {
48 ALOGE("%s: failed to allocate DMA region. errno=%d",
49 __FUNCTION__, errno);
50 close(res->fd);
51 res->fd = -1;
52 return alloc_res;
53 }
54
55 res->sz = sz;
56 ALOGV("%s: successfully allocated goldfish DMA region with size %lu cxt=%p",
57 __FUNCTION__, sz, res);
58 return 0;
59 } else {
60 ALOGE("%s: could not obtain fd to device! fd %d errno=%d\n",
61 __FUNCTION__, res->fd, errno);
62 return ENODEV;
63 }
64 }
65
goldfish_dma_map(struct goldfish_dma_context * cxt)66 void* goldfish_dma_map(struct goldfish_dma_context* cxt) {
67 ALOGV("%s: on fd %d errno=%d", __FUNCTION__, cxt->fd, errno);
68 cxt->mapped = mmap(0, cxt->sz, PROT_WRITE, MAP_SHARED, cxt->fd, 0);
69 ALOGV("%s: mapped addr=%p errno=%d", __FUNCTION__, cxt->mapped, errno);
70
71 if (cxt->mapped == MAP_FAILED) {
72 cxt->mapped = NULL;
73 }
74 return cxt->mapped;
75 }
76
goldfish_dma_unmap(struct goldfish_dma_context * cxt)77 int goldfish_dma_unmap(struct goldfish_dma_context* cxt) {
78 munmap(cxt->mapped, cxt->sz);
79 cxt->mapped = NULL;
80 cxt->sz = 0;
81 return 0;
82 }
83
goldfish_dma_write(struct goldfish_dma_context * cxt,void * to_write,uint32_t sz)84 void goldfish_dma_write(struct goldfish_dma_context* cxt,
85 void* to_write,
86 uint32_t sz) {
87 ALOGV("%s: mapped addr=%p", __FUNCTION__, cxt->mapped);
88 memcpy(cxt->mapped, to_write, sz);
89 }
90
goldfish_dma_free(goldfish_dma_context * cxt)91 void goldfish_dma_free(goldfish_dma_context* cxt) {
92 struct goldfish_dma_ioctl_info info;
93 close(cxt->fd);
94 }
95
goldfish_dma_guest_paddr(struct goldfish_dma_context * cxt)96 uint64_t goldfish_dma_guest_paddr(struct goldfish_dma_context* cxt) {
97 struct goldfish_dma_ioctl_info info;
98 ioctl(cxt->fd, GOLDFISH_DMA_IOC_GETOFF, &info);
99 return info.phys_begin;
100 }
101