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