1230557Sjimharris/*-
2230557Sjimharris * This file is provided under a dual BSD/GPLv2 license.  When using or
3230557Sjimharris * redistributing this file, you may do so under either license.
4230557Sjimharris *
5230557Sjimharris * GPL LICENSE SUMMARY
6230557Sjimharris *
7230557Sjimharris * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
8230557Sjimharris *
9230557Sjimharris * This program is free software; you can redistribute it and/or modify
10230557Sjimharris * it under the terms of version 2 of the GNU General Public License as
11230557Sjimharris * published by the Free Software Foundation.
12230557Sjimharris *
13230557Sjimharris * This program is distributed in the hope that it will be useful, but
14230557Sjimharris * WITHOUT ANY WARRANTY; without even the implied warranty of
15230557Sjimharris * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16230557Sjimharris * General Public License for more details.
17230557Sjimharris *
18230557Sjimharris * You should have received a copy of the GNU General Public License
19230557Sjimharris * along with this program; if not, write to the Free Software
20230557Sjimharris * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
21230557Sjimharris * The full GNU General Public License is included in this distribution
22230557Sjimharris * in the file called LICENSE.GPL.
23230557Sjimharris *
24230557Sjimharris * BSD LICENSE
25230557Sjimharris *
26230557Sjimharris * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
27230557Sjimharris * All rights reserved.
28230557Sjimharris *
29230557Sjimharris * Redistribution and use in source and binary forms, with or without
30230557Sjimharris * modification, are permitted provided that the following conditions
31230557Sjimharris * are met:
32230557Sjimharris *
33230557Sjimharris *   * Redistributions of source code must retain the above copyright
34230557Sjimharris *     notice, this list of conditions and the following disclaimer.
35230557Sjimharris *   * Redistributions in binary form must reproduce the above copyright
36230557Sjimharris *     notice, this list of conditions and the following disclaimer in
37230557Sjimharris *     the documentation and/or other materials provided with the
38230557Sjimharris *     distribution.
39230557Sjimharris *
40230557Sjimharris * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
41230557Sjimharris * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
42230557Sjimharris * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
43230557Sjimharris * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
44230557Sjimharris * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45230557Sjimharris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
46230557Sjimharris * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
47230557Sjimharris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
48230557Sjimharris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
49230557Sjimharris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
50230557Sjimharris * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51230557Sjimharris */
52230557Sjimharris
53230557Sjimharris#include <sys/cdefs.h>
54230557Sjimharris__FBSDID("$FreeBSD$");
55230557Sjimharris
56230557Sjimharris/**
57230557Sjimharris * @file
58230557Sjimharris *
59230557Sjimharris * @brief This file contains the implementation of the SCIF_SAS_CONTROLLER
60230557Sjimharris *        object.
61230557Sjimharris */
62230557Sjimharris
63230557Sjimharris
64230557Sjimharris#include <dev/isci/scil/sci_status.h>
65230557Sjimharris#include <dev/isci/scil/sci_util.h>
66230557Sjimharris#include <dev/isci/scil/sci_controller.h>
67230557Sjimharris#include <dev/isci/scil/scic_controller.h>
68230557Sjimharris#include <dev/isci/scil/scic_user_callback.h>
69230557Sjimharris#include <dev/isci/scil/scif_user_callback.h>
70230557Sjimharris
71230557Sjimharris#include <dev/isci/scil/scif_sas_controller.h>
72230557Sjimharris#include <dev/isci/scil/scif_sas_library.h>
73230557Sjimharris#include <dev/isci/scil/scif_sas_logger.h>
74230557Sjimharris
75230557Sjimharris
76230557Sjimharris//******************************************************************************
77230557Sjimharris//* P U B L I C   M E T H O D S
78230557Sjimharris//******************************************************************************
79230557Sjimharris
80230557SjimharrisSCI_STATUS scif_controller_construct(
81230557Sjimharris   SCI_LIBRARY_HANDLE_T      library,
82230557Sjimharris   SCI_CONTROLLER_HANDLE_T   controller,
83230557Sjimharris   void *                    user_object
84230557Sjimharris)
85230557Sjimharris{
86230557Sjimharris   SCI_STATUS              status        = SCI_SUCCESS;
87230557Sjimharris   SCIF_SAS_LIBRARY_T    * fw_library    = (SCIF_SAS_LIBRARY_T*) library;
88230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
89230557Sjimharris
90231137Sjimharris   // Validate the user supplied parameters.
91231137Sjimharris   if ((library == SCI_INVALID_HANDLE) || (controller == SCI_INVALID_HANDLE))
92231137Sjimharris      return SCI_FAILURE_INVALID_PARAMETER_VALUE;
93231137Sjimharris
94230557Sjimharris   SCIF_LOG_TRACE((
95230557Sjimharris      sci_base_object_get_logger(library),
96230557Sjimharris      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION,
97230557Sjimharris      "scif_controller_construct(0x%x, 0x%x) enter\n",
98230557Sjimharris      library, controller
99230557Sjimharris   ));
100230557Sjimharris
101230557Sjimharris   // Construct the base controller.  As part of constructing the base
102230557Sjimharris   // controller we ask it to also manage the MDL iteration for the Core.
103230557Sjimharris   sci_base_controller_construct(
104230557Sjimharris      &fw_controller->parent,
105230557Sjimharris      sci_base_object_get_logger(fw_library),
106230557Sjimharris      scif_sas_controller_state_table,
107230557Sjimharris      fw_controller->mdes,
108230557Sjimharris      SCIF_SAS_MAX_MEMORY_DESCRIPTORS,
109230557Sjimharris      sci_controller_get_memory_descriptor_list_handle(fw_controller->core_object)
110230557Sjimharris   );
111230557Sjimharris
112230557Sjimharris   scif_sas_controller_initialize_state_logging(fw_controller);
113230557Sjimharris
114230557Sjimharris   sci_object_set_association(fw_controller, user_object);
115230557Sjimharris
116230557Sjimharris   status = scic_controller_construct(
117230557Sjimharris               fw_library->core_object, fw_controller->core_object, fw_controller
118230557Sjimharris            );
119230557Sjimharris
120230557Sjimharris   // If the core controller was successfully constructed, then
121230557Sjimharris   // finish construction of the framework controller.
122230557Sjimharris   if (status == SCI_SUCCESS)
123230557Sjimharris   {
124230557Sjimharris      // Set the association in the core controller to this framework
125230557Sjimharris      // controller.
126230557Sjimharris      sci_object_set_association(
127230557Sjimharris         (SCI_OBJECT_HANDLE_T) fw_controller->core_object, fw_controller
128230557Sjimharris      );
129230557Sjimharris
130230557Sjimharris      sci_base_state_machine_change_state(
131230557Sjimharris        &fw_controller->parent.state_machine,
132230557Sjimharris         SCI_BASE_CONTROLLER_STATE_RESET
133230557Sjimharris      );
134230557Sjimharris   }
135230557Sjimharris
136230557Sjimharris   return status;
137230557Sjimharris}
138230557Sjimharris
139230557Sjimharris// ---------------------------------------------------------------------------
140230557Sjimharris
141230557SjimharrisSCI_STATUS scif_controller_initialize(
142230557Sjimharris   SCI_CONTROLLER_HANDLE_T   controller
143230557Sjimharris)
144230557Sjimharris{
145230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
146230557Sjimharris
147231137Sjimharris   // Validate the user supplied parameters.
148231137Sjimharris   if (controller == SCI_INVALID_HANDLE)
149231137Sjimharris      return SCI_FAILURE_INVALID_PARAMETER_VALUE;
150231137Sjimharris
151230557Sjimharris   SCIF_LOG_TRACE((
152230557Sjimharris      sci_base_object_get_logger(controller),
153230557Sjimharris      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION,
154230557Sjimharris      "scif_controller_initialize(0x%x) enter\n",
155230557Sjimharris      controller
156230557Sjimharris   ));
157230557Sjimharris
158230557Sjimharris   return fw_controller->state_handlers->initialize_handler(
159230557Sjimharris             &fw_controller->parent
160230557Sjimharris          );
161230557Sjimharris}
162230557Sjimharris
163230557Sjimharris// ---------------------------------------------------------------------------
164230557Sjimharris
165230557SjimharrisU32 scif_controller_get_suggested_start_timeout(
166230557Sjimharris   SCI_CONTROLLER_HANDLE_T  controller
167230557Sjimharris)
168230557Sjimharris{
169230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
170230557Sjimharris
171230557Sjimharris   // Validate the user supplied parameters.
172230557Sjimharris   if (controller == SCI_INVALID_HANDLE)
173230557Sjimharris      return 0;
174230557Sjimharris
175230557Sjimharris   // Currently we aren't adding any additional time into the suggested
176230557Sjimharris   // timeout value for the start operation.  Simply utilize the core
177230557Sjimharris   // value.
178230557Sjimharris   return scic_controller_get_suggested_start_timeout(fw_controller->core_object);
179230557Sjimharris}
180230557Sjimharris
181230557Sjimharris// ---------------------------------------------------------------------------
182230557Sjimharris
183230557SjimharrisSCI_STATUS scif_controller_start(
184230557Sjimharris   SCI_CONTROLLER_HANDLE_T  controller,
185230557Sjimharris   U32                      timeout
186230557Sjimharris)
187230557Sjimharris{
188230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
189230557Sjimharris
190231137Sjimharris   // Validate the user supplied parameters.
191231137Sjimharris   if (controller == SCI_INVALID_HANDLE)
192231137Sjimharris      return SCI_FAILURE_INVALID_PARAMETER_VALUE;
193231137Sjimharris
194230557Sjimharris   SCIF_LOG_TRACE((
195230557Sjimharris      sci_base_object_get_logger(controller),
196230557Sjimharris      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION,
197230557Sjimharris      "scif_controller_start(0x%x, 0x%x) enter\n",
198230557Sjimharris      controller, timeout
199230557Sjimharris   ));
200230557Sjimharris
201230557Sjimharris   return fw_controller->state_handlers->
202230557Sjimharris          start_handler(&fw_controller->parent, timeout);
203230557Sjimharris}
204230557Sjimharris
205230557Sjimharris// ---------------------------------------------------------------------------
206230557Sjimharris
207230557SjimharrisSCI_STATUS scif_controller_stop(
208230557Sjimharris   SCI_CONTROLLER_HANDLE_T  controller,
209230557Sjimharris   U32                      timeout
210230557Sjimharris)
211230557Sjimharris{
212230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
213230557Sjimharris
214231137Sjimharris   // Validate the user supplied parameters.
215231137Sjimharris   if (controller == SCI_INVALID_HANDLE)
216231137Sjimharris      return SCI_FAILURE_INVALID_PARAMETER_VALUE;
217231137Sjimharris
218230557Sjimharris   SCIF_LOG_TRACE((
219230557Sjimharris      sci_base_object_get_logger(controller),
220230557Sjimharris      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_SHUTDOWN,
221230557Sjimharris      "scif_controller_stop(0x%x, 0x%x) enter\n",
222230557Sjimharris      controller, timeout
223230557Sjimharris   ));
224230557Sjimharris
225230557Sjimharris   return fw_controller->state_handlers->
226230557Sjimharris          stop_handler(&fw_controller->parent, timeout);
227230557Sjimharris
228230557Sjimharris}
229230557Sjimharris
230230557Sjimharris// ---------------------------------------------------------------------------
231230557Sjimharris
232230557SjimharrisSCI_STATUS scif_controller_reset(
233230557Sjimharris   SCI_CONTROLLER_HANDLE_T  controller
234230557Sjimharris)
235230557Sjimharris{
236230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
237230557Sjimharris
238231137Sjimharris   // Validate the user supplied parameters.
239231137Sjimharris   if (controller == SCI_INVALID_HANDLE)
240231137Sjimharris      return SCI_FAILURE_INVALID_PARAMETER_VALUE;
241231137Sjimharris
242230557Sjimharris   SCIF_LOG_TRACE((
243230557Sjimharris      sci_base_object_get_logger(controller),
244230557Sjimharris      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_CONTROLLER_RESET,
245230557Sjimharris      "scif_controller_reset(0x%x) enter\n",
246230557Sjimharris      controller
247230557Sjimharris   ));
248230557Sjimharris
249230557Sjimharris   return fw_controller->state_handlers->
250230557Sjimharris          reset_handler(&fw_controller->parent);
251230557Sjimharris}
252230557Sjimharris
253230557Sjimharris// ---------------------------------------------------------------------------
254230557Sjimharris
255230557SjimharrisSCI_CONTROLLER_HANDLE_T scif_controller_get_scic_handle(
256230557Sjimharris   SCI_CONTROLLER_HANDLE_T   controller
257230557Sjimharris)
258230557Sjimharris{
259230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
260230557Sjimharris
261230557Sjimharris   return fw_controller->core_object;
262230557Sjimharris}
263230557Sjimharris
264230557Sjimharris// ---------------------------------------------------------------------------
265230557Sjimharris
266230557SjimharrisSCI_IO_STATUS scif_controller_start_io(
267230557Sjimharris   SCI_CONTROLLER_HANDLE_T     controller,
268230557Sjimharris   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
269230557Sjimharris   SCI_IO_REQUEST_HANDLE_T     io_request,
270230557Sjimharris   U16                         io_tag
271230557Sjimharris)
272230557Sjimharris{
273230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
274231296Sjimharris   SCI_STATUS              status;
275230557Sjimharris
276230557Sjimharris   SCIF_LOG_TRACE((
277230557Sjimharris      sci_base_object_get_logger(controller),
278230557Sjimharris      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
279230557Sjimharris      "scif_controller_start_io(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
280230557Sjimharris      controller, remote_device, io_request, io_tag
281230557Sjimharris   ));
282230557Sjimharris
283230557Sjimharris   if (
284230557Sjimharris         sci_pool_empty(fw_controller->hprq.pool)
285230557Sjimharris      || scif_sas_controller_sufficient_resource(controller)
286230557Sjimharris      )
287230557Sjimharris   {
288231296Sjimharris      status = fw_controller->state_handlers->start_io_handler(
289230557Sjimharris                (SCI_BASE_CONTROLLER_T*) controller,
290230557Sjimharris                (SCI_BASE_REMOTE_DEVICE_T*) remote_device,
291230557Sjimharris                (SCI_BASE_REQUEST_T*) io_request,
292230557Sjimharris                io_tag
293230557Sjimharris             );
294230557Sjimharris   }
295230557Sjimharris   else
296231296Sjimharris      status = SCI_FAILURE_INSUFFICIENT_RESOURCES;
297231296Sjimharris
298231296Sjimharris   return (SCI_IO_STATUS)status;
299230557Sjimharris}
300230557Sjimharris
301230557Sjimharris// ---------------------------------------------------------------------------
302230557Sjimharris
303230557SjimharrisSCI_TASK_STATUS scif_controller_start_task(
304230557Sjimharris   SCI_CONTROLLER_HANDLE_T     controller,
305230557Sjimharris   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
306230557Sjimharris   SCI_TASK_REQUEST_HANDLE_T   task_request,
307230557Sjimharris   U16                         io_tag
308230557Sjimharris)
309230557Sjimharris{
310230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
311231296Sjimharris   SCI_STATUS              status;
312230557Sjimharris
313230557Sjimharris   // Validate the user supplied parameters.
314230557Sjimharris   if (  (controller == SCI_INVALID_HANDLE)
315230557Sjimharris      || (remote_device == SCI_INVALID_HANDLE)
316230557Sjimharris      || (task_request == SCI_INVALID_HANDLE) )
317230557Sjimharris   {
318231296Sjimharris      return SCI_TASK_FAILURE_INVALID_PARAMETER_VALUE;
319230557Sjimharris   }
320230557Sjimharris
321231137Sjimharris   SCIF_LOG_TRACE((
322231137Sjimharris      sci_base_object_get_logger(controller),
323231137Sjimharris      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_TASK_MANAGEMENT,
324231137Sjimharris      "scif_controller_start_task(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
325231137Sjimharris      controller, remote_device, task_request, io_tag
326231137Sjimharris   ));
327231137Sjimharris
328230557Sjimharris   if (scif_sas_controller_sufficient_resource(controller))
329230557Sjimharris   {
330231296Sjimharris      status = fw_controller->state_handlers->start_task_handler(
331230557Sjimharris             (SCI_BASE_CONTROLLER_T*) controller,
332230557Sjimharris             (SCI_BASE_REMOTE_DEVICE_T*) remote_device,
333230557Sjimharris             (SCI_BASE_REQUEST_T*) task_request,
334230557Sjimharris             io_tag
335230557Sjimharris          );
336230557Sjimharris   }
337230557Sjimharris   else
338231296Sjimharris      status = SCI_FAILURE_INSUFFICIENT_RESOURCES;
339231296Sjimharris
340231296Sjimharris   return (SCI_TASK_STATUS)status;
341230557Sjimharris}
342230557Sjimharris
343230557Sjimharris// ---------------------------------------------------------------------------
344230557Sjimharris
345230557SjimharrisSCI_STATUS scif_controller_complete_io(
346230557Sjimharris   SCI_CONTROLLER_HANDLE_T     controller,
347230557Sjimharris   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
348230557Sjimharris   SCI_IO_REQUEST_HANDLE_T     io_request
349230557Sjimharris)
350230557Sjimharris{
351230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
352230557Sjimharris
353230557Sjimharris   SCIF_LOG_TRACE((
354230557Sjimharris      sci_base_object_get_logger(controller),
355230557Sjimharris      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
356230557Sjimharris      "scif_controller_complete_io(0x%x, 0x%x, 0x%x) enter\n",
357230557Sjimharris      controller, remote_device, io_request
358230557Sjimharris   ));
359230557Sjimharris
360230557Sjimharris   return fw_controller->state_handlers->complete_io_handler(
361230557Sjimharris             (SCI_BASE_CONTROLLER_T*) controller,
362230557Sjimharris             (SCI_BASE_REMOTE_DEVICE_T*) remote_device,
363230557Sjimharris             (SCI_BASE_REQUEST_T*) io_request
364230557Sjimharris          );
365230557Sjimharris}
366230557Sjimharris
367230557Sjimharris// ---------------------------------------------------------------------------
368230557Sjimharris
369230557SjimharrisSCI_STATUS scif_controller_complete_task(
370230557Sjimharris   SCI_CONTROLLER_HANDLE_T     controller,
371230557Sjimharris   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
372230557Sjimharris   SCI_TASK_REQUEST_HANDLE_T   task_request
373230557Sjimharris)
374230557Sjimharris{
375230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
376230557Sjimharris
377230557Sjimharris   // Validate the user supplied parameters.
378230557Sjimharris   if (  (controller == SCI_INVALID_HANDLE)
379230557Sjimharris      || (remote_device == SCI_INVALID_HANDLE)
380230557Sjimharris      || (task_request == SCI_INVALID_HANDLE) )
381230557Sjimharris   {
382230557Sjimharris      return SCI_FAILURE_INVALID_PARAMETER_VALUE;
383230557Sjimharris   }
384230557Sjimharris
385231137Sjimharris   SCIF_LOG_TRACE((
386231137Sjimharris      sci_base_object_get_logger(controller),
387231137Sjimharris      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_TASK_MANAGEMENT,
388231137Sjimharris      "scif_controller_complete_task(0x%x, 0x%x, 0x%x) enter\n",
389231137Sjimharris      controller, remote_device, task_request
390231137Sjimharris   ));
391231137Sjimharris
392230557Sjimharris   return fw_controller->state_handlers->complete_task_handler(
393230557Sjimharris             (SCI_BASE_CONTROLLER_T*) controller,
394230557Sjimharris             (SCI_BASE_REMOTE_DEVICE_T*) remote_device,
395230557Sjimharris             (SCI_BASE_REQUEST_T*) task_request
396230557Sjimharris          );
397230557Sjimharris}
398230557Sjimharris
399230557Sjimharris// ---------------------------------------------------------------------------
400230557Sjimharris
401230557SjimharrisSCI_STATUS scif_controller_get_domain_handle(
402230557Sjimharris   SCI_CONTROLLER_HANDLE_T   controller,
403230557Sjimharris   U8                        port_index,
404230557Sjimharris   SCI_DOMAIN_HANDLE_T     * domain_handle
405230557Sjimharris)
406230557Sjimharris{
407230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
408230557Sjimharris
409230557Sjimharris   // Validate the user supplied parameters.
410230557Sjimharris   if (controller == SCI_INVALID_HANDLE)
411230557Sjimharris      return SCI_FAILURE_INVALID_PARAMETER_VALUE;
412230557Sjimharris
413230557Sjimharris   // Retrieve the domain handle if the supplied index is legitimate.
414230557Sjimharris   if (port_index < SCI_MAX_PORTS)
415230557Sjimharris   {
416230557Sjimharris      *domain_handle = &fw_controller->domains[port_index];
417230557Sjimharris      return SCI_SUCCESS;
418230557Sjimharris   }
419230557Sjimharris
420230557Sjimharris   return SCI_FAILURE_INVALID_PORT;
421230557Sjimharris}
422230557Sjimharris
423230557Sjimharris/**
424230557Sjimharris * @brief This method builds the memory descriptor list for this
425230557Sjimharris *        controller.
426230557Sjimharris *
427230557Sjimharris * @param[in] fw_controller This parameter specifies the framework
428230557Sjimharris *            controller object for which to build the MDL.
429230557Sjimharris *
430230557Sjimharris * @return none
431230557Sjimharris */
432230557Sjimharrisvoid scif_sas_controller_build_mdl(
433230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller
434230557Sjimharris)
435230557Sjimharris{
436230557Sjimharris   // one internal request for each domain.
437230557Sjimharris   sci_base_mde_construct(
438230557Sjimharris      &fw_controller->mdes[SCIF_SAS_MDE_INTERNAL_IO],
439230557Sjimharris      4,
440230557Sjimharris      fw_controller->internal_request_entries *
441230557Sjimharris         scif_sas_internal_request_get_object_size(),
442230557Sjimharris      SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
443230557Sjimharris   );
444230557Sjimharris}
445230557Sjimharris
446230557Sjimharris// ---------------------------------------------------------------------------
447230557Sjimharris
448230557SjimharrisSCI_STATUS scif_controller_set_mode(
449230557Sjimharris   SCI_CONTROLLER_HANDLE_T   controller,
450230557Sjimharris   SCI_CONTROLLER_MODE       mode
451230557Sjimharris)
452230557Sjimharris{
453230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
454230557Sjimharris   SCI_STATUS              status          = SCI_SUCCESS;
455230557Sjimharris
456230557Sjimharris   if (
457230557Sjimharris         (fw_controller->parent.state_machine.current_state_id
458230557Sjimharris          == SCI_BASE_CONTROLLER_STATE_INITIALIZING)
459230557Sjimharris      || (fw_controller->parent.state_machine.current_state_id
460230557Sjimharris          == SCI_BASE_CONTROLLER_STATE_INITIALIZED)
461230557Sjimharris      )
462230557Sjimharris   {
463230557Sjimharris      switch (mode)
464230557Sjimharris      {
465230557Sjimharris      case SCI_MODE_SPEED:
466230557Sjimharris         fw_controller->internal_request_entries =
467230557Sjimharris            MIN(fw_controller->internal_request_entries, SCIF_SAS_MAX_INTERNAL_REQUEST_COUNT);
468230557Sjimharris         scif_sas_controller_build_mdl(fw_controller);
469230557Sjimharris      break;
470230557Sjimharris
471230557Sjimharris      case SCI_MODE_SIZE:
472230557Sjimharris         fw_controller->internal_request_entries =
473230557Sjimharris            MIN(fw_controller->internal_request_entries, SCIF_SAS_MIN_INTERNAL_REQUEST_COUNT);
474230557Sjimharris         scif_sas_controller_build_mdl(fw_controller);
475230557Sjimharris      break;
476230557Sjimharris
477230557Sjimharris      default:
478230557Sjimharris         status = SCI_FAILURE_INVALID_PARAMETER_VALUE;
479230557Sjimharris      break;
480230557Sjimharris      }
481230557Sjimharris   }
482230557Sjimharris   else
483230557Sjimharris      status = SCI_FAILURE_INVALID_STATE;
484230557Sjimharris
485230557Sjimharris   if (status != SCI_SUCCESS)
486230557Sjimharris   {
487230557Sjimharris      return status;
488230557Sjimharris   }
489230557Sjimharris   else
490230557Sjimharris   {
491230557Sjimharris      // Currently, the framework doesn't change any configurations for
492230557Sjimharris      // speed or size modes.  Default to speed mode basically.
493230557Sjimharris      return scic_controller_set_mode(fw_controller->core_object, mode);
494230557Sjimharris   }
495230557Sjimharris}
496230557Sjimharris
497230557Sjimharris// ---------------------------------------------------------------------------
498230557Sjimharris
499230557SjimharrisU32 scif_controller_get_sat_compliance_version(
500230557Sjimharris   void
501230557Sjimharris)
502230557Sjimharris{
503230557Sjimharris   /// @todo Fix return of SAT compliance version.
504230557Sjimharris   return 0;
505230557Sjimharris}
506230557Sjimharris
507230557Sjimharris// ---------------------------------------------------------------------------
508230557Sjimharris
509230557SjimharrisU32 scif_controller_get_sat_compliance_version_revision(
510230557Sjimharris   void
511230557Sjimharris)
512230557Sjimharris{
513230557Sjimharris   /// @todo Fix return of SAT compliance revision.
514230557Sjimharris   return 0;
515230557Sjimharris}
516230557Sjimharris
517230557Sjimharris// ---------------------------------------------------------------------------
518230557Sjimharris
519230557SjimharrisSCI_STATUS scif_user_parameters_set(
520230557Sjimharris   SCI_CONTROLLER_HANDLE_T   controller,
521230557Sjimharris   SCIF_USER_PARAMETERS_T  * scif_parms
522230557Sjimharris)
523230557Sjimharris{
524230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
525230557Sjimharris
526230557Sjimharris   //validate all the registry entries before overwriting the default parameter
527230557Sjimharris   //values.
528230557Sjimharris   if (scif_parms->sas.is_sata_ncq_enabled != 1 && scif_parms->sas.is_sata_ncq_enabled != 0)
529230557Sjimharris      return SCI_FAILURE_INVALID_PARAMETER_VALUE;
530230557Sjimharris
531230557Sjimharris   if (scif_parms->sas.max_ncq_depth < 1 && scif_parms->sas.max_ncq_depth > 32)
532230557Sjimharris      return SCI_FAILURE_INVALID_PARAMETER_VALUE;
533230557Sjimharris
534230557Sjimharris   if (scif_parms->sas.is_sata_standby_timer_enabled != 1
535230557Sjimharris       && scif_parms->sas.is_sata_standby_timer_enabled != 0)
536230557Sjimharris      return SCI_FAILURE_INVALID_PARAMETER_VALUE;
537230557Sjimharris
538230557Sjimharris   if (scif_parms->sas.is_non_zero_buffer_offsets_enabled != 1
539230557Sjimharris       && scif_parms->sas.is_non_zero_buffer_offsets_enabled != 0)
540230557Sjimharris      return SCI_FAILURE_INVALID_PARAMETER_VALUE;
541230557Sjimharris
542230557Sjimharris   if (scif_parms->sas.reset_type != SCI_SAS_ABORT_TASK
543230557Sjimharris       && scif_parms->sas.reset_type != SCI_SAS_ABORT_TASK_SET
544230557Sjimharris       && scif_parms->sas.reset_type != SCI_SAS_CLEAR_TASK_SET
545230557Sjimharris       && scif_parms->sas.reset_type != SCI_SAS_LOGICAL_UNIT_RESET
546230557Sjimharris       && scif_parms->sas.reset_type != SCI_SAS_I_T_NEXUS_RESET
547230557Sjimharris       && scif_parms->sas.reset_type != SCI_SAS_CLEAR_ACA
548230557Sjimharris       && scif_parms->sas.reset_type != SCI_SAS_QUERY_TASK
549230557Sjimharris       && scif_parms->sas.reset_type != SCI_SAS_QUERY_TASK_SET
550230557Sjimharris       && scif_parms->sas.reset_type != SCI_SAS_QUERY_ASYNCHRONOUS_EVENT
551230557Sjimharris       && scif_parms->sas.reset_type != SCI_SAS_HARD_RESET)
552230557Sjimharris      return SCI_FAILURE_INVALID_PARAMETER_VALUE;
553230557Sjimharris
554230557Sjimharris   if (scif_parms->sas.clear_affiliation_during_controller_stop != 1
555230557Sjimharris       && scif_parms->sas.clear_affiliation_during_controller_stop !=0)
556230557Sjimharris       return SCI_FAILURE_INVALID_PARAMETER_VALUE;
557230557Sjimharris
558230557Sjimharris   memcpy((&fw_controller->user_parameters), scif_parms, sizeof(*scif_parms));
559230557Sjimharris
560230557Sjimharris   // In the future more could be done to prevent setting parameters at the
561230557Sjimharris   // wrong time, but for now we'll simply set the values even if it is too
562230557Sjimharris   // late for them to take affect.
563230557Sjimharris   return SCI_SUCCESS;
564230557Sjimharris}
565230557Sjimharris
566230557Sjimharris// ---------------------------------------------------------------------------
567230557Sjimharris
568230557Sjimharris#if !defined(DISABLE_INTERRUPTS)
569230557Sjimharris
570230557Sjimharris/**
571230557Sjimharris * @brief This routine check each domain of the controller to see if
572230557Sjimharris *           any domain is overriding interrupt coalescence.
573230557Sjimharris *
574230557Sjimharris * @param[in] fw_controller frame controller
575230557Sjimharris * @param[in] fw_smp_phy The smp phy to be freed.
576230557Sjimharris *
577230557Sjimharris * @return none
578230557Sjimharris */
579230557Sjimharrisstatic
580230557SjimharrisBOOL scif_sas_controller_is_overriding_interrupt_coalescence(
581230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller
582230557Sjimharris)
583230557Sjimharris{
584230557Sjimharris   U8 index;
585230557Sjimharris
586230557Sjimharris   for(index = 0; index < SCI_MAX_DOMAINS; index++)
587230557Sjimharris   {
588230557Sjimharris      if(fw_controller->domains[index].parent.state_machine.current_state_id ==
589230557Sjimharris            SCI_BASE_DOMAIN_STATE_DISCOVERING)
590230557Sjimharris         return TRUE;
591230557Sjimharris   }
592230557Sjimharris
593230557Sjimharris   return FALSE;
594230557Sjimharris}
595230557Sjimharris
596230557SjimharrisSCI_STATUS scif_controller_set_interrupt_coalescence(
597230557Sjimharris   SCI_CONTROLLER_HANDLE_T controller,
598230557Sjimharris   U32                     coalesce_number,
599230557Sjimharris   U32                     coalesce_timeout
600230557Sjimharris)
601230557Sjimharris{
602230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T * )controller;
603230557Sjimharris
604230557Sjimharris   ///when framework is in the middle of temporarily overriding the interrupt
605230557Sjimharris   ///coalescence values, user's request of setting interrupt coalescence
606230557Sjimharris   ///will be saved. As soon as the framework done the temporary overriding,
607230557Sjimharris   ///it will serve user's request to set new interrupt coalescence.
608230557Sjimharris   if (scif_sas_controller_is_overriding_interrupt_coalescence(fw_controller))
609230557Sjimharris   {
610230557Sjimharris      U32 curr_coalesce_number;
611230557Sjimharris      U32 curr_coalesce_timeout;
612230557Sjimharris      SCI_STATUS core_status;
613230557Sjimharris
614230557Sjimharris      // save current interrupt coalescence info.
615230557Sjimharris      scic_controller_get_interrupt_coalescence (
616230557Sjimharris         fw_controller->core_object, &curr_coalesce_number, &curr_coalesce_timeout);
617230557Sjimharris
618230557Sjimharris      //try user's request out in the core, but immediately restore core's
619230557Sjimharris      //current setting.
620230557Sjimharris      core_status = scic_controller_set_interrupt_coalescence(
621230557Sjimharris                       fw_controller->core_object, coalesce_number, coalesce_timeout);
622230557Sjimharris
623230557Sjimharris      if ( core_status == SCI_SUCCESS )
624230557Sjimharris      {
625230557Sjimharris         fw_controller->saved_interrupt_coalesce_number = (U16)coalesce_number;
626230557Sjimharris         fw_controller->saved_interrupt_coalesce_timeout = coalesce_timeout;
627230557Sjimharris      }
628230557Sjimharris
629230557Sjimharris       //restore current interrupt coalescence.
630230557Sjimharris      scic_controller_set_interrupt_coalescence(
631230557Sjimharris         fw_controller->core_object, curr_coalesce_number, curr_coalesce_timeout);
632230557Sjimharris
633230557Sjimharris      return core_status;
634230557Sjimharris   }
635230557Sjimharris   else
636230557Sjimharris   {
637230557Sjimharris      ///If framework is not internally overriding the interrupt coalescence,
638230557Sjimharris      ///serve user's request immediately by passing the reqeust to core.
639230557Sjimharris      return scic_controller_set_interrupt_coalescence(
640230557Sjimharris                fw_controller->core_object, coalesce_number, coalesce_timeout);
641230557Sjimharris   }
642230557Sjimharris}
643230557Sjimharris
644230557Sjimharris// ---------------------------------------------------------------------------
645230557Sjimharris
646230557Sjimharrisvoid scif_controller_get_interrupt_coalescence(
647230557Sjimharris   SCI_CONTROLLER_HANDLE_T controller,
648230557Sjimharris   U32                   * coalesce_number,
649230557Sjimharris   U32                   * coalesce_timeout
650230557Sjimharris)
651230557Sjimharris{
652230557Sjimharris   SCIF_SAS_CONTROLLER_T * scif_controller = (SCIF_SAS_CONTROLLER_T * )controller;
653230557Sjimharris
654230557Sjimharris   scic_controller_get_interrupt_coalescence(
655230557Sjimharris      scif_controller->core_object, coalesce_number, coalesce_timeout);
656230557Sjimharris}
657230557Sjimharris
658230557Sjimharris/**
659230557Sjimharris * @brief This method will save the interrupt coalescence values.  If
660230557Sjimharris *        the interrupt coalescence values have already been saved,
661230557Sjimharris *        then this method performs no operations.
662230557Sjimharris *
663230557Sjimharris * @param[in,out] fw_controller This parameter specifies the controller
664230557Sjimharris *                for which to save the interrupt coalescence values.
665230557Sjimharris *
666230557Sjimharris * @return none
667230557Sjimharris */
668230557Sjimharrisvoid scif_sas_controller_save_interrupt_coalescence(
669230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller
670230557Sjimharris)
671230557Sjimharris{
672230557Sjimharris   if ( !scif_sas_controller_is_overriding_interrupt_coalescence(fw_controller))
673230557Sjimharris   {
674230557Sjimharris      // Override core's interrupt coalescing settings during SMP
675230557Sjimharris      // DISCOVER process cause' there is only 1 outstanding SMP
676230557Sjimharris      // request per domain is allowed.
677230557Sjimharris      scic_controller_get_interrupt_coalescence(
678230557Sjimharris         fw_controller->core_object,
679230557Sjimharris         (U32*)&(fw_controller->saved_interrupt_coalesce_number),
680230557Sjimharris         &(fw_controller->saved_interrupt_coalesce_timeout)
681230557Sjimharris      );
682230557Sjimharris
683230557Sjimharris      // Temporarily disable the interrupt coalescing.
684230557Sjimharris      scic_controller_set_interrupt_coalescence(fw_controller->core_object,0,0);
685230557Sjimharris   }
686230557Sjimharris}
687230557Sjimharris
688230557Sjimharris/**
689230557Sjimharris * @brief This method will restore the interrupt coalescence values.  If
690230557Sjimharris *        the interrupt coalescence values have not already been saved,
691230557Sjimharris *        then this method performs no operations.
692230557Sjimharris *
693230557Sjimharris * @param[in,out] fw_controller This parameter specifies the controller
694230557Sjimharris *                for which to restore the interrupt coalescence values.
695230557Sjimharris *
696230557Sjimharris * @return none
697230557Sjimharris */
698230557Sjimharrisvoid scif_sas_controller_restore_interrupt_coalescence(
699230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller
700230557Sjimharris)
701230557Sjimharris{
702230557Sjimharris   if ( !scif_sas_controller_is_overriding_interrupt_coalescence(fw_controller))
703230557Sjimharris      scic_controller_set_interrupt_coalescence(
704230557Sjimharris         fw_controller->core_object,
705230557Sjimharris         fw_controller->saved_interrupt_coalesce_number,
706230557Sjimharris         fw_controller->saved_interrupt_coalesce_timeout
707230557Sjimharris      );
708230557Sjimharris}
709230557Sjimharris
710230557Sjimharris#endif // !defined(DISABLE_INTERRUPTS)
711230557Sjimharris
712230557Sjimharris// ---------------------------------------------------------------------------
713230557Sjimharris
714230557Sjimharrisvoid scic_cb_controller_start_complete(
715230557Sjimharris   SCI_CONTROLLER_HANDLE_T  controller,
716230557Sjimharris   SCI_STATUS               completion_status
717230557Sjimharris)
718230557Sjimharris{
719230557Sjimharris   SCIF_SAS_CONTROLLER_T *fw_controller = (SCIF_SAS_CONTROLLER_T*)
720230557Sjimharris                                         sci_object_get_association(controller);
721230557Sjimharris
722230557Sjimharris   SCIF_LOG_TRACE((
723230557Sjimharris      sci_base_object_get_logger(controller),
724230557Sjimharris      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION,
725230557Sjimharris      "scic_cb_controller_start_complete(0x%x, 0x%x) enter\n",
726230557Sjimharris      controller, completion_status
727230557Sjimharris   ));
728230557Sjimharris
729230557Sjimharris   if (completion_status == SCI_SUCCESS
730230557Sjimharris       || completion_status == SCI_FAILURE_TIMEOUT)
731230557Sjimharris   {
732230557Sjimharris      // Even the initialization of the core controller timed out, framework
733230557Sjimharris      // controller should still transit to READY state.
734230557Sjimharris      sci_base_state_machine_change_state(
735230557Sjimharris         &fw_controller->parent.state_machine,
736230557Sjimharris         SCI_BASE_CONTROLLER_STATE_READY
737230557Sjimharris      );
738230557Sjimharris   }
739230557Sjimharris
740230557Sjimharris   scif_cb_controller_start_complete(fw_controller, completion_status);
741230557Sjimharris}
742230557Sjimharris
743230557Sjimharris// ---------------------------------------------------------------------------
744230557Sjimharris
745230557Sjimharrisvoid scic_cb_controller_stop_complete(
746230557Sjimharris   SCI_CONTROLLER_HANDLE_T  controller,
747230557Sjimharris   SCI_STATUS               completion_status
748230557Sjimharris)
749230557Sjimharris{
750230557Sjimharris   SCIF_SAS_CONTROLLER_T *fw_controller = (SCIF_SAS_CONTROLLER_T*)
751230557Sjimharris                                         sci_object_get_association(controller);
752230557Sjimharris
753230557Sjimharris   SCIF_LOG_TRACE((
754230557Sjimharris      sci_base_object_get_logger(controller),
755230557Sjimharris      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_SHUTDOWN,
756230557Sjimharris      "scic_cb_controller_stop_complete(0x%x, 0x%x) enter\n",
757230557Sjimharris      controller, completion_status
758230557Sjimharris   ));
759230557Sjimharris
760230557Sjimharris   if (completion_status == SCI_SUCCESS)
761230557Sjimharris   {
762230557Sjimharris      sci_base_state_machine_change_state(
763230557Sjimharris         &fw_controller->parent.state_machine,
764230557Sjimharris         SCI_BASE_CONTROLLER_STATE_STOPPED
765230557Sjimharris      );
766230557Sjimharris   }
767230557Sjimharris   else
768230557Sjimharris   {
769230557Sjimharris      sci_base_state_machine_change_state(
770230557Sjimharris         &fw_controller->parent.state_machine,
771230557Sjimharris         SCI_BASE_CONTROLLER_STATE_FAILED
772230557Sjimharris      );
773230557Sjimharris   }
774230557Sjimharris
775230557Sjimharris   scif_cb_controller_stop_complete(fw_controller, completion_status);
776230557Sjimharris}
777230557Sjimharris
778230557Sjimharris
779230557Sjimharris// ---------------------------------------------------------------------------
780230557Sjimharris
781230557Sjimharrisvoid scic_cb_controller_error(
782230557Sjimharris   SCI_CONTROLLER_HANDLE_T  controller,
783230557Sjimharris   SCI_CONTROLLER_ERROR error
784230557Sjimharris)
785230557Sjimharris{
786230557Sjimharris   SCIF_SAS_CONTROLLER_T *fw_controller = (SCIF_SAS_CONTROLLER_T*)
787230557Sjimharris                                         sci_object_get_association(controller);
788230557Sjimharris
789230557Sjimharris   fw_controller->parent.error = error;
790230557Sjimharris
791230557Sjimharris   SCIF_LOG_TRACE((
792230557Sjimharris      sci_base_object_get_logger(controller),
793230557Sjimharris      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_SHUTDOWN,
794230557Sjimharris      "scic_cb_controller_not_ready(0x%x) enter\n",
795230557Sjimharris      controller
796230557Sjimharris   ));
797230557Sjimharris
798230557Sjimharris   sci_base_state_machine_change_state(
799230557Sjimharris      &fw_controller->parent.state_machine,
800230557Sjimharris      SCI_BASE_CONTROLLER_STATE_FAILED
801230557Sjimharris   );
802230557Sjimharris}
803230557Sjimharris
804230557Sjimharris//******************************************************************************
805230557Sjimharris//* P R O T E C T E D    M E T H O D S
806230557Sjimharris//******************************************************************************
807230557Sjimharris
808230557Sjimharris/**
809230557Sjimharris * @brief This method is utilized to continue an internal IO operation
810230557Sjimharris *        on the controller.  This method is utilized for SAT translated
811230557Sjimharris *        requests that generate multiple ATA commands in order to fulfill
812230557Sjimharris *        the original SCSI request.
813230557Sjimharris *
814230557Sjimharris * @param[in]  controller This parameter specifies the controller on which
815230557Sjimharris *             to continue an internal IO request.
816230557Sjimharris * @param[in]  remote_device This parameter specifies the remote device
817230557Sjimharris *             on which to continue an internal IO request.
818230557Sjimharris * @param[in]  io_request This parameter specifies the IO request to be
819230557Sjimharris *             continue.
820230557Sjimharris *
821230557Sjimharris * @return Indicate if the continue operation was successful.
822230557Sjimharris * @retval SCI_SUCCESS This value is returned if the operation succeeded.
823230557Sjimharris */
824230557SjimharrisSCI_STATUS scif_sas_controller_continue_io(
825230557Sjimharris   SCI_CONTROLLER_HANDLE_T     controller,
826230557Sjimharris   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
827230557Sjimharris   SCI_IO_REQUEST_HANDLE_T     io_request
828230557Sjimharris)
829230557Sjimharris{
830230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
831230557Sjimharris
832230557Sjimharris   return fw_controller->state_handlers->continue_io_handler(
833230557Sjimharris             (SCI_BASE_CONTROLLER_T*) controller,
834230557Sjimharris             (SCI_BASE_REMOTE_DEVICE_T*) remote_device,
835230557Sjimharris             (SCI_BASE_REQUEST_T*) io_request
836230557Sjimharris          );
837230557Sjimharris}
838230557Sjimharris
839230557Sjimharris/**
840230557Sjimharris * @brief This method will attempt to destruct a framework controller.
841230557Sjimharris *        This includes free any resources retreived from the user (e.g.
842230557Sjimharris *        timers).
843230557Sjimharris *
844230557Sjimharris * @param[in]  fw_controller This parameter specifies the framework
845230557Sjimharris *             controller to destructed.
846230557Sjimharris *
847230557Sjimharris * @return none
848230557Sjimharris */
849230557Sjimharrisvoid scif_sas_controller_destruct(
850230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller
851230557Sjimharris)
852230557Sjimharris{
853230557Sjimharris   SCIF_LOG_TRACE((
854230557Sjimharris      sci_base_object_get_logger(fw_controller),
855230557Sjimharris      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_SHUTDOWN,
856230557Sjimharris      "scif_sas_controller_destruct(0x%x) enter\n",
857230557Sjimharris      fw_controller
858230557Sjimharris   ));
859230557Sjimharris}
860230557Sjimharris
861230557Sjimharris//-----------------------------------------------------------------------------
862230557Sjimharris// INTERNAL REQUEST RELATED METHODS
863230557Sjimharris//-----------------------------------------------------------------------------
864230557Sjimharris
865230557Sjimharris/**
866230557Sjimharris * @brief This routine is to allocate the memory for creating a new internal
867230557Sjimharris *        request.
868230557Sjimharris *
869230557Sjimharris * @param[in] scif_controller handle to frame controller
870230557Sjimharris *
871230557Sjimharris * @return void* address to internal request memory
872230557Sjimharris */
873230557Sjimharrisvoid * scif_sas_controller_allocate_internal_request(
874230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller
875230557Sjimharris)
876230557Sjimharris{
877230557Sjimharris   POINTER_UINT internal_io_address;
878230557Sjimharris
879230557Sjimharris   if( !sci_pool_empty(fw_controller->internal_request_memory_pool) )
880230557Sjimharris   {
881230557Sjimharris      sci_pool_get(
882230557Sjimharris         fw_controller->internal_request_memory_pool, internal_io_address
883230557Sjimharris      );
884230557Sjimharris
885230557Sjimharris      //clean the memory.
886230557Sjimharris      memset((char*)internal_io_address, 0, scif_sas_internal_request_get_object_size());
887230557Sjimharris
888230557Sjimharris      return (void *) internal_io_address;
889230557Sjimharris   }
890230557Sjimharris   else
891230557Sjimharris      return NULL;
892230557Sjimharris}
893230557Sjimharris
894230557Sjimharris/**
895230557Sjimharris * @brief This routine is to free the memory for a completed internal request.
896230557Sjimharris *
897230557Sjimharris * @param[in] scif_controller handle to frame controller
898230557Sjimharris * @param[in] fw_internal_io The internal IO to be freed.
899230557Sjimharris *
900230557Sjimharris * @return none
901230557Sjimharris */
902230557Sjimharrisvoid scif_sas_controller_free_internal_request(
903230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller,
904230557Sjimharris   void                  * fw_internal_request_buffer
905230557Sjimharris)
906230557Sjimharris{
907230557Sjimharris   SCIF_LOG_TRACE((
908230557Sjimharris      sci_base_object_get_logger(fw_controller),
909230557Sjimharris      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
910230557Sjimharris      "scif_controller_free_internal_request(0x%x, 0x%x) enter\n",
911230557Sjimharris      fw_controller, fw_internal_request_buffer
912230557Sjimharris   ));
913230557Sjimharris
914230557Sjimharris   //return the memory to to pool.
915230557Sjimharris   if( !sci_pool_full(fw_controller->internal_request_memory_pool) )
916230557Sjimharris   {
917230557Sjimharris      sci_pool_put(
918230557Sjimharris         fw_controller->internal_request_memory_pool,
919230557Sjimharris         (POINTER_UINT) fw_internal_request_buffer
920230557Sjimharris      );
921230557Sjimharris   }
922230557Sjimharris}
923230557Sjimharris
924230557Sjimharris
925230557Sjimharris/**
926230557Sjimharris * @brief this routine is called by OS' DPC to start io requests from internal
927230557Sjimharris *        high priority request queue
928230557Sjimharris * @param[in] fw_controller The framework controller.
929230557Sjimharris *
930230557Sjimharris * @return none
931230557Sjimharris */
932230557Sjimharrisvoid scif_sas_controller_start_high_priority_io(
933230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller
934230557Sjimharris)
935230557Sjimharris{
936230557Sjimharris   POINTER_UINT            io_address;
937230557Sjimharris   SCIF_SAS_IO_REQUEST_T * fw_io;
938230557Sjimharris   SCI_STATUS              status;
939230557Sjimharris
940230557Sjimharris   SCIF_LOG_TRACE((
941230557Sjimharris      sci_base_object_get_logger(fw_controller),
942230557Sjimharris      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
943230557Sjimharris      "scif_controller_start_high_priority_io(0x%x) enter\n",
944230557Sjimharris      fw_controller
945230557Sjimharris   ));
946230557Sjimharris
947230557Sjimharris   while ( !sci_pool_empty(fw_controller->hprq.pool) )
948230557Sjimharris   {
949230557Sjimharris      sci_pool_get(fw_controller->hprq.pool, io_address);
950230557Sjimharris
951230557Sjimharris      fw_io = (SCIF_SAS_IO_REQUEST_T *)io_address;
952230557Sjimharris
953230557Sjimharris      status = fw_controller->state_handlers->start_high_priority_io_handler(
954230557Sjimharris         (SCI_BASE_CONTROLLER_T*) fw_controller,
955230557Sjimharris         (SCI_BASE_REMOTE_DEVICE_T*) fw_io->parent.device,
956230557Sjimharris         (SCI_BASE_REQUEST_T*) fw_io,
957230557Sjimharris         SCI_CONTROLLER_INVALID_IO_TAG
958230557Sjimharris      );
959230557Sjimharris   }
960230557Sjimharris}
961230557Sjimharris
962230557Sjimharris/**
963230557Sjimharris * @brief This method will check how many outstanding IOs currently and number
964230557Sjimharris * of IOs in high priority queue, if the overall number exceeds the max_tc,
965230557Sjimharris * return FALSE.
966230557Sjimharris *
967230557Sjimharris * @param[in] fw_controller The framework controller.
968230557Sjimharris *
969230557Sjimharris * @return BOOL Indicate whether there is sufficient resource to start an IO.
970230557Sjimharris * @retvalue TRUE The controller has sufficient resource.
971230557Sjimharris * @retvalue FALSE There is not sufficient resource available.
972230557Sjimharris */
973230557SjimharrisBOOL scif_sas_controller_sufficient_resource(
974230557Sjimharris   SCIF_SAS_CONTROLLER_T *fw_controller
975230557Sjimharris)
976230557Sjimharris{
977230557Sjimharris   SCIF_SAS_DOMAIN_T * fw_domain;
978230557Sjimharris   U32 domain_index;
979230557Sjimharris   U32 outstanding_io_count = 0;
980230557Sjimharris   U32 high_priority_io_count = 0;
981230557Sjimharris
982230557Sjimharris   for(domain_index = 0; domain_index < SCI_MAX_DOMAINS; domain_index++)
983230557Sjimharris   {
984230557Sjimharris      fw_domain = &fw_controller->domains[domain_index];
985230557Sjimharris      outstanding_io_count += fw_domain->request_list.element_count;
986230557Sjimharris   }
987230557Sjimharris
988230557Sjimharris   high_priority_io_count = sci_pool_count(fw_controller->hprq.pool);
989230557Sjimharris
990230557Sjimharris   if ( (outstanding_io_count + high_priority_io_count) > SCI_MAX_IO_REQUESTS )
991230557Sjimharris      return FALSE;
992230557Sjimharris
993230557Sjimharris   return TRUE;
994230557Sjimharris}
995230557Sjimharris
996230557Sjimharris
997230557Sjimharris/**
998230557Sjimharris * @brief This method is the starting point to complete high prority io for a
999230557Sjimharris *        controller then down to domain, device.
1000230557Sjimharris *
1001230557Sjimharris * @param[in] fw_controller The framework controller
1002230557Sjimharris * @param[in] remote_device  The framework remote device.
1003230557Sjimharris * @param[in] io_request The high priority io request to be completed.
1004230557Sjimharris *
1005230557Sjimharris * @return SCI_STATUS indicate the completion status from framework down to the
1006230557Sjimharris *         core.
1007230557Sjimharris */
1008230557SjimharrisSCI_STATUS scif_sas_controller_complete_high_priority_io(
1009230557Sjimharris   SCIF_SAS_CONTROLLER_T    *fw_controller,
1010230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T *remote_device,
1011230557Sjimharris   SCIF_SAS_REQUEST_T       *io_request
1012230557Sjimharris)
1013230557Sjimharris{
1014230557Sjimharris   SCIF_LOG_TRACE((
1015230557Sjimharris      sci_base_object_get_logger(fw_controller),
1016230557Sjimharris      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
1017230557Sjimharris      "scif_sas_controller_complete_high_priority_io(0x%x, 0x%x, 0x%x) enter\n",
1018230557Sjimharris      fw_controller, remote_device, io_request
1019230557Sjimharris   ));
1020230557Sjimharris
1021230557Sjimharris   //call controller's new added complete_high_priority_io_handler
1022230557Sjimharris   return fw_controller->state_handlers->complete_high_priority_io_handler(
1023230557Sjimharris             (SCI_BASE_CONTROLLER_T*) fw_controller,
1024230557Sjimharris             (SCI_BASE_REMOTE_DEVICE_T*) remote_device,
1025230557Sjimharris             (SCI_BASE_REQUEST_T*) io_request
1026230557Sjimharris          );
1027230557Sjimharris}
1028230557Sjimharris
1029230557Sjimharris/**
1030230557Sjimharris
1031230557Sjimharris * @brief This routine is to allocate the memory for creating a smp phy object.
1032230557Sjimharris *
1033230557Sjimharris * @param[in] scif_controller handle to frame controller
1034230557Sjimharris *
1035230557Sjimharris * @return SCIF_SAS_SMP_PHY_T * An allocated space for smp phy. If failed to allocate,
1036230557Sjimharris *            return NULL.
1037230557Sjimharris */
1038230557SjimharrisSCIF_SAS_SMP_PHY_T * scif_sas_controller_allocate_smp_phy(
1039230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller
1040230557Sjimharris)
1041230557Sjimharris{
1042230557Sjimharris   SCIF_SAS_SMP_PHY_T * smp_phy;
1043230557Sjimharris
1044230557Sjimharris   SCIF_LOG_TRACE((
1045230557Sjimharris      sci_base_object_get_logger(fw_controller),
1046230557Sjimharris      SCIF_LOG_OBJECT_CONTROLLER,
1047230557Sjimharris      "scif_controller_allocate_smp_phy(0x%x) enter\n",
1048230557Sjimharris      fw_controller
1049230557Sjimharris   ));
1050230557Sjimharris
1051230557Sjimharris   if( !sci_fast_list_is_empty(&fw_controller->smp_phy_memory_list) )
1052230557Sjimharris   {
1053230557Sjimharris      smp_phy = (SCIF_SAS_SMP_PHY_T *)
1054230557Sjimharris         sci_fast_list_remove_head(&fw_controller->smp_phy_memory_list);
1055230557Sjimharris
1056230557Sjimharris      //clean the memory.
1057230557Sjimharris      memset((char*)smp_phy,
1058230557Sjimharris             0,
1059230557Sjimharris             sizeof(SCIF_SAS_SMP_PHY_T)
1060230557Sjimharris            );
1061230557Sjimharris
1062230557Sjimharris      return smp_phy;
1063230557Sjimharris   }
1064230557Sjimharris   else
1065230557Sjimharris      return NULL;
1066230557Sjimharris}
1067230557Sjimharris
1068230557Sjimharris/**
1069230557Sjimharris * @brief This routine is to free the memory for a released smp phy.
1070230557Sjimharris *
1071230557Sjimharris * @param[in] fw_controller The framework controller, a smp phy is released
1072230557Sjimharris *                to its memory.
1073230557Sjimharris * @param[in] fw_smp_phy The smp phy to be freed.
1074230557Sjimharris *
1075230557Sjimharris * @return none
1076230557Sjimharris */
1077230557Sjimharrisvoid scif_sas_controller_free_smp_phy(
1078230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller,
1079230557Sjimharris   SCIF_SAS_SMP_PHY_T    * smp_phy
1080230557Sjimharris)
1081230557Sjimharris{
1082230557Sjimharris   SCIF_LOG_TRACE((
1083230557Sjimharris      sci_base_object_get_logger(fw_controller),
1084230557Sjimharris      SCIF_LOG_OBJECT_CONTROLLER,
1085230557Sjimharris      "scif_controller_free_smp_phy(0x%x, 0x%x) enter\n",
1086230557Sjimharris      fw_controller, smp_phy
1087230557Sjimharris   ));
1088230557Sjimharris
1089230557Sjimharris   //return the memory to the list.
1090230557Sjimharris   sci_fast_list_insert_tail(
1091230557Sjimharris      &fw_controller->smp_phy_memory_list,
1092230557Sjimharris      &smp_phy->list_element
1093230557Sjimharris   );
1094230557Sjimharris}
1095230557Sjimharris
1096230557Sjimharris
1097230557Sjimharris/**
1098230557Sjimharris * @brief This method clear affiliation for all the EA SATA devices associated
1099230557Sjimharris *        to this controller.
1100230557Sjimharris *
1101230557Sjimharris * @param[in] fw_controller This parameter specifies the framework
1102230557Sjimharris *            controller object for whose remote devices are to be stopped.
1103230557Sjimharris *
1104230557Sjimharris * @return This method returns a value indicating if the operation completed.
1105230557Sjimharris * @retval SCI_COMPLETE This value indicates that all the EA SATA devices'
1106230557Sjimharris *         affiliation was cleared.
1107230557Sjimharris * @retval SCI_INCOMPLETE This value indicates clear affiliation activity is
1108230557Sjimharris *         yet to be completed.
1109230557Sjimharris */
1110230557SjimharrisSCI_STATUS scif_sas_controller_clear_affiliation(
1111230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller
1112230557Sjimharris)
1113230557Sjimharris{
1114230557Sjimharris   U8 index;
1115230557Sjimharris   SCI_STATUS status;
1116230557Sjimharris   SCIF_SAS_DOMAIN_T * fw_domain;
1117230557Sjimharris
1118230557Sjimharris   SCIF_LOG_TRACE((
1119230557Sjimharris      sci_base_object_get_logger(fw_controller),
1120230557Sjimharris      SCIF_LOG_OBJECT_CONTROLLER,
1121230557Sjimharris      "scif_sas_controller_clear_affiliation(0x%x) enter\n",
1122230557Sjimharris      fw_controller
1123230557Sjimharris   ));
1124230557Sjimharris
1125230557Sjimharris   index = fw_controller->current_domain_to_clear_affiliation;
1126230557Sjimharris
1127230557Sjimharris   if (index < SCI_MAX_DOMAINS)
1128230557Sjimharris   {
1129230557Sjimharris      fw_domain = &fw_controller->domains[index];
1130230557Sjimharris
1131230557Sjimharris      //Need to stop all the on-going smp activities before clearing affiliation.
1132230557Sjimharris      scif_sas_domain_cancel_smp_activities(fw_domain);
1133230557Sjimharris
1134230557Sjimharris      scif_sas_domain_start_clear_affiliation(fw_domain);
1135230557Sjimharris
1136230557Sjimharris      status = SCI_WARNING_SEQUENCE_INCOMPLETE;
1137230557Sjimharris   }
1138230557Sjimharris   else
1139230557Sjimharris   {  //the controller has done clear affiliation work to all its domains.
1140230557Sjimharris      scif_sas_controller_continue_to_stop(fw_controller);
1141230557Sjimharris      status = SCI_SUCCESS;
1142230557Sjimharris   }
1143230557Sjimharris
1144230557Sjimharris   return status;
1145230557Sjimharris}
1146230557Sjimharris
1147230557Sjimharris
1148230557Sjimharris/**
1149230557Sjimharris * @brief This method sets SCIF user parameters to
1150230557Sjimharris *        default values.  Users can override these values utilizing
1151230557Sjimharris *        the sciF_user_parameters_set() methods.
1152230557Sjimharris *
1153230557Sjimharris * @param[in] controller This parameter specifies the controller for
1154230557Sjimharris *            which to set the configuration parameters to their
1155230557Sjimharris *            default values.
1156230557Sjimharris *
1157230557Sjimharris * @return none
1158230557Sjimharris */
1159230557Sjimharrisvoid scif_sas_controller_set_default_config_parameters(
1160230557Sjimharris   SCIF_SAS_CONTROLLER_T * this_controller
1161230557Sjimharris)
1162230557Sjimharris{
1163230557Sjimharris   SCIF_USER_PARAMETERS_T * scif_parms = &(this_controller->user_parameters);
1164230557Sjimharris
1165230557Sjimharris   scif_parms->sas.is_sata_ncq_enabled = TRUE;
1166230557Sjimharris   scif_parms->sas.max_ncq_depth = 32;
1167230557Sjimharris   scif_parms->sas.is_sata_standby_timer_enabled = FALSE;
1168230557Sjimharris   scif_parms->sas.is_non_zero_buffer_offsets_enabled = FALSE;
1169230557Sjimharris   scif_parms->sas.reset_type = SCI_SAS_LOGICAL_UNIT_RESET;
1170230557Sjimharris   scif_parms->sas.clear_affiliation_during_controller_stop = TRUE;
1171230557Sjimharris   scif_parms->sas.ignore_fua = FALSE;
1172230557Sjimharris
1173230557Sjimharris}
1174230557Sjimharris
1175230557Sjimharris
1176230557Sjimharris/**
1177230557Sjimharris * @brief This method releases resource for framework controller and associated
1178230557Sjimharris *        objects.
1179230557Sjimharris *
1180230557Sjimharris * @param[in] fw_controller This parameter specifies the framework
1181230557Sjimharris *            controller and associated objects whose resources are to be released.
1182230557Sjimharris *
1183230557Sjimharris * @return This method returns a value indicating if the operation succeeded.
1184230557Sjimharris * @retval SCI_SUCCESS This value indicates that resource release succeeded.
1185230557Sjimharris * @retval SCI_FAILURE This value indicates certain failure during the process
1186230557Sjimharris *            of resource release.
1187230557Sjimharris */
1188230557SjimharrisSCI_STATUS scif_sas_controller_release_resource(
1189230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller
1190230557Sjimharris)
1191230557Sjimharris{
1192230557Sjimharris   U8 index;
1193230557Sjimharris   SCIF_SAS_DOMAIN_T * fw_domain;
1194230557Sjimharris
1195230557Sjimharris   SCIF_LOG_TRACE((
1196230557Sjimharris      sci_base_object_get_logger(fw_controller),
1197230557Sjimharris      SCIF_LOG_OBJECT_CONTROLLER,
1198230557Sjimharris      "scif_sas_controller_release_resource(0x%x) enter\n",
1199230557Sjimharris      fw_controller
1200230557Sjimharris   ));
1201230557Sjimharris
1202230557Sjimharris   //currently the only resource to be released is domain's timer.
1203230557Sjimharris   for (index = 0; index < SCI_MAX_DOMAINS; index++)
1204230557Sjimharris   {
1205230557Sjimharris      fw_domain = &fw_controller->domains[index];
1206230557Sjimharris
1207230557Sjimharris      scif_sas_domain_release_resource(fw_controller, fw_domain);
1208230557Sjimharris   }
1209230557Sjimharris
1210230557Sjimharris   return SCI_SUCCESS;
1211230557Sjimharris}
1212230557Sjimharris
1213230557Sjimharris
1214230557Sjimharris#ifdef SCI_LOGGING
1215230557Sjimharris/**
1216230557Sjimharris * This method will start state transition logging for the framework
1217230557Sjimharris * controller object.
1218230557Sjimharris *
1219230557Sjimharris * @param[in] fw_controller The framework controller object on which to
1220230557Sjimharris *       observe state changes.
1221230557Sjimharris *
1222230557Sjimharris * @return none
1223230557Sjimharris */
1224230557Sjimharrisvoid scif_sas_controller_initialize_state_logging(
1225230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller
1226230557Sjimharris)
1227230557Sjimharris{
1228230557Sjimharris   sci_base_state_machine_logger_initialize(
1229230557Sjimharris      &fw_controller->parent.state_machine_logger,
1230230557Sjimharris      &fw_controller->parent.state_machine,
1231230557Sjimharris      &fw_controller->parent.parent,
1232230557Sjimharris      scif_cb_logger_log_states,
1233230557Sjimharris      "SCIF_SAS_CONTROLLER_T", "base state machine",
1234230557Sjimharris      SCIF_LOG_OBJECT_CONTROLLER
1235230557Sjimharris   );
1236230557Sjimharris}
1237230557Sjimharris
1238230557Sjimharris/**
1239230557Sjimharris * This method will remove the logging of state transitions from the framework
1240230557Sjimharris * controller object.
1241230557Sjimharris *
1242230557Sjimharris * @param[in] fw_controller The framework controller to change.
1243230557Sjimharris *
1244230557Sjimharris * @return none
1245230557Sjimharris */
1246230557Sjimharrisvoid scif_sas_controller_deinitialize_state_logging(
1247230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller
1248230557Sjimharris)
1249230557Sjimharris{
1250230557Sjimharris   sci_base_state_machine_logger_deinitialize(
1251230557Sjimharris      &fw_controller->parent.state_machine_logger,
1252230557Sjimharris      &fw_controller->parent.state_machine
1253230557Sjimharris   );
1254230557Sjimharris}
1255230557Sjimharris#endif // SCI_LOGGING
1256