| /****************************************************************************** |
| *(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(); |
| } |
| |
| |