188c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang/*
288c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang * Copyright (C) 2016 Google, Inc.
388c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang *
488c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang * This software is licensed under the terms of the GNU General Public
588c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang * License version 2, as published by the Free Software Foundation, and
688c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang * may be copied, distributed, and modified under those terms.
788c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang *
888c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang * This program is distributed in the hope that it will be useful,
988c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang * but WITHOUT ANY WARRANTY; without even the implied warranty of
1088c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1188c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang * GNU General Public License for more details.
1288c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang *
1388c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang */
1488c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang
1588c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang#include "goldfish_dma.h"
1688c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang#include "qemu_pipe.h"
1788c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang
1888c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang#include <cutils/log.h>
1988c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang#include <sys/mman.h>
2088c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang#include <stdlib.h>
2188c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang#include <string.h>
2288c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang
2388c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yangint goldfish_dma_lock(struct goldfish_dma_context* cxt) {
2488c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang    struct goldfish_dma_ioctl_info info;
2588c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang
2688c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang    return ioctl(cxt->fd, GOLDFISH_DMA_IOC_LOCK, &info);
2788c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang}
2888c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang
2988c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yangint goldfish_dma_unlock(struct goldfish_dma_context* cxt) {
3088c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang    struct goldfish_dma_ioctl_info info;
3188c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang
3288c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang    return ioctl(cxt->fd, GOLDFISH_DMA_IOC_UNLOCK, &info);
3388c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang}
3488c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang
3588c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yangint goldfish_dma_create_region(uint32_t sz, struct goldfish_dma_context* res) {
3688c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang
3788c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang    res->fd = qemu_pipe_open("opengles");
3888c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang    res->mapped = NULL;
3988c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang    res->sz = 0;
4088c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang
4188c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang    if (res->fd > 0) {
4288c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang        // now alloc
4388c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang        struct goldfish_dma_ioctl_info info;
4488c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang        info.size = sz;
4588c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang        int alloc_res = ioctl(res->fd, GOLDFISH_DMA_IOC_CREATE_REGION, &info);
4688c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang
4788c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang        if (alloc_res) {
4888c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang            ALOGE("%s: failed to allocate DMA region. errno=%d",
4988c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang                  __FUNCTION__, errno);
5088c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang            close(res->fd);
5188c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang            res->fd = -1;
5288c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang            return alloc_res;
5388c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang        }
5488c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang
5588c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang        res->sz = sz;
5688c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang        ALOGV("%s: successfully allocated goldfish DMA region with size %lu cxt=%p",
5788c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang              __FUNCTION__, sz, res);
5888c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang        return 0;
5988c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang    } else {
6088c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang        ALOGE("%s: could not obtain fd to device! fd %d errno=%d\n",
6188c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang              __FUNCTION__, res->fd, errno);
6288c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang        return ENODEV;
6388c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang    }
6488c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang}
6588c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang
6688c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yangvoid* goldfish_dma_map(struct goldfish_dma_context* cxt) {
6788c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang    ALOGV("%s: on fd %d errno=%d", __FUNCTION__, cxt->fd, errno);
6888c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang    cxt->mapped = mmap(0, cxt->sz, PROT_WRITE, MAP_SHARED, cxt->fd, 0);
6988c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang    ALOGV("%s: mapped addr=%p errno=%d", __FUNCTION__, cxt->mapped, errno);
7088c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang
7188c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang    if (cxt->mapped == MAP_FAILED) {
7288c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang        cxt->mapped = NULL;
7388c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang    }
7488c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang    return cxt->mapped;
7588c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang}
7688c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang
7788c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yangint goldfish_dma_unmap(struct goldfish_dma_context* cxt) {
7888c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang    munmap(cxt->mapped, cxt->sz);
7988c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang    cxt->mapped = NULL;
8088c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang    cxt->sz = 0;
8188c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang    return 0;
8288c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang}
8388c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang
8488c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yangvoid goldfish_dma_write(struct goldfish_dma_context* cxt,
8588c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang                               void* to_write,
8688c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang                               uint32_t sz) {
8788c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang    ALOGV("%s: mapped addr=%p", __FUNCTION__, cxt->mapped);
8888c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang    memcpy(cxt->mapped, to_write, sz);
8988c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang}
9088c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang
9188c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yangvoid goldfish_dma_free(goldfish_dma_context* cxt) {
9288c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang    struct goldfish_dma_ioctl_info info;
9388c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang    close(cxt->fd);
9488c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang}
9588c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang
9688c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yanguint64_t goldfish_dma_guest_paddr(struct goldfish_dma_context* cxt) {
9788c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang    struct goldfish_dma_ioctl_info info;
9888c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang    ioctl(cxt->fd, GOLDFISH_DMA_IOC_GETOFF, &info);
9988c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang    return info.phys_begin;
10088c170cdf4d4a3c83ea61540d25bdcf4153fb5b8Lingfeng Yang}
101