예제 #1
0
파일: tw_cl_misc.c 프로젝트: coyizumi/cs111
/*
 * Function name:	tw_cl_print_ctlr_stats
 * Description:		Prints the current status of the controller.
 *
 * Input:		ctlr_handle-- controller handle
 * Output:		None
 * Return value:	None
 */
TW_VOID
tw_cl_print_ctlr_stats(struct tw_cl_ctlr_handle *ctlr_handle)
{
	struct tw_cli_ctlr_context	*ctlr =
		(struct tw_cli_ctlr_context *)(ctlr_handle->cl_ctlr_ctxt);
	TW_UINT32			status_reg;
	TW_INT8				desc[200];

	tw_cli_dbg_printf(7, ctlr->ctlr_handle, "", "entered");

	/* Print current controller details. */
	tw_cli_dbg_printf(0, ctlr_handle, "", "cl_ctlr_ctxt = %p", ctlr);

	tw_osl_memzero(desc, 200);
	status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr_handle);
	tw_cli_dbg_printf(0, ctlr_handle, "", "status reg = 0x%x %s",
		status_reg, tw_cli_describe_bits(status_reg, desc));

	tw_cli_dbg_printf(0, ctlr_handle, "", "CLq type  current  max");
	tw_cli_dbg_printf(0, ctlr_handle, "", "free      %04d     %04d",
		ctlr->q_stats[TW_CLI_FREE_Q].cur_len,
		ctlr->q_stats[TW_CLI_FREE_Q].max_len);
	tw_cli_dbg_printf(0, ctlr_handle, "", "busy      %04d     %04d",
		ctlr->q_stats[TW_CLI_BUSY_Q].cur_len,
		ctlr->q_stats[TW_CLI_BUSY_Q].max_len);
	tw_cli_dbg_printf(0, ctlr_handle, "", "pending   %04d     %04d",
		ctlr->q_stats[TW_CLI_PENDING_Q].cur_len,
		ctlr->q_stats[TW_CLI_PENDING_Q].max_len);
	tw_cli_dbg_printf(0, ctlr_handle, "", "complete  %04d     %04d",
		ctlr->q_stats[TW_CLI_COMPLETE_Q].cur_len,
		ctlr->q_stats[TW_CLI_COMPLETE_Q].max_len);
	tw_cli_dbg_printf(0, ctlr_handle, "", "AEN queue head %d  tail %d",
			ctlr->aen_head, ctlr->aen_tail);
}	
예제 #2
0
파일: tw_cl_misc.c 프로젝트: coyizumi/cs111
/*
 * Function name:	tw_cli_find_response
 * Description:		Find a particular response in the ctlr response queue.
 *
 * Input:		ctlr	-- ptr to per ctlr structure
 *			req_id	-- request id of the response to look for
 * Output:		None
 * Return value:	0	-- success
 *			non-zero-- failure
 */
TW_INT32
tw_cli_find_response(struct tw_cli_ctlr_context *ctlr, TW_INT32 req_id)
{
	TW_UINT32	resp;
	TW_INT32	resp_id;
	TW_UINT32	status_reg;

	tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");

	for (;;) {
		status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr->ctlr_handle);

		if (status_reg & TWA_STATUS_RESPONSE_QUEUE_EMPTY)
			return(TW_OSL_ENOTTY); /* no more response queue entries */

		if (ctlr->device_id == TW_CL_DEVICE_ID_9K) {
			resp = TW_CLI_READ_RESPONSE_QUEUE(ctlr->ctlr_handle);
			resp_id = GET_RESP_ID(resp);
		} else {
			resp = TW_CLI_READ_LARGE_RESPONSE_QUEUE(
				ctlr->ctlr_handle);
			resp_id = GET_LARGE_RESP_ID(resp);
		}
		if (resp_id == req_id)
			return(TW_OSL_ESUCCESS); /* found the req_id */
	}
}
예제 #3
0
/*
 * Function name:	twa_interrupt
 * Description:		Interrupt handler.  Determines the kind of interrupt,
 *			and returns TW_CL_TRUE if it recognizes the interrupt.
 *
 * Input:		ctlr_handle	-- controller handle
 * Output:		None
 * Return value:	TW_CL_TRUE -- interrupt recognized
 *			TW_CL_FALSE-- interrupt not recognized
 */
TW_INT32
tw_cl_interrupt(struct tw_cl_ctlr_handle *ctlr_handle)
{
	struct tw_cli_ctlr_context	*ctlr =
		(struct tw_cli_ctlr_context *)(ctlr_handle->cl_ctlr_ctxt);
	TW_UINT32			status_reg;
	TW_INT32			rc = TW_CL_FALSE;

	tw_cli_dbg_printf(10, ctlr_handle, tw_osl_cur_func(), "entered");

	/* If we don't have controller context, bail */
	if (ctlr == NULL)
		goto out;

	/*
	 * Bail If we get an interrupt while resetting, or shutting down.
	 */
	if (ctlr->reset_in_progress || !(ctlr->active))
		goto out;

	/* Read the status register to determine the type of interrupt. */
	status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr_handle);
	if (tw_cli_check_ctlr_state(ctlr, status_reg))
		goto out;

	/* Clear the interrupt. */
	if (status_reg & TWA_STATUS_HOST_INTERRUPT) {
		tw_cli_dbg_printf(6, ctlr_handle, tw_osl_cur_func(),
			"Host interrupt");
		TW_CLI_WRITE_CONTROL_REGISTER(ctlr_handle,
			TWA_CONTROL_CLEAR_HOST_INTERRUPT);
	}
	if (status_reg & TWA_STATUS_ATTENTION_INTERRUPT) {
		tw_cli_dbg_printf(6, ctlr_handle, tw_osl_cur_func(),
			"Attention interrupt");
		rc |= TW_CL_TRUE; /* request for a deferred isr call */
		tw_cli_process_attn_intr(ctlr);
		TW_CLI_WRITE_CONTROL_REGISTER(ctlr_handle,
			TWA_CONTROL_CLEAR_ATTENTION_INTERRUPT);
	}
	if (status_reg & TWA_STATUS_COMMAND_INTERRUPT) {
		tw_cli_dbg_printf(6, ctlr_handle, tw_osl_cur_func(),
			"Command interrupt");
		rc |= TW_CL_TRUE; /* request for a deferred isr call */
		tw_cli_process_cmd_intr(ctlr);
		if ((TW_CL_Q_FIRST_ITEM(&(ctlr->req_q_head[TW_CLI_PENDING_Q]))) == TW_CL_NULL)
			TW_CLI_WRITE_CONTROL_REGISTER(ctlr_handle,
				TWA_CONTROL_MASK_COMMAND_INTERRUPT);
	}
	if (status_reg & TWA_STATUS_RESPONSE_INTERRUPT) {
		tw_cli_dbg_printf(10, ctlr_handle, tw_osl_cur_func(),
			"Response interrupt");
		rc |= TW_CL_TRUE; /* request for a deferred isr call */
		tw_cli_process_resp_intr(ctlr);
	}
out:
	return(rc);
}
예제 #4
0
/*
 * Function name:	tw_cli_process_resp_intr
 * Description:		Looks for cmd completions from fw; queues cmds completed
 *			by fw into complete queue.
 *
 * Input:		ctlr	-- ptr to CL internal ctlr context
 * Output:		None
 * Return value:	0	-- no ctlr error
 *			non-zero-- ctlr error
 */
TW_INT32
tw_cli_process_resp_intr(struct tw_cli_ctlr_context *ctlr)
{
	TW_UINT32			resp;
	struct tw_cli_req_context	*req;
	TW_INT32			error;
	TW_UINT32			status_reg;
    
	tw_cli_dbg_printf(10, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");

	for (;;) {
		status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr->ctlr_handle);
		if ((error = tw_cli_check_ctlr_state(ctlr, status_reg)))
			break;
		if (status_reg & TWA_STATUS_RESPONSE_QUEUE_EMPTY) {
			tw_cli_dbg_printf(7, ctlr->ctlr_handle,
				tw_osl_cur_func(), "Response queue empty");
			break;
		}

		/* Response queue is not empty. */
		resp = TW_CLI_READ_RESPONSE_QUEUE(ctlr->ctlr_handle);
		{
			req = &(ctlr->req_ctxt_buf[GET_RESP_ID(resp)]);
		}

		if (req->state != TW_CLI_REQ_STATE_BUSY) {
			tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
				TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
				0x1201, 0x1, TW_CL_SEVERITY_ERROR_STRING,
				"Unposted command completed!!",
				"request = %p, status = %d",
				req, req->state);
#ifdef TW_OSL_DEBUG
			tw_cl_print_ctlr_stats(ctlr->ctlr_handle);
#endif /* TW_OSL_DEBUG */
			tw_cl_reset_ctlr(ctlr->ctlr_handle);
			return(TW_OSL_EIO);
		}

		/*
		 * Remove the request from the busy queue, mark it as complete,
		 * and enqueue it in the complete queue.
		 */
		tw_cli_req_q_remove_item(req, TW_CLI_BUSY_Q);
		req->state = TW_CLI_REQ_STATE_COMPLETE;
		tw_cli_req_q_insert_tail(req, TW_CLI_COMPLETE_Q);

	}

	/* Complete this, and other requests in the complete queue. */
	tw_cli_process_complete_queue(ctlr);
	
	return(error);
}
예제 #5
0
파일: tw_cl_misc.c 프로젝트: coyizumi/cs111
/*
 * Function name:	tw_cli_drain_response_queue
 * Description:		Drain the controller response queue.
 *
 * Input:		ctlr	-- ptr to per ctlr structure
 * Output:		None
 * Return value:	0	-- success
 *			non-zero-- failure
 */
TW_INT32
tw_cli_drain_response_queue(struct tw_cli_ctlr_context *ctlr)
{
	TW_UINT32	resp;
	TW_UINT32	status_reg;

	tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");

	for (;;) {
		status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr->ctlr_handle);

		if (status_reg & TWA_STATUS_RESPONSE_QUEUE_EMPTY)
			return(TW_OSL_ESUCCESS); /* no more response queue entries */

		resp = TW_CLI_READ_RESPONSE_QUEUE(ctlr->ctlr_handle);
	}
}
예제 #6
0
파일: tw_cl_misc.c 프로젝트: coyizumi/cs111
/*
 * Function name:	tw_cli_poll_status
 * Description:		Poll for a given status to show up in the firmware
 *			status register.
 *
 * Input:		ctlr	-- ptr to CL internal ctlr context
 *			status	-- status to look for
 *			timeout -- max # of seconds to wait before giving up
 * Output:		None
 * Return value:	0	-- success
 *			non-zero-- failure
 */
TW_INT32
tw_cli_poll_status(struct tw_cli_ctlr_context *ctlr, TW_UINT32 status,
	TW_UINT32 timeout)
{
	TW_TIME		end_time;
	TW_UINT32	status_reg;

	tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");

	end_time = tw_osl_get_local_time() + timeout;
	do {
		status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr->ctlr_handle);
		if ((status_reg & status) == status)
			/* got the required bit(s) */
			return(TW_OSL_ESUCCESS);

		tw_osl_delay(1000);
	} while (tw_osl_get_local_time() <= end_time);

	return(TW_OSL_ETIMEDOUT);
}
예제 #7
0
파일: tw_cl_io.c 프로젝트: coyizumi/cs111
/*
 * Function name:	tw_cli_submit_cmd
 * Description:		Submits a cmd to firmware.
 *
 * Input:		req	-- ptr to CL internal request context
 * Output:		None
 * Return value:	0	-- success
 *			non-zero-- failure
 */
TW_INT32
tw_cli_submit_cmd(struct tw_cli_req_context *req)
{
	struct tw_cli_ctlr_context	*ctlr = req->ctlr;
	struct tw_cl_ctlr_handle	*ctlr_handle = ctlr->ctlr_handle;
	TW_UINT32			status_reg;
	TW_INT32			error = 0;

	tw_cli_dbg_printf(10, ctlr_handle, tw_osl_cur_func(), "entered");

	/* Serialize access to the controller cmd queue. */
	tw_osl_get_lock(ctlr_handle, ctlr->io_lock);

	/* For 9650SE first write low 4 bytes */
	if ((ctlr->device_id == TW_CL_DEVICE_ID_9K_E) ||
	    (ctlr->device_id == TW_CL_DEVICE_ID_9K_SA))
		tw_osl_write_reg(ctlr_handle,
				 TWA_COMMAND_QUEUE_OFFSET_LOW,
				 (TW_UINT32)(req->cmd_pkt_phys + sizeof(struct tw_cl_command_header)), 4);

	status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr_handle);
	if (status_reg & TWA_STATUS_COMMAND_QUEUE_FULL) {
		struct tw_cl_req_packet	*req_pkt =
			(struct tw_cl_req_packet *)(req->orig_req);

		tw_cli_dbg_printf(7, ctlr_handle, tw_osl_cur_func(),
			"Cmd queue full");

		if ((req->flags & TW_CLI_REQ_FLAGS_INTERNAL)
			|| ((req_pkt) &&
			(req_pkt->flags & TW_CL_REQ_RETRY_ON_BUSY))
			) {
			if (req->state != TW_CLI_REQ_STATE_PENDING) {
				tw_cli_dbg_printf(2, ctlr_handle,
					tw_osl_cur_func(),
					"pending internal/ioctl request");
				req->state = TW_CLI_REQ_STATE_PENDING;
				tw_cli_req_q_insert_tail(req, TW_CLI_PENDING_Q);
				/* Unmask command interrupt. */
				TW_CLI_WRITE_CONTROL_REGISTER(ctlr_handle,
					TWA_CONTROL_UNMASK_COMMAND_INTERRUPT);
			} else
				error = TW_OSL_EBUSY;
		} else {
			error = TW_OSL_EBUSY;
		}
	} else {
		tw_cli_dbg_printf(10, ctlr_handle, tw_osl_cur_func(),
			"Submitting command");

		/* Insert command into busy queue */
		req->state = TW_CLI_REQ_STATE_BUSY;
		tw_cli_req_q_insert_tail(req, TW_CLI_BUSY_Q);

		if ((ctlr->device_id == TW_CL_DEVICE_ID_9K_E) ||
		    (ctlr->device_id == TW_CL_DEVICE_ID_9K_SA)) {
			/* Now write the high 4 bytes */
			tw_osl_write_reg(ctlr_handle, 
					 TWA_COMMAND_QUEUE_OFFSET_HIGH,
					 (TW_UINT32)(((TW_UINT64)(req->cmd_pkt_phys + sizeof(struct tw_cl_command_header)))>>32), 4);
		} else {
			if (ctlr->flags & TW_CL_64BIT_ADDRESSES) {