#include #include #include "cli.h" #include "shell_drv.h" #include #if CONFIG_CACHE_ENABLE #include "cache.h" #endif typedef struct { u8 chnl_id; u8 cpu_id; shell_ipc_rx_t rx_callback; shell_ipc_tx_complete_t tx_cmpl_callback; } shell_ipc_ext_t; static bool_t shell_ipc_init(shell_dev_ipc_t * dev_ipc); static bool_t shell_ipc_open(shell_dev_ipc_t * dev_ipc, shell_ipc_rx_t rx_callback, shell_ipc_tx_complete_t tx_complete); static u16 shell_ipc_read(shell_dev_ipc_t * dev_ipc, u8 * pBuf, u16 BufLen); static u16 shell_ipc_write_cmd(shell_dev_ipc_t * dev_ipc, mb_chnl_cmd_t * cmd_buf); static bool_t shell_ipc_ctrl(shell_dev_ipc_t * dev_ipc, u8 cmd, void *param); static bool_t shell_ipc_close(shell_dev_ipc_t * dev_ipc); static const shell_ipc_drv_t shell_ipc_drv = { .init = shell_ipc_init, .open = shell_ipc_open, .read = shell_ipc_read, .write_cmd = shell_ipc_write_cmd, .io_ctrl = shell_ipc_ctrl, .close = shell_ipc_close }; static shell_ipc_ext_t dev_ipc_ext = { .chnl_id = MB_CHNL_LOG, .cpu_id = MAILBOX_CPU1 }; shell_dev_ipc_t shell_dev_ipc = { .dev_drv = (struct _shell_ipc_drv *)&shell_ipc_drv, .dev_type = SHELL_DEV_MAILBOX, .dev_ext = &dev_ipc_ext }; #if CONFIG_AT static shell_ipc_ext_t atsvr_dev_ipc_ext = { .chnl_id = MB_CHNL_AT, .cpu_id = MAILBOX_CPU1 }; shell_dev_ipc_t atsvr_shell_dev_ipc = { .dev_drv = (struct _shell_ipc_drv *)&shell_ipc_drv, .dev_type = SHELL_DEV_MAILBOX, .dev_ext = &atsvr_dev_ipc_ext }; #endif /* =============================== internal functions =========================== */ static void shell_ipc_rx_isr(shell_ipc_ext_t *ipc_ext, mb_chnl_cmd_t *cmd_buf) { u32 result = ACK_STATE_FAIL; if(cmd_buf->hdr.cmd == MB_CMD_LOG_OUT) { if(ipc_ext->rx_callback != NULL) { log_cmd_t * log_cmd = (log_cmd_t *)cmd_buf; #if CONFIG_CACHE_ENABLE flush_dcache((void *)log_cmd->buf, log_cmd->len); #endif result = ipc_ext->rx_callback(log_cmd->hdr.cmd, log_cmd, ipc_ext->cpu_id); } } else if (cmd_buf->hdr.cmd == MB_CMD_ASSERT_OUT) { if(ipc_ext->rx_callback != NULL) { log_cmd_t * log_cmd = (log_cmd_t *)cmd_buf; #if CONFIG_CACHE_ENABLE flush_dcache((void *)log_cmd->buf, log_cmd->len); #endif log_cmd_t new_log_cmd_buf; new_log_cmd_buf.hdr.data = log_cmd->hdr.data; new_log_cmd_buf.buf = log_cmd->buf + 1; new_log_cmd_buf.len = log_cmd->len - 1; new_log_cmd_buf.tag = log_cmd->tag; result = ipc_ext->rx_callback(log_cmd->hdr.cmd, &new_log_cmd_buf, ipc_ext->cpu_id); /* assert_out must be handled in synchrously, so the buffer is free when return. */ log_cmd->buf[0] = 0; /* notify the sender that buffer can be freed now. */ } } else /* unknown cmd. */ { result = ACK_STATE_FAIL; } /* overwrite the cmd_buf->param3 after the ISR handle complete. * return the ack info to caller using the SAME buffer with cmd buffer. * !!!! [input as param / outpu as result ] !!!! */ mb_chnl_ack_t * ack_buf = (mb_chnl_ack_t *)cmd_buf; ack_buf->ack_state = result; return; } static void shell_ipc_tx_cmpl_isr(shell_ipc_ext_t *ipc_ext, mb_chnl_ack_t *ack_buf) { if (ipc_ext->tx_cmpl_callback != NULL) { ipc_ext->tx_cmpl_callback(ack_buf->hdr.cmd); } } /* =============================== shell ipc driver APIs =========================== */ static bool_t shell_ipc_init(shell_dev_ipc_t * dev_ipc) { u8 dev_id, cpu_id; shell_ipc_ext_t *ipc_ext; if(dev_ipc == NULL) return bFALSE; ipc_ext = (shell_ipc_ext_t *)dev_ipc->dev_ext; dev_id = ipc_ext->chnl_id; cpu_id = ipc_ext->cpu_id; memset(ipc_ext, 0, sizeof(shell_ipc_ext_t)); ipc_ext->chnl_id = dev_id; ipc_ext->cpu_id = cpu_id; return bTRUE; } static bool_t shell_ipc_open(shell_dev_ipc_t * dev_ipc, shell_ipc_rx_t rx_callback, shell_ipc_tx_complete_t tx_complete) { shell_ipc_ext_t *ipc_ext; if(dev_ipc == NULL) return bFALSE; ipc_ext = (shell_ipc_ext_t *)dev_ipc->dev_ext; ipc_ext->rx_callback = rx_callback; ipc_ext->tx_cmpl_callback = tx_complete; bk_err_t ret_code = mb_chnl_open(ipc_ext->chnl_id, ipc_ext); if(ret_code != BK_OK) return bFALSE; // call chnl driver to register isr callback; mb_chnl_ctrl(ipc_ext->chnl_id, MB_CHNL_SET_RX_ISR, (void *)shell_ipc_rx_isr); mb_chnl_ctrl(ipc_ext->chnl_id, MB_CHNL_SET_TX_CMPL_ISR, (void *)shell_ipc_tx_cmpl_isr); return bTRUE; } static u16 shell_ipc_read(shell_dev_ipc_t * dev_ipc, u8 * pBuf, u16 BufLen) { return 0; } /* call this after interrupt is DISABLED. */ static u16 shell_ipc_write_cmd(shell_dev_ipc_t * dev_ipc, mb_chnl_cmd_t * cmd_buf) { shell_ipc_ext_t *ipc_ext; ipc_ext = (shell_ipc_ext_t *)dev_ipc->dev_ext; bk_err_t ret_code; ret_code = mb_chnl_write(ipc_ext->chnl_id, cmd_buf); if(ret_code == BK_OK) { return 1; } return 0; } static bool_t shell_ipc_ctrl(shell_dev_ipc_t * dev_ipc, u8 cmd, void *param) { if(dev_ipc == NULL) return bFALSE; switch(cmd) { /* case SHELL_IPC_SET_RX_CALLBACK: ipc_ext->rx_callback = (shell_ipc_rx_t)param; break; */ default: return bFALSE; break; } return bTRUE; } static bool_t shell_ipc_close(shell_dev_ipc_t * dev_ipc) { shell_ipc_ext_t *ipc_ext; if(dev_ipc == NULL) return bFALSE; ipc_ext = (shell_ipc_ext_t *)dev_ipc->dev_ext; // call chnl driver to register isr callback; mb_chnl_ctrl(ipc_ext->chnl_id, MB_CHNL_SET_RX_ISR, NULL); mb_chnl_ctrl(ipc_ext->chnl_id, MB_CHNL_SET_TX_ISR, NULL); mb_chnl_ctrl(ipc_ext->chnl_id, MB_CHNL_SET_TX_CMPL_ISR, NULL); mb_chnl_close(ipc_ext->chnl_id); ipc_ext->rx_callback = NULL; return bTRUE; }