/*
 * Copyright © 2014 Kosma Moczek <kosma@cloudyourcar.com>
 * This program is free software. It comes without any warranty, to the extent
 * permitted by applicable law. You can redistribute it and/or modify it under
 * the terms of the Do What The Fuck You Want To Public License, Version 2, as
 * published by Sam Hocevar. See the COPYING file for more details.
 */

#if USE_LIB_RINGFS_RAM==1

#include "lib_ringfs_func.h"
#include "lib_ringfs.h"
#include "lib_ringfs_ram.h"

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
#ifdef FLASHSIM_LOG
#define logprintf(args...) printf(args)
#else
#define logprintf(args...) do {} while (0)
#endif
	
	
#define FLASH_RAM_SECTOR_SIZE       128
#define FLASH_RAM_TOTAL_SECTORS     16
#define FLASH_RAM_PARTITION_OFFSET  4
#define FLASH_RAM_PARTITION_SIZE    8
	

uint8_t ram_buf[FLASH_RAM_TOTAL_SECTORS][FLASH_RAM_SECTOR_SIZE] = {0};	
	
struct rfs_dev_ram {
    int size;
    int sector_size;
	
		uint8_t* buf;
    //FILE *fh;
};

struct rfs_dev_ram rfs_dev_ram_obj = {0};

struct rfs_dev_ram *ramHandle = 0;


void init_flash_driver_ram(void)
{
    ramHandle = rfs_dev_ram_open("example.ram",
            FLASH_RAM_TOTAL_SECTORS*FLASH_RAM_SECTOR_SIZE,
            FLASH_RAM_SECTOR_SIZE);
}

static int op_sector_erase(struct ringfs_flash_partition *flash, int address)
{
    (void) flash;
    rfs_dev_ram_sector_erase(ramHandle, address);
    return 0;
}

static ssize_t op_program(struct ringfs_flash_partition *flash, int address, const void *data, size_t size)
{
    (void) flash;
    rfs_dev_ram_program(ramHandle, address, data, size);
    return size;
}

static ssize_t op_read(struct ringfs_flash_partition *flash, int address, void *data, size_t size)
{
    (void) flash;
    rfs_dev_ram_read(ramHandle, address, data, size);
    return size;
}

struct ringfs_flash_partition rfs_disk_ram = {
    .sector_size 		= FLASH_RAM_SECTOR_SIZE,
    .sector_offset 	= FLASH_RAM_PARTITION_OFFSET,
    .sector_count 	= FLASH_RAM_PARTITION_SIZE,

    .sector_erase 	= op_sector_erase,
    .program 				= op_program,
    .read 					= op_read,
};


struct rfs_dev_ram *rfs_dev_ram_open(const char *name, int size, int sector_size)
{
    struct rfs_dev_ram *ram = &rfs_dev_ram_obj;
		ram = &rfs_dev_ram_obj;
	
    ram->size = size;
    ram->sector_size = sector_size;
#if 0	
    //ram->fh = fopen(name, "w+");
    //assert_param(ram->fh != NULL);
    //assert_param(ftruncate(fileno(ram->fh), size) == 0);
#else
		ram->buf = &ram_buf[0][0];
#endif
    return ram;
}

void rfs_dev_ram_close(struct rfs_dev_ram *ram)
{
    //fclose(ram->fh);
    //free(ram);
		memset(ram_buf, 0x00, sizeof(ram_buf));
}

void rfs_dev_ram_sector_erase(struct rfs_dev_ram *ram, int addr)
{
    int sector_start = addr - (addr % ram->sector_size);
    logprintf("rfs_dev_ram_erase  (0x%08x) * erasing sector at 0x%08x\n", addr, sector_start);
#if 0
    void *empty = malloc(ram->sector_size);
    assert_param(fseek(ram->fh, sector_start, SEEK_SET) == 0);
    assert_param(fwrite(empty, 1, ram->sector_size, ram->fh) == (size_t) ram->sector_size);

    free(empty);
#else
    memset(ram->buf+sector_start, 0xff, ram->sector_size);
#endif 	
}

void rfs_dev_ram_read(struct rfs_dev_ram *ram, int addr, uint8_t *buf, int len)
{
#if 0
    assert_param(fseek(ram->fh, addr, SEEK_SET) == 0);
    assert_param(fread(buf, 1, len, ram->fh) == (size_t) len);

    logprintf("rfs_dev_ram_read   (0x%08x) = %d bytes [ ", addr, len);
    for (int i=0; i<len; i++) {
        logprintf("%02x ", buf[i]);
        if (i == 15) {
            logprintf("... ");
            break;
        }
    }
    logprintf("]\n");
#else
	int32_t opt_len = 0;
	opt_len = len;
	if((addr+len) <= (ram->size))
	{		
		//地址和长度在合法的范围内；
	}
	else
	{
		//获取的内存空间超限，调整读取长度
		opt_len = ram->size - addr; 		
	}
	
	if(opt_len <= 0)
	{
		return;
	}
	
	memcpy(buf, ram->buf+addr, opt_len);	
	return;	
#endif	
}

void rfs_dev_ram_program(struct rfs_dev_ram *ram, int addr, const uint8_t *buf, int len)
{
#if 0	
    logprintf("rfs_dev_ram_program(0x%08x) + %d bytes [ ", addr, len);
    for (int i=0; i<len; i++) {
        logprintf("%02x ", buf[i]);
        if (i == 15) {
            logprintf("... ");
            break;
        }
    }
    logprintf("]\n");

    uint8_t *data = malloc(len);

    assert_param(fseek(ram->fh, addr, SEEK_SET) == 0);
    assert_param(fread(data, 1, len, ram->fh) == (size_t) len);

    for (int i=0; i<(int) len; i++)
        data[i] &= buf[i];

    assert_param(fseek(ram->fh, addr, SEEK_SET) == 0);
    assert_param(fwrite(data, 1, len, ram->fh) == (size_t) len);

    free(data);
		
#else
	int32_t opt_len = 0;
	opt_len = len;
	if((addr+len) <= (ram->size))
	{		
		//地址和长度在合法的范围内；
	}
	else
	{
		//获取的内存空间超限，调整读取长度
		opt_len = ram->size - addr; 		
	}
	
	if(opt_len <= 0)
	{
		return;
	}
	
	memcpy(ram->buf+addr, buf, opt_len);	
	return;	
#endif
}

#endif //----------------USE_LIB_RINGFS_RAM==1---------------------//
/* vim: set ts=4 sw=4 et: */
