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;
}
Esempio n. 3
0
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;
        }
    }
}