xref: /dflybsd-src/sys/dev/raid/twa/tw_cl_misc.c (revision d26841ecab7b9e18efdfee9ce80b153c2dc3bb9a)
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  *
271e0dd9ddSSascha Wildner  *	$FreeBSD: head/sys/dev/twa/tw_cl_misc.c 242827 2012-11-09 15:29:52Z rdivacky $
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 miscellaneous 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 /* AEN severity table. */
55df54c2f9SSascha Wildner TW_INT8	*tw_cli_severity_string_table[] = {
56df54c2f9SSascha Wildner 	"None",
57df54c2f9SSascha Wildner 	TW_CL_SEVERITY_ERROR_STRING,
58df54c2f9SSascha Wildner 	TW_CL_SEVERITY_WARNING_STRING,
59df54c2f9SSascha Wildner 	TW_CL_SEVERITY_INFO_STRING,
60df54c2f9SSascha Wildner 	TW_CL_SEVERITY_DEBUG_STRING,
61df54c2f9SSascha Wildner 	""
62df54c2f9SSascha Wildner };
63df54c2f9SSascha Wildner 
64df54c2f9SSascha Wildner 
65df54c2f9SSascha Wildner 
66df54c2f9SSascha Wildner /*
67df54c2f9SSascha Wildner  * Function name:	tw_cli_drain_complete_queue
68df54c2f9SSascha Wildner  * Description:		This function gets called during a controller reset.
69df54c2f9SSascha Wildner  *			It errors back to the OS Layer, all those requests that
70df54c2f9SSascha Wildner  *			are in the complete queue, at the time of the reset.
71df54c2f9SSascha Wildner  *			Any CL internal requests will be simply freed.
72df54c2f9SSascha Wildner  *
73df54c2f9SSascha Wildner  * Input:		ctlr	-- ptr to CL internal ctlr context
74df54c2f9SSascha Wildner  * Output:		None
75df54c2f9SSascha Wildner  * Return value:	None
76df54c2f9SSascha Wildner  */
77df54c2f9SSascha Wildner TW_VOID
tw_cli_drain_complete_queue(struct tw_cli_ctlr_context * ctlr)78df54c2f9SSascha Wildner tw_cli_drain_complete_queue(struct tw_cli_ctlr_context *ctlr)
79df54c2f9SSascha Wildner {
80df54c2f9SSascha Wildner 	struct tw_cli_req_context	*req;
81df54c2f9SSascha Wildner 	struct tw_cl_req_packet		*req_pkt;
82df54c2f9SSascha Wildner 
83df54c2f9SSascha Wildner 	tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
84df54c2f9SSascha Wildner 
85df54c2f9SSascha Wildner 	/* Walk the busy queue. */
864fbf05f9SSascha Wildner 	while ((req = tw_cli_req_q_remove_head(ctlr, TW_CLI_COMPLETE_Q)) !=
874fbf05f9SSascha Wildner 		TW_CL_NULL) {
88df54c2f9SSascha Wildner 		if (req->flags & TW_CLI_REQ_FLAGS_INTERNAL) {
89df54c2f9SSascha Wildner 			/*
90df54c2f9SSascha Wildner 			 * It's an internal request.  Set the appropriate
91df54c2f9SSascha Wildner 			 * error and call the CL internal callback if there's
92df54c2f9SSascha Wildner 			 * one.  If the request originator is polling for
93df54c2f9SSascha Wildner 			 * completion, he should be checking req->error to
94df54c2f9SSascha Wildner 			 * determine that the request did not go through.
95df54c2f9SSascha Wildner 			 * The request originators are responsible for the
96df54c2f9SSascha Wildner 			 * clean-up.
97df54c2f9SSascha Wildner 			 */
98df54c2f9SSascha Wildner 			req->error_code = TW_CL_ERR_REQ_BUS_RESET;
99df54c2f9SSascha Wildner 			if (req->tw_cli_callback)
100df54c2f9SSascha Wildner 				req->tw_cli_callback(req);
1014fbf05f9SSascha Wildner 		} else if (req->flags & TW_CLI_REQ_FLAGS_PASSTHRU) {
1024fbf05f9SSascha Wildner 			/* It's a passthru request.  Complete it. */
1034fbf05f9SSascha Wildner 			if ((req_pkt = req->orig_req) != TW_CL_NULL) {
104df54c2f9SSascha Wildner 				req_pkt->status = TW_CL_ERR_REQ_BUS_RESET;
1054fbf05f9SSascha Wildner 
1064fbf05f9SSascha Wildner 				if (req_pkt->tw_osl_callback)
107df54c2f9SSascha Wildner 					req_pkt->tw_osl_callback(req->req_handle);
108df54c2f9SSascha Wildner 			}
109df54c2f9SSascha Wildner 			tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
1104fbf05f9SSascha Wildner 		} else {
1114fbf05f9SSascha Wildner 			/* It's an external (SCSI) request.  Add it to the reset queue. */
1124fbf05f9SSascha Wildner 			tw_osl_untimeout(req->req_handle);
1134fbf05f9SSascha Wildner 			tw_cli_req_q_insert_tail(req, TW_CLI_RESET_Q);
114df54c2f9SSascha Wildner 		}
1154fbf05f9SSascha Wildner 	} /* End of while loop */
116df54c2f9SSascha Wildner }
117df54c2f9SSascha Wildner 
118df54c2f9SSascha Wildner 
119df54c2f9SSascha Wildner 
120df54c2f9SSascha Wildner /*
121df54c2f9SSascha Wildner  * Function name:	tw_cli_drain_busy_queue
122df54c2f9SSascha Wildner  * Description:		This function gets called during a controller reset.
123df54c2f9SSascha Wildner  *			It errors back to the OS Layer, all those requests that
124df54c2f9SSascha Wildner  *			were pending with the firmware, at the time of the
125df54c2f9SSascha Wildner  *			reset.
126df54c2f9SSascha Wildner  *
127df54c2f9SSascha Wildner  * Input:		ctlr	-- ptr to CL internal ctlr context
128df54c2f9SSascha Wildner  * Output:		None
129df54c2f9SSascha Wildner  * Return value:	None
130df54c2f9SSascha Wildner  */
131df54c2f9SSascha Wildner TW_VOID
tw_cli_drain_busy_queue(struct tw_cli_ctlr_context * ctlr)132df54c2f9SSascha Wildner tw_cli_drain_busy_queue(struct tw_cli_ctlr_context *ctlr)
133df54c2f9SSascha Wildner {
134df54c2f9SSascha Wildner 	struct tw_cli_req_context	*req;
135df54c2f9SSascha Wildner 	struct tw_cl_req_packet		*req_pkt;
136df54c2f9SSascha Wildner 
137df54c2f9SSascha Wildner 	tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
138df54c2f9SSascha Wildner 
139df54c2f9SSascha Wildner 	/* Walk the busy queue. */
1404fbf05f9SSascha Wildner 	while ((req = tw_cli_req_q_remove_head(ctlr, TW_CLI_BUSY_Q)) !=
1414fbf05f9SSascha Wildner 		TW_CL_NULL) {
142df54c2f9SSascha Wildner 		if (req->flags & TW_CLI_REQ_FLAGS_INTERNAL) {
143df54c2f9SSascha Wildner 			/*
144df54c2f9SSascha Wildner 			 * It's an internal request.  Set the appropriate
145df54c2f9SSascha Wildner 			 * error and call the CL internal callback if there's
146df54c2f9SSascha Wildner 			 * one.  If the request originator is polling for
147df54c2f9SSascha Wildner 			 * completion, he should be checking req->error to
148df54c2f9SSascha Wildner 			 * determine that the request did not go through.
149df54c2f9SSascha Wildner 			 * The request originators are responsible for the
150df54c2f9SSascha Wildner 			 * clean-up.
151df54c2f9SSascha Wildner 			 */
152df54c2f9SSascha Wildner 			req->error_code = TW_CL_ERR_REQ_BUS_RESET;
153df54c2f9SSascha Wildner 			if (req->tw_cli_callback)
154df54c2f9SSascha Wildner 				req->tw_cli_callback(req);
1554fbf05f9SSascha Wildner 		} else if (req->flags & TW_CLI_REQ_FLAGS_PASSTHRU) {
1564fbf05f9SSascha Wildner 			/* It's a passthru request.  Complete it. */
1574fbf05f9SSascha Wildner 			if ((req_pkt = req->orig_req) != TW_CL_NULL) {
158df54c2f9SSascha Wildner 				req_pkt->status = TW_CL_ERR_REQ_BUS_RESET;
1594fbf05f9SSascha Wildner 
1604fbf05f9SSascha Wildner 				if (req_pkt->tw_osl_callback)
161df54c2f9SSascha Wildner 					req_pkt->tw_osl_callback(req->req_handle);
162df54c2f9SSascha Wildner 			}
163df54c2f9SSascha Wildner 			tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
1644fbf05f9SSascha Wildner 		} else {
1654fbf05f9SSascha Wildner 			/* It's an external (SCSI) request.  Add it to the reset queue. */
1664fbf05f9SSascha Wildner 			tw_osl_untimeout(req->req_handle);
1674fbf05f9SSascha Wildner 			tw_cli_req_q_insert_tail(req, TW_CLI_RESET_Q);
168df54c2f9SSascha Wildner 		}
1694fbf05f9SSascha Wildner 	} /* End of while loop */
170df54c2f9SSascha Wildner }
171df54c2f9SSascha Wildner 
172df54c2f9SSascha Wildner 
173df54c2f9SSascha Wildner 
174df54c2f9SSascha Wildner /*
175df54c2f9SSascha Wildner  * Function name:	tw_cli_drain_pending_queue
176df54c2f9SSascha Wildner  * Description:		This function gets called during a controller reset.
177df54c2f9SSascha Wildner  *			It errors back to the OS Layer, all those requests that
178df54c2f9SSascha Wildner  *			were in the pending queue, at the time of the reset.
179df54c2f9SSascha Wildner  *
180df54c2f9SSascha Wildner  * Input:		ctlr	-- ptr to CL internal ctlr context
181df54c2f9SSascha Wildner  * Output:		None
182df54c2f9SSascha Wildner  * Return value:	None
183df54c2f9SSascha Wildner  */
184df54c2f9SSascha Wildner 
185df54c2f9SSascha Wildner TW_VOID
tw_cli_drain_pending_queue(struct tw_cli_ctlr_context * ctlr)186df54c2f9SSascha Wildner tw_cli_drain_pending_queue(struct tw_cli_ctlr_context *ctlr)
187df54c2f9SSascha Wildner {
188df54c2f9SSascha Wildner 	struct tw_cli_req_context	*req;
189df54c2f9SSascha Wildner 	struct tw_cl_req_packet		*req_pkt;
190df54c2f9SSascha Wildner 
191df54c2f9SSascha Wildner 	tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
192df54c2f9SSascha Wildner 
193df54c2f9SSascha Wildner 	/*
194df54c2f9SSascha Wildner 	 * Pull requests off the pending queue, and complete them.
195df54c2f9SSascha Wildner 	 */
1964fbf05f9SSascha Wildner 	while ((req = tw_cli_req_q_remove_head(ctlr, TW_CLI_PENDING_Q)) !=
1974fbf05f9SSascha Wildner 		TW_CL_NULL) {
198df54c2f9SSascha Wildner 		if (req->flags & TW_CLI_REQ_FLAGS_INTERNAL) {
199df54c2f9SSascha Wildner 			/*
200df54c2f9SSascha Wildner 			 * It's an internal request.  Set the appropriate
201df54c2f9SSascha Wildner 			 * error and call the CL internal callback if there's
202df54c2f9SSascha Wildner 			 * one.  If the request originator is polling for
203df54c2f9SSascha Wildner 			 * completion, he should be checking req->error to
204df54c2f9SSascha Wildner 			 * determine that the request did not go through.
205df54c2f9SSascha Wildner 			 * The request originators are responsible for the
206df54c2f9SSascha Wildner 			 * clean-up.
207df54c2f9SSascha Wildner 			 */
208df54c2f9SSascha Wildner 			req->error_code = TW_CL_ERR_REQ_BUS_RESET;
209df54c2f9SSascha Wildner 			if (req->tw_cli_callback)
210df54c2f9SSascha Wildner 				req->tw_cli_callback(req);
2114fbf05f9SSascha Wildner 		} else if (req->flags & TW_CLI_REQ_FLAGS_PASSTHRU) {
2124fbf05f9SSascha Wildner 			/* It's a passthru request.  Complete it. */
2134fbf05f9SSascha Wildner 			if ((req_pkt = req->orig_req) != TW_CL_NULL) {
214df54c2f9SSascha Wildner 				req_pkt->status = TW_CL_ERR_REQ_BUS_RESET;
2154fbf05f9SSascha Wildner 
2164fbf05f9SSascha Wildner 				if (req_pkt->tw_osl_callback)
217df54c2f9SSascha Wildner 					req_pkt->tw_osl_callback(req->req_handle);
218df54c2f9SSascha Wildner 			}
219df54c2f9SSascha Wildner 			tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
2204fbf05f9SSascha Wildner 		} else {
2214fbf05f9SSascha Wildner 			/* It's an external (SCSI) request.  Add it to the reset queue. */
2224fbf05f9SSascha Wildner 			tw_osl_untimeout(req->req_handle);
2234fbf05f9SSascha Wildner 			tw_cli_req_q_insert_tail(req, TW_CLI_RESET_Q);
224df54c2f9SSascha Wildner 		}
2254fbf05f9SSascha Wildner 	} /* End of while loop */
226df54c2f9SSascha Wildner }
227df54c2f9SSascha Wildner 
228df54c2f9SSascha Wildner 
229df54c2f9SSascha Wildner 
230df54c2f9SSascha Wildner /*
231df54c2f9SSascha Wildner  * Function name:	tw_cli_drain_response_queue
232df54c2f9SSascha Wildner  * Description:		Drain the controller response queue.
233df54c2f9SSascha Wildner  *
234df54c2f9SSascha Wildner  * Input:		ctlr	-- ptr to per ctlr structure
235df54c2f9SSascha Wildner  * Output:		None
236df54c2f9SSascha Wildner  * Return value:	0	-- success
237df54c2f9SSascha Wildner  *			non-zero-- failure
238df54c2f9SSascha Wildner  */
239df54c2f9SSascha Wildner TW_INT32
tw_cli_drain_response_queue(struct tw_cli_ctlr_context * ctlr)240df54c2f9SSascha Wildner tw_cli_drain_response_queue(struct tw_cli_ctlr_context *ctlr)
241df54c2f9SSascha Wildner {
242df54c2f9SSascha Wildner 	TW_UINT32	resp;
243df54c2f9SSascha Wildner 	TW_UINT32	status_reg;
244df54c2f9SSascha Wildner 
245df54c2f9SSascha Wildner 	tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
246df54c2f9SSascha Wildner 
247df54c2f9SSascha Wildner 	for (;;) {
248df54c2f9SSascha Wildner 		status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr->ctlr_handle);
249df54c2f9SSascha Wildner 
250df54c2f9SSascha Wildner 		if (status_reg & TWA_STATUS_RESPONSE_QUEUE_EMPTY)
251df54c2f9SSascha Wildner 			return(TW_OSL_ESUCCESS); /* no more response queue entries */
252df54c2f9SSascha Wildner 
253df54c2f9SSascha Wildner 		resp = TW_CLI_READ_RESPONSE_QUEUE(ctlr->ctlr_handle);
254df54c2f9SSascha Wildner 	}
255df54c2f9SSascha Wildner }
256df54c2f9SSascha Wildner 
257df54c2f9SSascha Wildner 
258df54c2f9SSascha Wildner 
259df54c2f9SSascha Wildner /*
260df54c2f9SSascha Wildner  * Function name:	tw_cli_find_response
261df54c2f9SSascha Wildner  * Description:		Find a particular response in the ctlr response queue.
262df54c2f9SSascha Wildner  *
263df54c2f9SSascha Wildner  * Input:		ctlr	-- ptr to per ctlr structure
264df54c2f9SSascha Wildner  *			req_id	-- request id of the response to look for
265df54c2f9SSascha Wildner  * Output:		None
266df54c2f9SSascha Wildner  * Return value:	0	-- success
267df54c2f9SSascha Wildner  *			non-zero-- failure
268df54c2f9SSascha Wildner  */
269df54c2f9SSascha Wildner TW_INT32
tw_cli_find_response(struct tw_cli_ctlr_context * ctlr,TW_INT32 req_id)270df54c2f9SSascha Wildner tw_cli_find_response(struct tw_cli_ctlr_context *ctlr, TW_INT32 req_id)
271df54c2f9SSascha Wildner {
272df54c2f9SSascha Wildner 	TW_UINT32	resp;
273df54c2f9SSascha Wildner 	TW_INT32	resp_id;
274df54c2f9SSascha Wildner 	TW_UINT32	status_reg;
275df54c2f9SSascha Wildner 
276df54c2f9SSascha Wildner 	tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
277df54c2f9SSascha Wildner 
278df54c2f9SSascha Wildner 	for (;;) {
279df54c2f9SSascha Wildner 		status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr->ctlr_handle);
280df54c2f9SSascha Wildner 
281df54c2f9SSascha Wildner 		if (status_reg & TWA_STATUS_RESPONSE_QUEUE_EMPTY)
282df54c2f9SSascha Wildner 			return(TW_OSL_ENOTTY); /* no more response queue entries */
283df54c2f9SSascha Wildner 
284df54c2f9SSascha Wildner 		if (ctlr->device_id == TW_CL_DEVICE_ID_9K) {
285df54c2f9SSascha Wildner 			resp = TW_CLI_READ_RESPONSE_QUEUE(ctlr->ctlr_handle);
286df54c2f9SSascha Wildner 			resp_id = GET_RESP_ID(resp);
287df54c2f9SSascha Wildner 		} else {
288df54c2f9SSascha Wildner 			resp = TW_CLI_READ_LARGE_RESPONSE_QUEUE(
289df54c2f9SSascha Wildner 				ctlr->ctlr_handle);
290df54c2f9SSascha Wildner 			resp_id = GET_LARGE_RESP_ID(resp);
291df54c2f9SSascha Wildner 		}
292df54c2f9SSascha Wildner 		if (resp_id == req_id)
293df54c2f9SSascha Wildner 			return(TW_OSL_ESUCCESS); /* found the req_id */
294df54c2f9SSascha Wildner 	}
295df54c2f9SSascha Wildner }
296df54c2f9SSascha Wildner 
297df54c2f9SSascha Wildner 
298df54c2f9SSascha Wildner 
299df54c2f9SSascha Wildner /*
300df54c2f9SSascha Wildner  * Function name:	tw_cli_drain_aen_queue
301df54c2f9SSascha Wildner  * Description:		Fetches all un-retrieved AEN's posted by fw.
302df54c2f9SSascha Wildner  *
303df54c2f9SSascha Wildner  * Input:		ctlr	-- ptr to CL internal ctlr context
304df54c2f9SSascha Wildner  * Output:		None
305df54c2f9SSascha Wildner  * Return value:	0	-- success
306df54c2f9SSascha Wildner  *			non-zero-- failure
307df54c2f9SSascha Wildner  */
308df54c2f9SSascha Wildner TW_INT32
tw_cli_drain_aen_queue(struct tw_cli_ctlr_context * ctlr)309df54c2f9SSascha Wildner tw_cli_drain_aen_queue(struct tw_cli_ctlr_context *ctlr)
310df54c2f9SSascha Wildner {
311df54c2f9SSascha Wildner 	struct tw_cli_req_context	*req;
312df54c2f9SSascha Wildner 	TW_TIME				end_time;
313df54c2f9SSascha Wildner 	TW_UINT16			aen_code;
314df54c2f9SSascha Wildner 	TW_INT32			error;
315df54c2f9SSascha Wildner 
316df54c2f9SSascha Wildner 	tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
317df54c2f9SSascha Wildner 
318df54c2f9SSascha Wildner 	for (;;) {
319df54c2f9SSascha Wildner 		if ((req = tw_cli_get_request(ctlr
320df54c2f9SSascha Wildner 			)) == TW_CL_NULL) {
321df54c2f9SSascha Wildner 			error = TW_OSL_EBUSY;
322df54c2f9SSascha Wildner 			break;
323df54c2f9SSascha Wildner 		}
324df54c2f9SSascha Wildner 
325df54c2f9SSascha Wildner 		req->flags |= TW_CLI_REQ_FLAGS_INTERNAL;
326df54c2f9SSascha Wildner 		req->tw_cli_callback = TW_CL_NULL;
327df54c2f9SSascha Wildner 		if ((error = tw_cli_send_scsi_cmd(req,
328df54c2f9SSascha Wildner 				0x03 /* REQUEST_SENSE */))) {
329df54c2f9SSascha Wildner 			tw_cli_dbg_printf(1, ctlr->ctlr_handle,
330df54c2f9SSascha Wildner 				tw_osl_cur_func(),
331df54c2f9SSascha Wildner 				"Cannot send command to fetch aen");
332df54c2f9SSascha Wildner 			break;
333df54c2f9SSascha Wildner 		}
334df54c2f9SSascha Wildner 
335df54c2f9SSascha Wildner 		end_time = tw_osl_get_local_time() +
336df54c2f9SSascha Wildner 			TW_CLI_REQUEST_TIMEOUT_PERIOD;
337df54c2f9SSascha Wildner 		do {
338df54c2f9SSascha Wildner 			if ((error = req->error_code))
339df54c2f9SSascha Wildner 				/*
340df54c2f9SSascha Wildner 				 * This will take care of completion due to
341df54c2f9SSascha Wildner 				 * a reset, or a failure in
342df54c2f9SSascha Wildner 				 * tw_cli_submit_pending_queue.
343df54c2f9SSascha Wildner 				 */
344df54c2f9SSascha Wildner 				goto out;
345df54c2f9SSascha Wildner 
346df54c2f9SSascha Wildner 			tw_cli_process_resp_intr(req->ctlr);
347df54c2f9SSascha Wildner 
348df54c2f9SSascha Wildner 			if ((req->state != TW_CLI_REQ_STATE_BUSY) &&
349df54c2f9SSascha Wildner 				(req->state != TW_CLI_REQ_STATE_PENDING))
350df54c2f9SSascha Wildner 				break;
351df54c2f9SSascha Wildner 		} while (tw_osl_get_local_time() <= end_time);
352df54c2f9SSascha Wildner 
353df54c2f9SSascha Wildner 		if (req->state != TW_CLI_REQ_STATE_COMPLETE) {
354df54c2f9SSascha Wildner 			error = TW_OSL_ETIMEDOUT;
355df54c2f9SSascha Wildner 			break;
356df54c2f9SSascha Wildner 		}
357df54c2f9SSascha Wildner 
358df54c2f9SSascha Wildner 		if ((error = req->cmd_pkt->command.cmd_pkt_9k.status)) {
3594fbf05f9SSascha Wildner #if       0
360c6fd73a3SSascha Wildner 			struct tw_cl_command_header	*cmd_hdr;
361c6fd73a3SSascha Wildner 			cmd_hdr = &req->cmd_pkt->cmd_hdr;
362df54c2f9SSascha Wildner 			tw_cli_create_ctlr_event(ctlr,
363df54c2f9SSascha Wildner 				TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR,
364df54c2f9SSascha Wildner 				cmd_hdr);
3654fbf05f9SSascha Wildner #endif // 0
366df54c2f9SSascha Wildner 			break;
367df54c2f9SSascha Wildner 		}
368df54c2f9SSascha Wildner 
369df54c2f9SSascha Wildner 		aen_code = tw_cli_manage_aen(ctlr, req);
370df54c2f9SSascha Wildner 		if (aen_code == TWA_AEN_QUEUE_EMPTY)
371df54c2f9SSascha Wildner 			break;
372df54c2f9SSascha Wildner 		if (aen_code == TWA_AEN_SYNC_TIME_WITH_HOST)
373df54c2f9SSascha Wildner 			continue;
374df54c2f9SSascha Wildner 
375df54c2f9SSascha Wildner 		ctlr->internal_req_busy = TW_CL_FALSE;
376df54c2f9SSascha Wildner 		tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
377df54c2f9SSascha Wildner 	}
378df54c2f9SSascha Wildner 
379df54c2f9SSascha Wildner out:
380df54c2f9SSascha Wildner 	if (req) {
381df54c2f9SSascha Wildner 		if (req->data)
382df54c2f9SSascha Wildner 			ctlr->internal_req_busy = TW_CL_FALSE;
383df54c2f9SSascha Wildner 		tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
384df54c2f9SSascha Wildner 	}
385df54c2f9SSascha Wildner 	return(error);
386df54c2f9SSascha Wildner }
387df54c2f9SSascha Wildner 
388df54c2f9SSascha Wildner 
389df54c2f9SSascha Wildner 
390df54c2f9SSascha Wildner /*
391df54c2f9SSascha Wildner  * Function name:	tw_cli_find_aen
392df54c2f9SSascha Wildner  * Description:		Reports whether a given AEN ever occurred.
393df54c2f9SSascha Wildner  *
394df54c2f9SSascha Wildner  * Input:		ctlr	-- ptr to CL internal ctlr context
395df54c2f9SSascha Wildner  *			aen_code-- AEN to look for
396df54c2f9SSascha Wildner  * Output:		None
397df54c2f9SSascha Wildner  * Return value:	0	-- success
398df54c2f9SSascha Wildner  *			non-zero-- failure
399df54c2f9SSascha Wildner  */
400df54c2f9SSascha Wildner TW_INT32
tw_cli_find_aen(struct tw_cli_ctlr_context * ctlr,TW_UINT16 aen_code)401df54c2f9SSascha Wildner tw_cli_find_aen(struct tw_cli_ctlr_context *ctlr, TW_UINT16 aen_code)
402df54c2f9SSascha Wildner {
403df54c2f9SSascha Wildner 	TW_UINT32	last_index;
404df54c2f9SSascha Wildner 	TW_INT32	i;
405df54c2f9SSascha Wildner 
406df54c2f9SSascha Wildner 	tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
407df54c2f9SSascha Wildner 
408df54c2f9SSascha Wildner 	if (ctlr->aen_q_wrapped)
409df54c2f9SSascha Wildner 		last_index = ctlr->aen_head;
410df54c2f9SSascha Wildner 	else
411df54c2f9SSascha Wildner 		last_index = 0;
412df54c2f9SSascha Wildner 
413df54c2f9SSascha Wildner 	i = ctlr->aen_head;
414df54c2f9SSascha Wildner 	do {
415df54c2f9SSascha Wildner 		i = (i + ctlr->max_aens_supported - 1) %
416df54c2f9SSascha Wildner 			ctlr->max_aens_supported;
417df54c2f9SSascha Wildner 		if (ctlr->aen_queue[i].aen_code == aen_code)
418df54c2f9SSascha Wildner 			return(TW_OSL_ESUCCESS);
419df54c2f9SSascha Wildner 	} while (i != last_index);
420df54c2f9SSascha Wildner 
421df54c2f9SSascha Wildner 	return(TW_OSL_EGENFAILURE);
422df54c2f9SSascha Wildner }
423df54c2f9SSascha Wildner 
424df54c2f9SSascha Wildner 
425df54c2f9SSascha Wildner 
426df54c2f9SSascha Wildner /*
427df54c2f9SSascha Wildner  * Function name:	tw_cli_poll_status
428df54c2f9SSascha Wildner  * Description:		Poll for a given status to show up in the firmware
429df54c2f9SSascha Wildner  *			status register.
430df54c2f9SSascha Wildner  *
431df54c2f9SSascha Wildner  * Input:		ctlr	-- ptr to CL internal ctlr context
432df54c2f9SSascha Wildner  *			status	-- status to look for
433df54c2f9SSascha Wildner  *			timeout -- max # of seconds to wait before giving up
434df54c2f9SSascha Wildner  * Output:		None
435df54c2f9SSascha Wildner  * Return value:	0	-- success
436df54c2f9SSascha Wildner  *			non-zero-- failure
437df54c2f9SSascha Wildner  */
438df54c2f9SSascha Wildner TW_INT32
tw_cli_poll_status(struct tw_cli_ctlr_context * ctlr,TW_UINT32 status,TW_UINT32 timeout)439df54c2f9SSascha Wildner tw_cli_poll_status(struct tw_cli_ctlr_context *ctlr, TW_UINT32 status,
440df54c2f9SSascha Wildner 	TW_UINT32 timeout)
441df54c2f9SSascha Wildner {
442df54c2f9SSascha Wildner 	TW_TIME		end_time;
443df54c2f9SSascha Wildner 	TW_UINT32	status_reg;
444df54c2f9SSascha Wildner 
445df54c2f9SSascha Wildner 	tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
446df54c2f9SSascha Wildner 
447df54c2f9SSascha Wildner 	end_time = tw_osl_get_local_time() + timeout;
448df54c2f9SSascha Wildner 	do {
449df54c2f9SSascha Wildner 		status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr->ctlr_handle);
450df54c2f9SSascha Wildner 		if ((status_reg & status) == status)
451df54c2f9SSascha Wildner 			/* got the required bit(s) */
452df54c2f9SSascha Wildner 			return(TW_OSL_ESUCCESS);
453df54c2f9SSascha Wildner 
454df54c2f9SSascha Wildner 		tw_osl_delay(1000);
455df54c2f9SSascha Wildner 	} while (tw_osl_get_local_time() <= end_time);
456df54c2f9SSascha Wildner 
457df54c2f9SSascha Wildner 	return(TW_OSL_ETIMEDOUT);
458df54c2f9SSascha Wildner }
459df54c2f9SSascha Wildner 
460df54c2f9SSascha Wildner 
461df54c2f9SSascha Wildner 
462df54c2f9SSascha Wildner /*
463df54c2f9SSascha Wildner  * Function name:	tw_cl_create_event
464df54c2f9SSascha Wildner  * Description:		Creates and queues ctlr/CL/OSL AEN's to be
465df54c2f9SSascha Wildner  *			supplied to user-space tools on request.
466df54c2f9SSascha Wildner  *			Also notifies OS Layer.
467df54c2f9SSascha Wildner  * Input:		ctlr	-- ptr to CL internal ctlr context
468df54c2f9SSascha Wildner  *			queue_event-- TW_CL_TRUE --> queue event;
469df54c2f9SSascha Wildner  *				      TW_CL_FALSE--> don't queue event
470df54c2f9SSascha Wildner  *							(simply notify OSL)
471df54c2f9SSascha Wildner  *			event_src  -- source of event
472df54c2f9SSascha Wildner  *			event_code -- AEN/error code
473df54c2f9SSascha Wildner  *			severity -- severity of event
474df54c2f9SSascha Wildner  *			severity_str--Text description of severity
475df54c2f9SSascha Wildner  *			event_desc -- standard string related to the event/error
476df54c2f9SSascha Wildner  *			event_specific_desc -- format string for additional
477df54c2f9SSascha Wildner  *						info about the event
478df54c2f9SSascha Wildner  *			... -- additional arguments conforming to the format
479df54c2f9SSascha Wildner  *				specified by event_specific_desc
480df54c2f9SSascha Wildner  * Output:		None
481df54c2f9SSascha Wildner  * Return value:	None
482df54c2f9SSascha Wildner  */
483df54c2f9SSascha Wildner TW_VOID
tw_cl_create_event(struct tw_cl_ctlr_handle * ctlr_handle,TW_UINT8 queue_event,TW_UINT8 event_src,TW_UINT16 event_code,TW_UINT8 severity,TW_UINT8 * severity_str,TW_UINT8 * event_desc,TW_UINT8 * event_specific_desc,...)484df54c2f9SSascha Wildner tw_cl_create_event(struct tw_cl_ctlr_handle *ctlr_handle,
485df54c2f9SSascha Wildner 	TW_UINT8 queue_event, TW_UINT8 event_src, TW_UINT16 event_code,
486df54c2f9SSascha Wildner 	TW_UINT8 severity, TW_UINT8 *severity_str, TW_UINT8 *event_desc,
487df54c2f9SSascha Wildner 	TW_UINT8 *event_specific_desc, ...)
488df54c2f9SSascha Wildner {
489df54c2f9SSascha Wildner 	struct tw_cli_ctlr_context	*ctlr = ctlr_handle->cl_ctlr_ctxt;
490df54c2f9SSascha Wildner 	struct tw_cl_event_packet	event_pkt;
491df54c2f9SSascha Wildner 	struct tw_cl_event_packet	*event;
492df54c2f9SSascha Wildner 	TW_UINT32			aen_head;
493*d26841ecSSascha Wildner 	__va_list			ap;
494df54c2f9SSascha Wildner 
495df54c2f9SSascha Wildner 	tw_cli_dbg_printf(8, ctlr_handle, tw_osl_cur_func(), "entered");
496df54c2f9SSascha Wildner 
497df54c2f9SSascha Wildner 	if ((ctlr) && (queue_event)) {
498df54c2f9SSascha Wildner 		/* Protect access to ctlr->aen_head. */
499df54c2f9SSascha Wildner 		tw_osl_get_lock(ctlr_handle, ctlr->gen_lock);
500df54c2f9SSascha Wildner 
501df54c2f9SSascha Wildner 		aen_head = ctlr->aen_head;
502df54c2f9SSascha Wildner 		ctlr->aen_head = (aen_head + 1) % ctlr->max_aens_supported;
503df54c2f9SSascha Wildner 
504df54c2f9SSascha Wildner 		/* Queue the event. */
505df54c2f9SSascha Wildner 		event = &(ctlr->aen_queue[aen_head]);
506df54c2f9SSascha Wildner 		tw_osl_memzero(event->parameter_data,
507df54c2f9SSascha Wildner 			sizeof(event->parameter_data));
508df54c2f9SSascha Wildner 
509df54c2f9SSascha Wildner 		if (event->retrieved == TW_CL_AEN_NOT_RETRIEVED)
510df54c2f9SSascha Wildner 			ctlr->aen_q_overflow = TW_CL_TRUE;
511df54c2f9SSascha Wildner 		event->sequence_id = ++(ctlr->aen_cur_seq_id);
512df54c2f9SSascha Wildner 		if ((aen_head + 1) == ctlr->max_aens_supported) {
513df54c2f9SSascha Wildner 			tw_cli_dbg_printf(4, ctlr->ctlr_handle,
514df54c2f9SSascha Wildner 				tw_osl_cur_func(), "AEN queue wrapped");
515df54c2f9SSascha Wildner 			ctlr->aen_q_wrapped = TW_CL_TRUE;
516df54c2f9SSascha Wildner 		}
517df54c2f9SSascha Wildner 
518df54c2f9SSascha Wildner 		/* Free access to ctlr->aen_head. */
519df54c2f9SSascha Wildner 		tw_osl_free_lock(ctlr_handle, ctlr->gen_lock);
520df54c2f9SSascha Wildner 	} else {
521df54c2f9SSascha Wildner 		event = &event_pkt;
522df54c2f9SSascha Wildner 		tw_osl_memzero(event, sizeof(struct tw_cl_event_packet));
523df54c2f9SSascha Wildner 	}
524df54c2f9SSascha Wildner 
525df54c2f9SSascha Wildner 	event->event_src = event_src;
526df54c2f9SSascha Wildner 	event->time_stamp_sec = (TW_UINT32)tw_osl_get_local_time();
527df54c2f9SSascha Wildner 	event->aen_code = event_code;
528df54c2f9SSascha Wildner 	event->severity = severity;
529df54c2f9SSascha Wildner 	tw_osl_strcpy(event->severity_str, severity_str);
530df54c2f9SSascha Wildner 	event->retrieved = TW_CL_AEN_NOT_RETRIEVED;
531df54c2f9SSascha Wildner 
532*d26841ecSSascha Wildner 	__va_start(ap, event_specific_desc);
533df54c2f9SSascha Wildner 	tw_osl_vsprintf(event->parameter_data, event_specific_desc, ap);
534*d26841ecSSascha Wildner 	__va_end(ap);
535df54c2f9SSascha Wildner 
536df54c2f9SSascha Wildner 	event->parameter_len =
537df54c2f9SSascha Wildner 		(TW_UINT8)(tw_osl_strlen(event->parameter_data));
538df54c2f9SSascha Wildner 	tw_osl_strcpy(event->parameter_data + event->parameter_len + 1,
539df54c2f9SSascha Wildner 		event_desc);
540df54c2f9SSascha Wildner 	event->parameter_len += (1 + tw_osl_strlen(event_desc));
541df54c2f9SSascha Wildner 
542df54c2f9SSascha Wildner 	tw_cli_dbg_printf(4, ctlr_handle, tw_osl_cur_func(),
543df54c2f9SSascha Wildner 		"event = %x %x %x %x %x %x %x\n %s",
544df54c2f9SSascha Wildner 		event->sequence_id,
545df54c2f9SSascha Wildner 		event->time_stamp_sec,
546df54c2f9SSascha Wildner 		event->aen_code,
547df54c2f9SSascha Wildner 		event->severity,
548df54c2f9SSascha Wildner 		event->retrieved,
549df54c2f9SSascha Wildner 		event->repeat_count,
550df54c2f9SSascha Wildner 		event->parameter_len,
551df54c2f9SSascha Wildner 		event->parameter_data);
552df54c2f9SSascha Wildner 
553df54c2f9SSascha Wildner 	tw_osl_notify_event(ctlr_handle, event);
554df54c2f9SSascha Wildner }
555df54c2f9SSascha Wildner 
556df54c2f9SSascha Wildner 
557df54c2f9SSascha Wildner 
558df54c2f9SSascha Wildner /*
559df54c2f9SSascha Wildner  * Function name:	tw_cli_get_request
560df54c2f9SSascha Wildner  * Description:		Gets a request pkt from the free queue.
561df54c2f9SSascha Wildner  *
562df54c2f9SSascha Wildner  * Input:		ctlr	-- ptr to CL internal ctlr context
563df54c2f9SSascha Wildner  *			req_pkt -- ptr to OSL built req_pkt, if there's one
564df54c2f9SSascha Wildner  * Output:		None
565df54c2f9SSascha Wildner  * Return value:	ptr to request pkt	-- success
566df54c2f9SSascha Wildner  *			TW_CL_NULL		-- failure
567df54c2f9SSascha Wildner  */
568df54c2f9SSascha Wildner struct tw_cli_req_context *
tw_cli_get_request(struct tw_cli_ctlr_context * ctlr)569df54c2f9SSascha Wildner tw_cli_get_request(struct tw_cli_ctlr_context *ctlr
570df54c2f9SSascha Wildner 	)
571df54c2f9SSascha Wildner {
572df54c2f9SSascha Wildner 	struct tw_cli_req_context	*req;
573df54c2f9SSascha Wildner 
574df54c2f9SSascha Wildner 	tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
575df54c2f9SSascha Wildner 
576df54c2f9SSascha Wildner 	{
577df54c2f9SSascha Wildner 		/* Get a free request packet. */
578df54c2f9SSascha Wildner 		req = tw_cli_req_q_remove_head(ctlr, TW_CLI_FREE_Q);
579df54c2f9SSascha Wildner 	}
580df54c2f9SSascha Wildner 
581df54c2f9SSascha Wildner 	/* Initialize some fields to their defaults. */
582df54c2f9SSascha Wildner 	if (req) {
583df54c2f9SSascha Wildner 		req->req_handle = TW_CL_NULL;
584df54c2f9SSascha Wildner 		req->data = TW_CL_NULL;
585df54c2f9SSascha Wildner 		req->length = 0;
586df54c2f9SSascha Wildner 		req->data_phys = 0;
587df54c2f9SSascha Wildner 		req->state = TW_CLI_REQ_STATE_INIT; /* req being initialized */
588df54c2f9SSascha Wildner 		req->flags = 0;
589df54c2f9SSascha Wildner 		req->error_code = 0;
590df54c2f9SSascha Wildner 		req->orig_req = TW_CL_NULL;
591df54c2f9SSascha Wildner 		req->tw_cli_callback = TW_CL_NULL;
592df54c2f9SSascha Wildner 
593df54c2f9SSascha Wildner 		/*
594df54c2f9SSascha Wildner 		 * Look at the status field in the command packet to see how
595df54c2f9SSascha Wildner 		 * it completed the last time it was used, and zero out only
596df54c2f9SSascha Wildner 		 * the portions that might have changed.  Note that we don't
597df54c2f9SSascha Wildner 		 * care to zero out the sglist.
598df54c2f9SSascha Wildner 		 */
599df54c2f9SSascha Wildner 		if (req->cmd_pkt->command.cmd_pkt_9k.status)
600df54c2f9SSascha Wildner 			tw_osl_memzero(req->cmd_pkt,
601df54c2f9SSascha Wildner 				sizeof(struct tw_cl_command_header) +
602df54c2f9SSascha Wildner 				28 /* max bytes before sglist */);
603df54c2f9SSascha Wildner 		else
604df54c2f9SSascha Wildner 			tw_osl_memzero(&(req->cmd_pkt->command),
605df54c2f9SSascha Wildner 				28 /* max bytes before sglist */);
606df54c2f9SSascha Wildner 
607df54c2f9SSascha Wildner 	}
608df54c2f9SSascha Wildner 	return(req);
609df54c2f9SSascha Wildner }
610df54c2f9SSascha Wildner 
611df54c2f9SSascha Wildner 
612df54c2f9SSascha Wildner 
613df54c2f9SSascha Wildner /*
614df54c2f9SSascha Wildner  * Function name:	tw_cli_dbg_printf
615df54c2f9SSascha Wildner  * Description:		Calls OSL print function if dbg_level is appropriate
616df54c2f9SSascha Wildner  *
617df54c2f9SSascha Wildner  * Input:		dbg_level -- Determines whether or not to print
618df54c2f9SSascha Wildner  *			ctlr_handle -- controller handle
619df54c2f9SSascha Wildner  *			cur_func -- text name of calling function
620df54c2f9SSascha Wildner  *			fmt -- format string for the arguments to follow
621df54c2f9SSascha Wildner  *			... -- variable number of arguments, to be printed
622df54c2f9SSascha Wildner  *				based on the fmt string
623df54c2f9SSascha Wildner  * Output:		None
624df54c2f9SSascha Wildner  * Return value:	None
625df54c2f9SSascha Wildner  */
626df54c2f9SSascha Wildner TW_VOID
tw_cli_dbg_printf(TW_UINT8 dbg_level,struct tw_cl_ctlr_handle * ctlr_handle,const TW_INT8 * cur_func,TW_INT8 * fmt,...)627df54c2f9SSascha Wildner tw_cli_dbg_printf(TW_UINT8 dbg_level,
628df54c2f9SSascha Wildner 	struct tw_cl_ctlr_handle *ctlr_handle, const TW_INT8 *cur_func,
629df54c2f9SSascha Wildner 	TW_INT8 *fmt, ...)
630df54c2f9SSascha Wildner {
631df54c2f9SSascha Wildner #ifdef TW_OSL_DEBUG
632df54c2f9SSascha Wildner 	TW_INT8	print_str[256];
633*d26841ecSSascha Wildner 	__va_list	ap;
634df54c2f9SSascha Wildner 
635df54c2f9SSascha Wildner 	tw_osl_memzero(print_str, 256);
636df54c2f9SSascha Wildner 	if (dbg_level <= TW_OSL_DEBUG_LEVEL_FOR_CL) {
637df54c2f9SSascha Wildner 		tw_osl_sprintf(print_str, "%s: ", cur_func);
638df54c2f9SSascha Wildner 
639*d26841ecSSascha Wildner 		__va_start(ap, fmt);
640df54c2f9SSascha Wildner 		tw_osl_vsprintf(print_str + tw_osl_strlen(print_str), fmt, ap);
641*d26841ecSSascha Wildner 		__va_end(ap);
642df54c2f9SSascha Wildner 
643df54c2f9SSascha Wildner 		tw_osl_strcpy(print_str + tw_osl_strlen(print_str), "\n");
644a7a95662SSascha Wildner 		tw_osl_dbg_printf(ctlr_handle, "%s", print_str);
645df54c2f9SSascha Wildner 	}
646df54c2f9SSascha Wildner #endif /* TW_OSL_DEBUG */
647df54c2f9SSascha Wildner }
648df54c2f9SSascha Wildner 
649df54c2f9SSascha Wildner 
650df54c2f9SSascha Wildner 
651df54c2f9SSascha Wildner /*
652df54c2f9SSascha Wildner  * Function name:	tw_cli_notify_ctlr_info
653df54c2f9SSascha Wildner  * Description:		Notify OSL of controller info (fw/BIOS versions, etc.).
654df54c2f9SSascha Wildner  *
655df54c2f9SSascha Wildner  * Input:		ctlr	-- ptr to CL internal ctlr context
656df54c2f9SSascha Wildner  * Output:		None
657df54c2f9SSascha Wildner  * Return value:	None
658df54c2f9SSascha Wildner  */
659df54c2f9SSascha Wildner TW_VOID
tw_cli_notify_ctlr_info(struct tw_cli_ctlr_context * ctlr)660df54c2f9SSascha Wildner tw_cli_notify_ctlr_info(struct tw_cli_ctlr_context *ctlr)
661df54c2f9SSascha Wildner {
662df54c2f9SSascha Wildner 	TW_INT8		fw_ver[16];
663df54c2f9SSascha Wildner 	TW_INT8		bios_ver[16];
664df54c2f9SSascha Wildner 	TW_INT8		ctlr_model[16];
665df54c2f9SSascha Wildner 	TW_INT32	error[3];
666df54c2f9SSascha Wildner 	TW_UINT8	num_ports = 0;
667df54c2f9SSascha Wildner 
668df54c2f9SSascha Wildner 	tw_cli_dbg_printf(5, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
669df54c2f9SSascha Wildner 
670df54c2f9SSascha Wildner 	/* Get the port count. */
671df54c2f9SSascha Wildner 	error[0] = tw_cli_get_param(ctlr, TWA_PARAM_CONTROLLER_TABLE,
672df54c2f9SSascha Wildner 			TWA_PARAM_CONTROLLER_PORT_COUNT, &num_ports,
673df54c2f9SSascha Wildner 			1, TW_CL_NULL);
674df54c2f9SSascha Wildner 
675df54c2f9SSascha Wildner 	/* Get the firmware and BIOS versions. */
676df54c2f9SSascha Wildner 	error[0] = tw_cli_get_param(ctlr, TWA_PARAM_VERSION_TABLE,
677df54c2f9SSascha Wildner 			TWA_PARAM_VERSION_FW, fw_ver, 16, TW_CL_NULL);
678df54c2f9SSascha Wildner 	error[1] = tw_cli_get_param(ctlr, TWA_PARAM_VERSION_TABLE,
679df54c2f9SSascha Wildner 			TWA_PARAM_VERSION_BIOS, bios_ver, 16, TW_CL_NULL);
680df54c2f9SSascha Wildner 	error[2] = tw_cli_get_param(ctlr, TWA_PARAM_VERSION_TABLE,
681df54c2f9SSascha Wildner 			TWA_PARAM_CTLR_MODEL, ctlr_model, 16, TW_CL_NULL);
682df54c2f9SSascha Wildner 
683df54c2f9SSascha Wildner 	tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
684df54c2f9SSascha Wildner 		TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
685df54c2f9SSascha Wildner 		0x1300, 0x3, TW_CL_SEVERITY_INFO_STRING,
686e45e2580SSascha Wildner 		"Controller details",
687df54c2f9SSascha Wildner 		"Model %.16s, %d ports, Firmware %.16s, BIOS %.16s",
688df54c2f9SSascha Wildner 		error[2]?(TW_INT8 *)TW_CL_NULL:ctlr_model,
689df54c2f9SSascha Wildner 		num_ports,
690df54c2f9SSascha Wildner 		error[0]?(TW_INT8 *)TW_CL_NULL:fw_ver,
691df54c2f9SSascha Wildner 		error[1]?(TW_INT8 *)TW_CL_NULL:bios_ver);
692df54c2f9SSascha Wildner }
693df54c2f9SSascha Wildner 
694df54c2f9SSascha Wildner 
695df54c2f9SSascha Wildner 
696df54c2f9SSascha Wildner /*
697df54c2f9SSascha Wildner  * Function name:	tw_cli_check_ctlr_state
698df54c2f9SSascha Wildner  * Description:		Makes sure that the fw status register reports a
699df54c2f9SSascha Wildner  *			proper status.
700df54c2f9SSascha Wildner  *
701df54c2f9SSascha Wildner  * Input:		ctlr	-- ptr to CL internal ctlr context
702df54c2f9SSascha Wildner  *			status_reg-- value in the status register
703df54c2f9SSascha Wildner  * Output:		None
704df54c2f9SSascha Wildner  * Return value:	0	-- no errors
705df54c2f9SSascha Wildner  *			non-zero-- errors
706df54c2f9SSascha Wildner  */
707df54c2f9SSascha Wildner TW_INT32
tw_cli_check_ctlr_state(struct tw_cli_ctlr_context * ctlr,TW_UINT32 status_reg)708df54c2f9SSascha Wildner tw_cli_check_ctlr_state(struct tw_cli_ctlr_context *ctlr, TW_UINT32 status_reg)
709df54c2f9SSascha Wildner {
710df54c2f9SSascha Wildner 	struct tw_cl_ctlr_handle	*ctlr_handle = ctlr->ctlr_handle;
711df54c2f9SSascha Wildner 	TW_INT32			error = TW_OSL_ESUCCESS;
712df54c2f9SSascha Wildner 
713df54c2f9SSascha Wildner 	tw_cli_dbg_printf(8, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
714df54c2f9SSascha Wildner 
715df54c2f9SSascha Wildner 	/* Check if the 'micro-controller ready' bit is not set. */
716df54c2f9SSascha Wildner 	if (!(status_reg & TWA_STATUS_MICROCONTROLLER_READY)) {
717df54c2f9SSascha Wildner 		TW_INT8	desc[200];
718df54c2f9SSascha Wildner 
719df54c2f9SSascha Wildner 		tw_osl_memzero(desc, 200);
720df54c2f9SSascha Wildner 		if (!(ctlr->reset_phase1_in_progress)) {
7214fbf05f9SSascha Wildner 			tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
722df54c2f9SSascha Wildner 				TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
723df54c2f9SSascha Wildner 				0x1301, 0x1, TW_CL_SEVERITY_ERROR_STRING,
724df54c2f9SSascha Wildner 				"Missing expected status bit(s)",
725df54c2f9SSascha Wildner 				"status reg = 0x%x; Missing bits: %s",
726df54c2f9SSascha Wildner 				status_reg,
727df54c2f9SSascha Wildner 				tw_cli_describe_bits(
728df54c2f9SSascha Wildner 					TWA_STATUS_MICROCONTROLLER_READY,
729df54c2f9SSascha Wildner 					desc));
730df54c2f9SSascha Wildner 			error = TW_OSL_EGENFAILURE;
731df54c2f9SSascha Wildner 		}
732df54c2f9SSascha Wildner 	}
733df54c2f9SSascha Wildner 
734df54c2f9SSascha Wildner 	/* Check if any error bits are set. */
735df54c2f9SSascha Wildner 	if ((status_reg & TWA_STATUS_UNEXPECTED_BITS) != 0) {
736df54c2f9SSascha Wildner 		TW_INT8	desc[200];
737df54c2f9SSascha Wildner 
738df54c2f9SSascha Wildner 		tw_osl_memzero(desc, 200);
739df54c2f9SSascha Wildner 
740df54c2f9SSascha Wildner 		/* Skip queue error msgs during 9650SE/9690SA reset */
741df54c2f9SSascha Wildner 		if (((ctlr->device_id != TW_CL_DEVICE_ID_9K_E) &&
742df54c2f9SSascha Wildner 		     (ctlr->device_id != TW_CL_DEVICE_ID_9K_SA)) ||
743df54c2f9SSascha Wildner 		    (!(ctlr->reset_in_progress)) ||
744df54c2f9SSascha Wildner 		    ((status_reg & TWA_STATUS_QUEUE_ERROR_INTERRUPT) == 0))
745f99dae5eSSascha Wildner 		{
7464fbf05f9SSascha Wildner 			tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
747df54c2f9SSascha Wildner 			    TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
748df54c2f9SSascha Wildner 			    0x1302, 0x1, TW_CL_SEVERITY_ERROR_STRING,
749df54c2f9SSascha Wildner 			    "Unexpected status bit(s)",
750df54c2f9SSascha Wildner 			    "status reg = 0x%x Unexpected bits: %s",
751df54c2f9SSascha Wildner 			    status_reg & TWA_STATUS_UNEXPECTED_BITS,
752df54c2f9SSascha Wildner 			    tw_cli_describe_bits(status_reg &
753df54c2f9SSascha Wildner 				    TWA_STATUS_UNEXPECTED_BITS, desc));
754f99dae5eSSascha Wildner 		}
755df54c2f9SSascha Wildner 
756df54c2f9SSascha Wildner 		if (status_reg & TWA_STATUS_PCI_PARITY_ERROR_INTERRUPT) {
7574fbf05f9SSascha Wildner 			tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
758df54c2f9SSascha Wildner 				TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
759df54c2f9SSascha Wildner 				0x1303, 0x1, TW_CL_SEVERITY_ERROR_STRING,
760df54c2f9SSascha Wildner 				"PCI parity error: clearing... "
761df54c2f9SSascha Wildner 				"Re-seat/move/replace card",
762df54c2f9SSascha Wildner 				"status reg = 0x%x %s",
763df54c2f9SSascha Wildner 				status_reg,
764df54c2f9SSascha Wildner 				tw_cli_describe_bits(status_reg, desc));
765df54c2f9SSascha Wildner 			TW_CLI_WRITE_CONTROL_REGISTER(ctlr->ctlr_handle,
766df54c2f9SSascha Wildner 				TWA_CONTROL_CLEAR_PARITY_ERROR);
767df54c2f9SSascha Wildner 
768df54c2f9SSascha Wildner #ifdef TW_OSL_PCI_CONFIG_ACCESSIBLE
769df54c2f9SSascha Wildner 			tw_osl_write_pci_config(ctlr->ctlr_handle,
770df54c2f9SSascha Wildner 				TW_CLI_PCI_CONFIG_STATUS_OFFSET,
771df54c2f9SSascha Wildner 				TWA_PCI_CONFIG_CLEAR_PARITY_ERROR, 2);
772df54c2f9SSascha Wildner #endif /* TW_OSL_PCI_CONFIG_ACCESSIBLE */
773df54c2f9SSascha Wildner 
774df54c2f9SSascha Wildner 		}
775df54c2f9SSascha Wildner 
776df54c2f9SSascha Wildner 		if (status_reg & TWA_STATUS_PCI_ABORT_INTERRUPT) {
7774fbf05f9SSascha Wildner 			tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
778df54c2f9SSascha Wildner 				TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
779df54c2f9SSascha Wildner 				0x1304, 0x1, TW_CL_SEVERITY_ERROR_STRING,
780df54c2f9SSascha Wildner 				"PCI abort: clearing... ",
781df54c2f9SSascha Wildner 				"status reg = 0x%x %s",
782df54c2f9SSascha Wildner 				status_reg,
783df54c2f9SSascha Wildner 				tw_cli_describe_bits(status_reg, desc));
784df54c2f9SSascha Wildner 			TW_CLI_WRITE_CONTROL_REGISTER(ctlr->ctlr_handle,
785df54c2f9SSascha Wildner 				TWA_CONTROL_CLEAR_PCI_ABORT);
786df54c2f9SSascha Wildner 
787df54c2f9SSascha Wildner #ifdef TW_OSL_PCI_CONFIG_ACCESSIBLE
788df54c2f9SSascha Wildner 			tw_osl_write_pci_config(ctlr->ctlr_handle,
789df54c2f9SSascha Wildner 				TW_CLI_PCI_CONFIG_STATUS_OFFSET,
790df54c2f9SSascha Wildner 				TWA_PCI_CONFIG_CLEAR_PCI_ABORT, 2);
791df54c2f9SSascha Wildner #endif /* TW_OSL_PCI_CONFIG_ACCESSIBLE */
792df54c2f9SSascha Wildner 
793df54c2f9SSascha Wildner 		}
794df54c2f9SSascha Wildner 
795df54c2f9SSascha Wildner 		if (status_reg & TWA_STATUS_QUEUE_ERROR_INTERRUPT) {
796df54c2f9SSascha Wildner 			/* Skip queue error msgs during 9650SE/9690SA reset */
797df54c2f9SSascha Wildner 			if (((ctlr->device_id != TW_CL_DEVICE_ID_9K_E) &&
798df54c2f9SSascha Wildner 			     (ctlr->device_id != TW_CL_DEVICE_ID_9K_SA)) ||
799df54c2f9SSascha Wildner 			    (!(ctlr->reset_in_progress)))
8004fbf05f9SSascha Wildner 				tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
801df54c2f9SSascha Wildner 						   TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
802df54c2f9SSascha Wildner 						   0x1305, 0x1, TW_CL_SEVERITY_ERROR_STRING,
803df54c2f9SSascha Wildner 						   "Controller queue error: clearing... ",
804df54c2f9SSascha Wildner 						   "status reg = 0x%x %s",
805df54c2f9SSascha Wildner 						   status_reg,
806df54c2f9SSascha Wildner 						   tw_cli_describe_bits(status_reg, desc));
807df54c2f9SSascha Wildner 			TW_CLI_WRITE_CONTROL_REGISTER(ctlr->ctlr_handle,
808df54c2f9SSascha Wildner 				TWA_CONTROL_CLEAR_QUEUE_ERROR);
809df54c2f9SSascha Wildner 		}
810df54c2f9SSascha Wildner 	}
811df54c2f9SSascha Wildner 	return(error);
812df54c2f9SSascha Wildner }
813df54c2f9SSascha Wildner 
814df54c2f9SSascha Wildner 
815df54c2f9SSascha Wildner 
816df54c2f9SSascha Wildner /*
817df54c2f9SSascha Wildner  * Function name:	tw_cli_describe_bits
818df54c2f9SSascha Wildner  * Description:		Given the value of the status register, returns a
819df54c2f9SSascha Wildner  *			string describing the meaning of each set bit.
820df54c2f9SSascha Wildner  *
821df54c2f9SSascha Wildner  * Input:		reg -- status register value
822df54c2f9SSascha Wildner  * Output:		Pointer to a string describing each set bit
823df54c2f9SSascha Wildner  * Return value:	Pointer to the string describing each set bit
824df54c2f9SSascha Wildner  */
825df54c2f9SSascha Wildner TW_INT8	*
tw_cli_describe_bits(TW_UINT32 reg,TW_INT8 * str)826df54c2f9SSascha Wildner tw_cli_describe_bits(TW_UINT32 reg, TW_INT8 *str)
827df54c2f9SSascha Wildner {
828df54c2f9SSascha Wildner 	tw_osl_strcpy(str, "[");
829df54c2f9SSascha Wildner 
830df54c2f9SSascha Wildner 	if (reg & TWA_STATUS_COMMAND_QUEUE_EMPTY)
831df54c2f9SSascha Wildner 		tw_osl_strcpy(&str[tw_osl_strlen(str)], "CMD_Q_EMPTY,");
832df54c2f9SSascha Wildner 	if (reg & TWA_STATUS_MICROCONTROLLER_READY)
833df54c2f9SSascha Wildner 		tw_osl_strcpy(&str[tw_osl_strlen(str)], "MC_RDY,");
834df54c2f9SSascha Wildner 	if (reg & TWA_STATUS_RESPONSE_QUEUE_EMPTY)
835df54c2f9SSascha Wildner 		tw_osl_strcpy(&str[tw_osl_strlen(str)], "RESP_Q_EMPTY,");
836df54c2f9SSascha Wildner 	if (reg & TWA_STATUS_COMMAND_QUEUE_FULL)
837df54c2f9SSascha Wildner 		tw_osl_strcpy(&str[tw_osl_strlen(str)], "CMD_Q_FULL,");
838df54c2f9SSascha Wildner 	if (reg & TWA_STATUS_RESPONSE_INTERRUPT)
839df54c2f9SSascha Wildner 		tw_osl_strcpy(&str[tw_osl_strlen(str)], "RESP_INTR,");
840df54c2f9SSascha Wildner 	if (reg & TWA_STATUS_COMMAND_INTERRUPT)
841df54c2f9SSascha Wildner 		tw_osl_strcpy(&str[tw_osl_strlen(str)], "CMD_INTR,");
842df54c2f9SSascha Wildner 	if (reg & TWA_STATUS_ATTENTION_INTERRUPT)
843df54c2f9SSascha Wildner 		tw_osl_strcpy(&str[tw_osl_strlen(str)], "ATTN_INTR,");
844df54c2f9SSascha Wildner 	if (reg & TWA_STATUS_HOST_INTERRUPT)
845df54c2f9SSascha Wildner 		tw_osl_strcpy(&str[tw_osl_strlen(str)], "HOST_INTR,");
846df54c2f9SSascha Wildner 	if (reg & TWA_STATUS_PCI_ABORT_INTERRUPT)
847df54c2f9SSascha Wildner 		tw_osl_strcpy(&str[tw_osl_strlen(str)], "PCI_ABRT,");
848df54c2f9SSascha Wildner 	if (reg & TWA_STATUS_QUEUE_ERROR_INTERRUPT)
849df54c2f9SSascha Wildner 		tw_osl_strcpy(&str[tw_osl_strlen(str)], "Q_ERR,");
850df54c2f9SSascha Wildner 	if (reg & TWA_STATUS_PCI_PARITY_ERROR_INTERRUPT)
851df54c2f9SSascha Wildner 		tw_osl_strcpy(&str[tw_osl_strlen(str)], "PCI_PERR");
852df54c2f9SSascha Wildner 
853df54c2f9SSascha Wildner 	tw_osl_strcpy(&str[tw_osl_strlen(str)], "]");
854df54c2f9SSascha Wildner 	return(str);
855df54c2f9SSascha Wildner }
856df54c2f9SSascha Wildner 
857df54c2f9SSascha Wildner 
858df54c2f9SSascha Wildner 
859df54c2f9SSascha Wildner #ifdef TW_OSL_DEBUG
860df54c2f9SSascha Wildner 
861df54c2f9SSascha Wildner /*
862df54c2f9SSascha Wildner  * Function name:	tw_cl_print_ctlr_stats
863df54c2f9SSascha Wildner  * Description:		Prints the current status of the controller.
864df54c2f9SSascha Wildner  *
865df54c2f9SSascha Wildner  * Input:		ctlr_handle-- controller handle
866df54c2f9SSascha Wildner  * Output:		None
867df54c2f9SSascha Wildner  * Return value:	None
868df54c2f9SSascha Wildner  */
869df54c2f9SSascha Wildner TW_VOID
tw_cl_print_ctlr_stats(struct tw_cl_ctlr_handle * ctlr_handle)870df54c2f9SSascha Wildner tw_cl_print_ctlr_stats(struct tw_cl_ctlr_handle *ctlr_handle)
871df54c2f9SSascha Wildner {
872df54c2f9SSascha Wildner 	struct tw_cli_ctlr_context	*ctlr =
873df54c2f9SSascha Wildner 		(struct tw_cli_ctlr_context *)(ctlr_handle->cl_ctlr_ctxt);
874df54c2f9SSascha Wildner 	TW_UINT32			status_reg;
875df54c2f9SSascha Wildner 	TW_INT8				desc[200];
876df54c2f9SSascha Wildner 
877df54c2f9SSascha Wildner 	tw_cli_dbg_printf(7, ctlr->ctlr_handle, "", "entered");
878df54c2f9SSascha Wildner 
879df54c2f9SSascha Wildner 	/* Print current controller details. */
880df54c2f9SSascha Wildner 	tw_cli_dbg_printf(0, ctlr_handle, "", "cl_ctlr_ctxt = %p", ctlr);
881df54c2f9SSascha Wildner 
882df54c2f9SSascha Wildner 	tw_osl_memzero(desc, 200);
883df54c2f9SSascha Wildner 	status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr_handle);
884df54c2f9SSascha Wildner 	tw_cli_dbg_printf(0, ctlr_handle, "", "status reg = 0x%x %s",
885df54c2f9SSascha Wildner 		status_reg, tw_cli_describe_bits(status_reg, desc));
886df54c2f9SSascha Wildner 
887df54c2f9SSascha Wildner 	tw_cli_dbg_printf(0, ctlr_handle, "", "CLq type  current  max");
888df54c2f9SSascha Wildner 	tw_cli_dbg_printf(0, ctlr_handle, "", "free      %04d     %04d",
889df54c2f9SSascha Wildner 		ctlr->q_stats[TW_CLI_FREE_Q].cur_len,
890df54c2f9SSascha Wildner 		ctlr->q_stats[TW_CLI_FREE_Q].max_len);
891df54c2f9SSascha Wildner 	tw_cli_dbg_printf(0, ctlr_handle, "", "busy      %04d     %04d",
892df54c2f9SSascha Wildner 		ctlr->q_stats[TW_CLI_BUSY_Q].cur_len,
893df54c2f9SSascha Wildner 		ctlr->q_stats[TW_CLI_BUSY_Q].max_len);
894df54c2f9SSascha Wildner 	tw_cli_dbg_printf(0, ctlr_handle, "", "pending   %04d     %04d",
895df54c2f9SSascha Wildner 		ctlr->q_stats[TW_CLI_PENDING_Q].cur_len,
896df54c2f9SSascha Wildner 		ctlr->q_stats[TW_CLI_PENDING_Q].max_len);
897df54c2f9SSascha Wildner 	tw_cli_dbg_printf(0, ctlr_handle, "", "complete  %04d     %04d",
898df54c2f9SSascha Wildner 		ctlr->q_stats[TW_CLI_COMPLETE_Q].cur_len,
899df54c2f9SSascha Wildner 		ctlr->q_stats[TW_CLI_COMPLETE_Q].max_len);
900df54c2f9SSascha Wildner 	tw_cli_dbg_printf(0, ctlr_handle, "", "AEN queue head %d  tail %d",
901df54c2f9SSascha Wildner 			ctlr->aen_head, ctlr->aen_tail);
902df54c2f9SSascha Wildner }
903df54c2f9SSascha Wildner 
904df54c2f9SSascha Wildner 
905df54c2f9SSascha Wildner 
906df54c2f9SSascha Wildner /*
907df54c2f9SSascha Wildner  * Function name:	tw_cl_reset_stats
908df54c2f9SSascha Wildner  * Description:		Resets CL maintained statistics for the controller.
909df54c2f9SSascha Wildner  *
910df54c2f9SSascha Wildner  * Input:		ctlr_handle-- controller handle
911df54c2f9SSascha Wildner  * Output:		None
912df54c2f9SSascha Wildner  * Return value:	None
913df54c2f9SSascha Wildner  */
914df54c2f9SSascha Wildner TW_VOID
tw_cl_reset_stats(struct tw_cl_ctlr_handle * ctlr_handle)915df54c2f9SSascha Wildner tw_cl_reset_stats(struct tw_cl_ctlr_handle *ctlr_handle)
916df54c2f9SSascha Wildner {
917df54c2f9SSascha Wildner 	struct tw_cli_ctlr_context	*ctlr =
918df54c2f9SSascha Wildner 		(struct tw_cli_ctlr_context *)(ctlr_handle->cl_ctlr_ctxt);
919df54c2f9SSascha Wildner 
920df54c2f9SSascha Wildner 	tw_cli_dbg_printf(7, ctlr_handle, tw_osl_cur_func(), "entered");
921df54c2f9SSascha Wildner 	ctlr->q_stats[TW_CLI_FREE_Q].max_len = 0;
922df54c2f9SSascha Wildner 	ctlr->q_stats[TW_CLI_BUSY_Q].max_len = 0;
923df54c2f9SSascha Wildner 	ctlr->q_stats[TW_CLI_PENDING_Q].max_len = 0;
924df54c2f9SSascha Wildner 	ctlr->q_stats[TW_CLI_COMPLETE_Q].max_len = 0;
925df54c2f9SSascha Wildner }
926df54c2f9SSascha Wildner 
927df54c2f9SSascha Wildner 
928df54c2f9SSascha Wildner 
929df54c2f9SSascha Wildner /*
930df54c2f9SSascha Wildner  * Function name:	tw_cli_print_req_info
931df54c2f9SSascha Wildner  * Description:		Prints CL internal details of a given request.
932df54c2f9SSascha Wildner  *
933df54c2f9SSascha Wildner  * Input:		req	-- ptr to CL internal request context
934df54c2f9SSascha Wildner  * Output:		None
935df54c2f9SSascha Wildner  * Return value:	None
936df54c2f9SSascha Wildner  */
937df54c2f9SSascha Wildner TW_VOID
tw_cl_print_req_info(struct tw_cl_req_handle * req_handle)938df54c2f9SSascha Wildner tw_cl_print_req_info(struct tw_cl_req_handle *req_handle)
939df54c2f9SSascha Wildner {
940df54c2f9SSascha Wildner 	struct tw_cli_req_context	*req = req_handle->cl_req_ctxt;
941df54c2f9SSascha Wildner 	struct tw_cli_ctlr_context	*ctlr = req->ctlr;
942df54c2f9SSascha Wildner 	struct tw_cl_ctlr_handle	*ctlr_handle = ctlr->ctlr_handle;
943df54c2f9SSascha Wildner 	struct tw_cl_command_packet	*cmd_pkt = req->cmd_pkt;
944df54c2f9SSascha Wildner 	struct tw_cl_command_9k		*cmd9k;
945df54c2f9SSascha Wildner 	union tw_cl_command_7k		*cmd7k;
946df54c2f9SSascha Wildner 	TW_UINT8			*cdb;
947df54c2f9SSascha Wildner 	TW_VOID				*sgl;
948df54c2f9SSascha Wildner 	TW_UINT32			sgl_entries;
949df54c2f9SSascha Wildner 	TW_UINT32			i;
950df54c2f9SSascha Wildner 
951df54c2f9SSascha Wildner 	tw_cli_dbg_printf(0, ctlr_handle, tw_osl_cur_func(),
952df54c2f9SSascha Wildner 		"CL details for request:");
953df54c2f9SSascha Wildner 	tw_cli_dbg_printf(0, ctlr_handle, tw_osl_cur_func(),
954df54c2f9SSascha Wildner 		"req_handle = %p, ctlr = %p,\n"
955df54c2f9SSascha Wildner 		"cmd_pkt = %p, cmd_pkt_phys = 0x%llx,\n"
956df54c2f9SSascha Wildner 		"data = %p, length = 0x%x, data_phys = 0x%llx,\n"
957df54c2f9SSascha Wildner 		"state = 0x%x, flags = 0x%x, error = 0x%x,\n"
958df54c2f9SSascha Wildner 		"orig_req = %p, callback = %p, req_id = 0x%x,\n"
959df54c2f9SSascha Wildner 		"next_req = %p, prev_req = %p",
960df54c2f9SSascha Wildner 		req_handle, ctlr,
961df54c2f9SSascha Wildner 		cmd_pkt, req->cmd_pkt_phys,
962df54c2f9SSascha Wildner 		req->data, req->length, req->data_phys,
963df54c2f9SSascha Wildner 		req->state, req->flags, req->error_code,
964df54c2f9SSascha Wildner 		req->orig_req, req->tw_cli_callback, req->request_id,
965df54c2f9SSascha Wildner 		req->link.next, req->link.prev);
966df54c2f9SSascha Wildner 
967df54c2f9SSascha Wildner 	if (req->flags & TW_CLI_REQ_FLAGS_9K) {
968df54c2f9SSascha Wildner 		cmd9k = &(cmd_pkt->command.cmd_pkt_9k);
969df54c2f9SSascha Wildner 		sgl = cmd9k->sg_list;
970df54c2f9SSascha Wildner 		sgl_entries = TW_CL_SWAP16(
971df54c2f9SSascha Wildner 			GET_SGL_ENTRIES(cmd9k->lun_h4__sgl_entries));
972df54c2f9SSascha Wildner 		tw_cli_dbg_printf(0, ctlr_handle, tw_osl_cur_func(),
973df54c2f9SSascha Wildner 			"9K cmd: opcode = 0x%x, unit = 0x%x, req_id = 0x%x,\n"
974df54c2f9SSascha Wildner 			"status = 0x%x, sgl_offset = 0x%x, sgl_entries = 0x%x",
975df54c2f9SSascha Wildner 			GET_OPCODE(cmd9k->res__opcode),
976df54c2f9SSascha Wildner 			cmd9k->unit,
977df54c2f9SSascha Wildner 			TW_CL_SWAP16(GET_REQ_ID(cmd9k->lun_l4__req_id)),
978df54c2f9SSascha Wildner 			cmd9k->status,
979df54c2f9SSascha Wildner 			cmd9k->sgl_offset,
980df54c2f9SSascha Wildner 			sgl_entries);
981df54c2f9SSascha Wildner 
982df54c2f9SSascha Wildner 		cdb = (TW_UINT8 *)(cmd9k->cdb);
983df54c2f9SSascha Wildner 		tw_cli_dbg_printf(0, ctlr_handle, tw_osl_cur_func(),
984df54c2f9SSascha Wildner 			"CDB: %x %x %x %x %x %x %x %x"
985df54c2f9SSascha Wildner 			"%x %x %x %x %x %x %x %x",
986df54c2f9SSascha Wildner 			cdb[0], cdb[1], cdb[2], cdb[3],
987df54c2f9SSascha Wildner 			cdb[4], cdb[5], cdb[6], cdb[7],
988df54c2f9SSascha Wildner 			cdb[8], cdb[9], cdb[10], cdb[11],
989df54c2f9SSascha Wildner 			cdb[12], cdb[13], cdb[14], cdb[15]);
990df54c2f9SSascha Wildner 	} else {
991df54c2f9SSascha Wildner 		cmd7k = &(cmd_pkt->command.cmd_pkt_7k);
992df54c2f9SSascha Wildner 		sgl = cmd7k->param.sgl;
993df54c2f9SSascha Wildner 		sgl_entries = (cmd7k->generic.size -
994df54c2f9SSascha Wildner 			GET_SGL_OFF(cmd7k->generic.sgl_off__opcode)) /
995df54c2f9SSascha Wildner 			((ctlr->flags & TW_CL_64BIT_ADDRESSES) ? 3 : 2);
996df54c2f9SSascha Wildner 		tw_cli_dbg_printf(0, ctlr_handle, tw_osl_cur_func(),
997df54c2f9SSascha Wildner 			"7K cmd: opcode = 0x%x, sgl_offset = 0x%x,\n"
998df54c2f9SSascha Wildner 			"size = 0x%x, req_id = 0x%x, unit = 0x%x,\n"
999df54c2f9SSascha Wildner 			"status = 0x%x, flags = 0x%x, count = 0x%x",
1000df54c2f9SSascha Wildner 			GET_OPCODE(cmd7k->generic.sgl_off__opcode),
1001df54c2f9SSascha Wildner 			GET_SGL_OFF(cmd7k->generic.sgl_off__opcode),
1002df54c2f9SSascha Wildner 			cmd7k->generic.size,
1003df54c2f9SSascha Wildner 			TW_CL_SWAP16(cmd7k->generic.request_id),
1004df54c2f9SSascha Wildner 			GET_UNIT(cmd7k->generic.host_id__unit),
1005df54c2f9SSascha Wildner 			cmd7k->generic.status,
1006df54c2f9SSascha Wildner 			cmd7k->generic.flags,
1007df54c2f9SSascha Wildner 			TW_CL_SWAP16(cmd7k->generic.count));
1008df54c2f9SSascha Wildner 	}
1009df54c2f9SSascha Wildner 
1010df54c2f9SSascha Wildner 	tw_cli_dbg_printf(0, ctlr_handle, tw_osl_cur_func(), "SG entries:");
1011df54c2f9SSascha Wildner 
1012df54c2f9SSascha Wildner 	if (ctlr->flags & TW_CL_64BIT_ADDRESSES) {
1013df54c2f9SSascha Wildner 		struct tw_cl_sg_desc64 *sgl64 = (struct tw_cl_sg_desc64 *)sgl;
1014df54c2f9SSascha Wildner 
1015df54c2f9SSascha Wildner 		for (i = 0; i < sgl_entries; i++) {
1016df54c2f9SSascha Wildner 			tw_cli_dbg_printf(0, ctlr_handle, tw_osl_cur_func(),
1017df54c2f9SSascha Wildner 				"0x%llx  0x%x",
1018df54c2f9SSascha Wildner 				sgl64[i].address, sgl64[i].length);
1019df54c2f9SSascha Wildner 		}
1020df54c2f9SSascha Wildner 	} else {
1021df54c2f9SSascha Wildner 		struct tw_cl_sg_desc32 *sgl32 = (struct tw_cl_sg_desc32 *)sgl;
1022df54c2f9SSascha Wildner 
1023df54c2f9SSascha Wildner 		for (i = 0; i < sgl_entries; i++) {
1024df54c2f9SSascha Wildner 			tw_cli_dbg_printf(0, ctlr_handle, tw_osl_cur_func(),
1025df54c2f9SSascha Wildner 				"0x%x  0x%x",
1026df54c2f9SSascha Wildner 				sgl32[i].address, sgl32[i].length);
1027df54c2f9SSascha Wildner 		}
1028df54c2f9SSascha Wildner 	}
1029df54c2f9SSascha Wildner }
1030df54c2f9SSascha Wildner 
1031df54c2f9SSascha Wildner #endif /* TW_OSL_DEBUG */
1032