tw_cl_intr.c revision 172496
1144966Svkashyap/*
2169400Sscottl * Copyright (c) 2004-07 Applied Micro Circuits Corporation.
3144966Svkashyap * Copyright (c) 2004-05 Vinod Kashyap
4144966Svkashyap * All rights reserved.
5144966Svkashyap *
6144966Svkashyap * Redistribution and use in source and binary forms, with or without
7144966Svkashyap * modification, are permitted provided that the following conditions
8144966Svkashyap * are met:
9144966Svkashyap * 1. Redistributions of source code must retain the above copyright
10144966Svkashyap *    notice, this list of conditions and the following disclaimer.
11144966Svkashyap * 2. Redistributions in binary form must reproduce the above copyright
12144966Svkashyap *    notice, this list of conditions and the following disclaimer in the
13144966Svkashyap *    documentation and/or other materials provided with the distribution.
14144966Svkashyap *
15144966Svkashyap * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16144966Svkashyap * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17144966Svkashyap * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18144966Svkashyap * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19144966Svkashyap * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20144966Svkashyap * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21144966Svkashyap * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22144966Svkashyap * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23144966Svkashyap * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24144966Svkashyap * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25144966Svkashyap * SUCH DAMAGE.
26144966Svkashyap *
27144966Svkashyap *	$FreeBSD: head/sys/dev/twa/tw_cl_intr.c 172496 2007-10-09 17:43:57Z scottl $
28144966Svkashyap */
29144966Svkashyap
30144966Svkashyap/*
31144966Svkashyap * AMCC'S 3ware driver for 9000 series storage controllers.
32144966Svkashyap *
33144966Svkashyap * Author: Vinod Kashyap
34169400Sscottl * Modifications by: Adam Radford
35172496Sscottl * Modifications by: Manjunath Ranganathaiah
36144966Svkashyap */
37144966Svkashyap
38144966Svkashyap
39144966Svkashyap/*
40144966Svkashyap * Common Layer interrupt handling functions.
41144966Svkashyap */
42144966Svkashyap
43144966Svkashyap
44144966Svkashyap#include "tw_osl_share.h"
45144966Svkashyap#include "tw_cl_share.h"
46144966Svkashyap#include "tw_cl_fwif.h"
47144966Svkashyap#include "tw_cl_ioctl.h"
48144966Svkashyap#include "tw_cl.h"
49144966Svkashyap#include "tw_cl_externs.h"
50144966Svkashyap#include "tw_osl_ioctl.h"
51144966Svkashyap
52144966Svkashyap
53144966Svkashyap
54144966Svkashyap/*
55144966Svkashyap * Function name:	twa_interrupt
56144966Svkashyap * Description:		Interrupt handler.  Determines the kind of interrupt,
57144966Svkashyap *			and returns TW_CL_TRUE if it recognizes the interrupt.
58144966Svkashyap *
59144966Svkashyap * Input:		ctlr_handle	-- controller handle
60144966Svkashyap * Output:		None
61144966Svkashyap * Return value:	TW_CL_TRUE -- interrupt recognized
62144966Svkashyap *			TW_CL_FALSE-- interrupt not recognized
63144966Svkashyap */
64144966SvkashyapTW_INT32
65144966Svkashyaptw_cl_interrupt(struct tw_cl_ctlr_handle *ctlr_handle)
66144966Svkashyap{
67144966Svkashyap	struct tw_cli_ctlr_context	*ctlr =
68144966Svkashyap		(struct tw_cli_ctlr_context *)(ctlr_handle->cl_ctlr_ctxt);
69144966Svkashyap	TW_UINT32			status_reg;
70144966Svkashyap	TW_INT32			rc = TW_CL_FALSE;
71144966Svkashyap
72144966Svkashyap	tw_cli_dbg_printf(10, ctlr_handle, tw_osl_cur_func(), "entered");
73144966Svkashyap
74169400Sscottl	/* If we don't have controller context, bail */
75169400Sscottl	if (ctlr == NULL)
76169400Sscottl		goto out;
77169400Sscottl
78172496Sscottl	/* If we get an interrupt while resetting, it is a shared
79172496Sscottl	   one for another device, so just bail */
80172496Sscottl	if (ctlr->state & TW_CLI_CTLR_STATE_RESET_IN_PROGRESS)
81172496Sscottl		goto out;
82172496Sscottl
83144966Svkashyap	/*
84152213Svkashyap	 * Synchronize access between writes to command and control registers
85152213Svkashyap	 * in 64-bit environments, on G66.
86144966Svkashyap	 */
87152213Svkashyap	if (ctlr->state & TW_CLI_CTLR_STATE_G66_WORKAROUND_NEEDED)
88152213Svkashyap		tw_osl_get_lock(ctlr_handle, ctlr->io_lock);
89144966Svkashyap
90144966Svkashyap	/* Read the status register to determine the type of interrupt. */
91144966Svkashyap	status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr_handle);
92144966Svkashyap	if (tw_cli_check_ctlr_state(ctlr, status_reg))
93169400Sscottl		goto out_unlock;
94144966Svkashyap
95144966Svkashyap	/* Clear the interrupt. */
96144966Svkashyap	if (status_reg & TWA_STATUS_HOST_INTERRUPT) {
97144966Svkashyap		tw_cli_dbg_printf(6, ctlr_handle, tw_osl_cur_func(),
98144966Svkashyap			"Host interrupt");
99144966Svkashyap		TW_CLI_WRITE_CONTROL_REGISTER(ctlr_handle,
100144966Svkashyap			TWA_CONTROL_CLEAR_HOST_INTERRUPT);
101144966Svkashyap		ctlr->host_intr_pending = 0; /* we don't use this */
102144966Svkashyap		rc |= TW_CL_FALSE; /* don't request for a deferred isr call */
103144966Svkashyap	}
104144966Svkashyap	if (status_reg & TWA_STATUS_ATTENTION_INTERRUPT) {
105144966Svkashyap		tw_cli_dbg_printf(6, ctlr_handle, tw_osl_cur_func(),
106144966Svkashyap			"Attention interrupt");
107144966Svkashyap		TW_CLI_WRITE_CONTROL_REGISTER(ctlr_handle,
108144966Svkashyap			TWA_CONTROL_CLEAR_ATTENTION_INTERRUPT);
109144966Svkashyap		ctlr->attn_intr_pending = 1;
110144966Svkashyap		rc |= TW_CL_TRUE; /* request for a deferred isr call */
111144966Svkashyap	}
112144966Svkashyap	if (status_reg & TWA_STATUS_COMMAND_INTERRUPT) {
113144966Svkashyap		tw_cli_dbg_printf(6, ctlr_handle, tw_osl_cur_func(),
114144966Svkashyap			"Command interrupt");
115144966Svkashyap		TW_CLI_WRITE_CONTROL_REGISTER(ctlr_handle,
116144966Svkashyap			TWA_CONTROL_MASK_COMMAND_INTERRUPT);
117144966Svkashyap		ctlr->cmd_intr_pending = 1;
118144966Svkashyap		rc |= TW_CL_TRUE; /* request for a deferred isr call */
119144966Svkashyap	}
120144966Svkashyap	if (status_reg & TWA_STATUS_RESPONSE_INTERRUPT) {
121144966Svkashyap		tw_cli_dbg_printf(10, ctlr_handle, tw_osl_cur_func(),
122144966Svkashyap			"Response interrupt");
123144966Svkashyap		TW_CLI_WRITE_CONTROL_REGISTER(ctlr_handle,
124144966Svkashyap			TWA_CONTROL_MASK_RESPONSE_INTERRUPT);
125144966Svkashyap		ctlr->resp_intr_pending = 1;
126144966Svkashyap		rc |= TW_CL_TRUE; /* request for a deferred isr call */
127144966Svkashyap	}
128169400Sscottlout_unlock:
129152213Svkashyap	if (ctlr->state & TW_CLI_CTLR_STATE_G66_WORKAROUND_NEEDED)
130152213Svkashyap		tw_osl_free_lock(ctlr_handle, ctlr->io_lock);
131169400Sscottlout:
132144966Svkashyap	return(rc);
133144966Svkashyap}
134144966Svkashyap
135144966Svkashyap
136144966Svkashyap
137144966Svkashyap/*
138144966Svkashyap * Function name:	tw_cl_deferred_interrupt
139144966Svkashyap * Description:		Deferred interrupt handler.  Does most of the processing
140144966Svkashyap *			related to an interrupt.
141144966Svkashyap *
142144966Svkashyap * Input:		ctlr_handle	-- controller handle
143144966Svkashyap * Output:		None
144144966Svkashyap * Return value:	None
145144966Svkashyap */
146144966SvkashyapTW_VOID
147144966Svkashyaptw_cl_deferred_interrupt(struct tw_cl_ctlr_handle *ctlr_handle)
148144966Svkashyap{
149144966Svkashyap	struct tw_cli_ctlr_context	*ctlr =
150144966Svkashyap		(struct tw_cli_ctlr_context *)(ctlr_handle->cl_ctlr_ctxt);
151144966Svkashyap
152144966Svkashyap	tw_cli_dbg_printf(10, ctlr_handle, tw_osl_cur_func(), "entered");
153144966Svkashyap
154144966Svkashyap	/* Dispatch based on the kind of interrupt. */
155144966Svkashyap	if (ctlr->host_intr_pending) {
156144966Svkashyap		tw_cli_dbg_printf(6, ctlr_handle, tw_osl_cur_func(),
157144966Svkashyap			"Processing Host interrupt");
158144966Svkashyap		ctlr->host_intr_pending = 0;
159144966Svkashyap		tw_cli_process_host_intr(ctlr);
160144966Svkashyap	}
161144966Svkashyap	if (ctlr->attn_intr_pending) {
162144966Svkashyap		tw_cli_dbg_printf(6, ctlr_handle, tw_osl_cur_func(),
163144966Svkashyap			"Processing Attention interrupt");
164144966Svkashyap		ctlr->attn_intr_pending = 0;
165144966Svkashyap		tw_cli_process_attn_intr(ctlr);
166144966Svkashyap	}
167144966Svkashyap	if (ctlr->cmd_intr_pending) {
168144966Svkashyap		tw_cli_dbg_printf(6, ctlr_handle, tw_osl_cur_func(),
169144966Svkashyap			"Processing Command interrupt");
170144966Svkashyap		ctlr->cmd_intr_pending = 0;
171144966Svkashyap		tw_cli_process_cmd_intr(ctlr);
172144966Svkashyap	}
173144966Svkashyap	if (ctlr->resp_intr_pending) {
174144966Svkashyap		tw_cli_dbg_printf(10, ctlr_handle, tw_osl_cur_func(),
175144966Svkashyap			"Processing Response interrupt");
176144966Svkashyap		ctlr->resp_intr_pending = 0;
177144966Svkashyap		tw_cli_process_resp_intr(ctlr);
178144966Svkashyap	}
179144966Svkashyap}
180144966Svkashyap
181144966Svkashyap
182144966Svkashyap
183144966Svkashyap/*
184144966Svkashyap * Function name:	tw_cli_process_host_intr
185144966Svkashyap * Description:		This function gets called if we triggered an interrupt.
186144966Svkashyap *			We don't use it as of now.
187144966Svkashyap *
188144966Svkashyap * Input:		ctlr	-- ptr to CL internal ctlr context
189144966Svkashyap * Output:		None
190144966Svkashyap * Return value:	None
191144966Svkashyap */
192144966SvkashyapTW_VOID
193144966Svkashyaptw_cli_process_host_intr(struct tw_cli_ctlr_context *ctlr)
194144966Svkashyap{
195144966Svkashyap	tw_cli_dbg_printf(6, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
196144966Svkashyap}
197144966Svkashyap
198144966Svkashyap
199144966Svkashyap
200144966Svkashyap/*
201144966Svkashyap * Function name:	tw_cli_process_attn_intr
202144966Svkashyap * Description:		This function gets called if the fw posted an AEN
203144966Svkashyap *			(Asynchronous Event Notification).  It fetches
204144966Svkashyap *			all the AEN's that the fw might have posted.
205144966Svkashyap *
206144966Svkashyap * Input:		ctlr	-- ptr to CL internal ctlr context
207144966Svkashyap * Output:		None
208144966Svkashyap * Return value:	None
209144966Svkashyap */
210144966SvkashyapTW_VOID
211144966Svkashyaptw_cli_process_attn_intr(struct tw_cli_ctlr_context *ctlr)
212144966Svkashyap{
213144966Svkashyap	TW_INT32	error;
214144966Svkashyap
215144966Svkashyap	tw_cli_dbg_printf(6, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
216144966Svkashyap
217144966Svkashyap	if ((error = tw_cli_get_aen(ctlr))) {
218144966Svkashyap		/*
219144966Svkashyap		 * If the driver is already in the process of retrieveing AEN's,
220144966Svkashyap		 * we will be returned TW_OSL_EBUSY.  In this case,
221144966Svkashyap		 * tw_cli_param_callback or tw_cli_aen_callback will eventually
222144966Svkashyap		 * retrieve the AEN this attention interrupt is for.  So, we
223144966Svkashyap		 * don't need to print the failure.
224144966Svkashyap		 */
225144966Svkashyap		if (error != TW_OSL_EBUSY)
226144966Svkashyap			tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
227144966Svkashyap				TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
228144966Svkashyap				0x1200, 0x1, TW_CL_SEVERITY_ERROR_STRING,
229144966Svkashyap				"Failed to fetch AEN",
230144966Svkashyap				"error = %d", error);
231144966Svkashyap	}
232144966Svkashyap}
233144966Svkashyap
234144966Svkashyap
235144966Svkashyap
236144966Svkashyap/*
237144966Svkashyap * Function name:	tw_cli_process_cmd_intr
238144966Svkashyap * Description:		This function gets called if we hit a queue full
239144966Svkashyap *			condition earlier, and the fw is now ready for
240144966Svkashyap *			new cmds.  Submits any pending requests.
241144966Svkashyap *
242144966Svkashyap * Input:		ctlr	-- ptr to CL internal ctlr context
243144966Svkashyap * Output:		None
244144966Svkashyap * Return value:	None
245144966Svkashyap */
246144966SvkashyapTW_VOID
247144966Svkashyaptw_cli_process_cmd_intr(struct tw_cli_ctlr_context *ctlr)
248144966Svkashyap{
249144966Svkashyap	tw_cli_dbg_printf(6, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
250144966Svkashyap
251144966Svkashyap	/*
252144966Svkashyap	 * Let the OS Layer submit any requests in its pending queue,
253144966Svkashyap	 * if it has one.
254144966Svkashyap	 */
255144966Svkashyap	tw_osl_ctlr_ready(ctlr->ctlr_handle);
256144966Svkashyap
257144966Svkashyap	/* Start any requests that might be in the pending queue. */
258144966Svkashyap	tw_cli_submit_pending_queue(ctlr);
259144966Svkashyap
260144966Svkashyap	/*
261144966Svkashyap	 * If tw_cli_submit_pending_queue was unsuccessful due to a "cmd queue
262144966Svkashyap	 * full" condition, cmd_intr will already have been unmasked by
263144966Svkashyap	 * tw_cli_submit_cmd.  We don't need to do it again... simply return.
264144966Svkashyap	 */
265144966Svkashyap}
266144966Svkashyap
267144966Svkashyap
268144966Svkashyap
269144966Svkashyap/*
270144966Svkashyap * Function name:	tw_cli_process_resp_intr
271144966Svkashyap * Description:		Looks for cmd completions from fw; queues cmds completed
272144966Svkashyap *			by fw into complete queue.
273144966Svkashyap *
274144966Svkashyap * Input:		ctlr	-- ptr to CL internal ctlr context
275144966Svkashyap * Output:		None
276144966Svkashyap * Return value:	0	-- no ctlr error
277144966Svkashyap *			non-zero-- ctlr error
278144966Svkashyap */
279144966SvkashyapTW_INT32
280144966Svkashyaptw_cli_process_resp_intr(struct tw_cli_ctlr_context *ctlr)
281144966Svkashyap{
282144966Svkashyap	TW_UINT32			resp;
283144966Svkashyap	struct tw_cli_req_context	*req;
284144966Svkashyap	TW_INT32			error;
285144966Svkashyap	TW_UINT32			status_reg;
286144966Svkashyap
287144966Svkashyap	tw_cli_dbg_printf(10, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
288144966Svkashyap
289144966Svkashyap	/* Serialize access to the controller response queue. */
290144966Svkashyap	tw_osl_get_lock(ctlr->ctlr_handle, ctlr->intr_lock);
291144966Svkashyap
292144966Svkashyap	for (;;) {
293144966Svkashyap		status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr->ctlr_handle);
294144966Svkashyap		if ((error = tw_cli_check_ctlr_state(ctlr, status_reg)))
295144966Svkashyap			break;
296144966Svkashyap		if (status_reg & TWA_STATUS_RESPONSE_QUEUE_EMPTY) {
297144966Svkashyap			tw_cli_dbg_printf(7, ctlr->ctlr_handle,
298144966Svkashyap				tw_osl_cur_func(), "Response queue empty");
299144966Svkashyap			break;
300144966Svkashyap		}
301144966Svkashyap
302144966Svkashyap		/* Response queue is not empty. */
303144966Svkashyap		resp = TW_CLI_READ_RESPONSE_QUEUE(ctlr->ctlr_handle);
304144966Svkashyap		{
305144966Svkashyap			req = &(ctlr->req_ctxt_buf[GET_RESP_ID(resp)]);
306144966Svkashyap		}
307144966Svkashyap
308144966Svkashyap		if (req->state != TW_CLI_REQ_STATE_BUSY) {
309144966Svkashyap			tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
310144966Svkashyap				TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
311144966Svkashyap				0x1201, 0x1, TW_CL_SEVERITY_ERROR_STRING,
312144966Svkashyap				"Unposted command completed!!",
313144966Svkashyap				"request = %p, status = %d",
314144966Svkashyap				req, req->state);
315144966Svkashyap#ifdef TW_OSL_DEBUG
316144966Svkashyap			tw_cl_print_ctlr_stats(ctlr->ctlr_handle);
317144966Svkashyap#endif /* TW_OSL_DEBUG */
318144966Svkashyap			tw_osl_free_lock(ctlr->ctlr_handle, ctlr->intr_lock);
319144966Svkashyap			tw_cl_reset_ctlr(ctlr->ctlr_handle);
320144966Svkashyap			return(TW_OSL_EIO);
321144966Svkashyap		}
322144966Svkashyap
323144966Svkashyap		/*
324144966Svkashyap		 * Remove the request from the busy queue, mark it as complete,
325144966Svkashyap		 * and enqueue it in the complete queue.
326144966Svkashyap		 */
327144966Svkashyap		tw_cli_req_q_remove_item(req, TW_CLI_BUSY_Q);
328144966Svkashyap		req->state = TW_CLI_REQ_STATE_COMPLETE;
329144966Svkashyap		tw_cli_req_q_insert_tail(req, TW_CLI_COMPLETE_Q);
330152213Svkashyap
331144966Svkashyap	}
332144966Svkashyap
333144966Svkashyap	/* Unmask the response interrupt. */
334144966Svkashyap	TW_CLI_WRITE_CONTROL_REGISTER(ctlr->ctlr_handle,
335144966Svkashyap		TWA_CONTROL_UNMASK_RESPONSE_INTERRUPT);
336144966Svkashyap
337144966Svkashyap	tw_osl_free_lock(ctlr->ctlr_handle, ctlr->intr_lock);
338144966Svkashyap
339144966Svkashyap	/* Complete this, and other requests in the complete queue. */
340144966Svkashyap	tw_cli_process_complete_queue(ctlr);
341144966Svkashyap
342144966Svkashyap	return(error);
343144966Svkashyap}
344144966Svkashyap
345144966Svkashyap
346144966Svkashyap
347144966Svkashyap/*
348144966Svkashyap * Function name:	tw_cli_submit_pending_queue
349144966Svkashyap * Description:		Kick starts any requests in the pending queue.
350144966Svkashyap *
351144966Svkashyap * Input:		ctlr	-- ptr to CL internal ctlr context
352144966Svkashyap * Output:		None
353144966Svkashyap * Return value:	0	-- all pending requests submitted successfully
354144966Svkashyap *			non-zero-- otherwise
355144966Svkashyap */
356144966SvkashyapTW_INT32
357144966Svkashyaptw_cli_submit_pending_queue(struct tw_cli_ctlr_context *ctlr)
358144966Svkashyap{
359144966Svkashyap	struct tw_cli_req_context	*req;
360144966Svkashyap	TW_INT32			error = TW_OSL_ESUCCESS;
361144966Svkashyap
362144966Svkashyap	tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
363144966Svkashyap
364144966Svkashyap	/*
365144966Svkashyap	 * Pull requests off the pending queue, and submit them.
366144966Svkashyap	 */
367144966Svkashyap	while ((req = tw_cli_req_q_remove_head(ctlr, TW_CLI_PENDING_Q)) !=
368144966Svkashyap		TW_CL_NULL) {
369144966Svkashyap		if ((error = tw_cli_submit_cmd(req))) {
370144966Svkashyap			if (error == TW_OSL_EBUSY) {
371144966Svkashyap				tw_cli_dbg_printf(2, ctlr->ctlr_handle,
372144966Svkashyap					tw_osl_cur_func(),
373144966Svkashyap					"Requeueing pending request");
374144966Svkashyap				req->state = TW_CLI_REQ_STATE_PENDING;
375144966Svkashyap				/*
376144966Svkashyap				 * Queue the request at the head of the pending
377144966Svkashyap				 * queue, and break away, so we don't try to
378144966Svkashyap				 * submit any more requests.
379144966Svkashyap				 */
380144966Svkashyap				tw_cli_req_q_insert_head(req, TW_CLI_PENDING_Q);
381144966Svkashyap				break;
382144966Svkashyap			} else {
383144966Svkashyap				tw_cl_create_event(ctlr->ctlr_handle,
384144966Svkashyap					TW_CL_FALSE,
385144966Svkashyap					TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
386144966Svkashyap					0x1202, 0x1,
387144966Svkashyap					TW_CL_SEVERITY_ERROR_STRING,
388144966Svkashyap					"Could not start request "
389144966Svkashyap					"in pending queue",
390144966Svkashyap					"request = %p, opcode = 0x%x, "
391144966Svkashyap					"error = %d", req,
392144966Svkashyap					GET_OPCODE(req->cmd_pkt->
393144966Svkashyap						command.cmd_pkt_9k.res__opcode),
394144966Svkashyap					error);
395144966Svkashyap				/*
396144966Svkashyap				 * Set the appropriate error and call the CL
397144966Svkashyap				 * internal callback if there's one.  If the
398144966Svkashyap				 * request originator is polling for completion,
399144966Svkashyap				 * he should be checking req->error to
400144966Svkashyap				 * determine that the request did not go
401144966Svkashyap				 * through.  The request originators are
402144966Svkashyap				 * responsible for the clean-up.
403144966Svkashyap				 */
404144966Svkashyap				req->error_code = error;
405144966Svkashyap				req->state = TW_CLI_REQ_STATE_COMPLETE;
406144966Svkashyap				if (req->tw_cli_callback)
407144966Svkashyap					req->tw_cli_callback(req);
408144966Svkashyap				error = TW_OSL_ESUCCESS;
409144966Svkashyap			}
410144966Svkashyap		}
411144966Svkashyap	}
412144966Svkashyap	return(error);
413144966Svkashyap}
414144966Svkashyap
415144966Svkashyap
416144966Svkashyap
417144966Svkashyap/*
418144966Svkashyap * Function name:	tw_cli_process_complete_queue
419144966Svkashyap * Description:		Calls the CL internal callback routine, if any, for
420144966Svkashyap *			each request in the complete queue.
421144966Svkashyap *
422144966Svkashyap * Input:		ctlr	-- ptr to CL internal ctlr context
423144966Svkashyap * Output:		None
424144966Svkashyap * Return value:	None
425144966Svkashyap */
426144966SvkashyapTW_VOID
427144966Svkashyaptw_cli_process_complete_queue(struct tw_cli_ctlr_context *ctlr)
428144966Svkashyap{
429144966Svkashyap	struct tw_cli_req_context	*req;
430144966Svkashyap
431144966Svkashyap	tw_cli_dbg_printf(10, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
432144966Svkashyap
433144966Svkashyap	/*
434144966Svkashyap	 * Pull commands off the completed list, dispatch them appropriately.
435144966Svkashyap	 */
436144966Svkashyap	while ((req = tw_cli_req_q_remove_head(ctlr, TW_CLI_COMPLETE_Q)) !=
437144966Svkashyap		TW_CL_NULL) {
438144966Svkashyap		/* Call the CL internal callback, if there's one. */
439144966Svkashyap		if (req->tw_cli_callback)
440144966Svkashyap			req->tw_cli_callback(req);
441144966Svkashyap	}
442144966Svkashyap}
443144966Svkashyap
444144966Svkashyap
445144966Svkashyap
446144966Svkashyap/*
447144966Svkashyap * Function name:	tw_cli_complete_io
448144966Svkashyap * Description:		CL internal callback for SCSI/fw passthru requests.
449144966Svkashyap *
450144966Svkashyap * Input:		req	-- ptr to CL internal request context
451144966Svkashyap * Output:		None
452144966Svkashyap * Return value:	None
453144966Svkashyap */
454144966SvkashyapTW_VOID
455144966Svkashyaptw_cli_complete_io(struct tw_cli_req_context *req)
456144966Svkashyap{
457144966Svkashyap	struct tw_cli_ctlr_context	*ctlr = req->ctlr;
458144966Svkashyap	struct tw_cl_req_packet		*req_pkt =
459144966Svkashyap		(struct tw_cl_req_packet *)(req->orig_req);
460144966Svkashyap
461144966Svkashyap	tw_cli_dbg_printf(8, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
462144966Svkashyap
463144966Svkashyap	req_pkt->status = TW_CL_ERR_REQ_SUCCESS;
464144966Svkashyap	if (req->error_code) {
465144966Svkashyap		req_pkt->status = TW_CL_ERR_REQ_UNABLE_TO_SUBMIT_COMMAND;
466144966Svkashyap		goto out;
467144966Svkashyap	}
468144966Svkashyap
469144966Svkashyap	if (req->state != TW_CLI_REQ_STATE_COMPLETE) {
470144966Svkashyap		tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
471144966Svkashyap			TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
472144966Svkashyap			0x1203, 0x1, TW_CL_SEVERITY_ERROR_STRING,
473144966Svkashyap			"I/O completion on incomplete command!!",
474144966Svkashyap			"request = %p, status = %d",
475144966Svkashyap			req, req->state);
476144966Svkashyap#ifdef TW_OSL_DEBUG
477144966Svkashyap		tw_cl_print_ctlr_stats(ctlr->ctlr_handle);
478144966Svkashyap#endif /* TW_OSL_DEBUG */
479144966Svkashyap		tw_cl_reset_ctlr(ctlr->ctlr_handle);
480144966Svkashyap		req_pkt->status = TW_CL_ERR_REQ_BUS_RESET;
481144966Svkashyap		goto out;
482144966Svkashyap	}
483144966Svkashyap
484144966Svkashyap	if (req->flags & TW_CLI_REQ_FLAGS_PASSTHRU) {
485144966Svkashyap		/* Copy the command packet back into OSL's space. */
486144966Svkashyap		tw_osl_memcpy(req_pkt->gen_req_pkt.pt_req.cmd_pkt, req->cmd_pkt,
487144966Svkashyap			sizeof(struct tw_cl_command_packet));
488144966Svkashyap	} else
489144966Svkashyap		tw_cli_scsi_complete(req);
490144966Svkashyap
491144966Svkashyapout:
492144966Svkashyap	req_pkt->tw_osl_callback(req->req_handle);
493144966Svkashyap	tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
494144966Svkashyap}
495144966Svkashyap
496144966Svkashyap
497144966Svkashyap
498144966Svkashyap/*
499144966Svkashyap * Function name:	tw_cli_scsi_complete
500144966Svkashyap * Description:		Completion routine for SCSI requests.
501144966Svkashyap *
502144966Svkashyap * Input:		req	-- ptr to CL internal request context
503144966Svkashyap * Output:		None
504144966Svkashyap * Return value:	None
505144966Svkashyap */
506144966SvkashyapTW_VOID
507144966Svkashyaptw_cli_scsi_complete(struct tw_cli_req_context *req)
508144966Svkashyap{
509144966Svkashyap	struct tw_cl_req_packet		*req_pkt =
510144966Svkashyap		(struct tw_cl_req_packet *)(req->orig_req);
511144966Svkashyap	struct tw_cl_scsi_req_packet	*scsi_req =
512144966Svkashyap		&(req_pkt->gen_req_pkt.scsi_req);
513144966Svkashyap	struct tw_cl_command_9k		*cmd =
514144966Svkashyap		&(req->cmd_pkt->command.cmd_pkt_9k);
515144966Svkashyap	struct tw_cl_command_header	*cmd_hdr;
516144966Svkashyap	TW_UINT16			error;
517144966Svkashyap	TW_UINT8			*cdb;
518144966Svkashyap
519144966Svkashyap	tw_cli_dbg_printf(8, req->ctlr->ctlr_handle, tw_osl_cur_func(),
520144966Svkashyap		"entered");
521144966Svkashyap
522144966Svkashyap	scsi_req->scsi_status = cmd->status;
523144966Svkashyap	if (! cmd->status)
524144966Svkashyap		return;
525144966Svkashyap
526144966Svkashyap	tw_cli_dbg_printf(1, req->ctlr->ctlr_handle, tw_osl_cur_func(),
527144966Svkashyap		"req_id = 0x%x, status = 0x%x",
528144966Svkashyap		GET_REQ_ID(cmd->lun_l4__req_id), cmd->status);
529144966Svkashyap
530144966Svkashyap	cmd_hdr = &(req->cmd_pkt->cmd_hdr);
531144966Svkashyap	error = cmd_hdr->status_block.error;
532144966Svkashyap	if ((error == TWA_ERROR_LOGICAL_UNIT_NOT_SUPPORTED) ||
533144966Svkashyap			(error == TWA_ERROR_UNIT_OFFLINE)) {
534144966Svkashyap		if (GET_LUN_L4(cmd->lun_l4__req_id))
535144966Svkashyap			req_pkt->status |= TW_CL_ERR_REQ_INVALID_LUN;
536144966Svkashyap		else
537144966Svkashyap			req_pkt->status |= TW_CL_ERR_REQ_INVALID_TARGET;
538144966Svkashyap	} else {
539144966Svkashyap		tw_cli_dbg_printf(2, req->ctlr->ctlr_handle,
540144966Svkashyap			tw_osl_cur_func(),
541144966Svkashyap			"cmd = %x %x %x %x %x %x %x",
542144966Svkashyap			GET_OPCODE(cmd->res__opcode),
543144966Svkashyap			GET_SGL_OFF(cmd->res__opcode),
544144966Svkashyap			cmd->unit,
545144966Svkashyap			cmd->lun_l4__req_id,
546144966Svkashyap			cmd->status,
547144966Svkashyap			cmd->sgl_offset,
548144966Svkashyap			cmd->lun_h4__sgl_entries);
549144966Svkashyap
550144966Svkashyap		cdb = (TW_UINT8 *)(cmd->cdb);
551144966Svkashyap		tw_cli_dbg_printf(2, req->ctlr->ctlr_handle,
552144966Svkashyap			tw_osl_cur_func(),
553144966Svkashyap			"cdb = %x %x %x %x %x %x %x %x "
554144966Svkashyap			"%x %x %x %x %x %x %x %x",
555144966Svkashyap			cdb[0], cdb[1], cdb[2], cdb[3],
556144966Svkashyap			cdb[4], cdb[5], cdb[6], cdb[7],
557144966Svkashyap			cdb[8], cdb[9], cdb[10], cdb[11],
558144966Svkashyap			cdb[12], cdb[13], cdb[14], cdb[15]);
559144966Svkashyap
560144966Svkashyap		/*
561144966Svkashyap		 * Print the error. Firmware doesn't yet support
562144966Svkashyap		 * the 'Mode Sense' cmd.  Don't print if the cmd
563144966Svkashyap		 * is 'Mode Sense', and the error is 'Invalid field
564144966Svkashyap		 * in CDB'.
565144966Svkashyap		 */
566144966Svkashyap		if (! ((cdb[0] == 0x1A) && (error == 0x10D)))
567144966Svkashyap			tw_cli_create_ctlr_event(req->ctlr,
568144966Svkashyap				TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR,
569144966Svkashyap				cmd_hdr);
570144966Svkashyap	}
571144966Svkashyap
572144966Svkashyap	if (scsi_req->sense_data) {
573144966Svkashyap		tw_osl_memcpy(scsi_req->sense_data, cmd_hdr->sense_data,
574144966Svkashyap			TWA_SENSE_DATA_LENGTH);
575144966Svkashyap		scsi_req->sense_len = TWA_SENSE_DATA_LENGTH;
576144966Svkashyap		req_pkt->status |= TW_CL_ERR_REQ_AUTO_SENSE_VALID;
577144966Svkashyap	}
578144966Svkashyap	req_pkt->status |= TW_CL_ERR_REQ_SCSI_ERROR;
579144966Svkashyap}
580144966Svkashyap
581144966Svkashyap
582144966Svkashyap
583144966Svkashyap/*
584144966Svkashyap * Function name:	tw_cli_param_callback
585144966Svkashyap * Description:		Callback for get/set_param requests.
586144966Svkashyap *
587144966Svkashyap * Input:		req	-- ptr to completed request pkt
588144966Svkashyap * Output:		None
589144966Svkashyap * Return value:	None
590144966Svkashyap */
591144966SvkashyapTW_VOID
592144966Svkashyaptw_cli_param_callback(struct tw_cli_req_context *req)
593144966Svkashyap{
594144966Svkashyap	struct tw_cli_ctlr_context	*ctlr = req->ctlr;
595144966Svkashyap	union tw_cl_command_7k		*cmd =
596144966Svkashyap		&(req->cmd_pkt->command.cmd_pkt_7k);
597144966Svkashyap	TW_INT32			error;
598144966Svkashyap
599144966Svkashyap	tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
600144966Svkashyap
601144966Svkashyap	/*
602144966Svkashyap	 * If the request was never submitted to the controller, the function
603144966Svkashyap	 * that sets req->error is responsible for calling tw_cl_create_event.
604144966Svkashyap	 */
605144966Svkashyap	if (! req->error_code)
606144966Svkashyap		if (cmd->param.status) {
607144966Svkashyap			tw_cli_create_ctlr_event(ctlr,
608144966Svkashyap				TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR,
609144966Svkashyap				&(req->cmd_pkt->cmd_hdr));
610144966Svkashyap			tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
611144966Svkashyap				TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
612144966Svkashyap				0x1204, 0x1, TW_CL_SEVERITY_ERROR_STRING,
613144966Svkashyap				"get/set_param failed",
614144966Svkashyap				"status = %d", cmd->param.status);
615144966Svkashyap		}
616144966Svkashyap
617144966Svkashyap	ctlr->state &= ~TW_CLI_CTLR_STATE_INTERNAL_REQ_BUSY;
618144966Svkashyap	tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
619144966Svkashyap
620144966Svkashyap	if ((ctlr->state & TW_CLI_CTLR_STATE_GET_MORE_AENS) &&
621144966Svkashyap		(!(ctlr->state & TW_CLI_CTLR_STATE_RESET_IN_PROGRESS))) {
622144966Svkashyap		ctlr->state &= ~TW_CLI_CTLR_STATE_GET_MORE_AENS;
623144966Svkashyap		tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(),
624144966Svkashyap			"Fetching more AEN's");
625144966Svkashyap		if ((error = tw_cli_get_aen(ctlr)))
626144966Svkashyap			tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
627144966Svkashyap				TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
628144966Svkashyap				0x1205, 0x1, TW_CL_SEVERITY_ERROR_STRING,
629144966Svkashyap				"Failed to fetch all AEN's from param_callback",
630144966Svkashyap				"error = %d", error);
631144966Svkashyap	}
632144966Svkashyap}
633144966Svkashyap
634144966Svkashyap
635144966Svkashyap
636144966Svkashyap/*
637144966Svkashyap * Function name:	tw_cli_aen_callback
638144966Svkashyap * Description:		Callback for requests to fetch AEN's.
639144966Svkashyap *
640144966Svkashyap * Input:		req	-- ptr to completed request pkt
641144966Svkashyap * Output:		None
642144966Svkashyap * Return value:	None
643144966Svkashyap */
644144966SvkashyapTW_VOID
645144966Svkashyaptw_cli_aen_callback(struct tw_cli_req_context *req)
646144966Svkashyap{
647144966Svkashyap	struct tw_cli_ctlr_context	*ctlr = req->ctlr;
648144966Svkashyap	struct tw_cl_command_header	*cmd_hdr;
649144966Svkashyap	struct tw_cl_command_9k		*cmd =
650144966Svkashyap		&(req->cmd_pkt->command.cmd_pkt_9k);
651144966Svkashyap	TW_UINT16			aen_code = TWA_AEN_QUEUE_EMPTY;
652144966Svkashyap	TW_INT32			error;
653144966Svkashyap
654144966Svkashyap	tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
655144966Svkashyap
656144966Svkashyap	tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(),
657144966Svkashyap		"req_id = 0x%x, req error = %d, status = 0x%x",
658144966Svkashyap		GET_REQ_ID(cmd->lun_l4__req_id), req->error_code, cmd->status);
659144966Svkashyap
660144966Svkashyap	/*
661144966Svkashyap	 * If the request was never submitted to the controller, the function
662144966Svkashyap	 * that sets error is responsible for calling tw_cl_create_event.
663144966Svkashyap	 */
664144966Svkashyap	if (!(error = req->error_code))
665144966Svkashyap		if ((error = cmd->status)) {
666144966Svkashyap			cmd_hdr = (struct tw_cl_command_header *)
667144966Svkashyap				(&(req->cmd_pkt->cmd_hdr));
668144966Svkashyap			tw_cli_create_ctlr_event(ctlr,
669144966Svkashyap				TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR,
670144966Svkashyap				cmd_hdr);
671144966Svkashyap			tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
672144966Svkashyap				TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
673144966Svkashyap				0x1206, 0x1, TW_CL_SEVERITY_ERROR_STRING,
674144966Svkashyap				"Request Sense failed",
675144966Svkashyap				"opcode = 0x%x, status = %d",
676144966Svkashyap				GET_OPCODE(cmd->res__opcode), cmd->status);
677144966Svkashyap		}
678144966Svkashyap
679144966Svkashyap	if (error) {
680144966Svkashyap		ctlr->state &= ~TW_CLI_CTLR_STATE_INTERNAL_REQ_BUSY;
681144966Svkashyap		tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
682144966Svkashyap		return;
683144966Svkashyap	}
684144966Svkashyap
685144966Svkashyap	tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(),
686144966Svkashyap		"Request Sense command succeeded");
687144966Svkashyap
688144966Svkashyap	aen_code = tw_cli_manage_aen(ctlr, req);
689144966Svkashyap
690144966Svkashyap	if (aen_code != TWA_AEN_SYNC_TIME_WITH_HOST) {
691144966Svkashyap		ctlr->state &= ~TW_CLI_CTLR_STATE_INTERNAL_REQ_BUSY;
692144966Svkashyap		tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
693144966Svkashyap		if (aen_code != TWA_AEN_QUEUE_EMPTY)
694144966Svkashyap			if ((error = tw_cli_get_aen(ctlr)))
695144966Svkashyap				tw_cl_create_event(ctlr->ctlr_handle,
696144966Svkashyap					TW_CL_FALSE,
697144966Svkashyap					TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
698144966Svkashyap					0x1207, 0x1,
699144966Svkashyap					TW_CL_SEVERITY_ERROR_STRING,
700144966Svkashyap					"Failed to fetch all AEN's",
701144966Svkashyap					"error = %d", error);
702144966Svkashyap	}
703144966Svkashyap}
704144966Svkashyap
705144966Svkashyap
706144966Svkashyap
707144966Svkashyap/*
708144966Svkashyap * Function name:	tw_cli_manage_aen
709144966Svkashyap * Description:		Handles AEN's.
710144966Svkashyap *
711144966Svkashyap * Input:		ctlr	-- ptr to CL internal ctlr context
712144966Svkashyap *			req	-- ptr to CL internal request context
713144966Svkashyap * Output:		None
714144966Svkashyap * Return value:	None
715144966Svkashyap */
716144966SvkashyapTW_UINT16
717144966Svkashyaptw_cli_manage_aen(struct tw_cli_ctlr_context *ctlr,
718144966Svkashyap	struct tw_cli_req_context *req)
719144966Svkashyap{
720144966Svkashyap	struct tw_cl_command_header	*cmd_hdr;
721144966Svkashyap	TW_UINT16			aen_code;
722144966Svkashyap	TW_TIME				local_time;
723144966Svkashyap	TW_TIME				sync_time;
724144966Svkashyap	TW_UINT32			error;
725144966Svkashyap
726144966Svkashyap	tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
727144966Svkashyap
728144966Svkashyap	cmd_hdr = (struct tw_cl_command_header *)(req->data);
729144966Svkashyap	aen_code = cmd_hdr->status_block.error;
730144966Svkashyap
731144966Svkashyap	switch (aen_code) {
732144966Svkashyap	case TWA_AEN_SYNC_TIME_WITH_HOST:
733144966Svkashyap		tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(),
734144966Svkashyap			"Received AEN_SYNC_TIME");
735144966Svkashyap		/*
736144966Svkashyap		 * Free the internal req pkt right here, since
737144966Svkashyap		 * tw_cli_set_param will need it.
738144966Svkashyap		 */
739144966Svkashyap		ctlr->state &= ~TW_CLI_CTLR_STATE_INTERNAL_REQ_BUSY;
740144966Svkashyap		tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
741144966Svkashyap
742144966Svkashyap		/*
743144966Svkashyap		 * We will use a callback in tw_cli_set_param only when
744144966Svkashyap		 * interrupts are enabled and we can expect our callback
745144966Svkashyap		 * to get called.  Setting the TW_CLI_CTLR_STATE_GET_MORE_AENS
746144966Svkashyap		 * flag will make the callback continue to try to retrieve
747144966Svkashyap		 * more AEN's.
748144966Svkashyap		 */
749144966Svkashyap		if (ctlr->state & TW_CLI_CTLR_STATE_INTR_ENABLED)
750144966Svkashyap			ctlr->state |= TW_CLI_CTLR_STATE_GET_MORE_AENS;
751144966Svkashyap		/* Calculate time (in seconds) since last Sunday 12.00 AM. */
752144966Svkashyap		local_time = tw_osl_get_local_time();
753144966Svkashyap		sync_time = (local_time - (3 * 86400)) % 604800;
754144966Svkashyap		if ((error = tw_cli_set_param(ctlr, TWA_PARAM_TIME_TABLE,
755144966Svkashyap				TWA_PARAM_TIME_SCHED_TIME, 4,
756144966Svkashyap				&sync_time,
757144966Svkashyap				(ctlr->state & TW_CLI_CTLR_STATE_INTR_ENABLED)
758144966Svkashyap				? tw_cli_param_callback : TW_CL_NULL)))
759144966Svkashyap			tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
760144966Svkashyap				TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
761144966Svkashyap				0x1208, 0x1, TW_CL_SEVERITY_ERROR_STRING,
762144966Svkashyap				"Unable to sync time with ctlr",
763144966Svkashyap				"error = %d", error);
764144966Svkashyap
765144966Svkashyap		break;
766144966Svkashyap
767144966Svkashyap
768144966Svkashyap	case TWA_AEN_QUEUE_EMPTY:
769144966Svkashyap		tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(),
770144966Svkashyap			"AEN queue empty");
771144966Svkashyap		break;
772144966Svkashyap
773144966Svkashyap
774144966Svkashyap	default:
775144966Svkashyap		/* Queue the event. */
776144966Svkashyap
777144966Svkashyap		tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(),
778144966Svkashyap			"Queueing AEN");
779144966Svkashyap		tw_cli_create_ctlr_event(ctlr,
780144966Svkashyap			TW_CL_MESSAGE_SOURCE_CONTROLLER_EVENT,
781144966Svkashyap			cmd_hdr);
782144966Svkashyap		break;
783144966Svkashyap	} /* switch */
784144966Svkashyap	return(aen_code);
785144966Svkashyap}
786144966Svkashyap
787144966Svkashyap
788144966Svkashyap
789144966Svkashyap/*
790144966Svkashyap * Function name:	tw_cli_enable_interrupts
791144966Svkashyap * Description:		Enables interrupts on the controller
792144966Svkashyap *
793144966Svkashyap * Input:		ctlr	-- ptr to CL internal ctlr context
794144966Svkashyap * Output:		None
795144966Svkashyap * Return value:	None
796144966Svkashyap */
797144966SvkashyapTW_VOID
798144966Svkashyaptw_cli_enable_interrupts(struct tw_cli_ctlr_context *ctlr)
799144966Svkashyap{
800144966Svkashyap	tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
801144966Svkashyap
802144966Svkashyap	ctlr->state |= TW_CLI_CTLR_STATE_INTR_ENABLED;
803144966Svkashyap	TW_CLI_WRITE_CONTROL_REGISTER(ctlr->ctlr_handle,
804144966Svkashyap		TWA_CONTROL_CLEAR_ATTENTION_INTERRUPT |
805144966Svkashyap		TWA_CONTROL_UNMASK_RESPONSE_INTERRUPT |
806144966Svkashyap		TWA_CONTROL_ENABLE_INTERRUPTS);
807144966Svkashyap}
808144966Svkashyap
809144966Svkashyap
810144966Svkashyap
811144966Svkashyap/*
812144966Svkashyap * Function name:	twa_setup
813144966Svkashyap * Description:		Disables interrupts on the controller
814144966Svkashyap *
815144966Svkashyap * Input:		ctlr	-- ptr to CL internal ctlr context
816144966Svkashyap * Output:		None
817144966Svkashyap * Return value:	None
818144966Svkashyap */
819144966SvkashyapTW_VOID
820144966Svkashyaptw_cli_disable_interrupts(struct tw_cli_ctlr_context *ctlr)
821144966Svkashyap{
822144966Svkashyap	tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
823144966Svkashyap
824144966Svkashyap	TW_CLI_WRITE_CONTROL_REGISTER(ctlr->ctlr_handle,
825144966Svkashyap		TWA_CONTROL_DISABLE_INTERRUPTS);
826144966Svkashyap	ctlr->state &= ~TW_CLI_CTLR_STATE_INTR_ENABLED;
827144966Svkashyap}
828144966Svkashyap
829