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