Example #1
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);
}
Example #2
0
/*
 * Function name:	tw_cl_start_io
 * Description:		Interface to OS Layer for accepting SCSI requests.
 *
 * Input:		ctlr_handle	-- controller handle
 *			req_pkt		-- OSL built request packet
 *			req_handle	-- request handle
 * Output:		None
 * Return value:	0	-- success
 *			non-zero-- failure
 */
TW_INT32
tw_cl_start_io(struct tw_cl_ctlr_handle *ctlr_handle,
	struct tw_cl_req_packet *req_pkt, struct tw_cl_req_handle *req_handle)
{
	struct tw_cli_ctlr_context		*ctlr;
	struct tw_cli_req_context		*req;
	struct tw_cl_command_9k			*cmd;
	struct tw_cl_scsi_req_packet		*scsi_req;
	TW_INT32				error = TW_CL_ERR_REQ_SUCCESS;

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

	ctlr = (struct tw_cli_ctlr_context *)(ctlr_handle->cl_ctlr_ctxt);

	/*
	 * If working with a firmware version that does not support multiple
	 * luns, and this request is directed at a non-zero lun, error it
	 * back right away.
	 */
	if ((req_pkt->gen_req_pkt.scsi_req.lun) &&
		(ctlr->working_srl < TWA_MULTI_LUN_FW_SRL)) {
		req_pkt->status |= (TW_CL_ERR_REQ_INVALID_LUN |
			TW_CL_ERR_REQ_SCSI_ERROR);
		req_pkt->tw_osl_callback(req_handle);
		return(TW_CL_ERR_REQ_SUCCESS);
	}

	if ((req = tw_cli_get_request(ctlr
		)) == TW_CL_NULL) {
		tw_cli_dbg_printf(2, ctlr_handle, tw_osl_cur_func(),
			"Out of request context packets: returning busy");
		return(TW_OSL_EBUSY);
	}

	req_handle->cl_req_ctxt = req;
	req->req_handle = req_handle;
	req->orig_req = req_pkt;
	req->tw_cli_callback = tw_cli_complete_io;

	req->flags |= TW_CLI_REQ_FLAGS_EXTERNAL;
	req->flags |= TW_CLI_REQ_FLAGS_9K;

	scsi_req = &(req_pkt->gen_req_pkt.scsi_req);

	/* Build the cmd pkt. */
	cmd = &(req->cmd_pkt->command.cmd_pkt_9k);

	req->cmd_pkt->cmd_hdr.header_desc.size_header = 128;

	cmd->res__opcode = BUILD_RES__OPCODE(0, TWA_FW_CMD_EXECUTE_SCSI);
	cmd->unit = (TW_UINT8)(scsi_req->unit);
	cmd->lun_l4__req_id = TW_CL_SWAP16(
		BUILD_LUN_L4__REQ_ID(scsi_req->lun, req->request_id));
	cmd->status = 0;
	cmd->sgl_offset = 16; /* offset from end of hdr = max cdb len */
	tw_osl_memcpy(cmd->cdb, scsi_req->cdb, scsi_req->cdb_len);

	if (req_pkt->flags & TW_CL_REQ_CALLBACK_FOR_SGLIST) {
		TW_UINT32	num_sgl_entries;

		req_pkt->tw_osl_sgl_callback(req_handle, cmd->sg_list,
			&num_sgl_entries);
		cmd->lun_h4__sgl_entries =
			TW_CL_SWAP16(BUILD_LUN_H4__SGL_ENTRIES(scsi_req->lun,
				num_sgl_entries));
	} else {
		cmd->lun_h4__sgl_entries =
			TW_CL_SWAP16(BUILD_LUN_H4__SGL_ENTRIES(scsi_req->lun,
				scsi_req->sgl_entries));
		tw_cli_fill_sg_list(ctlr, scsi_req->sg_list,
			cmd->sg_list, scsi_req->sgl_entries);
	}

	if (((TW_CL_Q_FIRST_ITEM(&(ctlr->req_q_head[TW_CLI_PENDING_Q]))) != TW_CL_NULL) ||
		(ctlr->reset_in_progress)) {
		tw_cli_req_q_insert_tail(req, TW_CLI_PENDING_Q);
		TW_CLI_WRITE_CONTROL_REGISTER(ctlr_handle,
			TWA_CONTROL_UNMASK_COMMAND_INTERRUPT);
	} else if ((error = tw_cli_submit_cmd(req))) {
		tw_cli_dbg_printf(2, ctlr_handle, tw_osl_cur_func(),
			"Could not start request. request = %p, error = %d",
			req, error);
		tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
	}
	return(error);
}