1 // Copyright 2016 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "goldfish_dma.h"
16
17 #include <qemu_pipe_bp.h>
18
19 #if PLATFORM_SDK_VERSION < 26
20 #include <cutils/log.h>
21 #else
22 #include <log/log.h>
23 #endif
24 #include <errno.h>
25 #ifdef __ANDROID__
26 #include <linux/ioctl.h>
27 #include <linux/types.h>
28 #include <sys/cdefs.h>
29 #endif
30 #include <sys/ioctl.h>
31 #include <sys/mman.h>
32 #include <fcntl.h>
33 #include <stdlib.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <unistd.h>
37
38 /* There is an ioctl associated with goldfish dma driver.
39 * Make it conflict with ioctls that are not likely to be used
40 * in the emulator.
41 * 'G' 00-3F drivers/misc/sgi-gru/grulib.h conflict!
42 * 'G' 00-0F linux/gigaset_dev.h conflict!
43 */
44 #define GOLDFISH_DMA_IOC_MAGIC 'G'
45
46 #define GOLDFISH_DMA_IOC_LOCK _IOWR(GOLDFISH_DMA_IOC_MAGIC, 0, struct goldfish_dma_ioctl_info)
47 #define GOLDFISH_DMA_IOC_UNLOCK _IOWR(GOLDFISH_DMA_IOC_MAGIC, 1, struct goldfish_dma_ioctl_info)
48 #define GOLDFISH_DMA_IOC_GETOFF _IOWR(GOLDFISH_DMA_IOC_MAGIC, 2, struct goldfish_dma_ioctl_info)
49 #define GOLDFISH_DMA_IOC_CREATE_REGION _IOWR(GOLDFISH_DMA_IOC_MAGIC, 3, struct goldfish_dma_ioctl_info)
50
51 struct goldfish_dma_ioctl_info {
52 uint64_t phys_begin;
53 uint64_t size;
54 };
55
goldfish_dma_create_region(uint32_t sz,struct goldfish_dma_context * res)56 int goldfish_dma_create_region(uint32_t sz, struct goldfish_dma_context* res) {
57
58 res->fd = qemu_pipe_open("opengles");
59 res->mapped_addr = 0;
60 res->size = 0;
61
62 if (res->fd > 0) {
63 // now alloc
64 struct goldfish_dma_ioctl_info info;
65 info.size = sz;
66 int alloc_res = ioctl(res->fd, GOLDFISH_DMA_IOC_CREATE_REGION, &info);
67
68 if (alloc_res) {
69 ALOGE("%s: failed to allocate DMA region. errno=%d",
70 __FUNCTION__, errno);
71 close(res->fd);
72 res->fd = -1;
73 return alloc_res;
74 }
75
76 res->size = sz;
77 ALOGV("%s: successfully allocated goldfish DMA region with size %u cxt=%p fd=%d",
78 __FUNCTION__, sz, res, res->fd);
79 return 0;
80 } else {
81 ALOGE("%s: could not obtain fd to device! fd %d errno=%d\n",
82 __FUNCTION__, res->fd, errno);
83 return ENODEV;
84 }
85 }
86
goldfish_dma_map(struct goldfish_dma_context * cxt)87 void* goldfish_dma_map(struct goldfish_dma_context* cxt) {
88 ALOGV("%s: on fd %d errno=%d", __FUNCTION__, cxt->fd, errno);
89 void *mapped = mmap(0, cxt->size, PROT_WRITE, MAP_SHARED, cxt->fd, 0);
90 ALOGV("%s: cxt=%p mapped=%p size=%u errno=%d",
91 __FUNCTION__, cxt, mapped, cxt->size, errno);
92
93 if (mapped == MAP_FAILED) {
94 mapped = NULL;
95 }
96
97 cxt->mapped_addr = reinterpret_cast<uint64_t>(mapped);
98 return mapped;
99 }
100
goldfish_dma_unmap(struct goldfish_dma_context * cxt)101 int goldfish_dma_unmap(struct goldfish_dma_context* cxt) {
102 ALOGV("%s: cxt=%p mapped=0x%" PRIu64, __FUNCTION__, cxt, cxt->mapped_addr);
103 munmap(reinterpret_cast<void *>(cxt->mapped_addr), cxt->size);
104 cxt->mapped_addr = 0;
105 cxt->size = 0;
106 return 0;
107 }
108
goldfish_dma_write(struct goldfish_dma_context * cxt,const void * to_write,uint32_t sz)109 void goldfish_dma_write(struct goldfish_dma_context* cxt,
110 const void* to_write,
111 uint32_t sz) {
112 ALOGV("%s: cxt=%p mapped=0x%" PRIu64 " to_write=%p size=%u",
113 __FUNCTION__, cxt, cxt->mapped_addr, to_write, sz);
114 memcpy(reinterpret_cast<void *>(cxt->mapped_addr), to_write, sz);
115 }
116
goldfish_dma_free(goldfish_dma_context * cxt)117 void goldfish_dma_free(goldfish_dma_context* cxt) {
118 close(cxt->fd);
119 }
120
goldfish_dma_guest_paddr(const struct goldfish_dma_context * cxt)121 uint64_t goldfish_dma_guest_paddr(const struct goldfish_dma_context* cxt) {
122 struct goldfish_dma_ioctl_info info;
123 ioctl(cxt->fd, GOLDFISH_DMA_IOC_GETOFF, &info);
124 return info.phys_begin;
125 }
126