xref: /freebsd-13.1/sys/dev/twa/tw_cl_init.c (revision bed02296)
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
tw_cl_ctlr_supported(TW_INT32 vendor_id,TW_INT32 device_id)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
tw_cl_get_pci_bar_info(TW_INT32 device_id,TW_INT32 bar_type,TW_INT32 * bar_num,TW_INT32 * bar0_offset,TW_INT32 * bar_size)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
tw_cl_get_mem_requirements(struct tw_cl_ctlr_handle * ctlr_handle,TW_UINT32 flags,TW_INT32 device_id,TW_INT32 max_simult_reqs,TW_INT32 max_aens,TW_UINT32 * alignment,TW_UINT32 * sg_size_factor,TW_UINT32 * non_dma_mem_size,TW_UINT32 * dma_mem_size)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
tw_cl_init_ctlr(struct tw_cl_ctlr_handle * ctlr_handle,TW_UINT32 flags,TW_INT32 device_id,TW_INT32 max_simult_reqs,TW_INT32 max_aens,TW_VOID * non_dma_mem,TW_VOID * dma_mem,TW_UINT64 dma_mem_phys)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
tw_cli_start_ctlr(struct tw_cli_ctlr_context * ctlr)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
tw_cl_shutdown_ctlr(struct tw_cl_ctlr_handle * ctlr_handle,TW_UINT32 flags)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
tw_cli_init_connection(struct tw_cli_ctlr_context * ctlr,TW_UINT16 message_credits,TW_UINT32 set_features,TW_UINT16 current_fw_srl,TW_UINT16 current_fw_arch_id,TW_UINT16 current_fw_branch,TW_UINT16 current_fw_build,TW_UINT16 * fw_on_ctlr_srl,TW_UINT16 * fw_on_ctlr_arch_id,TW_UINT16 * fw_on_ctlr_branch,TW_UINT16 * fw_on_ctlr_build,TW_UINT32 * init_connect_result)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 }
697