/*****************************************************************************
 函 数 名  : mailbox_init
 接口类型  : 对外接口
 功能描述  : 邮箱模块平台适配部分初始化
 输入参数  :

 输出参数  : 无
 返 回 值  : 线程操作句柄
 调用函数  : mailbox_init_platform
 被调函数  :

 修改历史      :
  1.日    期   : 2012年9月24日
    作    者   : 莫南 00176101
    修改内容   : 新生成函数

 详细描述: 初始化邮箱并初始化与平台相关的差异化部分,在邮箱初始化的时候调用。
*****************************************************************************/
signed int mailbox_init(void)
{

    if (MAILBOX_INIT_MAGIC == g_mailbox_handle.init_flag) {
        /*考虑到单核下电重启,静态数据不会丢失,这里只打印告警,
          返回错误的话,后面的平台初始化将调不到,IPC中断无法注册*/
        return mailbox_logerro_p1(MAILBOX_ERR_GUT_ALREADY_INIT, g_mailbox_handle.init_flag);
    }

    /*TODO:进行单核下电重启特性开发时,这行需要删除*/
    mailbox_memset(&g_mailbox_handle, 0x00, sizeof(struct mb));

#ifdef MAILBOX_OPEN_MNTN
    if ((MAILBOX_HEAD_BOTTOM_ADDR > (MAILBOX_MEM_BASEADDR + MAILBOX_MEM_HEAD_LEN)) ||
       (MAILBOX_MEMORY_BOTTOM_ADDR > (MAILBOX_MEM_BASEADDR + MAILBOX_MEM_LENGTH)))
    {
        mailbox_out(("mailbox address overflow: headbuttom valid(0x%x), config(0x%x)!\n\
          \r                          databuttom valid(0x%x), config(0x%x)!"RT,
        (MAILBOX_MEM_BASEADDR + MAILBOX_MEM_HEAD_LEN), MAILBOX_HEAD_BOTTOM_ADDR,
        (MAILBOX_MEM_BASEADDR + MAILBOX_MEM_LENGTH), MAILBOX_MEMORY_BOTTOM_ADDR));
        return mailbox_logerro_p0(MAILBOX_CRIT_GUT_MEMORY_CONFIG);
    }
#endif

    /*初始化邮箱主体部分,创建邮箱总句柄。*/
    if (MAILBOX_OK != mailbox_create_box(&g_mailbox_handle,
                          &g_mailbox_global_cfg_tbl[0], MAILBOX_LOCAL_CPUID)) {
        return mailbox_logerro_p0(MAILBOX_ERR_GUT_CREATE_BOX);
    }

    /*初始化平台差异部分*/
    if (MAILBOX_OK != mailbox_init_platform()) {
        return mailbox_logerro_p0(MAILBOX_ERR_GUT_INIT_PLATFORM);
    }

    g_mailbox_handle.init_flag = MAILBOX_INIT_MAGIC;

#ifndef _DRV_LLT_
//    mailbox_ifc_test_init();
#endif

    mailbox_out(("mb init OK!"RT));

    return MAILBOX_OK;
}
MAILBOX_EXTERN struct mb *mailbox_get_mb(void) {
	if (MAILBOX_INIT_MAGIC == g_mailbox_handle.init_flag) {
		return &g_mailbox_handle;
	}

	/*错误邮箱未初始化*/
	mailbox_out(("error: mb not init\n"));
	return MAILBOX_NULL;
}
MAILBOX_EXTERN void mailbox_assert(unsigned long ErroNo)
{
#ifndef _DRV_LLT_

    /*产品方案*/
    if(0 == check_himntn(HIMNTN_MBFULL_ASSERT))
    {
        systemError(BSP_MODU_MAILBOX, ErroNo, 0, 0, 0);
    }
    else
    {
        while (1)
        {
            mailbox_out(("mb Assert!\n"));
            msleep(1000); 
        }
    }

#endif
}
MAILBOX_GLOBAL long mailbox_init(void)
{
	unsigned long offset = 0;
	int i = 0;
	struct mb_head *head = NULL;

	if (MAILBOX_INIT_MAGIC == g_mailbox_handle.init_flag) {
		/*考虑到单核下电重启,静态数据不会丢失,这里只打印告警,
		返回错误的话,后面的平台初始化将调不到,IPC中断无法注册*/
		return mailbox_logerro_p1(MAILBOX_ERR_GUT_ALREADY_INIT, g_mailbox_handle.init_flag);
	}

	printk("func = %s, line = %d baseaddr = 0x%x\n", __func__, __LINE__, MAILBOX_MEM_BASEADDR);

	g_shareMemBase = ioremap(MAILBOX_MEM_BASEADDR, MAILBOX_MEM_LENGTH);
	/*初始化邮箱中的数据*/
//memset(g_shareMemBase,0x0,MAILBOX_MEM_LENGTH);

	if(NULL == g_shareMemBase) {
		printk("func = %s, mmap mailbox mem error!!\n", __func__);
		return mailbox_logerro_p0(MAILBOX_CRIT_GUT_MEMORY_CONFIG);
	}

	offset = (unsigned long)g_shareMemBase - MAILBOX_MEM_BASEADDR;
	for(i = 0; i < MAILBOX_GLOBAL_CHANNEL_NUM; i++) {
		g_mailbox_global_cfg_tbl[i].head_addr = g_mailbox_global_cfg_tbl[i].head_addr + offset;
		g_mailbox_global_cfg_tbl[i].data_addr = g_mailbox_global_cfg_tbl[i].data_addr + offset;

		printk("i = %d, head_addr = 0x%lx, data_addr = 0x%lx\n", i,
			   g_mailbox_global_cfg_tbl[i].head_addr, g_mailbox_global_cfg_tbl[i].data_addr);

		/*初始化邮箱头*/
		head = (struct mb_head *)g_mailbox_global_cfg_tbl[i].head_addr;
		head->ulFront = 0x0;
		head->ulRear = 0x0;
		head->ulFrontslice = 0x0;
		head->ulRearslice = 0x0;
	}

	/*TODO:进行单核下电重启特性开发时,这行需要删除*/
	mailbox_memset(&g_mailbox_handle, 0x00, sizeof(struct mb));

#ifdef MAILBOX_OPEN_MNTN
	if ((MAILBOX_HEAD_BOTTOM_ADDR > (MAILBOX_MEM_BASEADDR + MAILBOX_MEM_HEAD_LEN)) ||
		(MAILBOX_MEMORY_BOTTOM_ADDR > (MAILBOX_MEM_BASEADDR + MAILBOX_MEM_LENGTH))) {
		mailbox_out(("mailbox address overflow: headbuttom valid(0x%x), config(0x%x)!\n\\r							databuttom valid(0x%x), config(0x%x)!\n",
					 (MAILBOX_MEM_BASEADDR + MAILBOX_MEM_HEAD_LEN), MAILBOX_HEAD_BOTTOM_ADDR,
					 (MAILBOX_MEM_BASEADDR + MAILBOX_MEM_LENGTH), MAILBOX_MEMORY_BOTTOM_ADDR));
		return mailbox_logerro_p0(MAILBOX_CRIT_GUT_MEMORY_CONFIG);
	}
#endif

	/*初始化邮箱主体部分,创建邮箱总句柄。*/
	if (MAILBOX_OK != mailbox_create_box(&g_mailbox_handle,
										 &g_mailbox_global_cfg_tbl[0], MAILBOX_LOCAL_CPUID)) {
		return mailbox_logerro_p0(MAILBOX_ERR_GUT_CREATE_BOX);
	}

	/*初始化平台差异部分*/
	if (MAILBOX_OK != mailbox_init_platform()) {
		return mailbox_logerro_p0(MAILBOX_ERR_GUT_INIT_PLATFORM);
	}

	g_mailbox_handle.init_flag = MAILBOX_INIT_MAGIC;

#ifndef _DRV_LLT_
//mailbox_ifc_test_init();
#endif

//fixme: there isn't go to unremap
	g_slice_reg = (void*)ioremap(SLICE_REG, 0x4);
	if (NULL == g_slice_reg) {
		printk("ioremap of slice reg fail.\n");
	}

	mailbox_out(("mb init OK!\n"));

	return MAILBOX_OK;
}
MAILBOX_LOCAL long mailbox_request_channel(
	struct mb *mb,
	struct mb_buff ** mb_buf,
	unsigned long mailcode)
{
	struct mb_head		 *head	= MAILBOX_NULL;
	struct mb_queue 	 *queue = MAILBOX_NULL;
	struct mb_buff		 *mbuff = MAILBOX_NULL;
	long ret_val = MAILBOX_OK;

	mailbox_dpm_device_get();

	*mb_buf = MAILBOX_NULL;
	mbuff = mailbox_get_channel_handle(mb, mailcode);
	if (MAILBOX_NULL == mbuff) {
		ret_val = MAILBOX_ERRO;
		goto request_erro;
	}

	/*通过判断通道保护字,检查通道有没有初始化*/
	head = (struct mb_head*)mbuff->config->head_addr;
	if ((  (MAILBOX_PROTECT1 != head->ulProtectWord1) )
		|| (MAILBOX_PROTECT2 != head->ulProtectWord2)
		||(MAILBOX_PROTECT1 != head->ulProtectWord3)
		|| (MAILBOX_PROTECT2 != head->ulProtectWord4)) {
#if 1/*k3 modify 保护字不正确重新初始化一下邮箱头,不要return影响通信流程,后续再找根因*/
		/*保护字不正确,说明邮箱未初始化,或者内存被踩,报错。*/
		/* do not check cause hifi maybe not pwr on when the first ipc message send */

		mailbox_init_mem(mbuff->config);

		mailbox_logerro_p1(MAILBOX_NOT_READY, mailcode);
#endif
	}

	if(mailbox_get_src_id(mailcode) == mb->local_id) {
		/* 不允许在中断中发邮件*/
		if (MAILBOX_TRUE == mailbox_int_context()) {
//TODO:接下来的开发(IFC for 低功耗)可能需要支持在中断中发送邮件,这里就需要锁中断。
			ret_val = mailbox_logerro_p1(MAILBOX_ERR_GUT_SEND_MAIL_IN_INT_CONTEXT, mailcode);
			goto request_erro;
		} else {
			if (MAILBOX_OK != mailbox_mutex_lock(&mbuff->mutex)) {
				/*非中断发送,需要资源保护,获取当前通道资源。*/
				ret_val = mailbox_logerro_p1(MAILBOX_CRIT_GUT_MUTEX_LOCK_FAILED, mailcode);
				goto request_erro;
			}
		}
	}

	mbuff->mailcode = mailcode;

	/*共享内存队列,需要依据邮箱头信息对队列操作符进行填充*/
	queue = &mbuff->mail_queue;
	queue->front = queue->base + head->ulFront * sizeof(unsigned long);
	queue->rear  = queue->base + head->ulRear * sizeof(unsigned long);

	mbuff->mb = mb;
	*mb_buf = mbuff;
	return MAILBOX_OK;
request_erro:
	mailbox_out(("###mailbox_request_channel ERR! \n"));
	mailbox_dpm_device_put();
	return ret_val;
}