blob: 1aa52f6caf37cbfad98333ddda2cce9b5b31a639 [file] [log] [blame]
/******************************************************************************
*(C) Copyright 2013 Marvell International Ltd.
* All Rights Reserved
******************************************************************************/
/*--------------------------------------------------------------------------------------------------------------------
* -------------------------------------------------------------------------------------------------------------------
*
* Filename: iml_api.c
*
* Description: The APIs to handle IML log.
*
* History:
* Dec, 13 2013 - Zhongmin Wu(zmwu@marvell.com) Creation of file
*
* Notes:
*
******************************************************************************/
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <pthread.h>
#include <errno.h>
#include <termios.h>
#include <sys/mman.h>
#include <string.h>
#include "utlEventHandler.h"
#include "pxa_dbg.h"
#include "iml_config.h"
#include "iml_api.h"
#include "iml_state_machine.h"
#include "media_manager.h"
#define IML_DEV_PATH "/dev/imldev0"
#define BLOCK_SIZE 8192
#define SEGMENT_NUM 512
struct ring_ctl_head{
int block_number;
int read_index;
int write_index;
int u_write_index;
int signature;
char stuff[BLOCK_SIZE - 5 * sizeof(int)];
char data[0];
};
static utlEventHandlerId_T IMLDevHandler;
static int IMLDevfd = -1;
static char * iml_ring_buff;
static int get_next_read_block(struct ring_ctl_head *head)
{
return head->read_index + 1 == head->block_number ? 0
: head->read_index + 1;
}
static int get_free_read_blocks(struct ring_ctl_head *head)
{
int free = head->read_index - head->u_write_index;
if(free < 0)
{
free += head->block_number;
}
return free;
}
static void * block_to_addr(int block)
{
struct ring_ctl_head * head = (struct ring_ctl_head * )iml_ring_buff;
return block * BLOCK_SIZE + head->data;
}
static int read_data(void)
{
struct ring_ctl_head * head = (struct ring_ctl_head * )iml_ring_buff;
int ret;
int block;
int count = 0;
while(get_free_read_blocks(head) > 0)
{
block = get_next_read_block(head);
//DBGMSG("Send block %d to Meida\n", block);
ret = SendMediadata(block_to_addr(block),BLOCK_SIZE);
if(ret != BLOCK_SIZE)
ERRMSG("Data Send to Media error");
else if(ret > 0)
count += ret;
head->read_index = block;
}
return count;
}
static utlReturnCode_T ReceiveDataFromMSA(const utlEventHandlerType_T handler_type UNUSED,
const utlEventHandlerType_T event_type UNUSED,
const int fd UNUSED,
const utlRelativeTime_P2c period_p UNUSED,
void *arg_p UNUSED)
{
int ret = 0;
unsigned long total = 0;
total = read_data();
// DBGMSG("Read %d bytes this time\n", total);
return utlSUCCESS;
}
int openIMLPort(int ddr)
{
F_ENTER();
int fd, flag;
if(ddr)
flag = O_WRONLY;
else
flag = O_RDWR;
fd = open(imlConfig.sys_settings.diag_port, flag);
if(fd < 0)
{
ERRMSG("open %s error %s\n", IML_DEV_PATH, strerror(errno));
return fd;
}
IMLDevfd = fd;
if(!ddr)
{
iml_ring_buff = mmap(NULL,BLOCK_SIZE*SEGMENT_NUM,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
if(MAP_FAILED == iml_ring_buff)
{
iml_ring_buff = NULL;
ERRMSG("mmap %s error %s\n", IML_DEV_PATH, strerror(errno));
}
else
{
struct ring_ctl_head * head = (struct ring_ctl_head *)iml_ring_buff;
DBGMSG("iml ring head (%d): signature:%x, block number : %d, rang %p -> %p",
sizeof(struct ring_ctl_head), head->signature, head->block_number,
iml_ring_buff, iml_ring_buff + BLOCK_SIZE*SEGMENT_NUM);
IMLDevHandler = utlSetFdEventHandler(utlEVENT_HANDLER_TYPE_READ, utlEVENT_HANDLER_PRIORITY_LOW, IMLDevfd, ReceiveDataFromMSA, NULL);
}
}
F_LEAVE();
return 0;
}
int closeIMLPort(void)
{
F_ENTER();
if(iml_ring_buff)
{
utlDeleteEventHandler(IMLDevHandler);
munmap(iml_ring_buff, BLOCK_SIZE*SEGMENT_NUM);
iml_ring_buff = NULL;
}
close(IMLDevfd);
IMLDevfd = -1;
F_LEAVE();
return 0;
}
void InitIML(void)
{
F_ENTER();
InitIMLMachine();
F_LEAVE();
}