Home | History | Annotate | Download | only in OpenglCodecCommon
      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 #if PLATFORM_SDK_VERSION < 26
     19 #include <cutils/log.h>
     20 #else
     21 #include <log/log.h>
     22 #endif
     23 #include <errno.h>
     24 #ifdef __ANDROID__
     25 #include <linux/ioctl.h>
     26 #include <linux/types.h>
     27 #include <sys/cdefs.h>
     28 #endif
     29 #include <sys/ioctl.h>
     30 #include <sys/mman.h>
     31 #include <fcntl.h>
     32 #include <stdlib.h>
     33 #include <stdlib.h>
     34 #include <string.h>
     35 
     36 /* There is an ioctl associated with goldfish dma driver.
     37  * Make it conflict with ioctls that are not likely to be used
     38  * in the emulator.
     39  * 'G'	00-3F	drivers/misc/sgi-gru/grulib.h	conflict!
     40  * 'G'	00-0F	linux/gigaset_dev.h	conflict!
     41  */
     42 #define GOLDFISH_DMA_IOC_MAGIC	'G'
     43 
     44 #define GOLDFISH_DMA_IOC_LOCK			_IOWR(GOLDFISH_DMA_IOC_MAGIC, 0, struct goldfish_dma_ioctl_info)
     45 #define GOLDFISH_DMA_IOC_UNLOCK			_IOWR(GOLDFISH_DMA_IOC_MAGIC, 1, struct goldfish_dma_ioctl_info)
     46 #define GOLDFISH_DMA_IOC_GETOFF			_IOWR(GOLDFISH_DMA_IOC_MAGIC, 2, struct goldfish_dma_ioctl_info)
     47 #define GOLDFISH_DMA_IOC_CREATE_REGION	_IOWR(GOLDFISH_DMA_IOC_MAGIC, 3, struct goldfish_dma_ioctl_info)
     48 
     49 struct goldfish_dma_ioctl_info {
     50     uint64_t phys_begin;
     51     uint64_t size;
     52 };
     53 
     54 int goldfish_dma_create_region(uint32_t sz, struct goldfish_dma_context* res) {
     55 
     56     res->fd = qemu_pipe_open("opengles");
     57     res->mapped_addr = 0;
     58     res->size = 0;
     59 
     60     if (res->fd > 0) {
     61         // now alloc
     62         struct goldfish_dma_ioctl_info info;
     63         info.size = sz;
     64         int alloc_res = ioctl(res->fd, GOLDFISH_DMA_IOC_CREATE_REGION, &info);
     65 
     66         if (alloc_res) {
     67             ALOGE("%s: failed to allocate DMA region. errno=%d",
     68                   __FUNCTION__, errno);
     69             close(res->fd);
     70             res->fd = -1;
     71             return alloc_res;
     72         }
     73 
     74         res->size = sz;
     75         ALOGV("%s: successfully allocated goldfish DMA region with size %u cxt=%p fd=%d",
     76               __FUNCTION__, sz, res, res->fd);
     77         return 0;
     78     } else {
     79         ALOGE("%s: could not obtain fd to device! fd %d errno=%d\n",
     80               __FUNCTION__, res->fd, errno);
     81         return ENODEV;
     82     }
     83 }
     84 
     85 void* goldfish_dma_map(struct goldfish_dma_context* cxt) {
     86     ALOGV("%s: on fd %d errno=%d", __FUNCTION__, cxt->fd, errno);
     87     void *mapped = mmap(0, cxt->size, PROT_WRITE, MAP_SHARED, cxt->fd, 0);
     88     ALOGV("%s: cxt=%p mapped=%p size=%u errno=%d",
     89         __FUNCTION__, cxt, mapped, cxt->size, errno);
     90 
     91     if (mapped == MAP_FAILED) {
     92         mapped = NULL;
     93     }
     94 
     95     cxt->mapped_addr = reinterpret_cast<uint64_t>(mapped);
     96     return mapped;
     97 }
     98 
     99 int goldfish_dma_unmap(struct goldfish_dma_context* cxt) {
    100     ALOGV("%s: cxt=%p mapped=0x%" PRIu64, __FUNCTION__, cxt, cxt->mapped_addr);
    101     munmap(reinterpret_cast<void *>(cxt->mapped_addr), cxt->size);
    102     cxt->mapped_addr = 0;
    103     cxt->size = 0;
    104     return 0;
    105 }
    106 
    107 void goldfish_dma_write(struct goldfish_dma_context* cxt,
    108                                const void* to_write,
    109                                uint32_t sz) {
    110     ALOGV("%s: cxt=%p mapped=0x%" PRIu64 " to_write=%p size=%u",
    111         __FUNCTION__, cxt, cxt->mapped_addr, to_write, sz);
    112     memcpy(reinterpret_cast<void *>(cxt->mapped_addr), to_write, sz);
    113 }
    114 
    115 void goldfish_dma_free(goldfish_dma_context* cxt) {
    116     close(cxt->fd);
    117 }
    118 
    119 uint64_t goldfish_dma_guest_paddr(const struct goldfish_dma_context* cxt) {
    120     struct goldfish_dma_ioctl_info info;
    121     ioctl(cxt->fd, GOLDFISH_DMA_IOC_GETOFF, &info);
    122     return info.phys_begin;
    123 }
    124