/***************************************************************************** 函 数 名 : mailbox_request_channel 接口类型 : 对外接口 功能描述 : 打开一个邮箱通道,准备开始写或者一封邮件。 根据现有的邮箱通道号,创建一个邮箱操作符号,并根据邮箱头填充邮箱操作符信息 输入参数 : struct mb *mailbox 邮箱控制总句柄 unsigned long mailcode -- 待访问邮件的ID 输出参数 : 无 返 回 值 : 一个邮箱通道的操作符 调用函数 : 被调函数 : 修改历史 : 1.日 期 : 2012年9月27日 作 者 : 莫南 00176101 修改内容 : 新生成函数 *****************************************************************************/ MAILBOX_EXTERN struct mb_buff *mailbox_get_channel_handle( struct mb *mailbox, unsigned long mailcode) { struct mb_link *link_array = MAILBOX_NULL; struct mb_buff *mbuff = MAILBOX_NULL; unsigned long src_id = 0; unsigned long dst_id = 0; unsigned long carrier_id = 0; src_id = mailbox_get_src_id(mailcode); dst_id = mailbox_get_dst_id(mailcode); carrier_id = mailbox_get_carrier_id(mailcode); if (src_id == mailbox->local_id) { if (dst_id < MAILBOX_CPUID_BUTT) { link_array = &mailbox->send_tbl[dst_id]; } else { /*无效目标号,数组越界*/ mailbox_logerro_p1(MAILBOX_ERR_GUT_INVALID_CHANNEL_ID, mailcode); return MAILBOX_NULL; } } else if (dst_id == mailbox->local_id) { if (src_id < MAILBOX_CPUID_BUTT) { link_array = &mailbox->recv_tbl[src_id]; } else { /*无效目标号,数组越界*/ mailbox_logerro_p1(MAILBOX_ERR_GUT_INVALID_CHANNEL_ID, mailcode); return MAILBOX_NULL; } } else { /*此处已在收发入口判断*/ } if ((MAILBOX_NULL == link_array) || (0 == link_array->carrier_butt)) { /*当前两个CPU之间不存在任何邮箱通道*/ mailbox_logerro_p1(MAILBOX_ERR_GUT_INVALID_CPU_LINK, mailcode); return MAILBOX_NULL; } /*获得通道操作句柄*/ if (carrier_id < link_array->carrier_butt) { mbuff = &link_array->channel_buff[carrier_id]; } else { /*非法载体号,数组越界*/ mailbox_logerro_p1(MAILBOX_ERR_GUT_INVALID_CARRIER_ID, mailcode); return MAILBOX_NULL; } /*检查mail code中 use ID的合法性*/ if (mailbox_get_use_id(mailcode) >= mailbox_get_use_id(mbuff->config->butt_id)) { mailbox_logerro_p1(MAILBOX_ERR_GUT_INVALID_USER_ID, mailcode); #ifndef _DRV_LLT_ /*PC工程允许发送非法use ID,用于测试接收通道代码分支*/ return MAILBOX_NULL; #endif } return mbuff; }
/*获取一个邮箱物理通道buff*/ MAILBOX_EXTERN long mailbox_request_buff(unsigned long mailcode, struct mb_buff** mb_buf) { struct mb *mailbox = MAILBOX_NULL; unsigned long ret_val = MAILBOX_OK; struct mb_buff ** mbuf = (struct mb_buff **)mb_buf; mailbox = mailbox_get_mb(); *mbuf = MAILBOX_NULL; if (MAILBOX_NULL == mailbox){ return mailbox_logerro_p1(MAILBOX_ERR_GUT_INPUT_PARAMETER, mailcode); } /*检查是否为发送通道*/ if (mailbox->local_id != mailbox_get_src_id(mailcode)){ return mailbox_logerro_p1(MAILBOX_ERR_GUT_INVALID_SRC_CPU, mailcode); } /*获得此邮件邮箱通道的操作句柄: open mail*/ ret_val = mailbox_request_channel(mailbox, mbuf, mailcode); if (MAILBOX_OK == ret_val){ (*mbuf)->mb = mailbox; ret_val = mailbox_init_usr_queue(*mbuf); if (MAILBOX_OK == ret_val) { return MAILBOX_OK; } else { mailbox_release_channel(mailbox, *mbuf); *mbuf = MAILBOX_NULL; return ret_val; } } else { return ret_val; } }
MAILBOX_LOCAL int mailbox_request_channel( struct mb *mb, struct mb_buff ** mb_buf, unsigned int mailcode) { struct mb_head *head = MAILBOX_NULL; struct mb_queue *queue = MAILBOX_NULL; struct mb_buff *mbuff = MAILBOX_NULL; int ret_val = MAILBOX_OK; *mb_buf = MAILBOX_NULL; mbuff = mailbox_get_channel_handle(mb, mailcode); if (MAILBOX_NULL == mbuff) { ret_val = (int)MAILBOX_ERRO; goto request_erro;/*lint --e{801}*/ } /*通过判断通道保护字,检查通道有没有初始化*/ 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)) { /*保护字不正确,说明邮箱未初始化,或者内存被踩,报错。*/ ret_val = mailbox_logerro_p1(MAILBOX_NOT_READY, mailcode); goto request_erro;/*lint --e{801}*/ } 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;/*lint --e{801}*/ } else { if (MAILBOX_OK != mailbox_mutex_lock(&mbuff->mutex)) { /*非中断发送,需要资源保护,获取当前通道资源。*/ ret_val = mailbox_logerro_p1(MAILBOX_CRIT_GUT_MUTEX_LOCK_FAILED, mailcode); goto request_erro;/*lint --e{801}*/ } } } mbuff->mailcode = mailcode; /*共享内存队列,需要依据邮箱头信息对队列操作符进行填充*/ queue = &mbuff->mail_queue; queue->front = queue->base + head->ulFront * sizeof(unsigned int); queue->rear = queue->base + head->ulRear * sizeof(unsigned int); mbuff->mb = mb; *mb_buf = mbuff; return MAILBOX_OK; request_erro: //mailbox_out(("###mailbox_request_channel ERR!"RT)); return ret_val; }
/***************************************************************************** 函 数 名 : mailbox_calculate_space 接口类型 : 对内接口 功能描述 : 统计通道信息,计算需要分配的内存空间 输入参数 : struct mb *mb -- 邮箱总句柄 struct mb_cfg *config -- 邮箱通道的全局配置表。 unsigned long CpuID -- 注册此通道的CPU号。 输出参数 : 无 返 回 值 : 邮箱操作句柄 调用函数 : 被调函数 : 修改历史 : 1.日 期 : 2012年9月7日 作 者 : 莫南 00176101 修改内容 : 新生成函数 *****************************************************************************/ MAILBOX_LOCAL long mailbox_calculate_space( struct mb *mb, struct mb_cfg *config, unsigned long cpu_id) { struct mb_link *send_link = MAILBOX_NULL;/*指向主结构体的发送通道数组基地址*/ struct mb_link *recev_link = MAILBOX_NULL;/*指向主结构体的接收通道数组基地址*/ unsigned long ret_val = MAILBOX_OK; unsigned long src_id = 0; unsigned long dst_id = 0; unsigned long carrier_id = 0; send_link = mb->send_tbl; recev_link = mb->recv_tbl; while (MAILBOX_MAILCODE_INVALID != config->butt_id) { 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); /*检查是不是本CPU发送通道*/ if (cpu_id == src_id) { /*检查目的CPU的有效性*/ if (dst_id < MAILBOX_CPUID_BUTT) { /*记录此CPU连接的最大通道*/ if ((carrier_id + 1) > send_link[dst_id].carrier_butt) { send_link[dst_id].carrier_butt = (carrier_id + 1); } else { /*不记录*/ } } else { /*数组越界*/ ret_val = mailbox_logerro_p1(MAILBOX_ERR_GUT_INVALID_CHANNEL_ID, config->butt_id); } } /*检查是不是本CPU接收通道*/ if (cpu_id == dst_id) { /*检查发送CPU的有效性*/ if (src_id < MAILBOX_CPUID_BUTT) { /*记录此CPU连接的最大通道*/ if ((carrier_id + 1) > recev_link[src_id].carrier_butt) { recev_link[src_id].carrier_butt = (carrier_id + 1); } else { /*不记录*/ } } else { /*数组越界*/ ret_val = mailbox_logerro_p1(MAILBOX_ERR_GUT_INVALID_CHANNEL_ID, config->butt_id); } } config++; } return ret_val; }
/***************************************************************************** 函 数 名 : mailbox_release_channel 接口类型 : 对内接口 功能描述 : 关闭邮箱,释放资源。 输入参数 : mb_buff* mbuff - 邮箱通道缓存操作符 输出参数 : 无 返 回 值 : 邮箱关闭是否成功 调用函数 : 被调函数 : 修改历史 : 1.日 期 : 2012年9月27日 作 者 : 莫南 00176101 修改内容 : 新生成函数 *****************************************************************************/ MAILBOX_LOCAL long mailbox_release_channel(struct mb *mb, struct mb_buff *mbuff) { unsigned long channel_id = mbuff->channel_id; /*需要区分是读还是写*/ if (mb->local_id == mailbox_get_src_id(channel_id)) { if (MAILBOX_TRUE == mailbox_int_context()) { /*TODO:接下来的开发(IFC for 低功耗)可能需要支持在中断中发送邮件, 这里就需要解锁中断。*/ } else { mailbox_mutex_unlock(&mbuff->mutex); } } return MAILBOX_OK; }
/***************************************************************************** 函 数 名 : mailbox_flush_buff 接口类型 : 对内接口 功能描述 : 把邮箱消息队列的头尾指针写入邮箱头 输入参数 : mb_buff* mbuff - 邮箱通道操作符 输出参数 : 无 返 回 值 : MAILBOX_OK 调用函数 : 被调函数 : 修改历史 : 1.日 期 : 2013年5月08日 作 者 : 莫南 00176101 修改内容 : 新生成函数 *****************************************************************************/ MAILBOX_EXTERN long mailbox_flush_buff( struct mb_buff *mbuff) { struct mb_head *head = MAILBOX_NULL; struct mb_queue *queue = MAILBOX_NULL; unsigned long channel_id = mbuff->channel_id; struct mb *mb = mbuff->mb; /*把邮箱通道操作符的信息写回邮箱头。*/ head = (struct mb_head*)mbuff->config->head_addr; queue = &mbuff->mail_queue; /*需要区分是读还是写*/ if (mb->local_id == mailbox_get_src_id(channel_id)) { /*写关闭,更新邮箱头写指针,同时释放邮箱资源*/ head->ulFront = (queue->front - queue->base ) / sizeof(unsigned long) ; head->ulFrontslice = mailbox_get_timestamp(); } else if (mb->local_id == mailbox_get_dst_id(channel_id)) { /*读关闭,只更新邮箱头读指针*/ head->ulRear = (queue->rear - queue->base ) / sizeof(unsigned long); head->ulRearslice = mailbox_get_timestamp(); } return MAILBOX_OK; }
/***************************************************************************** 函 数 名 : 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; }
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; }