xref: /dflybsd-src/sys/dev/raid/twa/tw_cl_intr.c (revision 1e0dd9dd32a69a1d3bbe6a9e41c3a63aae59fb4d)
1df54c2f9SSascha Wildner /*
2df54c2f9SSascha Wildner  * Copyright (c) 2004-07 Applied Micro Circuits Corporation.
3df54c2f9SSascha Wildner  * Copyright (c) 2004-05 Vinod Kashyap
4df54c2f9SSascha Wildner  * All rights reserved.
5df54c2f9SSascha Wildner  *
6df54c2f9SSascha Wildner  * Redistribution and use in source and binary forms, with or without
7df54c2f9SSascha Wildner  * modification, are permitted provided that the following conditions
8df54c2f9SSascha Wildner  * are met:
9df54c2f9SSascha Wildner  * 1. Redistributions of source code must retain the above copyright
10df54c2f9SSascha Wildner  *    notice, this list of conditions and the following disclaimer.
11df54c2f9SSascha Wildner  * 2. Redistributions in binary form must reproduce the above copyright
12df54c2f9SSascha Wildner  *    notice, this list of conditions and the following disclaimer in the
13df54c2f9SSascha Wildner  *    documentation and/or other materials provided with the distribution.
14df54c2f9SSascha Wildner  *
15df54c2f9SSascha Wildner  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16df54c2f9SSascha Wildner  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17df54c2f9SSascha Wildner  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18df54c2f9SSascha Wildner  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19df54c2f9SSascha Wildner  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20df54c2f9SSascha Wildner  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21df54c2f9SSascha Wildner  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22df54c2f9SSascha Wildner  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23df54c2f9SSascha Wildner  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24df54c2f9SSascha Wildner  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25df54c2f9SSascha Wildner  * SUCH DAMAGE.
26df54c2f9SSascha Wildner  *
27*1e0dd9ddSSascha Wildner  *	$FreeBSD: head/sys/dev/twa/tw_cl_intr.c 212008 2010-08-30 19:15:04Z delphij $
28df54c2f9SSascha Wildner  */
29df54c2f9SSascha Wildner 
30df54c2f9SSascha Wildner /*
31df54c2f9SSascha Wildner  * AMCC'S 3ware driver for 9000 series storage controllers.
32df54c2f9SSascha Wildner  *
33df54c2f9SSascha Wildner  * Author: Vinod Kashyap
34df54c2f9SSascha Wildner  * Modifications by: Adam Radford
35df54c2f9SSascha Wildner  * Modifications by: Manjunath Ranganathaiah
36df54c2f9SSascha Wildner  */
37df54c2f9SSascha Wildner 
38df54c2f9SSascha Wildner 
39df54c2f9SSascha Wildner /*
40df54c2f9SSascha Wildner  * Common Layer interrupt handling functions.
41df54c2f9SSascha Wildner  */
42df54c2f9SSascha Wildner 
43df54c2f9SSascha Wildner 
44df54c2f9SSascha Wildner #include "tw_osl_share.h"
45df54c2f9SSascha Wildner #include "tw_cl_share.h"
46df54c2f9SSascha Wildner #include "tw_cl_fwif.h"
47df54c2f9SSascha Wildner #include "tw_cl_ioctl.h"
48df54c2f9SSascha Wildner #include "tw_cl.h"
49df54c2f9SSascha Wildner #include "tw_cl_externs.h"
50df54c2f9SSascha Wildner #include "tw_osl_ioctl.h"
51df54c2f9SSascha Wildner 
52df54c2f9SSascha Wildner 
53df54c2f9SSascha Wildner 
54df54c2f9SSascha Wildner /*
55df54c2f9SSascha Wildner  * Function name:	twa_interrupt
56df54c2f9SSascha Wildner  * Description:		Interrupt handler.  Determines the kind of interrupt,
57df54c2f9SSascha Wildner  *			and returns TW_CL_TRUE if it recognizes the interrupt.
58df54c2f9SSascha Wildner  *
59df54c2f9SSascha Wildner  * Input:		ctlr_handle	-- controller handle
60df54c2f9SSascha Wildner  * Output:		None
61df54c2f9SSascha Wildner  * Return value:	TW_CL_TRUE -- interrupt recognized
62df54c2f9SSascha Wildner  *			TW_CL_FALSE-- interrupt not recognized
63df54c2f9SSascha Wildner  */
64df54c2f9SSascha Wildner TW_INT32
tw_cl_interrupt(struct tw_cl_ctlr_handle * ctlr_handle)65df54c2f9SSascha Wildner tw_cl_interrupt(struct tw_cl_ctlr_handle *ctlr_handle)
66df54c2f9SSascha Wildner {
67df54c2f9SSascha Wildner 	struct tw_cli_ctlr_context	*ctlr =
68df54c2f9SSascha Wildner 		(struct tw_cli_ctlr_context *)(ctlr_handle->cl_ctlr_ctxt);
69df54c2f9SSascha Wildner 	TW_UINT32			status_reg;
70df54c2f9SSascha Wildner 	TW_INT32			rc = TW_CL_FALSE;
71df54c2f9SSascha Wildner 
72df54c2f9SSascha Wildner 	tw_cli_dbg_printf(10, ctlr_handle, tw_osl_cur_func(), "entered");
73df54c2f9SSascha Wildner 
74df54c2f9SSascha Wildner 	/* If we don't have controller context, bail */
75df54c2f9SSascha Wildner 	if (ctlr == NULL)
76df54c2f9SSascha Wildner 		goto out;
77df54c2f9SSascha Wildner 
78df54c2f9SSascha Wildner 	/*
79df54c2f9SSascha Wildner 	 * Bail If we get an interrupt while resetting, or shutting down.
80df54c2f9SSascha Wildner 	 */
81df54c2f9SSascha Wildner 	if (ctlr->reset_in_progress || !(ctlr->active))
82df54c2f9SSascha Wildner 		goto out;
83df54c2f9SSascha Wildner 
84df54c2f9SSascha Wildner 	/* Read the status register to determine the type of interrupt. */
85df54c2f9SSascha Wildner 	status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr_handle);
86df54c2f9SSascha Wildner 	if (tw_cli_check_ctlr_state(ctlr, status_reg))
87df54c2f9SSascha Wildner 		goto out;
88df54c2f9SSascha Wildner 
89df54c2f9SSascha Wildner 	/* Clear the interrupt. */
90df54c2f9SSascha Wildner 	if (status_reg & TWA_STATUS_HOST_INTERRUPT) {
91df54c2f9SSascha Wildner 		tw_cli_dbg_printf(6, ctlr_handle, tw_osl_cur_func(),
92df54c2f9SSascha Wildner 			"Host interrupt");
93df54c2f9SSascha Wildner 		TW_CLI_WRITE_CONTROL_REGISTER(ctlr_handle,
94df54c2f9SSascha Wildner 			TWA_CONTROL_CLEAR_HOST_INTERRUPT);
95df54c2f9SSascha Wildner 	}
96df54c2f9SSascha Wildner 	if (status_reg & TWA_STATUS_ATTENTION_INTERRUPT) {
97df54c2f9SSascha Wildner 		tw_cli_dbg_printf(6, ctlr_handle, tw_osl_cur_func(),
98df54c2f9SSascha Wildner 			"Attention interrupt");
99df54c2f9SSascha Wildner 		rc |= TW_CL_TRUE; /* request for a deferred isr call */
100df54c2f9SSascha Wildner 		tw_cli_process_attn_intr(ctlr);
101df54c2f9SSascha Wildner 		TW_CLI_WRITE_CONTROL_REGISTER(ctlr_handle,
102df54c2f9SSascha Wildner 			TWA_CONTROL_CLEAR_ATTENTION_INTERRUPT);
103df54c2f9SSascha Wildner 	}
104df54c2f9SSascha Wildner 	if (status_reg & TWA_STATUS_COMMAND_INTERRUPT) {
105df54c2f9SSascha Wildner 		tw_cli_dbg_printf(6, ctlr_handle, tw_osl_cur_func(),
106df54c2f9SSascha Wildner 			"Command interrupt");
107df54c2f9SSascha Wildner 		rc |= TW_CL_TRUE; /* request for a deferred isr call */
108df54c2f9SSascha Wildner 		tw_cli_process_cmd_intr(ctlr);
109df54c2f9SSascha Wildner 		if ((TW_CL_Q_FIRST_ITEM(&(ctlr->req_q_head[TW_CLI_PENDING_Q]))) == TW_CL_NULL)
110df54c2f9SSascha Wildner 			TW_CLI_WRITE_CONTROL_REGISTER(ctlr_handle,
111df54c2f9SSascha Wildner 				TWA_CONTROL_MASK_COMMAND_INTERRUPT);
112df54c2f9SSascha Wildner 	}
113df54c2f9SSascha Wildner 	if (status_reg & TWA_STATUS_RESPONSE_INTERRUPT) {
114df54c2f9SSascha Wildner 		tw_cli_dbg_printf(10, ctlr_handle, tw_osl_cur_func(),
115df54c2f9SSascha Wildner 			"Response interrupt");
116df54c2f9SSascha Wildner 		rc |= TW_CL_TRUE; /* request for a deferred isr call */
117df54c2f9SSascha Wildner 		tw_cli_process_resp_intr(ctlr);
118df54c2f9SSascha Wildner 	}
119df54c2f9SSascha Wildner out:
120df54c2f9SSascha Wildner 	return(rc);
121df54c2f9SSascha Wildner }
122df54c2f9SSascha Wildner 
123df54c2f9SSascha Wildner 
124df54c2f9SSascha Wildner 
125df54c2f9SSascha Wildner /*
126df54c2f9SSascha Wildner  * Function name:	tw_cli_process_host_intr
127df54c2f9SSascha Wildner  * Description:		This function gets called if we triggered an interrupt.
128df54c2f9SSascha Wildner  *			We don't use it as of now.
129df54c2f9SSascha Wildner  *
130df54c2f9SSascha Wildner  * Input:		ctlr	-- ptr to CL internal ctlr context
131df54c2f9SSascha Wildner  * Output:		None
132df54c2f9SSascha Wildner  * Return value:	None
133df54c2f9SSascha Wildner  */
134df54c2f9SSascha Wildner TW_VOID
tw_cli_process_host_intr(struct tw_cli_ctlr_context * ctlr)135df54c2f9SSascha Wildner tw_cli_process_host_intr(struct tw_cli_ctlr_context *ctlr)
136df54c2f9SSascha Wildner {
137df54c2f9SSascha Wildner 	tw_cli_dbg_printf(6, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
138df54c2f9SSascha Wildner }
139df54c2f9SSascha Wildner 
140df54c2f9SSascha Wildner 
141df54c2f9SSascha Wildner 
142df54c2f9SSascha Wildner /*
143df54c2f9SSascha Wildner  * Function name:	tw_cli_process_attn_intr
144df54c2f9SSascha Wildner  * Description:		This function gets called if the fw posted an AEN
145df54c2f9SSascha Wildner  *			(Asynchronous Event Notification).  It fetches
146df54c2f9SSascha Wildner  *			all the AEN's that the fw might have posted.
147df54c2f9SSascha Wildner  *
148df54c2f9SSascha Wildner  * Input:		ctlr	-- ptr to CL internal ctlr context
149df54c2f9SSascha Wildner  * Output:		None
150df54c2f9SSascha Wildner  * Return value:	None
151df54c2f9SSascha Wildner  */
152df54c2f9SSascha Wildner TW_VOID
tw_cli_process_attn_intr(struct tw_cli_ctlr_context * ctlr)153df54c2f9SSascha Wildner tw_cli_process_attn_intr(struct tw_cli_ctlr_context *ctlr)
154df54c2f9SSascha Wildner {
155df54c2f9SSascha Wildner 	TW_INT32	error;
156df54c2f9SSascha Wildner 
157df54c2f9SSascha Wildner 	tw_cli_dbg_printf(6, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
158df54c2f9SSascha Wildner 
159df54c2f9SSascha Wildner 	if ((error = tw_cli_get_aen(ctlr))) {
160df54c2f9SSascha Wildner 		/*
161df54c2f9SSascha Wildner 		 * If the driver is already in the process of retrieveing AEN's,
162df54c2f9SSascha Wildner 		 * we will be returned TW_OSL_EBUSY.  In this case,
163df54c2f9SSascha Wildner 		 * tw_cli_param_callback or tw_cli_aen_callback will eventually
164df54c2f9SSascha Wildner 		 * retrieve the AEN this attention interrupt is for.  So, we
165df54c2f9SSascha Wildner 		 * don't need to print the failure.
166df54c2f9SSascha Wildner 		 */
167df54c2f9SSascha Wildner 		if (error != TW_OSL_EBUSY)
168df54c2f9SSascha Wildner 			tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
169df54c2f9SSascha Wildner 				TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
170df54c2f9SSascha Wildner 				0x1200, 0x1, TW_CL_SEVERITY_ERROR_STRING,
171df54c2f9SSascha Wildner 				"Failed to fetch AEN",
172df54c2f9SSascha Wildner 				"error = %d", error);
173df54c2f9SSascha Wildner 	}
174df54c2f9SSascha Wildner }
175df54c2f9SSascha Wildner 
176df54c2f9SSascha Wildner 
177df54c2f9SSascha Wildner 
178df54c2f9SSascha Wildner /*
179df54c2f9SSascha Wildner  * Function name:	tw_cli_process_cmd_intr
180df54c2f9SSascha Wildner  * Description:		This function gets called if we hit a queue full
181df54c2f9SSascha Wildner  *			condition earlier, and the fw is now ready for
182df54c2f9SSascha Wildner  *			new cmds.  Submits any pending requests.
183df54c2f9SSascha Wildner  *
184df54c2f9SSascha Wildner  * Input:		ctlr	-- ptr to CL internal ctlr context
185df54c2f9SSascha Wildner  * Output:		None
186df54c2f9SSascha Wildner  * Return value:	None
187df54c2f9SSascha Wildner  */
188df54c2f9SSascha Wildner TW_VOID
tw_cli_process_cmd_intr(struct tw_cli_ctlr_context * ctlr)189df54c2f9SSascha Wildner tw_cli_process_cmd_intr(struct tw_cli_ctlr_context *ctlr)
190df54c2f9SSascha Wildner {
191df54c2f9SSascha Wildner 	tw_cli_dbg_printf(6, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
192df54c2f9SSascha Wildner 
193df54c2f9SSascha Wildner 	/* Start any requests that might be in the pending queue. */
194df54c2f9SSascha Wildner 	tw_cli_submit_pending_queue(ctlr);
195df54c2f9SSascha Wildner 
196df54c2f9SSascha Wildner 	/*
197df54c2f9SSascha Wildner 	 * If tw_cli_submit_pending_queue was unsuccessful due to a "cmd queue
198df54c2f9SSascha Wildner 	 * full" condition, cmd_intr will already have been unmasked by
199df54c2f9SSascha Wildner 	 * tw_cli_submit_cmd.  We don't need to do it again... simply return.
200df54c2f9SSascha Wildner 	 */
201df54c2f9SSascha Wildner }
202df54c2f9SSascha Wildner 
203df54c2f9SSascha Wildner 
204df54c2f9SSascha Wildner 
205df54c2f9SSascha Wildner /*
206df54c2f9SSascha Wildner  * Function name:	tw_cli_process_resp_intr
207df54c2f9SSascha Wildner  * Description:		Looks for cmd completions from fw; queues cmds completed
208df54c2f9SSascha Wildner  *			by fw into complete queue.
209df54c2f9SSascha Wildner  *
210df54c2f9SSascha Wildner  * Input:		ctlr	-- ptr to CL internal ctlr context
211df54c2f9SSascha Wildner  * Output:		None
212df54c2f9SSascha Wildner  * Return value:	0	-- no ctlr error
213df54c2f9SSascha Wildner  *			non-zero-- ctlr error
214df54c2f9SSascha Wildner  */
215df54c2f9SSascha Wildner TW_INT32
tw_cli_process_resp_intr(struct tw_cli_ctlr_context * ctlr)216df54c2f9SSascha Wildner tw_cli_process_resp_intr(struct tw_cli_ctlr_context *ctlr)
217df54c2f9SSascha Wildner {
218df54c2f9SSascha Wildner 	TW_UINT32			resp;
219df54c2f9SSascha Wildner 	struct tw_cli_req_context	*req;
220df54c2f9SSascha Wildner 	TW_INT32			error;
221df54c2f9SSascha Wildner 	TW_UINT32			status_reg;
222df54c2f9SSascha Wildner 
223df54c2f9SSascha Wildner 	tw_cli_dbg_printf(10, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
224df54c2f9SSascha Wildner 
225df54c2f9SSascha Wildner 	for (;;) {
226df54c2f9SSascha Wildner 		status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr->ctlr_handle);
227df54c2f9SSascha Wildner 		if ((error = tw_cli_check_ctlr_state(ctlr, status_reg)))
228df54c2f9SSascha Wildner 			break;
229df54c2f9SSascha Wildner 		if (status_reg & TWA_STATUS_RESPONSE_QUEUE_EMPTY) {
230df54c2f9SSascha Wildner 			tw_cli_dbg_printf(7, ctlr->ctlr_handle,
231df54c2f9SSascha Wildner 				tw_osl_cur_func(), "Response queue empty");
232df54c2f9SSascha Wildner 			break;
233df54c2f9SSascha Wildner 		}
234df54c2f9SSascha Wildner 
235df54c2f9SSascha Wildner 		/* Response queue is not empty. */
236df54c2f9SSascha Wildner 		resp = TW_CLI_READ_RESPONSE_QUEUE(ctlr->ctlr_handle);
237df54c2f9SSascha Wildner 		{
238df54c2f9SSascha Wildner 			req = &(ctlr->req_ctxt_buf[GET_RESP_ID(resp)]);
239df54c2f9SSascha Wildner 		}
240df54c2f9SSascha Wildner 
241df54c2f9SSascha Wildner 		if (req->state != TW_CLI_REQ_STATE_BUSY) {
242df54c2f9SSascha Wildner 			tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
243df54c2f9SSascha Wildner 				TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
244df54c2f9SSascha Wildner 				0x1201, 0x1, TW_CL_SEVERITY_ERROR_STRING,
245df54c2f9SSascha Wildner 				"Unposted command completed!!",
246df54c2f9SSascha Wildner 				"request = %p, status = %d",
247df54c2f9SSascha Wildner 				req, req->state);
248df54c2f9SSascha Wildner #ifdef TW_OSL_DEBUG
249df54c2f9SSascha Wildner 			tw_cl_print_ctlr_stats(ctlr->ctlr_handle);
250df54c2f9SSascha Wildner #endif /* TW_OSL_DEBUG */
2514fbf05f9SSascha Wildner 			continue;
252df54c2f9SSascha Wildner 		}
253df54c2f9SSascha Wildner 
254df54c2f9SSascha Wildner 		/*
255df54c2f9SSascha Wildner 		 * Remove the request from the busy queue, mark it as complete,
256df54c2f9SSascha Wildner 		 * and enqueue it in the complete queue.
257df54c2f9SSascha Wildner 		 */
258df54c2f9SSascha Wildner 		tw_cli_req_q_remove_item(req, TW_CLI_BUSY_Q);
259df54c2f9SSascha Wildner 		req->state = TW_CLI_REQ_STATE_COMPLETE;
260df54c2f9SSascha Wildner 		tw_cli_req_q_insert_tail(req, TW_CLI_COMPLETE_Q);
261df54c2f9SSascha Wildner 
262df54c2f9SSascha Wildner 	}
263df54c2f9SSascha Wildner 
264df54c2f9SSascha Wildner 	/* Complete this, and other requests in the complete queue. */
265df54c2f9SSascha Wildner 	tw_cli_process_complete_queue(ctlr);
266df54c2f9SSascha Wildner 
267df54c2f9SSascha Wildner 	return(error);
268df54c2f9SSascha Wildner }
269df54c2f9SSascha Wildner 
270df54c2f9SSascha Wildner 
271df54c2f9SSascha Wildner 
272df54c2f9SSascha Wildner /*
273df54c2f9SSascha Wildner  * Function name:	tw_cli_submit_pending_queue
274df54c2f9SSascha Wildner  * Description:		Kick starts any requests in the pending queue.
275df54c2f9SSascha Wildner  *
276df54c2f9SSascha Wildner  * Input:		ctlr	-- ptr to CL internal ctlr context
277df54c2f9SSascha Wildner  * Output:		None
278df54c2f9SSascha Wildner  * Return value:	0	-- all pending requests submitted successfully
279df54c2f9SSascha Wildner  *			non-zero-- otherwise
280df54c2f9SSascha Wildner  */
281df54c2f9SSascha Wildner TW_INT32
tw_cli_submit_pending_queue(struct tw_cli_ctlr_context * ctlr)282df54c2f9SSascha Wildner tw_cli_submit_pending_queue(struct tw_cli_ctlr_context *ctlr)
283df54c2f9SSascha Wildner {
284df54c2f9SSascha Wildner 	struct tw_cli_req_context	*req;
285df54c2f9SSascha Wildner 	TW_INT32			error = TW_OSL_ESUCCESS;
286df54c2f9SSascha Wildner 
287df54c2f9SSascha Wildner 	tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
288df54c2f9SSascha Wildner 
289df54c2f9SSascha Wildner 	/*
290df54c2f9SSascha Wildner 	 * Pull requests off the pending queue, and submit them.
291df54c2f9SSascha Wildner 	 */
292df54c2f9SSascha Wildner 	while ((req = tw_cli_req_q_remove_head(ctlr, TW_CLI_PENDING_Q)) !=
293df54c2f9SSascha Wildner 		TW_CL_NULL) {
294df54c2f9SSascha Wildner 		if ((error = tw_cli_submit_cmd(req))) {
295df54c2f9SSascha Wildner 			if (error == TW_OSL_EBUSY) {
296df54c2f9SSascha Wildner 				tw_cli_dbg_printf(2, ctlr->ctlr_handle,
297df54c2f9SSascha Wildner 					tw_osl_cur_func(),
298df54c2f9SSascha Wildner 					"Requeueing pending request");
299df54c2f9SSascha Wildner 				req->state = TW_CLI_REQ_STATE_PENDING;
300df54c2f9SSascha Wildner 				/*
301df54c2f9SSascha Wildner 				 * Queue the request at the head of the pending
302df54c2f9SSascha Wildner 				 * queue, and break away, so we don't try to
303df54c2f9SSascha Wildner 				 * submit any more requests.
304df54c2f9SSascha Wildner 				 */
305df54c2f9SSascha Wildner 				tw_cli_req_q_insert_head(req, TW_CLI_PENDING_Q);
306df54c2f9SSascha Wildner 				break;
307df54c2f9SSascha Wildner 			} else {
308df54c2f9SSascha Wildner 				tw_cl_create_event(ctlr->ctlr_handle,
309df54c2f9SSascha Wildner 					TW_CL_FALSE,
310df54c2f9SSascha Wildner 					TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
311df54c2f9SSascha Wildner 					0x1202, 0x1,
312df54c2f9SSascha Wildner 					TW_CL_SEVERITY_ERROR_STRING,
313df54c2f9SSascha Wildner 					"Could not start request "
314df54c2f9SSascha Wildner 					"in pending queue",
315df54c2f9SSascha Wildner 					"request = %p, opcode = 0x%x, "
316df54c2f9SSascha Wildner 					"error = %d", req,
317df54c2f9SSascha Wildner 					GET_OPCODE(req->cmd_pkt->
318df54c2f9SSascha Wildner 						command.cmd_pkt_9k.res__opcode),
319df54c2f9SSascha Wildner 					error);
320df54c2f9SSascha Wildner 				/*
321df54c2f9SSascha Wildner 				 * Set the appropriate error and call the CL
322df54c2f9SSascha Wildner 				 * internal callback if there's one.  If the
323df54c2f9SSascha Wildner 				 * request originator is polling for completion,
324df54c2f9SSascha Wildner 				 * he should be checking req->error to
325df54c2f9SSascha Wildner 				 * determine that the request did not go
326df54c2f9SSascha Wildner 				 * through.  The request originators are
327df54c2f9SSascha Wildner 				 * responsible for the clean-up.
328df54c2f9SSascha Wildner 				 */
329df54c2f9SSascha Wildner 				req->error_code = error;
330df54c2f9SSascha Wildner 				req->state = TW_CLI_REQ_STATE_COMPLETE;
331df54c2f9SSascha Wildner 				if (req->tw_cli_callback)
332df54c2f9SSascha Wildner 					req->tw_cli_callback(req);
333df54c2f9SSascha Wildner 				error = TW_OSL_ESUCCESS;
334df54c2f9SSascha Wildner 			}
335df54c2f9SSascha Wildner 		}
336df54c2f9SSascha Wildner 	}
337df54c2f9SSascha Wildner 	return(error);
338df54c2f9SSascha Wildner }
339df54c2f9SSascha Wildner 
340df54c2f9SSascha Wildner 
341df54c2f9SSascha Wildner 
342df54c2f9SSascha Wildner /*
343df54c2f9SSascha Wildner  * Function name:	tw_cli_process_complete_queue
344df54c2f9SSascha Wildner  * Description:		Calls the CL internal callback routine, if any, for
345df54c2f9SSascha Wildner  *			each request in the complete queue.
346df54c2f9SSascha Wildner  *
347df54c2f9SSascha Wildner  * Input:		ctlr	-- ptr to CL internal ctlr context
348df54c2f9SSascha Wildner  * Output:		None
349df54c2f9SSascha Wildner  * Return value:	None
350df54c2f9SSascha Wildner  */
351df54c2f9SSascha Wildner TW_VOID
tw_cli_process_complete_queue(struct tw_cli_ctlr_context * ctlr)352df54c2f9SSascha Wildner tw_cli_process_complete_queue(struct tw_cli_ctlr_context *ctlr)
353df54c2f9SSascha Wildner {
354df54c2f9SSascha Wildner 	struct tw_cli_req_context	*req;
355df54c2f9SSascha Wildner 
356df54c2f9SSascha Wildner 	tw_cli_dbg_printf(10, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
357df54c2f9SSascha Wildner 
358df54c2f9SSascha Wildner 	/*
359df54c2f9SSascha Wildner 	 * Pull commands off the completed list, dispatch them appropriately.
360df54c2f9SSascha Wildner 	 */
361df54c2f9SSascha Wildner 	while ((req = tw_cli_req_q_remove_head(ctlr, TW_CLI_COMPLETE_Q)) !=
362df54c2f9SSascha Wildner 		TW_CL_NULL) {
363df54c2f9SSascha Wildner 		/* Call the CL internal callback, if there's one. */
364df54c2f9SSascha Wildner 		if (req->tw_cli_callback)
365df54c2f9SSascha Wildner 			req->tw_cli_callback(req);
366df54c2f9SSascha Wildner 	}
367df54c2f9SSascha Wildner }
368df54c2f9SSascha Wildner 
369df54c2f9SSascha Wildner 
370df54c2f9SSascha Wildner 
371df54c2f9SSascha Wildner /*
372df54c2f9SSascha Wildner  * Function name:	tw_cli_complete_io
373df54c2f9SSascha Wildner  * Description:		CL internal callback for SCSI/fw passthru requests.
374df54c2f9SSascha Wildner  *
375df54c2f9SSascha Wildner  * Input:		req	-- ptr to CL internal request context
376df54c2f9SSascha Wildner  * Output:		None
377df54c2f9SSascha Wildner  * Return value:	None
378df54c2f9SSascha Wildner  */
379df54c2f9SSascha Wildner TW_VOID
tw_cli_complete_io(struct tw_cli_req_context * req)380df54c2f9SSascha Wildner tw_cli_complete_io(struct tw_cli_req_context *req)
381df54c2f9SSascha Wildner {
382df54c2f9SSascha Wildner 	struct tw_cli_ctlr_context	*ctlr = req->ctlr;
383df54c2f9SSascha Wildner 	struct tw_cl_req_packet		*req_pkt =
384df54c2f9SSascha Wildner 		(struct tw_cl_req_packet *)(req->orig_req);
385df54c2f9SSascha Wildner 
386df54c2f9SSascha Wildner 	tw_cli_dbg_printf(8, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
387df54c2f9SSascha Wildner 
388df54c2f9SSascha Wildner 	req_pkt->status = TW_CL_ERR_REQ_SUCCESS;
389df54c2f9SSascha Wildner 	if (req->error_code) {
390df54c2f9SSascha Wildner 		req_pkt->status = TW_CL_ERR_REQ_UNABLE_TO_SUBMIT_COMMAND;
391df54c2f9SSascha Wildner 		goto out;
392df54c2f9SSascha Wildner 	}
393df54c2f9SSascha Wildner 
394df54c2f9SSascha Wildner 	if (req->state != TW_CLI_REQ_STATE_COMPLETE) {
395df54c2f9SSascha Wildner 		tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
396df54c2f9SSascha Wildner 			TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
397df54c2f9SSascha Wildner 			0x1203, 0x1, TW_CL_SEVERITY_ERROR_STRING,
398df54c2f9SSascha Wildner 			"I/O completion on incomplete command!!",
399df54c2f9SSascha Wildner 			"request = %p, status = %d",
400df54c2f9SSascha Wildner 			req, req->state);
401df54c2f9SSascha Wildner #ifdef TW_OSL_DEBUG
402df54c2f9SSascha Wildner 		tw_cl_print_ctlr_stats(ctlr->ctlr_handle);
403df54c2f9SSascha Wildner #endif /* TW_OSL_DEBUG */
4044fbf05f9SSascha Wildner 		return;
405df54c2f9SSascha Wildner 	}
406df54c2f9SSascha Wildner 
407df54c2f9SSascha Wildner 	if (req->flags & TW_CLI_REQ_FLAGS_PASSTHRU) {
408df54c2f9SSascha Wildner 		/* Copy the command packet back into OSL's space. */
409df54c2f9SSascha Wildner 		tw_osl_memcpy(req_pkt->gen_req_pkt.pt_req.cmd_pkt, req->cmd_pkt,
410df54c2f9SSascha Wildner 			sizeof(struct tw_cl_command_packet));
411df54c2f9SSascha Wildner 	} else
412df54c2f9SSascha Wildner 		tw_cli_scsi_complete(req);
413df54c2f9SSascha Wildner 
414df54c2f9SSascha Wildner out:
415df54c2f9SSascha Wildner 	req_pkt->tw_osl_callback(req->req_handle);
416df54c2f9SSascha Wildner 	tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
417df54c2f9SSascha Wildner }
418df54c2f9SSascha Wildner 
419df54c2f9SSascha Wildner 
420df54c2f9SSascha Wildner 
421df54c2f9SSascha Wildner /*
422df54c2f9SSascha Wildner  * Function name:	tw_cli_scsi_complete
423df54c2f9SSascha Wildner  * Description:		Completion routine for SCSI requests.
424df54c2f9SSascha Wildner  *
425df54c2f9SSascha Wildner  * Input:		req	-- ptr to CL internal request context
426df54c2f9SSascha Wildner  * Output:		None
427df54c2f9SSascha Wildner  * Return value:	None
428df54c2f9SSascha Wildner  */
429df54c2f9SSascha Wildner TW_VOID
tw_cli_scsi_complete(struct tw_cli_req_context * req)430df54c2f9SSascha Wildner tw_cli_scsi_complete(struct tw_cli_req_context *req)
431df54c2f9SSascha Wildner {
432df54c2f9SSascha Wildner 	struct tw_cl_req_packet		*req_pkt =
433df54c2f9SSascha Wildner 		(struct tw_cl_req_packet *)(req->orig_req);
434df54c2f9SSascha Wildner 	struct tw_cl_scsi_req_packet	*scsi_req =
435df54c2f9SSascha Wildner 		&(req_pkt->gen_req_pkt.scsi_req);
436df54c2f9SSascha Wildner 	struct tw_cl_command_9k		*cmd =
437df54c2f9SSascha Wildner 		&(req->cmd_pkt->command.cmd_pkt_9k);
438df54c2f9SSascha Wildner 	struct tw_cl_command_header	*cmd_hdr;
439df54c2f9SSascha Wildner 	TW_UINT16			error;
440df54c2f9SSascha Wildner 	TW_UINT8			*cdb;
441df54c2f9SSascha Wildner 
442df54c2f9SSascha Wildner 	tw_cli_dbg_printf(8, req->ctlr->ctlr_handle, tw_osl_cur_func(),
443df54c2f9SSascha Wildner 		"entered");
444df54c2f9SSascha Wildner 
445df54c2f9SSascha Wildner 	scsi_req->scsi_status = cmd->status;
446df54c2f9SSascha Wildner 	if (! cmd->status)
447df54c2f9SSascha Wildner 		return;
448df54c2f9SSascha Wildner 
449df54c2f9SSascha Wildner 	tw_cli_dbg_printf(1, req->ctlr->ctlr_handle, tw_osl_cur_func(),
450df54c2f9SSascha Wildner 		"req_id = 0x%x, status = 0x%x",
451df54c2f9SSascha Wildner 		GET_REQ_ID(cmd->lun_l4__req_id), cmd->status);
452df54c2f9SSascha Wildner 
453df54c2f9SSascha Wildner 	cmd_hdr = &(req->cmd_pkt->cmd_hdr);
454df54c2f9SSascha Wildner 	error = cmd_hdr->status_block.error;
455df54c2f9SSascha Wildner 	if ((error == TWA_ERROR_LOGICAL_UNIT_NOT_SUPPORTED) ||
456df54c2f9SSascha Wildner 			(error == TWA_ERROR_UNIT_OFFLINE)) {
457df54c2f9SSascha Wildner 		if (GET_LUN_L4(cmd->lun_l4__req_id))
458df54c2f9SSascha Wildner 			req_pkt->status |= TW_CL_ERR_REQ_INVALID_LUN;
459df54c2f9SSascha Wildner 		else
460df54c2f9SSascha Wildner 			req_pkt->status |= TW_CL_ERR_REQ_INVALID_TARGET;
461df54c2f9SSascha Wildner 	} else {
462df54c2f9SSascha Wildner 		tw_cli_dbg_printf(2, req->ctlr->ctlr_handle,
463df54c2f9SSascha Wildner 			tw_osl_cur_func(),
464df54c2f9SSascha Wildner 			"cmd = %x %x %x %x %x %x %x",
465df54c2f9SSascha Wildner 			GET_OPCODE(cmd->res__opcode),
466df54c2f9SSascha Wildner 			GET_SGL_OFF(cmd->res__opcode),
467df54c2f9SSascha Wildner 			cmd->unit,
468df54c2f9SSascha Wildner 			cmd->lun_l4__req_id,
469df54c2f9SSascha Wildner 			cmd->status,
470df54c2f9SSascha Wildner 			cmd->sgl_offset,
471df54c2f9SSascha Wildner 			cmd->lun_h4__sgl_entries);
472df54c2f9SSascha Wildner 
473df54c2f9SSascha Wildner 		cdb = (TW_UINT8 *)(cmd->cdb);
474df54c2f9SSascha Wildner 		tw_cli_dbg_printf(2, req->ctlr->ctlr_handle,
475df54c2f9SSascha Wildner 			tw_osl_cur_func(),
476df54c2f9SSascha Wildner 			"cdb = %x %x %x %x %x %x %x %x "
477df54c2f9SSascha Wildner 			"%x %x %x %x %x %x %x %x",
478df54c2f9SSascha Wildner 			cdb[0], cdb[1], cdb[2], cdb[3],
479df54c2f9SSascha Wildner 			cdb[4], cdb[5], cdb[6], cdb[7],
480df54c2f9SSascha Wildner 			cdb[8], cdb[9], cdb[10], cdb[11],
481df54c2f9SSascha Wildner 			cdb[12], cdb[13], cdb[14], cdb[15]);
482df54c2f9SSascha Wildner 
4834fbf05f9SSascha Wildner #if       0
484df54c2f9SSascha Wildner 		/*
485df54c2f9SSascha Wildner 		 * Print the error. Firmware doesn't yet support
486df54c2f9SSascha Wildner 		 * the 'Mode Sense' cmd.  Don't print if the cmd
487df54c2f9SSascha Wildner 		 * is 'Mode Sense', and the error is 'Invalid field
488df54c2f9SSascha Wildner 		 * in CDB'.
489df54c2f9SSascha Wildner 		 */
490df54c2f9SSascha Wildner 		if (! ((cdb[0] == 0x1A) && (error == 0x10D)))
491df54c2f9SSascha Wildner 			tw_cli_create_ctlr_event(req->ctlr,
492df54c2f9SSascha Wildner 				TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR,
493df54c2f9SSascha Wildner 				cmd_hdr);
4944fbf05f9SSascha Wildner #endif // 0
495df54c2f9SSascha Wildner 	}
496df54c2f9SSascha Wildner 
497df54c2f9SSascha Wildner 	if (scsi_req->sense_data) {
498df54c2f9SSascha Wildner 		tw_osl_memcpy(scsi_req->sense_data, cmd_hdr->sense_data,
499df54c2f9SSascha Wildner 			TWA_SENSE_DATA_LENGTH);
500df54c2f9SSascha Wildner 		scsi_req->sense_len = TWA_SENSE_DATA_LENGTH;
501df54c2f9SSascha Wildner 		req_pkt->status |= TW_CL_ERR_REQ_AUTO_SENSE_VALID;
502df54c2f9SSascha Wildner 	}
503df54c2f9SSascha Wildner 	req_pkt->status |= TW_CL_ERR_REQ_SCSI_ERROR;
504df54c2f9SSascha Wildner }
505df54c2f9SSascha Wildner 
506df54c2f9SSascha Wildner 
507df54c2f9SSascha Wildner 
508df54c2f9SSascha Wildner /*
509df54c2f9SSascha Wildner  * Function name:	tw_cli_param_callback
510df54c2f9SSascha Wildner  * Description:		Callback for get/set_param requests.
511df54c2f9SSascha Wildner  *
512df54c2f9SSascha Wildner  * Input:		req	-- ptr to completed request pkt
513df54c2f9SSascha Wildner  * Output:		None
514df54c2f9SSascha Wildner  * Return value:	None
515df54c2f9SSascha Wildner  */
516df54c2f9SSascha Wildner TW_VOID
tw_cli_param_callback(struct tw_cli_req_context * req)517df54c2f9SSascha Wildner tw_cli_param_callback(struct tw_cli_req_context *req)
518df54c2f9SSascha Wildner {
519df54c2f9SSascha Wildner 	struct tw_cli_ctlr_context	*ctlr = req->ctlr;
520df54c2f9SSascha Wildner 	union tw_cl_command_7k		*cmd =
521df54c2f9SSascha Wildner 		&(req->cmd_pkt->command.cmd_pkt_7k);
522df54c2f9SSascha Wildner 	TW_INT32			error;
523df54c2f9SSascha Wildner 
524df54c2f9SSascha Wildner 	tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
525df54c2f9SSascha Wildner 
526df54c2f9SSascha Wildner 	/*
527df54c2f9SSascha Wildner 	 * If the request was never submitted to the controller, the function
528df54c2f9SSascha Wildner 	 * that sets req->error is responsible for calling tw_cl_create_event.
529df54c2f9SSascha Wildner 	 */
530df54c2f9SSascha Wildner 	if (! req->error_code)
531df54c2f9SSascha Wildner 		if (cmd->param.status) {
5324fbf05f9SSascha Wildner #if       0
533df54c2f9SSascha Wildner 			tw_cli_create_ctlr_event(ctlr,
534df54c2f9SSascha Wildner 				TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR,
535df54c2f9SSascha Wildner 				&(req->cmd_pkt->cmd_hdr));
5364fbf05f9SSascha Wildner #endif // 0
537df54c2f9SSascha Wildner 			tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
538df54c2f9SSascha Wildner 				TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
539df54c2f9SSascha Wildner 				0x1204, 0x1, TW_CL_SEVERITY_ERROR_STRING,
540df54c2f9SSascha Wildner 				"get/set_param failed",
541df54c2f9SSascha Wildner 				"status = %d", cmd->param.status);
542df54c2f9SSascha Wildner 		}
543df54c2f9SSascha Wildner 
544df54c2f9SSascha Wildner 	ctlr->internal_req_busy = TW_CL_FALSE;
545df54c2f9SSascha Wildner 	tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
546df54c2f9SSascha Wildner 
547df54c2f9SSascha Wildner 	if ((ctlr->get_more_aens) && (!(ctlr->reset_in_progress))) {
548df54c2f9SSascha Wildner 		ctlr->get_more_aens = TW_CL_FALSE;
549df54c2f9SSascha Wildner 		tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(),
550df54c2f9SSascha Wildner 			"Fetching more AEN's");
551df54c2f9SSascha Wildner 		if ((error = tw_cli_get_aen(ctlr)))
552df54c2f9SSascha Wildner 			tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
553df54c2f9SSascha Wildner 				TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
554df54c2f9SSascha Wildner 				0x1205, 0x1, TW_CL_SEVERITY_ERROR_STRING,
555df54c2f9SSascha Wildner 				"Failed to fetch all AEN's from param_callback",
556df54c2f9SSascha Wildner 				"error = %d", error);
557df54c2f9SSascha Wildner 	}
558df54c2f9SSascha Wildner }
559df54c2f9SSascha Wildner 
560df54c2f9SSascha Wildner 
561df54c2f9SSascha Wildner 
562df54c2f9SSascha Wildner /*
563df54c2f9SSascha Wildner  * Function name:	tw_cli_aen_callback
564df54c2f9SSascha Wildner  * Description:		Callback for requests to fetch AEN's.
565df54c2f9SSascha Wildner  *
566df54c2f9SSascha Wildner  * Input:		req	-- ptr to completed request pkt
567df54c2f9SSascha Wildner  * Output:		None
568df54c2f9SSascha Wildner  * Return value:	None
569df54c2f9SSascha Wildner  */
570df54c2f9SSascha Wildner TW_VOID
tw_cli_aen_callback(struct tw_cli_req_context * req)571df54c2f9SSascha Wildner tw_cli_aen_callback(struct tw_cli_req_context *req)
572df54c2f9SSascha Wildner {
573df54c2f9SSascha Wildner 	struct tw_cli_ctlr_context	*ctlr = req->ctlr;
574df54c2f9SSascha Wildner 	struct tw_cl_command_9k		*cmd =
575df54c2f9SSascha Wildner 		&(req->cmd_pkt->command.cmd_pkt_9k);
576df54c2f9SSascha Wildner 	TW_UINT16			aen_code = TWA_AEN_QUEUE_EMPTY;
577df54c2f9SSascha Wildner 	TW_INT32			error;
578df54c2f9SSascha Wildner 
579df54c2f9SSascha Wildner 	tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
580df54c2f9SSascha Wildner 
581df54c2f9SSascha Wildner 	tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(),
582df54c2f9SSascha Wildner 		"req_id = 0x%x, req error = %d, status = 0x%x",
583df54c2f9SSascha Wildner 		GET_REQ_ID(cmd->lun_l4__req_id), req->error_code, cmd->status);
584df54c2f9SSascha Wildner 
585df54c2f9SSascha Wildner 	/*
586df54c2f9SSascha Wildner 	 * If the request was never submitted to the controller, the function
587df54c2f9SSascha Wildner 	 * that sets error is responsible for calling tw_cl_create_event.
588df54c2f9SSascha Wildner 	 */
589df54c2f9SSascha Wildner 	if (!(error = req->error_code))
590df54c2f9SSascha Wildner 		if ((error = cmd->status)) {
591c6fd73a3SSascha Wildner #if       0
592c6fd73a3SSascha Wildner 			struct tw_cl_command_header	*cmd_hdr;
593df54c2f9SSascha Wildner 			cmd_hdr = (struct tw_cl_command_header *)
594df54c2f9SSascha Wildner 				(&(req->cmd_pkt->cmd_hdr));
595df54c2f9SSascha Wildner 			tw_cli_create_ctlr_event(ctlr,
596df54c2f9SSascha Wildner 				TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR,
597df54c2f9SSascha Wildner 				cmd_hdr);
5984fbf05f9SSascha Wildner #endif // 0
599df54c2f9SSascha Wildner 			tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
600df54c2f9SSascha Wildner 				TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
601df54c2f9SSascha Wildner 				0x1206, 0x1, TW_CL_SEVERITY_ERROR_STRING,
602df54c2f9SSascha Wildner 				"Request Sense failed",
603df54c2f9SSascha Wildner 				"opcode = 0x%x, status = %d",
604df54c2f9SSascha Wildner 				GET_OPCODE(cmd->res__opcode), cmd->status);
605df54c2f9SSascha Wildner 		}
606df54c2f9SSascha Wildner 
607df54c2f9SSascha Wildner 	if (error) {
608df54c2f9SSascha Wildner 		ctlr->internal_req_busy = TW_CL_FALSE;
609df54c2f9SSascha Wildner 		tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
610df54c2f9SSascha Wildner 		return;
611df54c2f9SSascha Wildner 	}
612df54c2f9SSascha Wildner 
613df54c2f9SSascha Wildner 	tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(),
614df54c2f9SSascha Wildner 		"Request Sense command succeeded");
615df54c2f9SSascha Wildner 
616df54c2f9SSascha Wildner 	aen_code = tw_cli_manage_aen(ctlr, req);
617df54c2f9SSascha Wildner 
618df54c2f9SSascha Wildner 	if (aen_code != TWA_AEN_SYNC_TIME_WITH_HOST) {
619df54c2f9SSascha Wildner 		ctlr->internal_req_busy = TW_CL_FALSE;
620df54c2f9SSascha Wildner 		tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
621df54c2f9SSascha Wildner 		if (aen_code != TWA_AEN_QUEUE_EMPTY)
622df54c2f9SSascha Wildner 			if ((error = tw_cli_get_aen(ctlr)))
623df54c2f9SSascha Wildner 				tw_cl_create_event(ctlr->ctlr_handle,
624df54c2f9SSascha Wildner 					TW_CL_FALSE,
625df54c2f9SSascha Wildner 					TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
626df54c2f9SSascha Wildner 					0x1207, 0x1,
627df54c2f9SSascha Wildner 					TW_CL_SEVERITY_ERROR_STRING,
628df54c2f9SSascha Wildner 					"Failed to fetch all AEN's",
629df54c2f9SSascha Wildner 					"error = %d", error);
630df54c2f9SSascha Wildner 	}
631df54c2f9SSascha Wildner }
632df54c2f9SSascha Wildner 
633df54c2f9SSascha Wildner 
634df54c2f9SSascha Wildner 
635df54c2f9SSascha Wildner /*
636df54c2f9SSascha Wildner  * Function name:	tw_cli_manage_aen
637df54c2f9SSascha Wildner  * Description:		Handles AEN's.
638df54c2f9SSascha Wildner  *
639df54c2f9SSascha Wildner  * Input:		ctlr	-- ptr to CL internal ctlr context
640df54c2f9SSascha Wildner  *			req	-- ptr to CL internal request context
641df54c2f9SSascha Wildner  * Output:		None
642df54c2f9SSascha Wildner  * Return value:	None
643df54c2f9SSascha Wildner  */
644df54c2f9SSascha Wildner TW_UINT16
tw_cli_manage_aen(struct tw_cli_ctlr_context * ctlr,struct tw_cli_req_context * req)645df54c2f9SSascha Wildner tw_cli_manage_aen(struct tw_cli_ctlr_context *ctlr,
646df54c2f9SSascha Wildner 	struct tw_cli_req_context *req)
647df54c2f9SSascha Wildner {
648df54c2f9SSascha Wildner 	struct tw_cl_command_header	*cmd_hdr;
649df54c2f9SSascha Wildner 	TW_UINT16			aen_code;
650df54c2f9SSascha Wildner 	TW_TIME				local_time;
651df54c2f9SSascha Wildner 	TW_TIME				sync_time;
652df54c2f9SSascha Wildner 	TW_UINT32			error;
653df54c2f9SSascha Wildner 
654df54c2f9SSascha Wildner 	tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
655df54c2f9SSascha Wildner 
656df54c2f9SSascha Wildner 	cmd_hdr = (struct tw_cl_command_header *)(req->data);
657df54c2f9SSascha Wildner 	aen_code = cmd_hdr->status_block.error;
658df54c2f9SSascha Wildner 
659df54c2f9SSascha Wildner 	switch (aen_code) {
660df54c2f9SSascha Wildner 	case TWA_AEN_SYNC_TIME_WITH_HOST:
661df54c2f9SSascha Wildner 		tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(),
662df54c2f9SSascha Wildner 			"Received AEN_SYNC_TIME");
663df54c2f9SSascha Wildner 		/*
664df54c2f9SSascha Wildner 		 * Free the internal req pkt right here, since
665df54c2f9SSascha Wildner 		 * tw_cli_set_param will need it.
666df54c2f9SSascha Wildner 		 */
667df54c2f9SSascha Wildner 		ctlr->internal_req_busy = TW_CL_FALSE;
668df54c2f9SSascha Wildner 		tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
669df54c2f9SSascha Wildner 
670df54c2f9SSascha Wildner 		/*
671df54c2f9SSascha Wildner 		 * We will use a callback in tw_cli_set_param only when
672df54c2f9SSascha Wildner 		 * interrupts are enabled and we can expect our callback
673df54c2f9SSascha Wildner 		 * to get called.  Setting the get_more_aens
674df54c2f9SSascha Wildner 		 * flag will make the callback continue to try to retrieve
675df54c2f9SSascha Wildner 		 * more AEN's.
676df54c2f9SSascha Wildner 		 */
677df54c2f9SSascha Wildner 		if (ctlr->interrupts_enabled)
678df54c2f9SSascha Wildner 			ctlr->get_more_aens = TW_CL_TRUE;
679df54c2f9SSascha Wildner 		/* Calculate time (in seconds) since last Sunday 12.00 AM. */
680df54c2f9SSascha Wildner 		local_time = tw_osl_get_local_time();
681df54c2f9SSascha Wildner 		sync_time = (local_time - (3 * 86400)) % 604800;
682df54c2f9SSascha Wildner 		if ((error = tw_cli_set_param(ctlr, TWA_PARAM_TIME_TABLE,
683df54c2f9SSascha Wildner 				TWA_PARAM_TIME_SCHED_TIME, 4,
684df54c2f9SSascha Wildner 				&sync_time,
685df54c2f9SSascha Wildner 				(ctlr->interrupts_enabled)
686df54c2f9SSascha Wildner 				? tw_cli_param_callback : TW_CL_NULL)))
687df54c2f9SSascha Wildner 			tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
688df54c2f9SSascha Wildner 				TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
689df54c2f9SSascha Wildner 				0x1208, 0x1, TW_CL_SEVERITY_ERROR_STRING,
690df54c2f9SSascha Wildner 				"Unable to sync time with ctlr",
691df54c2f9SSascha Wildner 				"error = %d", error);
692df54c2f9SSascha Wildner 
693df54c2f9SSascha Wildner 		break;
694df54c2f9SSascha Wildner 
695df54c2f9SSascha Wildner 
696df54c2f9SSascha Wildner 	case TWA_AEN_QUEUE_EMPTY:
697df54c2f9SSascha Wildner 		tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(),
698df54c2f9SSascha Wildner 			"AEN queue empty");
699df54c2f9SSascha Wildner 		break;
700df54c2f9SSascha Wildner 
701df54c2f9SSascha Wildner 
702df54c2f9SSascha Wildner 	default:
703df54c2f9SSascha Wildner 		/* Queue the event. */
704df54c2f9SSascha Wildner 
705df54c2f9SSascha Wildner 		tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(),
706df54c2f9SSascha Wildner 			"Queueing AEN");
707df54c2f9SSascha Wildner 		tw_cli_create_ctlr_event(ctlr,
708df54c2f9SSascha Wildner 			TW_CL_MESSAGE_SOURCE_CONTROLLER_EVENT,
709df54c2f9SSascha Wildner 			cmd_hdr);
710df54c2f9SSascha Wildner 		break;
711df54c2f9SSascha Wildner 	} /* switch */
712df54c2f9SSascha Wildner 	return(aen_code);
713df54c2f9SSascha Wildner }
714df54c2f9SSascha Wildner 
715df54c2f9SSascha Wildner 
716df54c2f9SSascha Wildner 
717df54c2f9SSascha Wildner /*
718df54c2f9SSascha Wildner  * Function name:	tw_cli_enable_interrupts
719df54c2f9SSascha Wildner  * Description:		Enables interrupts on the controller
720df54c2f9SSascha Wildner  *
721df54c2f9SSascha Wildner  * Input:		ctlr	-- ptr to CL internal ctlr context
722df54c2f9SSascha Wildner  * Output:		None
723df54c2f9SSascha Wildner  * Return value:	None
724df54c2f9SSascha Wildner  */
725df54c2f9SSascha Wildner TW_VOID
tw_cli_enable_interrupts(struct tw_cli_ctlr_context * ctlr)726df54c2f9SSascha Wildner tw_cli_enable_interrupts(struct tw_cli_ctlr_context *ctlr)
727df54c2f9SSascha Wildner {
728df54c2f9SSascha Wildner 	tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
729df54c2f9SSascha Wildner 
730df54c2f9SSascha Wildner 	ctlr->interrupts_enabled = TW_CL_TRUE;
731df54c2f9SSascha Wildner 	TW_CLI_WRITE_CONTROL_REGISTER(ctlr->ctlr_handle,
732df54c2f9SSascha Wildner 		TWA_CONTROL_CLEAR_ATTENTION_INTERRUPT |
733df54c2f9SSascha Wildner 		TWA_CONTROL_UNMASK_RESPONSE_INTERRUPT |
734df54c2f9SSascha Wildner 		TWA_CONTROL_ENABLE_INTERRUPTS);
735df54c2f9SSascha Wildner }
736df54c2f9SSascha Wildner 
737df54c2f9SSascha Wildner 
738df54c2f9SSascha Wildner 
739df54c2f9SSascha Wildner /*
740df54c2f9SSascha Wildner  * Function name:	twa_setup
741df54c2f9SSascha Wildner  * Description:		Disables interrupts on the controller
742df54c2f9SSascha Wildner  *
743df54c2f9SSascha Wildner  * Input:		ctlr	-- ptr to CL internal ctlr context
744df54c2f9SSascha Wildner  * Output:		None
745df54c2f9SSascha Wildner  * Return value:	None
746df54c2f9SSascha Wildner  */
747df54c2f9SSascha Wildner TW_VOID
tw_cli_disable_interrupts(struct tw_cli_ctlr_context * ctlr)748df54c2f9SSascha Wildner tw_cli_disable_interrupts(struct tw_cli_ctlr_context *ctlr)
749df54c2f9SSascha Wildner {
750df54c2f9SSascha Wildner 	tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
751df54c2f9SSascha Wildner 
752df54c2f9SSascha Wildner 	TW_CLI_WRITE_CONTROL_REGISTER(ctlr->ctlr_handle,
753df54c2f9SSascha Wildner 		TWA_CONTROL_DISABLE_INTERRUPTS);
754df54c2f9SSascha Wildner 	ctlr->interrupts_enabled = TW_CL_FALSE;
755df54c2f9SSascha Wildner }
756