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