kal_int32 cc_irq_unmask(kal_uint32 index) { /* it is assumed that IRQ ID aligns index of CC IRQ!! */ /* Please check this during pre-sillicon. */ if (!CC_IRQ_RX_INDEX_IS_IN_RANGE(index)) { return CC_IRQ_ERR_PARAM; } index = CC_IRQ_RX_INDEX_OFFSET(index); IRQUnmask(CC_IRQ_INTR_ID_START + index); return CC_IRQ_SUCCESS; }
kal_int32 cc_irq_register_callback(kal_uint32 index, CC_IRQ_CALLBACK_P cb) { if (!CC_IRQ_RX_INDEX_IS_IN_RANGE(index)) { return CC_IRQ_ERR_PARAM; } if (NULL == cb) { return CC_IRQ_ERR_PARAM; } index = CC_IRQ_RX_INDEX_OFFSET(index); cc_irq_cb[index] = cb; return CC_IRQ_SUCCESS; }
void md_pccif_isr(kal_uint32 index) { kal_uint32 buff[CC_IRQ_BUFF_MAX / sizeof(kal_uint32)]; kal_uint32 chl_rx_mask, i, rx_chl_start, tmp_chl; kal_uint32 savedMask, log_index; /* get pended channel mask */ chl_rx_mask = *PCCIF_RCHNUM; chl_rx_mask = MD_PCCIF_HW_GET_CHL_MASK(index, chl_rx_mask); rx_chl_start = md_pccif_rx_chl_ptr[index]; /* scan each channel from md_pccif_rx_chl_ptr[index] until reach 0 */ for (i = 0; i < MD_PCCIF_HW_CHL_NUMBER_PER_IRQ; i++) { tmp_chl = (rx_chl_start + i) % MD_PCCIF_HW_CHL_NUMBER_PER_IRQ; if (chl_rx_mask & (1 << tmp_chl)) { md_pccif_pkt_hdr_t *hdr; kal_uint32 *src_addr; kal_uint32 length, ack_mask, rx_chl_number, read_ptr; /* get logging index */ CC_IRQ_DRV_MASK_ALL_INTERRUPT(savedMask); log_index = md_pccif_dbg_rx_log_ptr; md_pccif_dbg_rx_log_ptr = (md_pccif_dbg_rx_log_ptr + 1) % MD_PCCIF_DBG_LOG_MAX; CC_IRQ_DRV_RESTORE_ALL_INTERRUPT(savedMask); /* ======== Part 1 - copy buffer ======== */ src_addr = (kal_uint32*)(tmp_chl * MD_PCCIF_CHL_PKT_SIZE + MD_PCCIF_GET_READ_ADDR_BASE(index)); read_ptr = (kal_uint32)src_addr - MD_PCCIF_GET_READ_ADDR_BASE(index); hdr = (md_pccif_pkt_hdr_t*)src_addr++; length = hdr->length; ASSERT(length <= MD_PCCIF_HDR_LEN + CC_IRQ_BUFF_MAX); ASSERT(hdr->type < MD_PCCIF_HDR_TYPE_MAX); ASSERT(hdr->index == index); /* get occupied channel number according to length */ rx_chl_number = (length / MD_PCCIF_CHL_PKT_SIZE) + ((length % MD_PCCIF_CHL_PKT_SIZE)?1:0); length -= MD_PCCIF_HDR_LEN; /* copy buffer */ if (read_ptr + MD_PCCIF_HDR_LEN + length <= PCCIF_BUFFER_SIZE) { CC_IRQ_MEM_CPY((void*)buff, (void*)src_addr, length); read_ptr = read_ptr + length; } /* wrap case */ else { kal_uint32 cpy_len_h, cpy_len_l; cpy_len_h = PCCIF_BUFFER_SIZE - read_ptr - MD_PCCIF_HDR_LEN; cpy_len_l = length - cpy_len_h; CC_IRQ_MEM_CPY((void*)buff, (void*)src_addr, cpy_len_h); CC_IRQ_MEM_CPY((void*)buff + cpy_len_h, (void*)MD_PCCIF_GET_READ_ADDR_BASE(index), cpy_len_l); read_ptr = cpy_len_l; } if (read_ptr & 0xF) read_ptr = (read_ptr & ~0xF) + 0x10; md_pccif_dbg_rx_log[log_index].index = index; md_pccif_dbg_rx_log[log_index].hdr = *(kal_uint32*)hdr; md_pccif_dbg_rx_log[log_index].length = length; md_pccif_dbg_rx_log[log_index].rx_chl = tmp_chl; md_pccif_dbg_rx_log[log_index].ack_chl = (tmp_chl - MD_PCCIF_HW_CHL_START_OFF(index) + rx_chl_number) % MD_PCCIF_HW_CHL_NUMBER_PER_IRQ; kal_mem_cpy(md_pccif_dbg_rx_log[log_index].buff, buff, length); /* is general RX is allowed?? */ if (md_pccif_op_enable == KAL_TRUE) { if (hdr->type == MD_PCCIF_HDR_TYPE_PARA) cc_irq_cb[index](buff[0], buff[1], buff[2]); else cc_irq_cb[index]((kal_uint32)buff, length, 0); /* update md_pccif_rx_chl_ptr */ ASSERT(tmp_chl + MD_PCCIF_HW_CHL_START_OFF(index) >= MD_PCCIF_HW_CHL_START_OFF(index)); md_pccif_rx_chl_ptr[index] = (tmp_chl + rx_chl_number) % MD_PCCIF_HW_CHL_NUMBER_PER_IRQ; } else { if (CC_IRQ_RX_INDEX_OFFSET(CC_IRQ_SYS_RX_INDEX) == index) { cc_irq_cb[index]((kal_uint32)buff, length, 0); } else { /* Only system packet is allowed before handshake */ EXT_ASSERT(0, index, 0, 0); } } /* if general RX is disabllowed, only process init handshake packet. */ /* ACK channel */ ack_mask = 1 << (tmp_chl + MD_PCCIF_HW_CHL_START_OFF(index)); *PCCIF_ACK = ack_mask; /* when a channel is processed, clear the rx mask */ /* if all the channels are processed, break */ chl_rx_mask &= ~(1 << tmp_chl); if (chl_rx_mask == 0) break; } } }