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