/*
 * Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.

 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of The Linux Foundation nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#define DEBUG 0
#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <fcntl.h>
#include <cutils/log.h>
#include <errno.h>
#include <utils/Trace.h>
#include <cutils/trace.h>
#include "gralloc_priv.h"
#include "ionalloc.h"

using gralloc::IonAlloc;

#define ION_DEVICE "/dev/ion"

int IonAlloc::open_device()
{
    if(mIonFd == FD_INIT)
        mIonFd = open(ION_DEVICE, O_RDONLY);

    if(mIonFd < 0 ) {
        ALOGE("%s: Failed to open ion device - %s",
              __FUNCTION__, strerror(errno));
        mIonFd = FD_INIT;
        return -errno;
    }
    return 0;
}

void IonAlloc::close_device()
{
    if(mIonFd >= 0)
        close(mIonFd);
    mIonFd = FD_INIT;
}

int IonAlloc::alloc_buffer(alloc_data& data)
{
    ATRACE_CALL();
    Locker::Autolock _l(mLock);
    int err = 0;
    struct ion_handle_data handle_data;
    struct ion_fd_data fd_data;
    struct ion_allocation_data ionAllocData;
    void *base = 0;

    ionAllocData.len = data.size;
    ionAllocData.align = data.align;
    ionAllocData.heap_id_mask = data.heapId;
    ionAllocData.flags = data.flags;
    ionAllocData.flags |= data.uncached ? 0 : ION_FLAG_CACHED;
    err = open_device();
    if (err)
        return err;
    if(ioctl(mIonFd, ION_IOC_ALLOC, &ionAllocData)) {
        err = -errno;
        ALOGE("ION_IOC_ALLOC failed with error - %s", strerror(errno));
        return err;
    }

    fd_data.handle = ionAllocData.handle;
    handle_data.handle = ionAllocData.handle;
    if(ioctl(mIonFd, ION_IOC_MAP, &fd_data)) {
        err = -errno;
        ALOGE("%s: ION_IOC_MAP failed with error - %s",
              __FUNCTION__, strerror(errno));
        ioctl(mIonFd, ION_IOC_FREE, &handle_data);
        return err;
    }

    if(!(data.flags & ION_SECURE)) {
        base = mmap(0, ionAllocData.len, PROT_READ|PROT_WRITE,
                    MAP_SHARED, fd_data.fd, 0);
        if(base == MAP_FAILED) {
            err = -errno;
            ALOGE("%s: Failed to map the allocated memory: %s",
                  __FUNCTION__, strerror(errno));
            ioctl(mIonFd, ION_IOC_FREE, &handle_data);
            return err;
        }
    }

    data.base = base;
    data.fd = fd_data.fd;
    ioctl(mIonFd, ION_IOC_FREE, &handle_data);
    ALOGD_IF(DEBUG, "ion: Allocated buffer base:%p size:%zu fd:%d",
          data.base, ionAllocData.len, data.fd);
    return 0;
}


int IonAlloc::free_buffer(void* base, unsigned int size, unsigned int offset,
        int fd)
{
    ATRACE_CALL();
    Locker::Autolock _l(mLock);
    ALOGD_IF(DEBUG, "ion: Freeing buffer base:%p size:%u fd:%d",
          base, size, fd);
    int err = 0;
    err = open_device();
    if (err)
        return err;

    if(base)
        err = unmap_buffer(base, size, offset);
    close(fd);
    return err;
}

int IonAlloc::map_buffer(void **pBase, unsigned int size, unsigned int offset,
        int fd)
{
    ATRACE_CALL();
    int err = 0;
    void *base = 0;
    // It is a (quirky) requirement of ION to have opened the
    // ion fd in the process that is doing the mapping
    err = open_device();
    if (err)
        return err;

    base = mmap(0, size, PROT_READ| PROT_WRITE,
                MAP_SHARED, fd, 0);
    *pBase = base;
    if(base == MAP_FAILED) {
        err = -errno;
        ALOGE("ion: Failed to map memory in the client: %s",
              strerror(errno));
    } else {
        ALOGD_IF(DEBUG, "ion: Mapped buffer base:%p size:%u offset:%u fd:%d",
              base, size, offset, fd);
    }
    return err;
}

int IonAlloc::unmap_buffer(void *base, unsigned int size,
        unsigned int /*offset*/)
{
    ATRACE_CALL();
    ALOGD_IF(DEBUG, "ion: Unmapping buffer  base:%p size:%u", base, size);
    int err = 0;
    if(munmap(base, size)) {
        err = -errno;
        ALOGE("ion: Failed to unmap memory at %p : %s",
              base, strerror(errno));
    }
    return err;

}
int IonAlloc::clean_buffer(void *base, unsigned int size, unsigned int offset,
        int fd, int op)
{
    ATRACE_CALL();
    ATRACE_INT("operation id", op);
    struct ion_flush_data flush_data;
    struct ion_fd_data fd_data;
    struct ion_handle_data handle_data;
    int err = 0;

    err = open_device();
    if (err)
        return err;

    fd_data.fd = fd;
    if (ioctl(mIonFd, ION_IOC_IMPORT, &fd_data)) {
        err = -errno;
        ALOGE("%s: ION_IOC_IMPORT failed with error - %s",
              __FUNCTION__, strerror(errno));
        return err;
    }

    handle_data.handle = fd_data.handle;
    flush_data.handle  = fd_data.handle;
    flush_data.vaddr   = base;
    // offset and length are unsigned int
    flush_data.offset  = offset;
    flush_data.length  = size;

    struct ion_custom_data d;
    switch(op) {
    case CACHE_CLEAN:
        d.cmd = ION_IOC_CLEAN_CACHES;
        break;
    case CACHE_INVALIDATE:
            d.cmd = ION_IOC_INV_CACHES;
        break;
    case CACHE_CLEAN_AND_INVALIDATE:
    default:
        d.cmd = ION_IOC_CLEAN_INV_CACHES;
    }

    d.arg = (unsigned long int)&flush_data;

    if(ioctl(mIonFd, ION_IOC_CUSTOM, &d)) {
        err = -errno;
        ALOGE("%s: ION_IOC_CLEAN_INV_CACHES failed with error - %s",

              __FUNCTION__, strerror(errno));
        ioctl(mIonFd, ION_IOC_FREE, &handle_data);
        return err;
    }
    ioctl(mIonFd, ION_IOC_FREE, &handle_data);
    return 0;
}

