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