1144966Svkashyap/*
2169400Sscottl * Copyright (c) 2004-07 Applied Micro Circuits Corporation.
3144966Svkashyap * Copyright (c) 2004-05 Vinod Kashyap
4144966Svkashyap * All rights reserved.
5144966Svkashyap *
6144966Svkashyap * Redistribution and use in source and binary forms, with or without
7144966Svkashyap * modification, are permitted provided that the following conditions
8144966Svkashyap * are met:
9144966Svkashyap * 1. Redistributions of source code must retain the above copyright
10144966Svkashyap *    notice, this list of conditions and the following disclaimer.
11144966Svkashyap * 2. Redistributions in binary form must reproduce the above copyright
12144966Svkashyap *    notice, this list of conditions and the following disclaimer in the
13144966Svkashyap *    documentation and/or other materials provided with the distribution.
14144966Svkashyap *
15144966Svkashyap * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16144966Svkashyap * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17144966Svkashyap * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18144966Svkashyap * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19144966Svkashyap * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20144966Svkashyap * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21144966Svkashyap * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22144966Svkashyap * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23144966Svkashyap * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24144966Svkashyap * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25144966Svkashyap * SUCH DAMAGE.
26144966Svkashyap *
27144966Svkashyap *	$FreeBSD: releng/10.3/sys/dev/twa/tw_cl_init.c 212008 2010-08-30 19:15:04Z delphij $
28144966Svkashyap */
29144966Svkashyap
30144966Svkashyap/*
31144966Svkashyap * AMCC'S 3ware driver for 9000 series storage controllers.
32144966Svkashyap *
33144966Svkashyap * Author: Vinod Kashyap
34169400Sscottl * Modifications by: Adam Radford
35172496Sscottl * Modifications by: Manjunath Ranganathaiah
36144966Svkashyap */
37144966Svkashyap
38144966Svkashyap
39144966Svkashyap/*
40144966Svkashyap * Common Layer initialization functions.
41144966Svkashyap */
42144966Svkashyap
43144966Svkashyap
44144966Svkashyap#include "tw_osl_share.h"
45144966Svkashyap#include "tw_cl_share.h"
46144966Svkashyap#include "tw_cl_fwif.h"
47144966Svkashyap#include "tw_cl_ioctl.h"
48144966Svkashyap#include "tw_cl.h"
49144966Svkashyap#include "tw_cl_externs.h"
50144966Svkashyap#include "tw_osl_ioctl.h"
51144966Svkashyap
52144966Svkashyap
53144966Svkashyap/*
54144966Svkashyap * Function name:	tw_cl_ctlr_supported
55144966Svkashyap * Description:		Determines if a controller is supported.
56144966Svkashyap *
57144966Svkashyap * Input:		vendor_id -- vendor id of the controller
58144966Svkashyap *			device_id -- device id of the controller
59144966Svkashyap * Output:		None
60144966Svkashyap * Return value:	TW_CL_TRUE-- controller supported
61144966Svkashyap *			TW_CL_FALSE-- controller not supported
62144966Svkashyap */
63144966SvkashyapTW_INT32
64144966Svkashyaptw_cl_ctlr_supported(TW_INT32 vendor_id, TW_INT32 device_id)
65144966Svkashyap{
66152213Svkashyap	if ((vendor_id == TW_CL_VENDOR_ID) &&
67152213Svkashyap		((device_id == TW_CL_DEVICE_ID_9K) ||
68169400Sscottl		 (device_id == TW_CL_DEVICE_ID_9K_X) ||
69172496Sscottl		 (device_id == TW_CL_DEVICE_ID_9K_E) ||
70172496Sscottl		 (device_id == TW_CL_DEVICE_ID_9K_SA)))
71144966Svkashyap		return(TW_CL_TRUE);
72144966Svkashyap	return(TW_CL_FALSE);
73144966Svkashyap}
74144966Svkashyap
75144966Svkashyap
76144966Svkashyap
77144966Svkashyap/*
78152213Svkashyap * Function name:	tw_cl_get_pci_bar_info
79152213Svkashyap * Description:		Returns PCI BAR info.
80152213Svkashyap *
81152213Svkashyap * Input:		device_id -- device id of the controller
82152213Svkashyap *			bar_type -- type of PCI BAR in question
83152213Svkashyap * Output:		bar_num -- PCI BAR number corresponding to bar_type
84152213Svkashyap *			bar0_offset -- byte offset from BAR 0 (0x10 in
85152213Svkashyap *					PCI config space)
86152213Svkashyap *			bar_size -- size, in bytes, of the BAR in question
87152213Svkashyap * Return value:	0 -- success
88152213Svkashyap *			non-zero -- failure
89152213Svkashyap */
90152213SvkashyapTW_INT32
91152213Svkashyaptw_cl_get_pci_bar_info(TW_INT32 device_id, TW_INT32 bar_type,
92152213Svkashyap	TW_INT32 *bar_num, TW_INT32 *bar0_offset, TW_INT32 *bar_size)
93152213Svkashyap{
94152213Svkashyap	TW_INT32	error = TW_OSL_ESUCCESS;
95152213Svkashyap
96152213Svkashyap	switch(device_id) {
97152213Svkashyap	case TW_CL_DEVICE_ID_9K:
98152213Svkashyap		switch(bar_type) {
99152213Svkashyap		case TW_CL_BAR_TYPE_IO:
100152213Svkashyap			*bar_num = 0;
101152213Svkashyap			*bar0_offset = 0;
102152213Svkashyap			*bar_size = 4;
103152213Svkashyap			break;
104152213Svkashyap
105152213Svkashyap		case TW_CL_BAR_TYPE_MEM:
106152213Svkashyap			*bar_num = 1;
107152213Svkashyap			*bar0_offset = 0x4;
108152213Svkashyap			*bar_size = 8;
109152213Svkashyap			break;
110152213Svkashyap
111152213Svkashyap		case TW_CL_BAR_TYPE_SBUF:
112152213Svkashyap			*bar_num = 2;
113152213Svkashyap			*bar0_offset = 0xC;
114152213Svkashyap			*bar_size = 8;
115152213Svkashyap			break;
116152213Svkashyap		}
117152213Svkashyap		break;
118152213Svkashyap
119152213Svkashyap	case TW_CL_DEVICE_ID_9K_X:
120169400Sscottl	case TW_CL_DEVICE_ID_9K_E:
121172496Sscottl	case TW_CL_DEVICE_ID_9K_SA:
122152213Svkashyap		switch(bar_type) {
123152213Svkashyap		case TW_CL_BAR_TYPE_IO:
124152213Svkashyap			*bar_num = 2;
125152213Svkashyap			*bar0_offset = 0x10;
126152213Svkashyap			*bar_size = 4;
127152213Svkashyap			break;
128152213Svkashyap
129152213Svkashyap		case TW_CL_BAR_TYPE_MEM:
130152213Svkashyap			*bar_num = 1;
131152213Svkashyap			*bar0_offset = 0x8;
132152213Svkashyap			*bar_size = 8;
133152213Svkashyap			break;
134152213Svkashyap
135152213Svkashyap		case TW_CL_BAR_TYPE_SBUF:
136152213Svkashyap			*bar_num = 0;
137152213Svkashyap			*bar0_offset = 0;
138152213Svkashyap			*bar_size = 8;
139152213Svkashyap			break;
140152213Svkashyap		}
141152213Svkashyap		break;
142152213Svkashyap
143152213Svkashyap	default:
144152213Svkashyap		error = TW_OSL_ENOTTY;
145152213Svkashyap		break;
146152213Svkashyap	}
147152213Svkashyap
148152213Svkashyap	return(error);
149152213Svkashyap}
150152213Svkashyap
151152213Svkashyap
152152213Svkashyap
153152213Svkashyap/*
154144966Svkashyap * Function name:	tw_cl_get_mem_requirements
155144966Svkashyap * Description:		Provides info about Common Layer requirements for a
156144966Svkashyap *			controller, given the controller type (in 'flags').
157144966Svkashyap * Input:		ctlr_handle -- controller handle
158144966Svkashyap *			flags -- more info passed by the OS Layer
159152213Svkashyap *			device_id -- device id of the controller
160144966Svkashyap *			max_simult_reqs -- maximum # of simultaneous
161144966Svkashyap *					requests that the OS Layer expects
162144966Svkashyap *					the Common Layer to support
163144966Svkashyap *			max_aens -- maximun # of AEN's needed to be supported
164144966Svkashyap * Output:		alignment -- alignment needed for all DMA'able
165144966Svkashyap *					buffers
166144966Svkashyap *			sg_size_factor -- every SG element should have a size
167144966Svkashyap *					that's a multiple of this number
168144966Svkashyap *			non_dma_mem_size -- # of bytes of memory needed for
169144966Svkashyap *					non-DMA purposes
170144966Svkashyap *			dma_mem_size -- # of bytes of DMA'able memory needed
171144966Svkashyap *			per_req_dma_mem_size -- # of bytes of DMA'able memory
172144966Svkashyap *					needed per request, if applicable
173144966Svkashyap *			per_req_non_dma_mem_size -- # of bytes of memory needed
174144966Svkashyap *					per request for non-DMA purposes,
175144966Svkashyap *					if applicable
176144966Svkashyap * Output:		None
177144966Svkashyap * Return value:	0	-- success
178144966Svkashyap *			non-zero-- failure
179144966Svkashyap */
180144966SvkashyapTW_INT32
181144966Svkashyaptw_cl_get_mem_requirements(struct tw_cl_ctlr_handle *ctlr_handle,
182152213Svkashyap	TW_UINT32 flags, TW_INT32 device_id, TW_INT32 max_simult_reqs,
183152213Svkashyap	TW_INT32 max_aens, TW_UINT32 *alignment, TW_UINT32 *sg_size_factor,
184144966Svkashyap	TW_UINT32 *non_dma_mem_size, TW_UINT32 *dma_mem_size
185144966Svkashyap	)
186144966Svkashyap{
187152213Svkashyap	if (device_id == 0)
188152213Svkashyap		device_id = TW_CL_DEVICE_ID_9K;
189152213Svkashyap
190144966Svkashyap	if (max_simult_reqs > TW_CL_MAX_SIMULTANEOUS_REQUESTS) {
191144966Svkashyap		tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
192144966Svkashyap			TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
193144966Svkashyap			0x1000, 0x1, TW_CL_SEVERITY_ERROR_STRING,
194144966Svkashyap			"Too many simultaneous requests to support!",
195144966Svkashyap			"requested = %d, supported = %d, error = %d\n",
196144966Svkashyap			max_simult_reqs, TW_CL_MAX_SIMULTANEOUS_REQUESTS,
197144966Svkashyap			TW_OSL_EBIG);
198144966Svkashyap		return(TW_OSL_EBIG);
199144966Svkashyap	}
200144966Svkashyap
201152213Svkashyap	*alignment = TWA_ALIGNMENT(device_id);
202152213Svkashyap	*sg_size_factor = TWA_SG_ELEMENT_SIZE_FACTOR(device_id);
203144966Svkashyap
204144966Svkashyap	/*
205144966Svkashyap	 * Total non-DMA memory needed is the sum total of memory needed for
206144966Svkashyap	 * the controller context, request packets (including the 1 needed for
207144966Svkashyap	 * CL internal requests), and event packets.
208144966Svkashyap	 */
209144966Svkashyap
210144966Svkashyap	*non_dma_mem_size = sizeof(struct tw_cli_ctlr_context) +
211208969Sdelphij		(sizeof(struct tw_cli_req_context) * max_simult_reqs) +
212144966Svkashyap		(sizeof(struct tw_cl_event_packet) * max_aens);
213144966Svkashyap
214144966Svkashyap
215144966Svkashyap	/*
216144966Svkashyap	 * Total DMA'able memory needed is the sum total of memory needed for
217144966Svkashyap	 * all command packets (including the 1 needed for CL internal
218144966Svkashyap	 * requests), and memory needed to hold the payload for internal
219144966Svkashyap	 * requests.
220144966Svkashyap	 */
221144966Svkashyap
222144966Svkashyap	*dma_mem_size = (sizeof(struct tw_cl_command_packet) *
223208969Sdelphij		(max_simult_reqs)) + (TW_CLI_SECTOR_SIZE);
224144966Svkashyap
225144966Svkashyap	return(0);
226144966Svkashyap}
227144966Svkashyap
228144966Svkashyap
229144966Svkashyap
230144966Svkashyap/*
231144966Svkashyap * Function name:	tw_cl_init_ctlr
232144966Svkashyap * Description:		Initializes driver data structures for the controller.
233144966Svkashyap *
234144966Svkashyap * Input:		ctlr_handle -- controller handle
235144966Svkashyap *			flags -- more info passed by the OS Layer
236152213Svkashyap *			device_id -- device id of the controller
237144966Svkashyap *			max_simult_reqs -- maximum # of simultaneous requests
238144966Svkashyap *					that the OS Layer expects the Common
239144966Svkashyap *					Layer to support
240144966Svkashyap *			max_aens -- maximun # of AEN's needed to be supported
241144966Svkashyap *			non_dma_mem -- ptr to allocated non-DMA memory
242144966Svkashyap *			dma_mem -- ptr to allocated DMA'able memory
243144966Svkashyap *			dma_mem_phys -- physical address of dma_mem
244144966Svkashyap * Output:		None
245144966Svkashyap * Return value:	0	-- success
246144966Svkashyap *			non-zero-- failure
247144966Svkashyap */
248144966SvkashyapTW_INT32
249144966Svkashyaptw_cl_init_ctlr(struct tw_cl_ctlr_handle *ctlr_handle, TW_UINT32 flags,
250152213Svkashyap	TW_INT32 device_id, TW_INT32 max_simult_reqs, TW_INT32 max_aens,
251152213Svkashyap	TW_VOID *non_dma_mem, TW_VOID *dma_mem, TW_UINT64 dma_mem_phys
252144966Svkashyap	)
253144966Svkashyap{
254144966Svkashyap	struct tw_cli_ctlr_context	*ctlr;
255144966Svkashyap	struct tw_cli_req_context	*req;
256144966Svkashyap	TW_UINT8			*free_non_dma_mem;
257144966Svkashyap	TW_INT32			error = TW_OSL_ESUCCESS;
258144966Svkashyap	TW_INT32			i;
259144966Svkashyap
260144966Svkashyap	tw_cli_dbg_printf(3, ctlr_handle, tw_osl_cur_func(), "entered");
261144966Svkashyap
262144966Svkashyap	if (flags & TW_CL_START_CTLR_ONLY) {
263144966Svkashyap		ctlr = (struct tw_cli_ctlr_context *)
264144966Svkashyap			(ctlr_handle->cl_ctlr_ctxt);
265144966Svkashyap		goto start_ctlr;
266144966Svkashyap	}
267144966Svkashyap
268144966Svkashyap	if (max_simult_reqs > TW_CL_MAX_SIMULTANEOUS_REQUESTS) {
269144966Svkashyap		tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
270144966Svkashyap			TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
271144966Svkashyap			0x1000, 0x1, TW_CL_SEVERITY_ERROR_STRING,
272144966Svkashyap			"Too many simultaneous requests to support!",
273144966Svkashyap			"requested = %d, supported = %d, error = %d\n",
274144966Svkashyap			max_simult_reqs, TW_CL_MAX_SIMULTANEOUS_REQUESTS,
275144966Svkashyap			TW_OSL_EBIG);
276144966Svkashyap		return(TW_OSL_EBIG);
277144966Svkashyap	}
278144966Svkashyap
279144966Svkashyap	if ((non_dma_mem == TW_CL_NULL) || (dma_mem == TW_CL_NULL)
280144966Svkashyap		) {
281144966Svkashyap		tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
282144966Svkashyap			TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
283144966Svkashyap			0x1001, 0x1, TW_CL_SEVERITY_ERROR_STRING,
284144966Svkashyap			"Insufficient memory for Common Layer's internal usage",
285144966Svkashyap			"error = %d\n", TW_OSL_ENOMEM);
286144966Svkashyap		return(TW_OSL_ENOMEM);
287144966Svkashyap	}
288144966Svkashyap
289144966Svkashyap	tw_osl_memzero(non_dma_mem, sizeof(struct tw_cli_ctlr_context) +
290208969Sdelphij		(sizeof(struct tw_cli_req_context) * max_simult_reqs) +
291144966Svkashyap		(sizeof(struct tw_cl_event_packet) * max_aens));
292144966Svkashyap
293144966Svkashyap	tw_osl_memzero(dma_mem,
294144966Svkashyap		(sizeof(struct tw_cl_command_packet) *
295208969Sdelphij		max_simult_reqs) +
296144966Svkashyap		TW_CLI_SECTOR_SIZE);
297144966Svkashyap
298144966Svkashyap	free_non_dma_mem = (TW_UINT8 *)non_dma_mem;
299144966Svkashyap
300144966Svkashyap	ctlr = (struct tw_cli_ctlr_context *)free_non_dma_mem;
301144966Svkashyap	free_non_dma_mem += sizeof(struct tw_cli_ctlr_context);
302144966Svkashyap
303144966Svkashyap	ctlr_handle->cl_ctlr_ctxt = ctlr;
304144966Svkashyap	ctlr->ctlr_handle = ctlr_handle;
305144966Svkashyap
306152213Svkashyap	ctlr->device_id = (TW_UINT32)device_id;
307152213Svkashyap	ctlr->arch_id = TWA_ARCH_ID(device_id);
308152213Svkashyap	ctlr->flags = flags;
309152213Svkashyap	ctlr->sg_size_factor = TWA_SG_ELEMENT_SIZE_FACTOR(device_id);
310208969Sdelphij	ctlr->max_simult_reqs = max_simult_reqs;
311144966Svkashyap	ctlr->max_aens_supported = max_aens;
312144966Svkashyap
313144966Svkashyap	/* Initialize queues of CL internal request context packets. */
314144966Svkashyap	tw_cli_req_q_init(ctlr, TW_CLI_FREE_Q);
315144966Svkashyap	tw_cli_req_q_init(ctlr, TW_CLI_BUSY_Q);
316144966Svkashyap	tw_cli_req_q_init(ctlr, TW_CLI_PENDING_Q);
317144966Svkashyap	tw_cli_req_q_init(ctlr, TW_CLI_COMPLETE_Q);
318212008Sdelphij	tw_cli_req_q_init(ctlr, TW_CLI_RESET_Q);
319144966Svkashyap
320144966Svkashyap	/* Initialize all locks used by CL. */
321144966Svkashyap	ctlr->gen_lock = &(ctlr->gen_lock_handle);
322144966Svkashyap	tw_osl_init_lock(ctlr_handle, "tw_cl_gen_lock", ctlr->gen_lock);
323144966Svkashyap	ctlr->io_lock = &(ctlr->io_lock_handle);
324144966Svkashyap	tw_osl_init_lock(ctlr_handle, "tw_cl_io_lock", ctlr->io_lock);
325144966Svkashyap
326144966Svkashyap	/* Initialize CL internal request context packets. */
327144966Svkashyap	ctlr->req_ctxt_buf = (struct tw_cli_req_context *)free_non_dma_mem;
328144966Svkashyap	free_non_dma_mem += (sizeof(struct tw_cli_req_context) *
329208969Sdelphij		max_simult_reqs);
330144966Svkashyap
331144966Svkashyap	ctlr->cmd_pkt_buf = (struct tw_cl_command_packet *)dma_mem;
332144966Svkashyap	ctlr->cmd_pkt_phys = dma_mem_phys;
333144966Svkashyap
334144966Svkashyap	ctlr->internal_req_data = (TW_UINT8 *)
335144966Svkashyap		(ctlr->cmd_pkt_buf +
336208969Sdelphij		max_simult_reqs);
337144966Svkashyap	ctlr->internal_req_data_phys = ctlr->cmd_pkt_phys +
338144966Svkashyap		(sizeof(struct tw_cl_command_packet) *
339208969Sdelphij		max_simult_reqs);
340144966Svkashyap
341208969Sdelphij	for (i = 0; i < max_simult_reqs; i++) {
342144966Svkashyap		req = &(ctlr->req_ctxt_buf[i]);
343144966Svkashyap
344144966Svkashyap		req->cmd_pkt = &(ctlr->cmd_pkt_buf[i]);
345144966Svkashyap		req->cmd_pkt_phys = ctlr->cmd_pkt_phys +
346144966Svkashyap			(i * sizeof(struct tw_cl_command_packet));
347144966Svkashyap
348144966Svkashyap		req->request_id = i;
349144966Svkashyap		req->ctlr = ctlr;
350144966Svkashyap
351144966Svkashyap		/* Insert request into the free queue. */
352144966Svkashyap		tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
353144966Svkashyap	}
354144966Svkashyap
355144966Svkashyap	/* Initialize the AEN queue. */
356144966Svkashyap	ctlr->aen_queue = (struct tw_cl_event_packet *)free_non_dma_mem;
357144966Svkashyap
358144966Svkashyap
359144966Svkashyapstart_ctlr:
360144966Svkashyap	/*
361144966Svkashyap	 * Disable interrupts.  Interrupts will be enabled in tw_cli_start_ctlr
362144966Svkashyap	 * (only) if initialization succeeded.
363144966Svkashyap	 */
364144966Svkashyap	tw_cli_disable_interrupts(ctlr);
365144966Svkashyap
366144966Svkashyap	/* Initialize the controller. */
367144966Svkashyap	if ((error = tw_cli_start_ctlr(ctlr))) {
368144966Svkashyap		/* Soft reset the controller, and try one more time. */
369144966Svkashyap		tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
370144966Svkashyap			TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
371144966Svkashyap			0x1002, 0x1, TW_CL_SEVERITY_ERROR_STRING,
372144966Svkashyap			"Controller initialization failed. Retrying...",
373144966Svkashyap			"error = %d\n", error);
374144966Svkashyap		if ((error = tw_cli_soft_reset(ctlr))) {
375144966Svkashyap			tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
376144966Svkashyap				TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
377144966Svkashyap				0x1003, 0x1, TW_CL_SEVERITY_ERROR_STRING,
378144966Svkashyap				"Controller soft reset failed",
379144966Svkashyap				"error = %d\n", error);
380144966Svkashyap			return(error);
381144966Svkashyap		} else if ((error = tw_cli_start_ctlr(ctlr))) {
382144966Svkashyap			tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
383144966Svkashyap				TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
384144966Svkashyap				0x1004, 0x1, TW_CL_SEVERITY_ERROR_STRING,
385144966Svkashyap				"Controller initialization retry failed",
386144966Svkashyap				"error = %d\n", error);
387144966Svkashyap			return(error);
388144966Svkashyap		}
389144966Svkashyap	}
390144966Svkashyap	/* Notify some info about the controller to the OSL. */
391144966Svkashyap	tw_cli_notify_ctlr_info(ctlr);
392144966Svkashyap
393208969Sdelphij	/* Mark the controller active. */
394208969Sdelphij	ctlr->active = TW_CL_TRUE;
395144966Svkashyap	return(error);
396144966Svkashyap}
397144966Svkashyap
398144966Svkashyap/*
399144966Svkashyap * Function name:	tw_cli_start_ctlr
400144966Svkashyap * Description:		Establishes a logical connection with the controller.
401169400Sscottl *			Determines whether or not the driver is compatible
402169400Sscottl *                      with the firmware on the controller, before proceeding
403169400Sscottl *                      to work with it.
404144966Svkashyap *
405144966Svkashyap * Input:		ctlr	-- ptr to per ctlr structure
406144966Svkashyap * Output:		None
407144966Svkashyap * Return value:	0	-- success
408144966Svkashyap *			non-zero-- failure
409144966Svkashyap */
410144966SvkashyapTW_INT32
411144966Svkashyaptw_cli_start_ctlr(struct tw_cli_ctlr_context *ctlr)
412144966Svkashyap{
413144966Svkashyap	TW_UINT16	fw_on_ctlr_srl = 0;
414144966Svkashyap	TW_UINT16	fw_on_ctlr_arch_id = 0;
415144966Svkashyap	TW_UINT16	fw_on_ctlr_branch = 0;
416144966Svkashyap	TW_UINT16	fw_on_ctlr_build = 0;
417144966Svkashyap	TW_UINT32	init_connect_result = 0;
418144966Svkashyap	TW_INT32	error = TW_OSL_ESUCCESS;
419144966Svkashyap
420144966Svkashyap	tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
421144966Svkashyap
422144966Svkashyap	/* Wait for the controller to become ready. */
423144966Svkashyap	if ((error = tw_cli_poll_status(ctlr,
424144966Svkashyap			TWA_STATUS_MICROCONTROLLER_READY,
425144966Svkashyap			TW_CLI_REQUEST_TIMEOUT_PERIOD))) {
426144966Svkashyap		tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
427144966Svkashyap			TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
428144966Svkashyap			0x1009, 0x1, TW_CL_SEVERITY_ERROR_STRING,
429144966Svkashyap			"Microcontroller not ready",
430144966Svkashyap			"error = %d", error);
431144966Svkashyap		return(error);
432144966Svkashyap	}
433144966Svkashyap	/* Drain the response queue. */
434144966Svkashyap	if ((error = tw_cli_drain_response_queue(ctlr))) {
435144966Svkashyap		tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
436144966Svkashyap			TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
437144966Svkashyap			0x100A, 0x1, TW_CL_SEVERITY_ERROR_STRING,
438144966Svkashyap			"Can't drain response queue",
439144966Svkashyap			"error = %d", error);
440144966Svkashyap		return(error);
441144966Svkashyap	}
442144966Svkashyap	/* Establish a logical connection with the controller. */
443144966Svkashyap	if ((error = tw_cli_init_connection(ctlr,
444144966Svkashyap			(TW_UINT16)(ctlr->max_simult_reqs),
445144966Svkashyap			TWA_EXTENDED_INIT_CONNECT, TWA_CURRENT_FW_SRL,
446152213Svkashyap			(TW_UINT16)(ctlr->arch_id),
447152213Svkashyap			TWA_CURRENT_FW_BRANCH(ctlr->arch_id),
448152213Svkashyap			TWA_CURRENT_FW_BUILD(ctlr->arch_id),
449152213Svkashyap			&fw_on_ctlr_srl, &fw_on_ctlr_arch_id,
450152213Svkashyap			&fw_on_ctlr_branch, &fw_on_ctlr_build,
451152213Svkashyap			&init_connect_result))) {
452144966Svkashyap		tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
453144966Svkashyap			TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
454144966Svkashyap			0x100B, 0x2, TW_CL_SEVERITY_WARNING_STRING,
455144966Svkashyap			"Can't initialize connection in current mode",
456144966Svkashyap			"error = %d", error);
457144966Svkashyap		return(error);
458144966Svkashyap	}
459144966Svkashyap	{
460169400Sscottl		 /* See if we can at least work with the firmware on the
461169400Sscottl                 * controller in the current mode.
462144966Svkashyap		 */
463144966Svkashyap		if (init_connect_result & TWA_CTLR_FW_COMPATIBLE) {
464144966Svkashyap			/* Yes, we can.  Make note of the operating mode. */
465144966Svkashyap			if (init_connect_result & TWA_CTLR_FW_SAME_OR_NEWER) {
466144966Svkashyap				ctlr->working_srl = TWA_CURRENT_FW_SRL;
467152213Svkashyap				ctlr->working_branch =
468152213Svkashyap					TWA_CURRENT_FW_BRANCH(ctlr->arch_id);
469152213Svkashyap				ctlr->working_build =
470152213Svkashyap					TWA_CURRENT_FW_BUILD(ctlr->arch_id);
471144966Svkashyap			} else {
472144966Svkashyap				ctlr->working_srl = fw_on_ctlr_srl;
473144966Svkashyap				ctlr->working_branch = fw_on_ctlr_branch;
474144966Svkashyap				ctlr->working_build = fw_on_ctlr_build;
475144966Svkashyap			}
476144966Svkashyap		} else {
477144966Svkashyap			/*
478144966Svkashyap			 * No, we can't.  See if we can at least work with
479169400Sscottl			 * it in the base mode.
480144966Svkashyap			 */
481144966Svkashyap			tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
482144966Svkashyap				TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
483144966Svkashyap				0x1010, 0x2, TW_CL_SEVERITY_WARNING_STRING,
484144966Svkashyap				"Driver/Firmware mismatch. "
485144966Svkashyap				"Negotiating for base level...",
486144966Svkashyap				" ");
487144966Svkashyap			if ((error = tw_cli_init_connection(ctlr,
488144966Svkashyap					(TW_UINT16)(ctlr->max_simult_reqs),
489144966Svkashyap					TWA_EXTENDED_INIT_CONNECT,
490152213Svkashyap					TWA_BASE_FW_SRL,
491152213Svkashyap					(TW_UINT16)(ctlr->arch_id),
492144966Svkashyap					TWA_BASE_FW_BRANCH, TWA_BASE_FW_BUILD,
493144966Svkashyap					&fw_on_ctlr_srl, &fw_on_ctlr_arch_id,
494144966Svkashyap					&fw_on_ctlr_branch, &fw_on_ctlr_build,
495144966Svkashyap					&init_connect_result))) {
496144966Svkashyap				tw_cl_create_event(ctlr->ctlr_handle,
497144966Svkashyap					TW_CL_FALSE,
498144966Svkashyap					TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
499144966Svkashyap					0x1011, 0x1,
500144966Svkashyap					TW_CL_SEVERITY_ERROR_STRING,
501144966Svkashyap					"Can't initialize connection in "
502144966Svkashyap					"base mode",
503144966Svkashyap					" ");
504144966Svkashyap				return(error);
505144966Svkashyap			}
506144966Svkashyap			if (!(init_connect_result & TWA_CTLR_FW_COMPATIBLE)) {
507144966Svkashyap				/*
508144966Svkashyap				 * The firmware on the controller is not even
509144966Svkashyap				 * compatible with our base mode.  We cannot
510144966Svkashyap				 * work with it.  Bail...
511144966Svkashyap				 */
512144966Svkashyap				return(1);
513144966Svkashyap			}
514144966Svkashyap			/*
515144966Svkashyap			 * We can work with this firmware, but only in
516144966Svkashyap			 * base mode.
517144966Svkashyap			 */
518144966Svkashyap			ctlr->working_srl = TWA_BASE_FW_SRL;
519144966Svkashyap			ctlr->working_branch = TWA_BASE_FW_BRANCH;
520144966Svkashyap			ctlr->working_build = TWA_BASE_FW_BUILD;
521144966Svkashyap			ctlr->operating_mode = TWA_BASE_MODE;
522144966Svkashyap		}
523152213Svkashyap		ctlr->fw_on_ctlr_srl = fw_on_ctlr_srl;
524152213Svkashyap		ctlr->fw_on_ctlr_branch = fw_on_ctlr_branch;
525152213Svkashyap		ctlr->fw_on_ctlr_build = fw_on_ctlr_build;
526144966Svkashyap	}
527144966Svkashyap
528144966Svkashyap	/* Drain the AEN queue */
529144966Svkashyap	if ((error = tw_cli_drain_aen_queue(ctlr)))
530144966Svkashyap		/*
531144966Svkashyap		 * We will just print that we couldn't drain the AEN queue.
532144966Svkashyap		 * There's no need to bail out.
533144966Svkashyap		 */
534144966Svkashyap		tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
535144966Svkashyap			TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
536144966Svkashyap			0x1014, 0x2, TW_CL_SEVERITY_WARNING_STRING,
537144966Svkashyap			"Can't drain AEN queue",
538144966Svkashyap			"error = %d", error);
539144966Svkashyap
540144966Svkashyap	/* Enable interrupts. */
541144966Svkashyap	tw_cli_enable_interrupts(ctlr);
542144966Svkashyap
543144966Svkashyap	return(TW_OSL_ESUCCESS);
544144966Svkashyap}
545144966Svkashyap
546144966Svkashyap
547144966Svkashyap/*
548144966Svkashyap * Function name:	tw_cl_shutdown_ctlr
549144966Svkashyap * Description:		Closes logical connection with the controller.
550144966Svkashyap *
551144966Svkashyap * Input:		ctlr	-- ptr to per ctlr structure
552144966Svkashyap *			flags	-- more info passed by the OS Layer
553144966Svkashyap * Output:		None
554144966Svkashyap * Return value:	0	-- success
555144966Svkashyap *			non-zero-- failure
556144966Svkashyap */
557144966SvkashyapTW_INT32
558144966Svkashyaptw_cl_shutdown_ctlr(struct tw_cl_ctlr_handle *ctlr_handle, TW_UINT32 flags)
559144966Svkashyap{
560144966Svkashyap	struct tw_cli_ctlr_context	*ctlr =
561144966Svkashyap		(struct tw_cli_ctlr_context *)(ctlr_handle->cl_ctlr_ctxt);
562144966Svkashyap	TW_INT32			error;
563144966Svkashyap
564144966Svkashyap	tw_cli_dbg_printf(3, ctlr_handle, tw_osl_cur_func(), "entered");
565144966Svkashyap	/*
566144966Svkashyap	 * Mark the controller as inactive, disable any further interrupts,
567144966Svkashyap	 * and notify the controller that we are going down.
568144966Svkashyap	 */
569208969Sdelphij	ctlr->active = TW_CL_FALSE;
570144966Svkashyap
571144966Svkashyap	tw_cli_disable_interrupts(ctlr);
572144966Svkashyap
573144966Svkashyap	/* Let the controller know that we are going down. */
574144966Svkashyap	if ((error = tw_cli_init_connection(ctlr, TWA_SHUTDOWN_MESSAGE_CREDITS,
575144966Svkashyap			0, 0, 0, 0, 0, TW_CL_NULL, TW_CL_NULL, TW_CL_NULL,
576144966Svkashyap			TW_CL_NULL, TW_CL_NULL)))
577144966Svkashyap		tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
578144966Svkashyap			TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
579144966Svkashyap			0x1015, 0x1, TW_CL_SEVERITY_ERROR_STRING,
580144966Svkashyap			"Can't close connection with controller",
581144966Svkashyap			"error = %d", error);
582144966Svkashyap
583144966Svkashyap	if (flags & TW_CL_STOP_CTLR_ONLY)
584144966Svkashyap		goto ret;
585144966Svkashyap
586144966Svkashyap	/* Destroy all locks used by CL. */
587144966Svkashyap	tw_osl_destroy_lock(ctlr_handle, ctlr->gen_lock);
588144966Svkashyap	tw_osl_destroy_lock(ctlr_handle, ctlr->io_lock);
589144966Svkashyap
590144966Svkashyapret:
591144966Svkashyap	return(error);
592144966Svkashyap}
593144966Svkashyap
594144966Svkashyap
595144966Svkashyap
596144966Svkashyap/*
597144966Svkashyap * Function name:	tw_cli_init_connection
598144966Svkashyap * Description:		Sends init_connection cmd to firmware
599144966Svkashyap *
600144966Svkashyap * Input:		ctlr		-- ptr to per ctlr structure
601144966Svkashyap *			message_credits	-- max # of requests that we might send
602144966Svkashyap *					 down simultaneously.  This will be
603144966Svkashyap *					 typically set to 256 at init-time or
604144966Svkashyap *					after a reset, and to 1 at shutdown-time
605144966Svkashyap *			set_features	-- indicates if we intend to use 64-bit
606144966Svkashyap *					sg, also indicates if we want to do a
607144966Svkashyap *					basic or an extended init_connection;
608144966Svkashyap *
609144966Svkashyap * Note: The following input/output parameters are valid, only in case of an
610144966Svkashyap *		extended init_connection:
611144966Svkashyap *
612144966Svkashyap *			current_fw_srl		-- srl of fw we are bundled
613144966Svkashyap *						with, if any; 0 otherwise
614144966Svkashyap *			current_fw_arch_id	-- arch_id of fw we are bundled
615144966Svkashyap *						with, if any; 0 otherwise
616144966Svkashyap *			current_fw_branch	-- branch # of fw we are bundled
617144966Svkashyap *						with, if any; 0 otherwise
618144966Svkashyap *			current_fw_build	-- build # of fw we are bundled
619144966Svkashyap *						with, if any; 0 otherwise
620144966Svkashyap * Output:		fw_on_ctlr_srl		-- srl of fw on ctlr
621144966Svkashyap *			fw_on_ctlr_arch_id	-- arch_id of fw on ctlr
622144966Svkashyap *			fw_on_ctlr_branch	-- branch # of fw on ctlr
623144966Svkashyap *			fw_on_ctlr_build	-- build # of fw on ctlr
624144966Svkashyap *			init_connect_result	-- result bitmap of fw response
625144966Svkashyap * Return value:	0	-- success
626144966Svkashyap *			non-zero-- failure
627144966Svkashyap */
628144966SvkashyapTW_INT32
629144966Svkashyaptw_cli_init_connection(struct tw_cli_ctlr_context *ctlr,
630144966Svkashyap	TW_UINT16 message_credits, TW_UINT32 set_features,
631144966Svkashyap	TW_UINT16 current_fw_srl, TW_UINT16 current_fw_arch_id,
632144966Svkashyap	TW_UINT16 current_fw_branch, TW_UINT16 current_fw_build,
633144966Svkashyap	TW_UINT16 *fw_on_ctlr_srl, TW_UINT16 *fw_on_ctlr_arch_id,
634144966Svkashyap	TW_UINT16 *fw_on_ctlr_branch, TW_UINT16 *fw_on_ctlr_build,
635144966Svkashyap	TW_UINT32 *init_connect_result)
636144966Svkashyap{
637144966Svkashyap	struct tw_cli_req_context		*req;
638144966Svkashyap	struct tw_cl_command_init_connect	*init_connect;
639144966Svkashyap	TW_INT32				error = TW_OSL_EBUSY;
640144966Svkashyap
641144966Svkashyap	tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
642144966Svkashyap
643144966Svkashyap	/* Get a request packet. */
644144966Svkashyap	if ((req = tw_cli_get_request(ctlr
645144966Svkashyap		)) == TW_CL_NULL)
646144966Svkashyap		goto out;
647144966Svkashyap
648144966Svkashyap	req->flags |= TW_CLI_REQ_FLAGS_INTERNAL;
649144966Svkashyap
650144966Svkashyap	/* Build the cmd pkt. */
651144966Svkashyap	init_connect = &(req->cmd_pkt->command.cmd_pkt_7k.init_connect);
652144966Svkashyap
653144966Svkashyap	req->cmd_pkt->cmd_hdr.header_desc.size_header = 128;
654144966Svkashyap
655144966Svkashyap	init_connect->res1__opcode =
656144966Svkashyap		BUILD_RES__OPCODE(0, TWA_FW_CMD_INIT_CONNECTION);
657144966Svkashyap   	init_connect->request_id =
658144966Svkashyap		(TW_UINT8)(TW_CL_SWAP16(req->request_id));
659144966Svkashyap	init_connect->message_credits = TW_CL_SWAP16(message_credits);
660144966Svkashyap	init_connect->features = TW_CL_SWAP32(set_features);
661144966Svkashyap	if (ctlr->flags & TW_CL_64BIT_ADDRESSES)
662190329Sjhb		init_connect->features |= TW_CL_SWAP32(TWA_64BIT_SG_ADDRESSES);
663144966Svkashyap	if (set_features & TWA_EXTENDED_INIT_CONNECT) {
664144966Svkashyap		/*
665144966Svkashyap		 * Fill in the extra fields needed for an extended
666144966Svkashyap		 * init_connect.
667144966Svkashyap		 */
668144966Svkashyap		init_connect->size = 6;
669144966Svkashyap		init_connect->fw_srl = TW_CL_SWAP16(current_fw_srl);
670144966Svkashyap		init_connect->fw_arch_id = TW_CL_SWAP16(current_fw_arch_id);
671144966Svkashyap		init_connect->fw_branch = TW_CL_SWAP16(current_fw_branch);
672144966Svkashyap		init_connect->fw_build = TW_CL_SWAP16(current_fw_build);
673144966Svkashyap	} else
674144966Svkashyap		init_connect->size = 3;
675144966Svkashyap
676144966Svkashyap	/* Submit the command, and wait for it to complete. */
677144966Svkashyap	error = tw_cli_submit_and_poll_request(req,
678144966Svkashyap		TW_CLI_REQUEST_TIMEOUT_PERIOD);
679144966Svkashyap	if (error)
680144966Svkashyap		goto out;
681144966Svkashyap	if ((error = init_connect->status)) {
682212008Sdelphij#if       0
683144966Svkashyap		tw_cli_create_ctlr_event(ctlr,
684144966Svkashyap			TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR,
685144966Svkashyap			&(req->cmd_pkt->cmd_hdr));
686212008Sdelphij#endif // 0
687144966Svkashyap		goto out;
688144966Svkashyap	}
689144966Svkashyap	if (set_features & TWA_EXTENDED_INIT_CONNECT) {
690144966Svkashyap		*fw_on_ctlr_srl = TW_CL_SWAP16(init_connect->fw_srl);
691144966Svkashyap		*fw_on_ctlr_arch_id = TW_CL_SWAP16(init_connect->fw_arch_id);
692144966Svkashyap		*fw_on_ctlr_branch = TW_CL_SWAP16(init_connect->fw_branch);
693144966Svkashyap		*fw_on_ctlr_build = TW_CL_SWAP16(init_connect->fw_build);
694144966Svkashyap		*init_connect_result = TW_CL_SWAP32(init_connect->result);
695144966Svkashyap	}
696144966Svkashyap	tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
697144966Svkashyap	return(error);
698144966Svkashyap
699144966Svkashyapout:
700144966Svkashyap	tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
701144966Svkashyap		TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
702144966Svkashyap		0x1016, 0x1, TW_CL_SEVERITY_ERROR_STRING,
703144966Svkashyap		"init_connection failed",
704144966Svkashyap		"error = %d", error);
705144966Svkashyap	if (req)
706144966Svkashyap		tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
707144966Svkashyap	return(error);
708144966Svkashyap}
709144966Svkashyap
710144966Svkashyap
711