1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2004-07 Applied Micro Circuits Corporation.
5 * Copyright (c) 2004-05 Vinod Kashyap
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $FreeBSD$
30 */
31
32 /*
33 * AMCC'S 3ware driver for 9000 series storage controllers.
34 *
35 * Author: Vinod Kashyap
36 * Modifications by: Adam Radford
37 * Modifications by: Manjunath Ranganathaiah
38 */
39
40 /*
41 * Common Layer initialization functions.
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 * Function name: tw_cl_ctlr_supported
54 * Description: Determines if a controller is supported.
55 *
56 * Input: vendor_id -- vendor id of the controller
57 * device_id -- device id of the controller
58 * Output: None
59 * Return value: TW_CL_TRUE-- controller supported
60 * TW_CL_FALSE-- controller not supported
61 */
62 TW_INT32
63 tw_cl_ctlr_supported(TW_INT32 vendor_id, TW_INT32 device_id)
64 {
65 if ((vendor_id == TW_CL_VENDOR_ID) &&
66 ((device_id == TW_CL_DEVICE_ID_9K) ||
67 (device_id == TW_CL_DEVICE_ID_9K_X) ||
68 (device_id == TW_CL_DEVICE_ID_9K_E) ||
69 (device_id == TW_CL_DEVICE_ID_9K_SA)))
70 return(TW_CL_TRUE);
71 return(TW_CL_FALSE);
72 }
73
74 /*
75 * Function name: tw_cl_get_pci_bar_info
76 * Description: Returns PCI BAR info.
77 *
78 * Input: device_id -- device id of the controller
79 * bar_type -- type of PCI BAR in question
80 * Output: bar_num -- PCI BAR number corresponding to bar_type
81 * bar0_offset -- byte offset from BAR 0 (0x10 in
82 * PCI config space)
83 * bar_size -- size, in bytes, of the BAR in question
84 * Return value: 0 -- success
85 * non-zero -- failure
86 */
87 TW_INT32
88 tw_cl_get_pci_bar_info(TW_INT32 device_id, TW_INT32 bar_type,
89 TW_INT32 *bar_num, TW_INT32 *bar0_offset, TW_INT32 *bar_size)
90 {
91 TW_INT32 error = TW_OSL_ESUCCESS;
92
93 switch(device_id) {
94 case TW_CL_DEVICE_ID_9K:
95 switch(bar_type) {
96 case TW_CL_BAR_TYPE_IO:
97 *bar_num = 0;
98 *bar0_offset = 0;
99 *bar_size = 4;
100 break;
101
102 case TW_CL_BAR_TYPE_MEM:
103 *bar_num = 1;
104 *bar0_offset = 0x4;
105 *bar_size = 8;
106 break;
107
108 case TW_CL_BAR_TYPE_SBUF:
109 *bar_num = 2;
110 *bar0_offset = 0xC;
111 *bar_size = 8;
112 break;
113 }
114 break;
115
116 case TW_CL_DEVICE_ID_9K_X:
117 case TW_CL_DEVICE_ID_9K_E:
118 case TW_CL_DEVICE_ID_9K_SA:
119 switch(bar_type) {
120 case TW_CL_BAR_TYPE_IO:
121 *bar_num = 2;
122 *bar0_offset = 0x10;
123 *bar_size = 4;
124 break;
125
126 case TW_CL_BAR_TYPE_MEM:
127 *bar_num = 1;
128 *bar0_offset = 0x8;
129 *bar_size = 8;
130 break;
131
132 case TW_CL_BAR_TYPE_SBUF:
133 *bar_num = 0;
134 *bar0_offset = 0;
135 *bar_size = 8;
136 break;
137 }
138 break;
139
140 default:
141 error = TW_OSL_ENOTTY;
142 break;
143 }
144
145 return(error);
146 }
147
148 /*
149 * Function name: tw_cl_get_mem_requirements
150 * Description: Provides info about Common Layer requirements for a
151 * controller, given the controller type (in 'flags').
152 * Input: ctlr_handle -- controller handle
153 * flags -- more info passed by the OS Layer
154 * device_id -- device id of the controller
155 * max_simult_reqs -- maximum # of simultaneous
156 * requests that the OS Layer expects
157 * the Common Layer to support
158 * max_aens -- maximun # of AEN's needed to be supported
159 * Output: alignment -- alignment needed for all DMA'able
160 * buffers
161 * sg_size_factor -- every SG element should have a size
162 * that's a multiple of this number
163 * non_dma_mem_size -- # of bytes of memory needed for
164 * non-DMA purposes
165 * dma_mem_size -- # of bytes of DMA'able memory needed
166 * per_req_dma_mem_size -- # of bytes of DMA'able memory
167 * needed per request, if applicable
168 * per_req_non_dma_mem_size -- # of bytes of memory needed
169 * per request for non-DMA purposes,
170 * if applicable
171 * Output: None
172 * Return value: 0 -- success
173 * non-zero-- failure
174 */
175 TW_INT32
176 tw_cl_get_mem_requirements(struct tw_cl_ctlr_handle *ctlr_handle,
177 TW_UINT32 flags, TW_INT32 device_id, TW_INT32 max_simult_reqs,
178 TW_INT32 max_aens, TW_UINT32 *alignment, TW_UINT32 *sg_size_factor,
179 TW_UINT32 *non_dma_mem_size, TW_UINT32 *dma_mem_size
180 )
181 {
182 if (device_id == 0)
183 device_id = TW_CL_DEVICE_ID_9K;
184
185 if (max_simult_reqs > TW_CL_MAX_SIMULTANEOUS_REQUESTS) {
186 tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
187 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
188 0x1000, 0x1, TW_CL_SEVERITY_ERROR_STRING,
189 "Too many simultaneous requests to support!",
190 "requested = %d, supported = %d, error = %d\n",
191 max_simult_reqs, TW_CL_MAX_SIMULTANEOUS_REQUESTS,
192 TW_OSL_EBIG);
193 return(TW_OSL_EBIG);
194 }
195
196 *alignment = TWA_ALIGNMENT(device_id);
197 *sg_size_factor = TWA_SG_ELEMENT_SIZE_FACTOR(device_id);
198
199 /*
200 * Total non-DMA memory needed is the sum total of memory needed for
201 * the controller context, request packets (including the 1 needed for
202 * CL internal requests), and event packets.
203 */
204
205 *non_dma_mem_size = sizeof(struct tw_cli_ctlr_context) +
206 (sizeof(struct tw_cli_req_context) * max_simult_reqs) +
207 (sizeof(struct tw_cl_event_packet) * max_aens);
208
209 /*
210 * Total DMA'able memory needed is the sum total of memory needed for
211 * all command packets (including the 1 needed for CL internal
212 * requests), and memory needed to hold the payload for internal
213 * requests.
214 */
215
216 *dma_mem_size = (sizeof(struct tw_cl_command_packet) *
217 (max_simult_reqs)) + (TW_CLI_SECTOR_SIZE);
218
219 return(0);
220 }
221
222 /*
223 * Function name: tw_cl_init_ctlr
224 * Description: Initializes driver data structures for the controller.
225 *
226 * Input: ctlr_handle -- controller handle
227 * flags -- more info passed by the OS Layer
228 * device_id -- device id of the controller
229 * max_simult_reqs -- maximum # of simultaneous requests
230 * that the OS Layer expects the Common
231 * Layer to support
232 * max_aens -- maximun # of AEN's needed to be supported
233 * non_dma_mem -- ptr to allocated non-DMA memory
234 * dma_mem -- ptr to allocated DMA'able memory
235 * dma_mem_phys -- physical address of dma_mem
236 * Output: None
237 * Return value: 0 -- success
238 * non-zero-- failure
239 */
240 TW_INT32
241 tw_cl_init_ctlr(struct tw_cl_ctlr_handle *ctlr_handle, TW_UINT32 flags,
242 TW_INT32 device_id, TW_INT32 max_simult_reqs, TW_INT32 max_aens,
243 TW_VOID *non_dma_mem, TW_VOID *dma_mem, TW_UINT64 dma_mem_phys
244 )
245 {
246 struct tw_cli_ctlr_context *ctlr;
247 struct tw_cli_req_context *req;
248 TW_UINT8 *free_non_dma_mem;
249 TW_INT32 error = TW_OSL_ESUCCESS;
250 TW_INT32 i;
251
252 tw_cli_dbg_printf(3, ctlr_handle, tw_osl_cur_func(), "entered");
253
254 if (flags & TW_CL_START_CTLR_ONLY) {
255 ctlr = (struct tw_cli_ctlr_context *)
256 (ctlr_handle->cl_ctlr_ctxt);
257 goto start_ctlr;
258 }
259
260 if (max_simult_reqs > TW_CL_MAX_SIMULTANEOUS_REQUESTS) {
261 tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
262 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
263 0x1000, 0x1, TW_CL_SEVERITY_ERROR_STRING,
264 "Too many simultaneous requests to support!",
265 "requested = %d, supported = %d, error = %d\n",
266 max_simult_reqs, TW_CL_MAX_SIMULTANEOUS_REQUESTS,
267 TW_OSL_EBIG);
268 return(TW_OSL_EBIG);
269 }
270
271 if ((non_dma_mem == TW_CL_NULL) || (dma_mem == TW_CL_NULL)
272 ) {
273 tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
274 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
275 0x1001, 0x1, TW_CL_SEVERITY_ERROR_STRING,
276 "Insufficient memory for Common Layer's internal usage",
277 "error = %d\n", TW_OSL_ENOMEM);
278 return(TW_OSL_ENOMEM);
279 }
280
281 tw_osl_memzero(non_dma_mem, sizeof(struct tw_cli_ctlr_context) +
282 (sizeof(struct tw_cli_req_context) * max_simult_reqs) +
283 (sizeof(struct tw_cl_event_packet) * max_aens));
284
285 tw_osl_memzero(dma_mem,
286 (sizeof(struct tw_cl_command_packet) *
287 max_simult_reqs) +
288 TW_CLI_SECTOR_SIZE);
289
290 free_non_dma_mem = (TW_UINT8 *)non_dma_mem;
291
292 ctlr = (struct tw_cli_ctlr_context *)free_non_dma_mem;
293 free_non_dma_mem += sizeof(struct tw_cli_ctlr_context);
294
295 ctlr_handle->cl_ctlr_ctxt = ctlr;
296 ctlr->ctlr_handle = ctlr_handle;
297
298 ctlr->device_id = (TW_UINT32)device_id;
299 ctlr->arch_id = TWA_ARCH_ID(device_id);
300 ctlr->flags = flags;
301 ctlr->sg_size_factor = TWA_SG_ELEMENT_SIZE_FACTOR(device_id);
302 ctlr->max_simult_reqs = max_simult_reqs;
303 ctlr->max_aens_supported = max_aens;
304
305 /* Initialize queues of CL internal request context packets. */
306 tw_cli_req_q_init(ctlr, TW_CLI_FREE_Q);
307 tw_cli_req_q_init(ctlr, TW_CLI_BUSY_Q);
308 tw_cli_req_q_init(ctlr, TW_CLI_PENDING_Q);
309 tw_cli_req_q_init(ctlr, TW_CLI_COMPLETE_Q);
310 tw_cli_req_q_init(ctlr, TW_CLI_RESET_Q);
311
312 /* Initialize all locks used by CL. */
313 ctlr->gen_lock = &(ctlr->gen_lock_handle);
314 tw_osl_init_lock(ctlr_handle, "tw_cl_gen_lock", ctlr->gen_lock);
315 ctlr->io_lock = &(ctlr->io_lock_handle);
316 tw_osl_init_lock(ctlr_handle, "tw_cl_io_lock", ctlr->io_lock);
317
318 /* Initialize CL internal request context packets. */
319 ctlr->req_ctxt_buf = (struct tw_cli_req_context *)free_non_dma_mem;
320 free_non_dma_mem += (sizeof(struct tw_cli_req_context) *
321 max_simult_reqs);
322
323 ctlr->cmd_pkt_buf = (struct tw_cl_command_packet *)dma_mem;
324 ctlr->cmd_pkt_phys = dma_mem_phys;
325
326 ctlr->internal_req_data = (TW_UINT8 *)
327 (ctlr->cmd_pkt_buf +
328 max_simult_reqs);
329 ctlr->internal_req_data_phys = ctlr->cmd_pkt_phys +
330 (sizeof(struct tw_cl_command_packet) *
331 max_simult_reqs);
332
333 for (i = 0; i < max_simult_reqs; i++) {
334 req = &(ctlr->req_ctxt_buf[i]);
335
336 req->cmd_pkt = &(ctlr->cmd_pkt_buf[i]);
337 req->cmd_pkt_phys = ctlr->cmd_pkt_phys +
338 (i * sizeof(struct tw_cl_command_packet));
339
340 req->request_id = i;
341 req->ctlr = ctlr;
342
343 /* Insert request into the free queue. */
344 tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
345 }
346
347 /* Initialize the AEN queue. */
348 ctlr->aen_queue = (struct tw_cl_event_packet *)free_non_dma_mem;
349
350 start_ctlr:
351 /*
352 * Disable interrupts. Interrupts will be enabled in tw_cli_start_ctlr
353 * (only) if initialization succeeded.
354 */
355 tw_cli_disable_interrupts(ctlr);
356
357 /* Initialize the controller. */
358 if ((error = tw_cli_start_ctlr(ctlr))) {
359 /* Soft reset the controller, and try one more time. */
360 tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
361 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
362 0x1002, 0x1, TW_CL_SEVERITY_ERROR_STRING,
363 "Controller initialization failed. Retrying...",
364 "error = %d\n", error);
365 if ((error = tw_cli_soft_reset(ctlr))) {
366 tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
367 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
368 0x1003, 0x1, TW_CL_SEVERITY_ERROR_STRING,
369 "Controller soft reset failed",
370 "error = %d\n", error);
371 return(error);
372 } else if ((error = tw_cli_start_ctlr(ctlr))) {
373 tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
374 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
375 0x1004, 0x1, TW_CL_SEVERITY_ERROR_STRING,
376 "Controller initialization retry failed",
377 "error = %d\n", error);
378 return(error);
379 }
380 }
381 /* Notify some info about the controller to the OSL. */
382 tw_cli_notify_ctlr_info(ctlr);
383
384 /* Mark the controller active. */
385 ctlr->active = TW_CL_TRUE;
386 return(error);
387 }
388
389 /*
390 * Function name: tw_cli_start_ctlr
391 * Description: Establishes a logical connection with the controller.
392 * Determines whether or not the driver is compatible
393 * with the firmware on the controller, before proceeding
394 * to work with it.
395 *
396 * Input: ctlr -- ptr to per ctlr structure
397 * Output: None
398 * Return value: 0 -- success
399 * non-zero-- failure
400 */
401 TW_INT32
402 tw_cli_start_ctlr(struct tw_cli_ctlr_context *ctlr)
403 {
404 TW_UINT16 fw_on_ctlr_srl = 0;
405 TW_UINT16 fw_on_ctlr_arch_id = 0;
406 TW_UINT16 fw_on_ctlr_branch = 0;
407 TW_UINT16 fw_on_ctlr_build = 0;
408 TW_UINT32 init_connect_result = 0;
409 TW_INT32 error = TW_OSL_ESUCCESS;
410
411 tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
412
413 /* Wait for the controller to become ready. */
414 if ((error = tw_cli_poll_status(ctlr,
415 TWA_STATUS_MICROCONTROLLER_READY,
416 TW_CLI_REQUEST_TIMEOUT_PERIOD))) {
417 tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
418 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
419 0x1009, 0x1, TW_CL_SEVERITY_ERROR_STRING,
420 "Microcontroller not ready",
421 "error = %d", error);
422 return(error);
423 }
424 /* Drain the response queue. */
425 if ((error = tw_cli_drain_response_queue(ctlr))) {
426 tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
427 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
428 0x100A, 0x1, TW_CL_SEVERITY_ERROR_STRING,
429 "Can't drain response queue",
430 "error = %d", error);
431 return(error);
432 }
433 /* Establish a logical connection with the controller. */
434 if ((error = tw_cli_init_connection(ctlr,
435 (TW_UINT16)(ctlr->max_simult_reqs),
436 TWA_EXTENDED_INIT_CONNECT, TWA_CURRENT_FW_SRL,
437 (TW_UINT16)(ctlr->arch_id),
438 TWA_CURRENT_FW_BRANCH(ctlr->arch_id),
439 TWA_CURRENT_FW_BUILD(ctlr->arch_id),
440 &fw_on_ctlr_srl, &fw_on_ctlr_arch_id,
441 &fw_on_ctlr_branch, &fw_on_ctlr_build,
442 &init_connect_result))) {
443 tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
444 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
445 0x100B, 0x2, TW_CL_SEVERITY_WARNING_STRING,
446 "Can't initialize connection in current mode",
447 "error = %d", error);
448 return(error);
449 }
450 {
451 /* See if we can at least work with the firmware on the
452 * controller in the current mode.
453 */
454 if (init_connect_result & TWA_CTLR_FW_COMPATIBLE) {
455 /* Yes, we can. Make note of the operating mode. */
456 if (init_connect_result & TWA_CTLR_FW_SAME_OR_NEWER) {
457 ctlr->working_srl = TWA_CURRENT_FW_SRL;
458 ctlr->working_branch =
459 TWA_CURRENT_FW_BRANCH(ctlr->arch_id);
460 ctlr->working_build =
461 TWA_CURRENT_FW_BUILD(ctlr->arch_id);
462 } else {
463 ctlr->working_srl = fw_on_ctlr_srl;
464 ctlr->working_branch = fw_on_ctlr_branch;
465 ctlr->working_build = fw_on_ctlr_build;
466 }
467 } else {
468 /*
469 * No, we can't. See if we can at least work with
470 * it in the base mode.
471 */
472 tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
473 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
474 0x1010, 0x2, TW_CL_SEVERITY_WARNING_STRING,
475 "Driver/Firmware mismatch. "
476 "Negotiating for base level...",
477 " ");
478 if ((error = tw_cli_init_connection(ctlr,
479 (TW_UINT16)(ctlr->max_simult_reqs),
480 TWA_EXTENDED_INIT_CONNECT,
481 TWA_BASE_FW_SRL,
482 (TW_UINT16)(ctlr->arch_id),
483 TWA_BASE_FW_BRANCH, TWA_BASE_FW_BUILD,
484 &fw_on_ctlr_srl, &fw_on_ctlr_arch_id,
485 &fw_on_ctlr_branch, &fw_on_ctlr_build,
486 &init_connect_result))) {
487 tw_cl_create_event(ctlr->ctlr_handle,
488 TW_CL_FALSE,
489 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
490 0x1011, 0x1,
491 TW_CL_SEVERITY_ERROR_STRING,
492 "Can't initialize connection in "
493 "base mode",
494 " ");
495 return(error);
496 }
497 if (!(init_connect_result & TWA_CTLR_FW_COMPATIBLE)) {
498 /*
499 * The firmware on the controller is not even
500 * compatible with our base mode. We cannot
501 * work with it. Bail...
502 */
503 return(1);
504 }
505 /*
506 * We can work with this firmware, but only in
507 * base mode.
508 */
509 ctlr->working_srl = TWA_BASE_FW_SRL;
510 ctlr->working_branch = TWA_BASE_FW_BRANCH;
511 ctlr->working_build = TWA_BASE_FW_BUILD;
512 ctlr->operating_mode = TWA_BASE_MODE;
513 }
514 ctlr->fw_on_ctlr_srl = fw_on_ctlr_srl;
515 ctlr->fw_on_ctlr_branch = fw_on_ctlr_branch;
516 ctlr->fw_on_ctlr_build = fw_on_ctlr_build;
517 }
518
519 /* Drain the AEN queue */
520 if ((error = tw_cli_drain_aen_queue(ctlr)))
521 /*
522 * We will just print that we couldn't drain the AEN queue.
523 * There's no need to bail out.
524 */
525 tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
526 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
527 0x1014, 0x2, TW_CL_SEVERITY_WARNING_STRING,
528 "Can't drain AEN queue",
529 "error = %d", error);
530
531 /* Enable interrupts. */
532 tw_cli_enable_interrupts(ctlr);
533
534 return(TW_OSL_ESUCCESS);
535 }
536
537 /*
538 * Function name: tw_cl_shutdown_ctlr
539 * Description: Closes logical connection with the controller.
540 *
541 * Input: ctlr -- ptr to per ctlr structure
542 * flags -- more info passed by the OS Layer
543 * Output: None
544 * Return value: 0 -- success
545 * non-zero-- failure
546 */
547 TW_INT32
548 tw_cl_shutdown_ctlr(struct tw_cl_ctlr_handle *ctlr_handle, TW_UINT32 flags)
549 {
550 struct tw_cli_ctlr_context *ctlr =
551 (struct tw_cli_ctlr_context *)(ctlr_handle->cl_ctlr_ctxt);
552 TW_INT32 error;
553
554 tw_cli_dbg_printf(3, ctlr_handle, tw_osl_cur_func(), "entered");
555 /*
556 * Mark the controller as inactive, disable any further interrupts,
557 * and notify the controller that we are going down.
558 */
559 ctlr->active = TW_CL_FALSE;
560
561 tw_cli_disable_interrupts(ctlr);
562
563 /* Let the controller know that we are going down. */
564 if ((error = tw_cli_init_connection(ctlr, TWA_SHUTDOWN_MESSAGE_CREDITS,
565 0, 0, 0, 0, 0, TW_CL_NULL, TW_CL_NULL, TW_CL_NULL,
566 TW_CL_NULL, TW_CL_NULL)))
567 tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
568 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
569 0x1015, 0x1, TW_CL_SEVERITY_ERROR_STRING,
570 "Can't close connection with controller",
571 "error = %d", error);
572
573 if (flags & TW_CL_STOP_CTLR_ONLY)
574 goto ret;
575
576 /* Destroy all locks used by CL. */
577 tw_osl_destroy_lock(ctlr_handle, ctlr->gen_lock);
578 tw_osl_destroy_lock(ctlr_handle, ctlr->io_lock);
579
580 ret:
581 return(error);
582 }
583
584 /*
585 * Function name: tw_cli_init_connection
586 * Description: Sends init_connection cmd to firmware
587 *
588 * Input: ctlr -- ptr to per ctlr structure
589 * message_credits -- max # of requests that we might send
590 * down simultaneously. This will be
591 * typically set to 256 at init-time or
592 * after a reset, and to 1 at shutdown-time
593 * set_features -- indicates if we intend to use 64-bit
594 * sg, also indicates if we want to do a
595 * basic or an extended init_connection;
596 *
597 * Note: The following input/output parameters are valid, only in case of an
598 * extended init_connection:
599 *
600 * current_fw_srl -- srl of fw we are bundled
601 * with, if any; 0 otherwise
602 * current_fw_arch_id -- arch_id of fw we are bundled
603 * with, if any; 0 otherwise
604 * current_fw_branch -- branch # of fw we are bundled
605 * with, if any; 0 otherwise
606 * current_fw_build -- build # of fw we are bundled
607 * with, if any; 0 otherwise
608 * Output: fw_on_ctlr_srl -- srl of fw on ctlr
609 * fw_on_ctlr_arch_id -- arch_id of fw on ctlr
610 * fw_on_ctlr_branch -- branch # of fw on ctlr
611 * fw_on_ctlr_build -- build # of fw on ctlr
612 * init_connect_result -- result bitmap of fw response
613 * Return value: 0 -- success
614 * non-zero-- failure
615 */
616 TW_INT32
617 tw_cli_init_connection(struct tw_cli_ctlr_context *ctlr,
618 TW_UINT16 message_credits, TW_UINT32 set_features,
619 TW_UINT16 current_fw_srl, TW_UINT16 current_fw_arch_id,
620 TW_UINT16 current_fw_branch, TW_UINT16 current_fw_build,
621 TW_UINT16 *fw_on_ctlr_srl, TW_UINT16 *fw_on_ctlr_arch_id,
622 TW_UINT16 *fw_on_ctlr_branch, TW_UINT16 *fw_on_ctlr_build,
623 TW_UINT32 *init_connect_result)
624 {
625 struct tw_cli_req_context *req;
626 struct tw_cl_command_init_connect *init_connect;
627 TW_INT32 error = TW_OSL_EBUSY;
628
629 tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
630
631 /* Get a request packet. */
632 if ((req = tw_cli_get_request(ctlr
633 )) == TW_CL_NULL)
634 goto out;
635
636 req->flags |= TW_CLI_REQ_FLAGS_INTERNAL;
637
638 /* Build the cmd pkt. */
639 init_connect = &(req->cmd_pkt->command.cmd_pkt_7k.init_connect);
640
641 req->cmd_pkt->cmd_hdr.header_desc.size_header = 128;
642
643 init_connect->res1__opcode =
644 BUILD_RES__OPCODE(0, TWA_FW_CMD_INIT_CONNECTION);
645 init_connect->request_id =
646 (TW_UINT8)(TW_CL_SWAP16(req->request_id));
647 init_connect->message_credits = TW_CL_SWAP16(message_credits);
648 init_connect->features = TW_CL_SWAP32(set_features);
649 if (ctlr->flags & TW_CL_64BIT_ADDRESSES)
650 init_connect->features |= TW_CL_SWAP32(TWA_64BIT_SG_ADDRESSES);
651 if (set_features & TWA_EXTENDED_INIT_CONNECT) {
652 /*
653 * Fill in the extra fields needed for an extended
654 * init_connect.
655 */
656 init_connect->size = 6;
657 init_connect->fw_srl = TW_CL_SWAP16(current_fw_srl);
658 init_connect->fw_arch_id = TW_CL_SWAP16(current_fw_arch_id);
659 init_connect->fw_branch = TW_CL_SWAP16(current_fw_branch);
660 init_connect->fw_build = TW_CL_SWAP16(current_fw_build);
661 } else
662 init_connect->size = 3;
663
664 /* Submit the command, and wait for it to complete. */
665 error = tw_cli_submit_and_poll_request(req,
666 TW_CLI_REQUEST_TIMEOUT_PERIOD);
667 if (error)
668 goto out;
669 if ((error = init_connect->status)) {
670 #if 0
671 tw_cli_create_ctlr_event(ctlr,
672 TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR,
673 &(req->cmd_pkt->cmd_hdr));
674 #endif // 0
675 goto out;
676 }
677 if (set_features & TWA_EXTENDED_INIT_CONNECT) {
678 *fw_on_ctlr_srl = TW_CL_SWAP16(init_connect->fw_srl);
679 *fw_on_ctlr_arch_id = TW_CL_SWAP16(init_connect->fw_arch_id);
680 *fw_on_ctlr_branch = TW_CL_SWAP16(init_connect->fw_branch);
681 *fw_on_ctlr_build = TW_CL_SWAP16(init_connect->fw_build);
682 *init_connect_result = TW_CL_SWAP32(init_connect->result);
683 }
684 tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
685 return(error);
686
687 out:
688 tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
689 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
690 0x1016, 0x1, TW_CL_SEVERITY_ERROR_STRING,
691 "init_connection failed",
692 "error = %d", error);
693 if (req)
694 tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
695 return(error);
696 }
Cache object: ece4cd9cb613e2f17f44dd0c0c7d0c2f
|