Exemple #1
0
/*
 * Check if the provided PDU size is compatible with the
 * channel PDU size
 *
 *  Return the response to send ACK/NACK
 */
static int dlp_ctrl_check_pdu_size(struct dlp_channel *ch_ctx,
					struct dlp_command_params *params,
					struct dlp_command_params *tx_params)
{
	int size, response;

	memcpy(tx_params, params, sizeof(struct dlp_command_params));

	size = ((params->data2 << 8) | params->data1);

	/* OPEN_CONN => ACK by default */
	response = DLP_CMD_ACK;
	tx_params->data3 = CMD_ID(params->data3, params->id);

	/* Check the requested PDU size */
	if (ch_ctx->rx.pdu_size != size) {
		pr_err(DRVNAME ": ch%d wrong pdu size %d (expected %d)\n",
				ch_ctx->hsi_channel,
				size,
				ch_ctx->rx.pdu_size);

		/* OPEN_CONN => NACK (Unexpected PDU size) */
		response = DLP_CMD_NACK;

		/* Set the response params */
		tx_params->data1 = 0;
		tx_params->data2 = 0;
		tx_params->data3 = CMD_ID_ERR(params,
				EDLP_ERR_WRONG_PDU_SIZE);
	}

	return response;
}
Exemple #2
0
/* ARGSUSED */
static int
op_sort(cmd_t *cmd, boolean_t smpl)
{
	page_t *cur;
	int cmd_id;

	if ((cur = page_current_get()) != NULL) {
		cmd_id = CMD_ID(cmd);
		sortkey_set(cmd_id, cur);
		(void) op_refresh(cmd, B_FALSE);
	}

	return (0);
}
Exemple #3
0
/*
 * The common entry for processing command.
 */
static void
cmd_received(cmd_t *cmd, boolean_t *quit, struct timespec *timeout)
{
	boolean_t badcmd, execute;
	int cmd_id = CMD_ID(cmd);

	execute = B_TRUE;
	*quit = B_FALSE;

	switch (cmd_id) {
	case CMD_QUIT_ID:
		*quit = B_TRUE;
		return;

	case CMD_RESIZE_ID:
		/*
		 * The screen resize signal would trigger this
		 * command. Destroy existing screen and curses
		 * resources and then re-init the curses resources.
		 */
		win_fix_fini();
		page_win_destroy();
		reg_curses_fini();
		if (reg_curses_init(B_FALSE)) {
			win_fix_init();
		} else {
			execute = B_FALSE;
		}

		timeout_set(timeout, DISP_DEFAULT_INTVAL);
		break;

	case CMD_REFRESH_ID:
		/*
		 * User hit the hotkey 'R' to refresh current window.
		 */
		timeout_set(timeout, DISP_DEFAULT_INTVAL);
		break;
	}

	if (execute) {
		cmd_execute(cmd, &badcmd);
	}
}
Exemple #4
0
int
os_op_callchain_count(cmd_t *cmd, boolean_t smpl)
{
	page_t *cur;
	count_id_t countid;
	int cmd_id;

	if ((cur = page_current_get()) != NULL) {
		cmd_id = CMD_ID(cmd);
		if ((countid = callchain_countid_set(cmd_id, cur)) == COUNT_INVALID) {
			return (0);	
		}

		perf_profiling_partpause(countid);
		op_refresh(cmd, smpl);
	}

	return (0);
}
Exemple #5
0
bool retrace_frame(uint64_t* num_cmds)
{
    *num_cmds = 0;

    while (1) {
        char id = trace_read_id();

        switch (id) {
            case TRACE_EOF:
                return false;

            case TRACE_CMD: {
                uint32_t cmd[CMD_MAX_INTS];
                uint32_t length;
                trace_read_cmd(cmd, &length);

                rdp_cmd(cmd, length);
                (*num_cmds)++;

                if (CMD_ID(cmd) == CMD_ID_SYNC_FULL) {
                    return true;
                }

                break;
            }

            case TRACE_RDRAM:
                trace_read_rdram();
                break;

            case TRACE_VI:
                trace_read_vi(plugin_get_vi_registers());
                vi_update();
                break;
        }
    }
}
Exemple #6
0
/*
 * The common entry to process all commands.
 */
void
cmd_execute(cmd_t *cmd, boolean_t *badcmd)
{
	cmd_id_t cmd_id;
	win_type_t type;
	page_t *cur;
	switch_t *s;
	boolean_t b = B_TRUE, smpl = B_FALSE;

	if ((cmd_id = CMD_ID(cmd)) == CMD_INVALID_ID) {
		goto L_EXIT;
	}

	b = B_FALSE;

	if ((cur = page_current_get()) == NULL) {
		/* It's the first window. */
		type = WIN_TYPE_RAW_NUM;
	} else {
		type = PAGE_WIN_TYPE(cur);
	}

	s = &s_switch[type][cmd_id];
	if (s->preop != NULL) {
		(void) s->preop(cmd, &smpl);
	}

	if (s->op != NULL) {
		(void) s->op(cmd, smpl);
	}

L_EXIT:
	if (badcmd != NULL) {
		*badcmd = b;
	}
}
Exemple #7
0
/**
 * Send an HSI msg AND wait for the status
 *
 * @ch_ctx: a reference to the channel context to use
 * @id: the DLP command id
 * @response_id: the expected response id
 * @interm_state: the intermidiate state (to be set when TX is OK)
 * @final_state: the final state (to be set when RX (response) is OK)
 * @param1: the DLP command params
 * @param2: the DLP command params
 * @param3: the DLP command params
 *
 * This function blocks the caller until a response is received
 * or the timeout expires
 */
static int dlp_ctrl_cmd_send(struct dlp_channel *ch_ctx,
				unsigned char id,
				unsigned char response_id,
				unsigned char interm_state,
				unsigned char final_state,
				unsigned char param1,
				unsigned char param2, unsigned char param3)
{
	int ret = 0, old_state;
	struct dlp_ctrl_context *ctrl_ctx;
	struct dlp_command *dlp_cmd;
	struct dlp_command_params expected_resp;
	struct hsi_msg *tx_msg = NULL;

	/* Check the link readiness (TTY still opened) */
	if (!dlp_tty_is_link_valid()) {
		if (EDLP_CTRL_TX_DATA_REPORT)
			pr_debug(DRVNAME ": CH%d (HSI CH%d) cmd 0x%X ignored (close:%d, Time out: %d)\n",
					ch_ctx->ch_id, ch_ctx->hsi_channel,
					id, dlp_drv.tty_closed,
					dlp_drv.tx_timeout);

		return ret;
	}

	ctrl_ctx = DLP_CTRL_CTX;

	mutex_lock(&ch_ctx->tx.cmd_sync);

	/* Save the current channel state */
	old_state = dlp_ctrl_get_channel_state(ch_ctx->hsi_channel);

	/* Backup RX callback */
	dlp_save_rx_callbacks(&ctrl_ctx->ehandler);

	/* Allocate the DLP command */
	dlp_cmd = dlp_ctrl_cmd_alloc(ch_ctx, id, param1, param2, param3);
	if (!dlp_cmd) {
		pr_err(DRVNAME ": Out of memory (dlp_cmd: 0x%X)\n", id);
		ret = -ENOMEM;
		goto out;
	}

	/* Allocate a new TX msg */
	tx_msg = dlp_pdu_alloc(DLP_CHANNEL_CTRL,
			       HSI_MSG_WRITE,
			       DLP_CTRL_TX_PDU_SIZE,
			       1,
			       dlp_cmd,
			       dlp_ctrl_complete_tx, dlp_ctrl_msg_destruct);

	if (!tx_msg) {
		pr_err(DRVNAME ": dlp_pdu_alloc(TX) failed\n");
		ret = -ENOMEM;
		goto free_cmd;
	}

	/* Copy the command data */
	memcpy(sg_virt(tx_msg->sgt.sgl),
	       &dlp_cmd->params, sizeof(struct dlp_command_params));

	/* Send the TX HSI msg */
	ret = hsi_async(tx_msg->cl, tx_msg);
	if (ret) {
		pr_err(DRVNAME ": Unable to send 0x%X cmd (ret:%d)\n",
			dlp_cmd->params.id, ret);

		/* Free the TX msg */
		dlp_pdu_free(tx_msg, tx_msg->channel);

		goto free_cmd;
	}

	/* Dump the TX command */
	if (EDLP_CTRL_TX_DATA_REPORT)
		pr_debug(DRVNAME ": CTRL_TX (0x%X)\n",
				*((u32 *)&dlp_cmd->params));

	/* Wait for TX msg to be sent */
	ret = wait_for_completion_timeout(&ch_ctx->tx.cmd_xfer_done,
					  msecs_to_jiffies(DLP_CMD_TX_TIMOUT));
	if (ret == 0) {
		pr_err(DRVNAME ": hsi_ch:%d, cmd:0x%X => TX timeout\n",
			dlp_cmd->params.channel, dlp_cmd->params.id);

		/* No need to call the complete sending call back,
		 * because of failure */
		tx_msg->complete = NULL;
		tx_msg->context = NULL;
		ret = -EIO;
		/* free only the cmd, because
		 * the message is already in the controller fifo.
		 * It will be freed when the controller fifo will be
		 * flushed/freed
		 */
		goto free_cmd;
	}

	/* TX msg sent, check the status */
	if (dlp_cmd->status) {
		pr_err(DRVNAME ": Failed to send cmd:0x%X\n",
				dlp_cmd->params.id);

		ret = -EIO;
		/* free only the command because
		 * the message has been already freed by the complete_tx
		 * callback
		 */
		goto free_cmd;
	}

	/* TX OK */
	/* 1. Set the intermidiate channel state */
	if (interm_state != DLP_CH_STATE_NONE)
		dlp_ctrl_set_channel_state(ch_ctx->hsi_channel, interm_state);

	/* Wait for response ? */
	if (response_id == DLP_CMD_NONE) {
		ret = 0;
		goto no_resp;
	}

	/* 2. Wait for the response */
	ret = wait_for_completion_timeout(&ch_ctx->rx.cmd_xfer_done,
					  msecs_to_jiffies(DLP_CMD_RX_TIMOUT));
	if (ret == 0) {
		pr_err(DRVNAME ": hsi_ch:%d, cmd:0x%X => RX timeout\n",
			dlp_cmd->params.channel, dlp_cmd->params.id);

		ret = -EIO;
		goto free_cmd;
	}

	/* Set the expected response params */
	expected_resp.id = response_id;
	expected_resp.channel = ch_ctx->hsi_channel;

	switch (id) {
	case DLP_CMD_CLOSE_CONN:
		expected_resp.data1 = param3;
		expected_resp.data2 = param2;
		expected_resp.data3 = CMD_ID(param1, id);
		break;

	case DLP_CMD_OPEN_CONN:
	default:
		expected_resp.data1 = param1;
		expected_resp.data2 = param2;
		expected_resp.data3 = CMD_ID(param3, id);
	}

	/* Check the received response params */
	ret = 0;
	if (memcmp(&ctrl_ctx->response.params,
				&expected_resp,
				sizeof(expected_resp))) {
		pr_err(DRVNAME": cmd 0x%X unexpected response 0x%X (expected 0x%X)",
			id,
			(unsigned int)(*(u32 *)&ctrl_ctx->response.params),
			(unsigned int)(*(u32 *)(&expected_resp)));

		tx_msg->context = NULL;
		ret = -EIO;
		goto free_cmd;
	}

no_resp:
	/* Response received & OK => set the new channel state */
	if (final_state != DLP_CH_STATE_NONE)
		dlp_ctrl_set_channel_state(ch_ctx->hsi_channel, final_state);

free_cmd:
	/* Free the DLP command */
	dlp_ctrl_cmd_free(dlp_cmd);

out:
	/* Restore RX callback */
	dlp_restore_rx_callbacks(&ctrl_ctx->ehandler);

	/* Restore the channel state in error case */
	if (ret)
		dlp_ctrl_set_channel_state(ch_ctx->hsi_channel, old_state);

	mutex_unlock(&ch_ctx->tx.cmd_sync);

	return ret;
}
Exemple #8
0
static void dlp_ctrl_complete_rx(struct hsi_msg *msg)
{
	struct dlp_channel *ch_ctx;
	struct dlp_ctrl_context *ctrl_ctx;
	struct dlp_command *dlp_cmd = msg->context;
	struct dlp_command_params params, tx_params;
	unsigned long flags;
	int hsi_channel, elp_channel, ret, response, msg_complete, state;

	params.channel = 0; /* To please KlocWork */

	/* Check the link readiness (TTY still opened) */
	if (!dlp_tty_is_link_valid()) {
		if (EDLP_CTRL_RX_DATA_REPORT)
			pr_debug(DRVNAME ": CTRL: CH%d RX PDU ignored (close:%d, Time out: %d)\n",
				params.channel,
				dlp_drv.tty_closed, dlp_drv.tx_timeout);
		/* Delete the received msg */
		dlp_pdu_free(msg, msg->channel);

		/* Delete the command */
		dlp_ctrl_cmd_free(dlp_cmd);
		return;
	}

	/* Copy the reponse */
	memcpy(&params,
			sg_virt(msg->sgt.sgl),
			sizeof(struct dlp_command_params));

	ctrl_ctx = DLP_CTRL_CTX;
	response = -1;
	memcpy(&tx_params, &params, sizeof(struct dlp_command_params));
	msg_complete = (msg->status == HSI_STATUS_COMPLETED);

	/* Dump the RX command */
	if (EDLP_CTRL_RX_DATA_REPORT)
		pr_debug(DRVNAME ": CTRL_RX (0x%X)\n", *((u32 *)&params));

	hsi_channel = params.channel;
	if ((hsi_channel < 0) || (hsi_channel >= DLP_CHANNEL_COUNT)) {
		pr_err(DRVNAME ": Invalid HSI channel id (%d)\n", hsi_channel);
		goto push_rx;
	}

	elp_channel = dlp_drv.channels_hsi[hsi_channel].edlp_channel;
	ch_ctx = DLP_CHANNEL_CTX(elp_channel);
	switch (params.id) {
	case DLP_CMD_NOP:
		break;

	case DLP_CMD_CREDITS:
		if (!msg_complete)
			break;

		/* Increase the CREDITS counter */
		spin_lock_irqsave(&ch_ctx->lock, flags);
		ch_ctx->credits += params.data3;
		ret = ch_ctx->credits;
		spin_unlock_irqrestore(&ch_ctx->lock, flags);

		/* Credits available ==> Notify the channel */
		if (ch_ctx->credits_available_cb)
			ch_ctx->credits_available_cb(ch_ctx);

		/* CREDITS => ACK */
		response = DLP_CMD_ACK;

		/* Set the response params */
		tx_params.data1 = params.data3;
		tx_params.data2 = 0;
		tx_params.data3 = 0;
		break;

	case DLP_CMD_OPEN_CONN:
		if (!msg_complete)
			break;

		/* Ready ? if not, just save the OPEN_CONN request params */
		spin_lock_irqsave(&ctrl_ctx->open_lock, flags);
		state = dlp_ctrl_get_channel_state(hsi_channel);
		if ((state != DLP_CH_STATE_OPENING) && (state != DLP_CH_STATE_OPENED)) {
			struct dlp_hsi_channel *hsi_ch;

			hsi_ch = &dlp_drv.channels_hsi[hsi_channel];
			memcpy(&hsi_ch->open_conn, &params, sizeof(params));
			spin_unlock_irqrestore(&ctrl_ctx->open_lock, flags);

			response = -1;

			pr_debug(DRVNAME ": HSI CH%d OPEN_CONN received (postponed) when state is %d\n",
					params.channel, state);
			goto push_rx;
		} else
			spin_unlock_irqrestore(&ctrl_ctx->open_lock, flags);

		pr_debug(DRVNAME ": HSI CH%d OPEN_CONN received (size: %d)\n",
					params.channel,
					(params.data2 << 8) | params.data1);

		/* Check the PDU size */
		response = dlp_ctrl_check_pdu_size(ch_ctx, &params, &tx_params);
		break;

	case DLP_CMD_CLOSE_CONN:
		/* CLOSE_CONN => ACK */
		response = DLP_CMD_ACK;

		/* Set the response params */
		tx_params.data1 = params.data3;
		tx_params.data2 = 0;
		tx_params.data3 = CMD_ID(params.data3, params.id);
		pr_debug(DRVNAME ": ch%d close_conn received\n",
				params.channel);
		break;

	default:
		/* Save the modem response */
		ctrl_ctx->response.status = (msg_complete ? 0 : -EIO);

		memcpy(&ctrl_ctx->response.params,
		       &params, sizeof(struct dlp_command_params));

		/* Command done, notify the sender */
		complete(&ch_ctx->rx.cmd_xfer_done);
		break;
	}

	/* Any response to send ? */
	if (response == -1)
		goto push_rx;

	dlp_ctrl_send_response(ch_ctx, &tx_params, response);

push_rx:
	/* Push the RX msg again for futur response */
	ret = hsi_async(msg->cl, msg);
	if (ret) {
		pr_err(DRVNAME ": RX push failed, ret:%d\n", ret);

		/* We have A BIG PROBLEM if the RX msg cant be  */
		/* pushed again in the controller ==>           */
		/* No response could be received (FIFO empty)   */

		/* Delete the received msg */
		dlp_pdu_free(msg, msg->channel);

		/* Delete the command */
		dlp_ctrl_cmd_free(dlp_cmd);
	}
}
Exemple #9
0
void rdp_update(void)
{
    uint32_t** dp_reg = plugin_get_dp_registers();
    uint32_t dp_current_al = (*dp_reg[DP_CURRENT] & ~7) >> 2;
    uint32_t dp_end_al = (*dp_reg[DP_END] & ~7) >> 2;

    // don't do anything if the RDP has crashed or the registers are not set up correctly
    if (rdp_pipeline_crashed || dp_end_al <= dp_current_al) {
        return;
    }

    // while there's data in the command buffer...
    while (dp_end_al - dp_current_al > 0) {
        uint32_t i, toload;
        bool xbus_dma = (*dp_reg[DP_STATUS] & DP_STATUS_XBUS_DMA) != 0;
        uint32_t* dmem = (uint32_t*)plugin_get_dmem();
        uint32_t* cmd_buf = rdp_cmd_buf[rdp_cmd_buf_pos];

        // when reading the first int, extract the command ID and update the buffer length
        if (rdp_cmd_pos == 0) {
            if (xbus_dma) {
                cmd_buf[rdp_cmd_pos++] = dmem[dp_current_al++ & 0x3ff];
            } else {
                cmd_buf[rdp_cmd_pos++] = rdram_read_idx32(dp_current_al++);
            }

            rdp_cmd_id = CMD_ID(cmd_buf);
            rdp_cmd_len = rdp_commands[rdp_cmd_id].length >> 2;
        }

        // copy more data from the N64 to the local command buffer
        toload = MIN(dp_end_al - dp_current_al, rdp_cmd_len - 1);

        if (xbus_dma) {
            for (i = 0; i < toload; i++) {
                cmd_buf[rdp_cmd_pos++] = dmem[dp_current_al++ & 0x3ff];
            }
        } else {
            for (i = 0; i < toload; i++) {
                cmd_buf[rdp_cmd_pos++] = rdram_read_idx32(dp_current_al++);
            }
        }

        // if there's enough data for the current command...
        if (rdp_cmd_pos == rdp_cmd_len) {
            // check if parallel processing is enabled
            if (config.parallel) {
                // special case: sync_full always needs to be run in main thread
                if (rdp_cmd_id == CMD_ID_SYNC_FULL) {
                    // first, run all pending commands
                    cmd_flush();

                    // parameters are unused, so NULL is fine
                    rdp_sync_full(NULL, NULL);
                } else {
                    // increment buffer position
                    rdp_cmd_buf_pos++;

                    // flush buffer when it is full or when the current command requires a sync
                    if (rdp_cmd_buf_pos >= CMD_BUFFER_SIZE || rdp_commands[rdp_cmd_id].sync) {
                        cmd_flush();
                    }
                }
            } else {
                // run command directly
                cmd_run(&rdp_states[0], cmd_buf);
            }

            // reset current command buffer to prepare for the next one
            cmd_init();
        }
    }

    // update DP registers to indicate that all bytes have been read
    *dp_reg[DP_START] = *dp_reg[DP_CURRENT] = *dp_reg[DP_END];
}
Exemple #10
0
static void cmd_run(struct rdp_state* rdp, const uint32_t* arg)
{
    uint32_t cmd_id = CMD_ID(arg);
    rdp_commands[cmd_id].handler(rdp, arg);
}