Ejemplo n.º 1
0
/*****************************************************************************
 函 数 名  : mailbox_init_all_handle
 接口类型  : 对内接口
 功能描述  : 初始化邮箱的所有通道句柄
 输入参数  : struct mb *mb  -- 邮箱总句柄
             struct mb_cfg *config  -- 邮箱通道的全局配置表。
             unsigned long  cpu_id     -- 注册此通道的CPU号。
 输出参数  : 无
 返 回 值  : 邮箱操作句柄
 调用函数  :
 被调函数  :

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

*****************************************************************************/
MAILBOX_LOCAL long mailbox_init_all_handle(
                struct mb           *mb,
                struct mb_cfg    *config,
                unsigned long     cpu_id)
{
    struct mb_queue        *queue  = MAILBOX_NULL;
    unsigned long           direct= MIALBOX_DIRECTION_INVALID; /*标记当前邮箱通道
                                            是不是本核相关的有效通道*/
    unsigned long           ret_val      = MAILBOX_OK;
    struct mb_link         *send_link    = MAILBOX_NULL;/*指向主结构体的发送通道
                                                          数组基地址*/
    struct mb_link         *recv_link = MAILBOX_NULL;   /*指向主结构体的接收通道
                                                          数组基地址*/
    struct mb_buff         *mbuf_prob   = &g_mailbox_channel_handle_pool[0];
    struct mb_cb           *cb_prob  = &g_mailbox_user_cb_pool[0];
    struct mb_buff         *mbuf_cur = MAILBOX_NULL;    /*指向正在处理的邮箱通道*/
    unsigned long           channel_sum    = 0;
    unsigned long           use_sum    = 0;
    unsigned long           src_id       = 0;
    unsigned long           dst_id       = 0;
    unsigned long           carrier_id   = 0;
    unsigned long           use_max      = 0;

    send_link  =  mb->send_tbl;
    recv_link  =  mb->recv_tbl;

    /*第二次循环对每个通道句柄分配空间,并赋值。(这段代码变量太多,不方便拆开另建函数)*/
    /*初始化每个邮箱的控制句柄*/
    while (MAILBOX_MAILCODE_INVALID != config->butt_id) {
        direct = MIALBOX_DIRECTION_INVALID;
        src_id       = mailbox_get_src_id(config->butt_id);
        dst_id       = mailbox_get_dst_id(config->butt_id);
        carrier_id   = mailbox_get_carrier_id(config->butt_id);
        use_max      = mailbox_get_use_id(config->butt_id);

        /*检查是不是本CPU发送通道*/
        if (cpu_id == src_id) {
            direct = MIALBOX_DIRECTION_SEND;

            /*没有分配空间则分配空间*/
            if (MAILBOX_NULL == send_link[dst_id].channel_buff) {
                send_link[dst_id].channel_buff = mbuf_prob;
                mbuf_prob += (send_link[dst_id].carrier_butt);
                channel_sum  += (send_link[dst_id].carrier_butt);
                if (channel_sum > MAILBOX_CHANNEL_NUM) {
                    return mailbox_logerro_p1(MAILBOX_CRIT_GUT_INIT_CHANNEL_POOL_TOO_SMALL,
                                                channel_sum);
                }
            }
            mbuf_cur = &send_link[dst_id].channel_buff[carrier_id];
        }

        /*检查是不是本CPU接收通道*/
        if (cpu_id == dst_id) {
             direct = MIALBOX_DIRECTION_RECEIVE;

            /*没有分配空间则分配空间*/
            if (MAILBOX_NULL == recv_link[src_id].channel_buff) {
                recv_link[src_id].channel_buff = mbuf_prob;
                mbuf_prob += (recv_link[src_id].carrier_butt);
                channel_sum  += (recv_link[src_id].carrier_butt);
                if (channel_sum > MAILBOX_CHANNEL_NUM) {
                    return mailbox_logerro_p1(MAILBOX_CRIT_GUT_INIT_CHANNEL_POOL_TOO_SMALL,
                                                channel_sum);
                }
            }

            mbuf_cur = &recv_link[src_id].channel_buff[carrier_id];

            /*1。为邮件注册回调函数申请空间*/
            mbuf_cur->read_cb = cb_prob;
            cb_prob += use_max;
            use_sum   += use_max;
            if (use_sum > MAILBOX_USER_NUM) {
                return mailbox_logerro_p1(MAILBOX_CRIT_GUT_INIT_USER_POOL_TOO_SMALL, use_sum);
            }

            /*3.注册邮箱线程回调接口,用于获取共享内存邮箱数据的处理*/
            ret_val = mailbox_process_register(mailbox_get_channel_id(config->butt_id),
                                                mailbox_read_channel, mbuf_cur);

            /*4.初始化邮箱共享内存,设置标志位。*/
            ret_val |= mailbox_init_mem(config);

        }

        if ((MIALBOX_DIRECTION_INVALID != direct ) && (MAILBOX_NULL != mbuf_cur)) {
            /*给控制句柄赋予邮箱ID号*/
            mbuf_cur->channel_id = mailbox_get_channel_id(config->butt_id);
            mbuf_cur->seq_num = MAILBOX_SEQNUM_START;
#ifdef MAILBOX_OPEN_MNTN
            mbuf_cur->mntn.peak_traffic_left = MAILBOX_QUEUE_LEFT_INVALID;
            mbuf_cur->mntn.mbuff    = mbuf_cur;
#endif
            /*给邮箱配置物理资源*/
            mbuf_cur->config = config;

            /*初始化通道资源*/
            queue = &(mbuf_cur->mail_queue);

            /*初始化邮箱通道的环形队列控制符,以下两项是初始化以后不会再变化的。*/
            queue->length  = mbuf_cur->config->data_size -
                            (MAILBOX_DATA_LEN_PROTECT_NUM * MAILBOX_PROTECT_LEN);
            queue->base    = mbuf_cur->config->data_addr +
                           (MAILBOX_DATA_BASE_PROTECT_NUM * MAILBOX_PROTECT_LEN);


            /*把此通道注册到具体平台*/
            ret_val = mailbox_channel_register(mailbox_get_channel_id(config->butt_id), /*lint !e539*/
                       config->int_src,
                       mailbox_get_dst_id(config->butt_id),
                       direct,
                       &mbuf_cur->mutex);
        }

        config++;
    }

    /*检查内存池大小是否刚好,如果报错,请检查宏设置是否匹配:
      这里检查下面三个数组的空间是否适配。
        g_mailbox_global_cfg_tbl[];
        g_mailbox_channel_handle_pool[MAILBOX_CHANNEL_NUM];
        g_mailbox_user_cb_pool[MAILBOX_USER_NUM];
    */
    if((unsigned long)MAILBOX_CHANNEL_NUM != channel_sum ) {
        ret_val = mailbox_logerro_p1(MAILBOX_ERR_GUT_INIT_CHANNEL_POOL_TOO_LARGE,
                                    (MAILBOX_CHANNEL_NUM<<16) | channel_sum);
    }

    if(MAILBOX_USER_NUM != use_sum) {
       ret_val = mailbox_logerro_p1(MAILBOX_ERR_GUT_INIT_USER_POOL_TOO_LARGE, use_sum);
    }

    return ret_val;
}
Ejemplo n.º 2
0
/*****************************************************************************
 函 数 名  : mailbox_read_mail
 接口类型  : 对内接口
 功能描述  : 读取并处理一封邮箱的正文数据内容,接受邮箱数据的数据层入口,
                并且调用上层注册的邮件数据处理回调函数
 输入参数  : mb_buff*       mbuff  - 邮箱通道操作符

 输出参数  : 无
 返 回 值  : 读取的邮件数据长度,包括邮件头,返回0表示失败。
 调用函数  :
 被调函数  :

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

*****************************************************************************/
MAILBOX_LOCAL long mailbox_read_mail(struct mb_buff *mbuff)
{
    struct mb_mail        mail;
    struct mb_cb         *read_cb = MAILBOX_NULL;/*此邮箱通道的功能回调函数队列*/
    struct mb_queue       tmp_queue;
    struct mb_queue      *usr_queue   = MAILBOX_NULL;
    struct mb_queue      *m_queue   = MAILBOX_NULL;
    unsigned long         use_id;
    unsigned long         slice_start;
    unsigned long         to_bottom;
    void                 *usr_handle;
    void                 *usr_data;
    void (*usr_func)(void *mbuf, void *handle, void *data);

    m_queue = &(mbuff->mail_queue);
    usr_queue = &(mbuff->usr_queue);
    mailbox_memcpy((void *) usr_queue, (const void *) m_queue, sizeof(struct mb_queue));

    /*保存临时队列状态,交换读写指针。*/
    tmp_queue.base   = usr_queue->base;
    tmp_queue.length = usr_queue->length;
    tmp_queue.front  = usr_queue->rear;
    tmp_queue.rear   = usr_queue->front;

    /*读取邮件的头信息*/
    mailbox_queue_read(usr_queue, (char*)&mail, sizeof(struct mb_mail));

    /*1.检查邮件头,判断读到的消息是否存在异常,包括SN号是否连续、消息滞留时间是否过长。
      2.填充信息读取时间*/
    mailbox_check_mail(mbuff, &mail, m_queue->rear);

    /*把读取时间写回邮箱队列*/
    mailbox_queue_write(&tmp_queue, (char*)&mail, sizeof(struct mb_mail));
    use_id = mailbox_get_use_id(mail.ulMailCode);

    /*检查Use ID的有效性*/
    if (use_id >= mailbox_get_use_id(mbuff->config->butt_id)) {
        mailbox_logerro_p1(MAILBOX_ERR_GUT_INVALID_USER_ID, mail.ulMailCode);
        goto EXIT;
    }

    read_cb = &mbuff->read_cb[use_id];
    mailbox_mutex_lock(&mbuff->mutex);
    usr_handle = read_cb->handle;
    usr_data = read_cb->data;
    usr_func = read_cb->func;
    mailbox_mutex_unlock(&mbuff->mutex);
    if (MAILBOX_NULL != usr_func) {
        usr_queue->size = mail.ulMsgLength;
        slice_start = mailbox_get_timestamp();
        usr_func(mbuff, usr_handle , usr_data);

        /*记录可维可测信息*/
#ifdef MAILBOX_OPEN_MNTN
         mailbox_record_receive(&mbuff->mntn, mbuff->channel_id, slice_start);
#endif
    } else {
        mailbox_logerro_p1(MAILBOX_ERR_GUT_READ_CALLBACK_NOT_FIND, mail.ulMailCode);
    }

EXIT:

    /*不管用户有没有用回调读数据,读了多少数据,邮箱队列的读指针都需要按实际
      大小偏移,以保证后面邮件读取的正确性。*/
    to_bottom  = (m_queue->base + m_queue->length) - m_queue->rear;
    if (to_bottom > (mail.ulMsgLength + sizeof(struct mb_mail))) {
        m_queue->rear += (mail.ulMsgLength + sizeof(struct mb_mail));
    } else {
        m_queue->rear = m_queue->base + ((mail.ulMsgLength +
            sizeof(struct mb_mail)) - to_bottom);
    }

    /*读保证指针4字节对齐*/
    m_queue->rear = mailbox_align_size(m_queue->rear, MAILBOX_ALIGN);

    return (mailbox_align_size(mail.ulMsgLength, MAILBOX_ALIGN)
            + sizeof(struct mb_mail));

}
Ejemplo n.º 3
0
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_EXTERN long mailbox_process_register(
                unsigned long channel_id, 
                 long (*cb)(unsigned long channel_id),
                 void *priv)
{
    struct mb_local_work        *local_work    =   MAILBOX_NULL;
    struct mb_local_cfg         *local_cfg  =  &g_mb_local_cfg_tbl[0];
    struct mb_local_proc        *local_proc =  &g_mailbox_local_proc_tbl[0];
    struct mb_local_cfg*         find_cfg     =   MAILBOX_NULL;
    unsigned long count = sizeof(g_mailbox_local_proc_tbl)/sizeof(struct mb_local_proc);

    while (MAILBOX_MAILCODE_INVALID != local_cfg->channel_id) {
        /*找到与传入邮箱ID最适配的系统邮箱配置*/
        if (local_cfg->channel_id ==  channel_id) {
            find_cfg = local_cfg;
            break;
        }
        local_cfg++;
    }

    if (find_cfg) {
        /*加入邮箱任务对应的邮箱工作队列*/
        while (count) {
            if (find_cfg->property == local_proc->proc_id) {
                if (local_proc->work_list) {
                    local_work = local_proc->work_list;
                    while (MAILBOX_NULL != local_work->next) {
                        local_work = local_work->next;
                    }
                    local_work->next            = (struct mb_local_work *)kcalloc(
                                                    sizeof(struct mb_local_work), 1, GFP_KERNEL);
                    if (NULL == local_work->next)  {
                        (void)printk(KERN_ERR "%s: memory alloc error!\n",__func__);
                        return MAILBOX_ERR_LINUX_ALLOC_MEMORY;
                    }
                    local_work->next->channel_id = find_cfg->channel_id;
                    local_work->next->cb  = cb;
                    local_work->next->next = MAILBOX_NULL;
                    local_work->next->mb_priv = priv;

                } else {
                    local_proc->work_list     = (struct mb_local_work *)kcalloc(
                                                   sizeof(struct mb_local_work), 1, GFP_KERNEL);
                    if (NULL == local_proc->work_list) {
                        (void)printk(KERN_ERR "%s: memory alloc error!\n",__func__);
                        return MAILBOX_ERR_LINUX_ALLOC_MEMORY;
                    }
                    local_proc->work_list->channel_id = find_cfg->channel_id;
                    local_proc->work_list->cb  = cb;
                    local_proc->work_list->next = MAILBOX_NULL;
                    local_proc->work_list->mb_priv = priv;
                }

            }
            count--;
            local_proc++;
        }

        return MAILBOX_OK;
    }

    return  mailbox_logerro_p1(MAILBOX_ERR_LINUX_CHANNEL_NOT_FIND, channel_id);

}
Ejemplo n.º 5
0
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;
}