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 method implementations for the
60230557Sjimharris *        SCIF_SAS_SMP_IO_REQUEST object.  The contents will implement SMP
61230557Sjimharris *        specific functionality.
62230557Sjimharris */
63230557Sjimharris
64230557Sjimharris#include <dev/isci/scil/scif_sas_smp_io_request.h>
65230557Sjimharris#include <dev/isci/scil/scif_sas_logger.h>
66230557Sjimharris#include <dev/isci/scil/scif_sas_controller.h>
67230557Sjimharris#include <dev/isci/scil/sci_controller.h>
68230557Sjimharris
69230557Sjimharris#include <dev/isci/scil/sci_status.h>
70230557Sjimharris#include <dev/isci/scil/scic_io_request.h>
71230557Sjimharris#include <dev/isci/scil/scic_user_callback.h>
72230557Sjimharris
73230557Sjimharris#include <dev/isci/scil/intel_sas.h>
74230557Sjimharris
75230557Sjimharris/**
76230557Sjimharris * @brief This routine is to fill in the space given by core the SMP command
77230557Sjimharris *        frame. Then it calls core's construction.
78230557Sjimharris *
79230557Sjimharris * @param[in] fw_io The smp io request to be constructed.
80230557Sjimharris * @param[in] smp_command The SMP request filled according to SAS spec.
81230557Sjimharris *
82230557Sjimharris * @return none
83230557Sjimharris */
84230557Sjimharrisvoid scif_sas_smp_request_construct(
85230557Sjimharris   SCIF_SAS_REQUEST_T * fw_request,
86230557Sjimharris   SMP_REQUEST_T * smp_command
87230557Sjimharris)
88230557Sjimharris{
89230557Sjimharris   void * command_iu_address =
90230557Sjimharris      scic_io_request_get_command_iu_address(fw_request->core_object);
91230557Sjimharris
92230557Sjimharris   //copy the smp_command to the address;
93230557Sjimharris   memcpy( (char*) command_iu_address,
94230557Sjimharris           smp_command,
95230557Sjimharris           sizeof(SMP_REQUEST_T)
96230557Sjimharris          );
97230557Sjimharris
98230557Sjimharris   scic_io_request_construct_smp(fw_request->core_object);
99230557Sjimharris
100230557Sjimharris   fw_request->protocol_complete_handler
101230557Sjimharris      = NULL;
102230557Sjimharris}
103230557Sjimharris
104230557Sjimharris/**
105230557Sjimharris * @brief This method will perform all of the construction common to all
106230557Sjimharris *        SMP requests (e.g. filling in the frame type, zero-out memory,
107230557Sjimharris *        etc.).
108230557Sjimharris *
109230557Sjimharris * @param[out] smp_request This parameter specifies the SMP request
110230557Sjimharris *             structure containing the SMP request to be sent to the
111230557Sjimharris *             SMP target.
112230557Sjimharris * @param[in]  smp_function This parameter specifies the SMP function to
113230557Sjimharris *             sent.
114230557Sjimharris * @param[in]  smp_response_length This parameter specifies the length of
115230557Sjimharris *             the response (in DWORDs) that will be returned for this
116230557Sjimharris *             SMP request.
117230557Sjimharris * @param[in]  smp_request_length This parameter specifies the length of
118230557Sjimharris *             the request (in DWORDs) that will be sent.
119230557Sjimharris */
120230557Sjimharrisstatic
121230557Sjimharrisvoid scif_sas_smp_protocol_request_construct(
122230557Sjimharris   SMP_REQUEST_T * smp_request,
123230557Sjimharris   U8              smp_function,
124230557Sjimharris   U8              smp_response_length,
125230557Sjimharris   U8              smp_request_length
126230557Sjimharris)
127230557Sjimharris{
128230557Sjimharris   memset((char*)smp_request, 0, sizeof(SMP_REQUEST_T));
129230557Sjimharris
130230557Sjimharris   smp_request->header.smp_frame_type            = SMP_FRAME_TYPE_REQUEST;
131230557Sjimharris   smp_request->header.function                  = smp_function;
132230557Sjimharris   smp_request->header.allocated_response_length = smp_response_length;
133230557Sjimharris   smp_request->header.request_length            = smp_request_length;
134230557Sjimharris}
135230557Sjimharris
136230557Sjimharris
137230557Sjimharris/**
138230557Sjimharris * @brief This method will allocate the internal IO request object and
139230557Sjimharris *        construct its contents based upon the supplied SMP request.
140230557Sjimharris *
141230557Sjimharris * @param[in] fw_controller This parameter specifies the controller object
142230557Sjimharris *            from which to allocate the internal IO request.
143230557Sjimharris * @param[in] fw_device This parameter specifies the remote device for
144230557Sjimharris *            which the internal IO request is destined.
145230557Sjimharris * @param[in] smp_request This parameter specifies the SMP request contents
146230557Sjimharris *            to be sent to the SMP target.
147230557Sjimharris *
148230557Sjimharris * @return void * The address of built scif sas smp request.
149230557Sjimharris */
150230557Sjimharrisstatic
151230557Sjimharrisvoid * scif_sas_smp_request_build(
152230557Sjimharris   SCIF_SAS_CONTROLLER_T    * fw_controller,
153230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
154230557Sjimharris   SMP_REQUEST_T            * smp_request,
155230557Sjimharris   void                     * external_request_object,
156230557Sjimharris   void                     * external_memory
157230557Sjimharris)
158230557Sjimharris{
159230557Sjimharris   if (external_memory != NULL && external_request_object != NULL)
160230557Sjimharris   {
161230557Sjimharris      scif_sas_io_request_construct_smp(
162230557Sjimharris         fw_controller,
163230557Sjimharris         fw_device,
164230557Sjimharris         external_memory,
165230557Sjimharris         (char *)external_memory + sizeof(SCIF_SAS_IO_REQUEST_T),
166230557Sjimharris         SCI_CONTROLLER_INVALID_IO_TAG,
167230557Sjimharris         smp_request,
168230557Sjimharris         external_request_object
169230557Sjimharris      );
170230557Sjimharris
171230557Sjimharris      return external_memory;
172230557Sjimharris   }
173230557Sjimharris   else
174230557Sjimharris   {
175230557Sjimharris      void * internal_io_memory;
176230557Sjimharris      internal_io_memory = scif_sas_controller_allocate_internal_request(fw_controller);
177230557Sjimharris      ASSERT(internal_io_memory != NULL);
178230557Sjimharris
179230557Sjimharris      if (internal_io_memory != NULL)
180230557Sjimharris      {
181230557Sjimharris         //construct, only when we got valid io memory.
182230557Sjimharris         scif_sas_internal_io_request_construct_smp(
183230557Sjimharris            fw_controller,
184230557Sjimharris            fw_device,
185230557Sjimharris            internal_io_memory,
186230557Sjimharris            SCI_CONTROLLER_INVALID_IO_TAG,
187230557Sjimharris            smp_request
188230557Sjimharris         );
189230557Sjimharris      }
190230557Sjimharris      else
191230557Sjimharris      {
192230557Sjimharris         SCIF_LOG_ERROR((
193230557Sjimharris            sci_base_object_get_logger(fw_controller),
194230557Sjimharris            SCIF_LOG_OBJECT_IO_REQUEST,
195230557Sjimharris            "scif_sas_smp_request_build, no memory available!\n"
196230557Sjimharris         ));
197230557Sjimharris      }
198230557Sjimharris
199230557Sjimharris      return internal_io_memory;
200230557Sjimharris   }
201230557Sjimharris}
202230557Sjimharris
203230557Sjimharris/**
204230557Sjimharris * @brief construct a smp Report Genernal command to the fw_device.
205230557Sjimharris *
206230557Sjimharris * @param[in] fw_controller The framework controller object.
207230557Sjimharris * @param[in] fw_device the framework device that the REPORT GENERAL command
208230557Sjimharris *       targets to.
209230557Sjimharris *
210230557Sjimharris * @return void * address to the built scif sas smp request.
211230557Sjimharris */
212230557Sjimharrisvoid * scif_sas_smp_request_construct_report_general(
213230557Sjimharris   SCIF_SAS_CONTROLLER_T    * fw_controller,
214230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T * fw_device
215230557Sjimharris)
216230557Sjimharris{
217230557Sjimharris   SMP_REQUEST_T smp_report_general;
218230557Sjimharris
219230557Sjimharris   // Build the REPORT GENERAL request.
220230557Sjimharris   scif_sas_smp_protocol_request_construct(
221230557Sjimharris      &smp_report_general,
222230557Sjimharris      SMP_FUNCTION_REPORT_GENERAL,
223230557Sjimharris      sizeof(SMP_RESPONSE_REPORT_GENERAL_T) / sizeof(U32),
224230557Sjimharris      0
225230557Sjimharris   );
226230557Sjimharris
227230557Sjimharris   smp_report_general.request.report_general.crc = 0;
228230557Sjimharris
229230557Sjimharris   SCIF_LOG_INFO((
230230557Sjimharris      sci_base_object_get_logger(fw_device),
231230557Sjimharris      SCIF_LOG_OBJECT_IO_REQUEST | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
232230557Sjimharris      "SMP REPORT GENERAL -  Device:0x%x\n",
233230557Sjimharris      fw_device
234230557Sjimharris   ));
235230557Sjimharris
236230557Sjimharris   return scif_sas_smp_request_build(
237230557Sjimharris             fw_controller, fw_device, &smp_report_general, NULL, NULL);
238230557Sjimharris}
239230557Sjimharris
240230557Sjimharris/**
241230557Sjimharris * @brief construct a SMP Report Manufacturer Info request to the fw_device.
242230557Sjimharris *
243230557Sjimharris * @param[in] fw_controller The framework controller object.
244230557Sjimharris * @param[in] fw_device the framework device that the REPORT MANUFACTURER
245230557Sjimharris *            INFO targets to.
246230557Sjimharris *
247230557Sjimharris * @return void * address to the built scif sas smp request.
248230557Sjimharris */
249230557Sjimharrisvoid * scif_sas_smp_request_construct_report_manufacturer_info(
250230557Sjimharris   SCIF_SAS_CONTROLLER_T    * fw_controller,
251230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T * fw_device
252230557Sjimharris)
253230557Sjimharris{
254230557Sjimharris   SMP_REQUEST_T smp_report_manufacturer_info;
255230557Sjimharris
256230557Sjimharris   scif_sas_smp_protocol_request_construct(
257230557Sjimharris      &smp_report_manufacturer_info,
258230557Sjimharris      SMP_FUNCTION_REPORT_MANUFACTURER_INFORMATION,
259230557Sjimharris      sizeof(SMP_RESPONSE_REPORT_MANUFACTURER_INFORMATION_T) / sizeof(U32),
260230557Sjimharris      0
261230557Sjimharris   );
262230557Sjimharris
263230557Sjimharris   smp_report_manufacturer_info.request.report_general.crc = 0;
264230557Sjimharris
265230557Sjimharris   SCIF_LOG_INFO((
266230557Sjimharris      sci_base_object_get_logger(fw_device),
267230557Sjimharris      SCIF_LOG_OBJECT_IO_REQUEST | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
268230557Sjimharris      "SMP REPORT MANUFACTURER_INFO -  Device:0x%x\n",
269230557Sjimharris      fw_device
270230557Sjimharris   ));
271230557Sjimharris
272230557Sjimharris   return scif_sas_smp_request_build(
273230557Sjimharris             fw_controller, fw_device, &smp_report_manufacturer_info, NULL, NULL
274230557Sjimharris          );
275230557Sjimharris}
276230557Sjimharris
277230557Sjimharris/**
278230557Sjimharris * @brief construct a smp Discover command to the fw_device.
279230557Sjimharris * @param[in] fw_controller The framework controller object.
280230557Sjimharris * @param[in] fw_device the framework smp device that DISCOVER command targets
281230557Sjimharris *       to.
282230557Sjimharris * @param[in] phy_identifier The phy index the DISCOVER command targets to.
283230557Sjimharris *
284230557Sjimharris * @return void * address to the built scif sas smp request.
285230557Sjimharris */
286230557Sjimharrisvoid * scif_sas_smp_request_construct_discover(
287230557Sjimharris   SCIF_SAS_CONTROLLER_T    * fw_controller,
288230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
289230557Sjimharris   U8                         phy_identifier,
290230557Sjimharris   void                     * external_request_object,
291230557Sjimharris   void                     * external_memory
292230557Sjimharris)
293230557Sjimharris{
294230557Sjimharris   SMP_REQUEST_T smp_discover;
295230557Sjimharris
296230557Sjimharris   scif_sas_smp_protocol_request_construct(
297230557Sjimharris      &smp_discover,
298230557Sjimharris      SMP_FUNCTION_DISCOVER,
299230557Sjimharris      sizeof(SMP_RESPONSE_DISCOVER_T) / sizeof(U32),
300230557Sjimharris      sizeof(SMP_REQUEST_PHY_IDENTIFIER_T) / sizeof(U32)
301230557Sjimharris   );
302230557Sjimharris
303230557Sjimharris   smp_discover.request.discover.phy_identifier = phy_identifier;
304230557Sjimharris
305230557Sjimharris   SCIF_LOG_INFO((
306230557Sjimharris      sci_base_object_get_logger(fw_device),
307230557Sjimharris      SCIF_LOG_OBJECT_IO_REQUEST | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
308230557Sjimharris      "SMP DISCOVER - Device:0x%x PhyId:0x%x\n",
309230557Sjimharris      fw_device, phy_identifier
310230557Sjimharris   ));
311230557Sjimharris
312230557Sjimharris   return scif_sas_smp_request_build(
313230557Sjimharris             fw_controller, fw_device, &smp_discover,
314230557Sjimharris             external_request_object, external_memory
315230557Sjimharris          );
316230557Sjimharris}
317230557Sjimharris
318230557Sjimharris
319230557Sjimharris/**
320230557Sjimharris * @brief construct a smp REPORT PHY SATA command to the fw_device.
321230557Sjimharris * @param[in] fw_controller The framework controller object.
322230557Sjimharris * @param[in] fw_device the framework smp device that DISCOVER command targets
323230557Sjimharris *       to.
324230557Sjimharris * @param[in] phy_identifier The phy index the DISCOVER command targets to.
325230557Sjimharris *
326230557Sjimharris * @return void * address to the built scif sas smp request.
327230557Sjimharris */
328230557Sjimharrisvoid * scif_sas_smp_request_construct_report_phy_sata(
329230557Sjimharris   SCIF_SAS_CONTROLLER_T    * fw_controller,
330230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
331230557Sjimharris   U8                         phy_identifier
332230557Sjimharris)
333230557Sjimharris{
334230557Sjimharris   SMP_REQUEST_T report_phy_sata;
335230557Sjimharris
336230557Sjimharris   scif_sas_smp_protocol_request_construct(
337230557Sjimharris      &report_phy_sata,
338230557Sjimharris      SMP_FUNCTION_REPORT_PHY_SATA,
339230557Sjimharris      sizeof(SMP_RESPONSE_REPORT_PHY_SATA_T) / sizeof(U32),
340230557Sjimharris      sizeof(SMP_REQUEST_PHY_IDENTIFIER_T) / sizeof(U32)
341230557Sjimharris   );
342230557Sjimharris
343230557Sjimharris   report_phy_sata.request.report_phy_sata.phy_identifier = phy_identifier;
344230557Sjimharris
345230557Sjimharris   SCIF_LOG_INFO((
346230557Sjimharris      sci_base_object_get_logger(fw_device),
347230557Sjimharris      SCIF_LOG_OBJECT_IO_REQUEST | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
348230557Sjimharris      "SMP REPORT PHY SATA - Device:0x%x PhyId:0x%x\n",
349230557Sjimharris      fw_device, phy_identifier
350230557Sjimharris   ));
351230557Sjimharris
352230557Sjimharris   return scif_sas_smp_request_build(
353230557Sjimharris             fw_controller, fw_device, &report_phy_sata, NULL, NULL);
354230557Sjimharris}
355230557Sjimharris
356230557Sjimharris
357230557Sjimharris/**
358230557Sjimharris * @brief construct a smp REPORT PHY SATA command to the fw_device.
359230557Sjimharris * @param[in] fw_controller The framework controller object.
360230557Sjimharris * @param[in] fw_device the framework smp device that PHY CONTROL command
361230557Sjimharris *       targets to.
362230557Sjimharris * @param[in] phy_identifier The phy index the DISCOVER command targets to.
363230557Sjimharris *
364230557Sjimharris * @return void * address to the built scif sas smp request.
365230557Sjimharris */
366230557Sjimharrisvoid * scif_sas_smp_request_construct_phy_control(
367230557Sjimharris   SCIF_SAS_CONTROLLER_T    * fw_controller,
368230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
369230557Sjimharris   U8                         phy_operation,
370230557Sjimharris   U8                         phy_identifier,
371230557Sjimharris   void                     * external_request_object,
372230557Sjimharris   void                     * external_memory
373230557Sjimharris)
374230557Sjimharris{
375230557Sjimharris   SMP_REQUEST_T phy_control;
376230557Sjimharris
377230557Sjimharris   scif_sas_smp_protocol_request_construct(
378230557Sjimharris      &phy_control,
379230557Sjimharris      SMP_FUNCTION_PHY_CONTROL,
380230557Sjimharris      0,
381230557Sjimharris      sizeof(SMP_REQUEST_PHY_CONTROL_T) / sizeof(U32)
382230557Sjimharris   );
383230557Sjimharris
384230557Sjimharris   phy_control.request.phy_control.phy_operation = phy_operation;
385230557Sjimharris   phy_control.request.phy_control.phy_identifier = phy_identifier;
386230557Sjimharris
387230557Sjimharris   return scif_sas_smp_request_build(
388230557Sjimharris             fw_controller, fw_device, &phy_control,
389230557Sjimharris             external_request_object, external_memory
390230557Sjimharris          );
391230557Sjimharris}
392230557Sjimharris
393230557Sjimharris
394230557Sjimharris/**
395230557Sjimharris * @brief construct a smp CONFIG ROUTE INFO command to the fw_device.
396230557Sjimharris *
397230557Sjimharris * @param[in] fw_controller The framework controller object.
398230557Sjimharris * @param[in] fw_device the framework smp device that PHY CONTROL command
399230557Sjimharris *       targets to.
400230557Sjimharris * @param[in] phy_id The phy, whose route entry at route_index is to be configured.
401230557Sjimharris * @param[in] route_index The index of a phy's route entry that is to be configured.
402230557Sjimharris * @param[in] destination_sas_address A sas address for an route table entry
403230557Sjimharris *
404230557Sjimharris * @return void * address to the built scif sas smp request.
405230557Sjimharris */
406230557Sjimharrisvoid * scif_sas_smp_request_construct_config_route_info(
407230557Sjimharris   struct SCIF_SAS_CONTROLLER    * fw_controller,
408230557Sjimharris   struct SCIF_SAS_REMOTE_DEVICE * fw_device,
409230557Sjimharris   U8                              phy_id,
410230557Sjimharris   U16                             route_index,
411230557Sjimharris   SCI_SAS_ADDRESS_T               destination_sas_address,
412230557Sjimharris   BOOL                            disable_expander_route_entry
413230557Sjimharris)
414230557Sjimharris{
415230557Sjimharris   SMP_REQUEST_T config_route_info;
416230557Sjimharris
417230557Sjimharris   scif_sas_smp_protocol_request_construct(
418230557Sjimharris      &config_route_info,
419230557Sjimharris      SMP_FUNCTION_CONFIGURE_ROUTE_INFORMATION,
420230557Sjimharris      0,
421230557Sjimharris      sizeof(SMP_REQUEST_CONFIGURE_ROUTE_INFORMATION_T) / sizeof(U32)
422230557Sjimharris   );
423230557Sjimharris
424230557Sjimharris   config_route_info.request.configure_route_information.phy_identifier = phy_id;
425230557Sjimharris   config_route_info.request.configure_route_information.expander_route_index_high =
426230557Sjimharris      ((route_index & 0xff00) >> 8);
427230557Sjimharris   config_route_info.request.configure_route_information.expander_route_index =
428230557Sjimharris      route_index & 0xff;
429230557Sjimharris   config_route_info.request.configure_route_information.routed_sas_address[0] =
430230557Sjimharris      destination_sas_address.high;
431230557Sjimharris   config_route_info.request.configure_route_information.routed_sas_address[1] =
432230557Sjimharris      destination_sas_address.low;
433230557Sjimharris
434230557Sjimharris   if (disable_expander_route_entry == TRUE)
435230557Sjimharris      config_route_info.request.configure_route_information.disable_route_entry = 1;
436230557Sjimharris
437230557Sjimharris   return scif_sas_smp_request_build(
438230557Sjimharris             fw_controller, fw_device, &config_route_info,
439230557Sjimharris             NULL, NULL
440230557Sjimharris          );
441230557Sjimharris}
442230557Sjimharris
443230557Sjimharris/**
444230557Sjimharris * @brief This method retry the internal smp request.
445230557Sjimharris *
446230557Sjimharris * @param[in] fw_device This parameter specifies the remote device for
447230557Sjimharris *            which the internal IO request is destined.
448230557Sjimharris * @param[in] retry_count This parameter specifies how many times the
449230557Sjimharris *            old smp request has been retried.
450230557Sjimharris *
451230557Sjimharris * @return none.
452230557Sjimharris */
453230557SjimharrisSCI_STATUS scif_sas_smp_internal_request_retry(
454230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T * fw_device
455230557Sjimharris)
456230557Sjimharris{
457230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller;
458230557Sjimharris   SCIF_SAS_IO_REQUEST_T * new_io;
459230557Sjimharris   void                  * new_request_memory = NULL;
460230557Sjimharris   U8 retry_count = fw_device->protocol_device.smp_device.io_retry_count;
461230557Sjimharris
462230557Sjimharris   SCIF_LOG_TRACE((
463230557Sjimharris      sci_base_object_get_logger(fw_device),
464230557Sjimharris      SCIF_LOG_OBJECT_IO_REQUEST | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
465230557Sjimharris      "scif_sas_smp_internal_request_retry(0x%x, 0x%x) time %d!\n",
466230557Sjimharris      fw_device, retry_count
467230557Sjimharris   ));
468230557Sjimharris
469230557Sjimharris   fw_controller = fw_device->domain->controller;
470230557Sjimharris
471230557Sjimharris   switch (fw_device->protocol_device.smp_device.current_smp_request)
472230557Sjimharris   {
473230557Sjimharris      case SMP_FUNCTION_REPORT_GENERAL:
474230557Sjimharris         new_request_memory = scif_sas_smp_request_construct_report_general(
475230557Sjimharris            fw_controller, fw_device
476230557Sjimharris         );
477230557Sjimharris         break;
478230557Sjimharris
479230557Sjimharris      case SMP_FUNCTION_DISCOVER:
480230557Sjimharris         //We are retrying an internal io. So we are going to allocate
481230557Sjimharris         //a new memory from internal io memory pool.
482230557Sjimharris         new_request_memory = scif_sas_smp_request_construct_discover(
483230557Sjimharris            fw_controller, fw_device,
484230557Sjimharris            fw_device->protocol_device.smp_device.current_activity_phy_index,
485230557Sjimharris            NULL, NULL
486230557Sjimharris         );
487230557Sjimharris
488230557Sjimharris         break;
489230557Sjimharris
490230557Sjimharris      case SMP_FUNCTION_REPORT_PHY_SATA:
491230557Sjimharris         new_request_memory = scif_sas_smp_request_construct_report_phy_sata(
492230557Sjimharris            fw_controller, fw_device,
493230557Sjimharris            fw_device->protocol_device.smp_device.current_activity_phy_index
494230557Sjimharris         );
495230557Sjimharris         break;
496230557Sjimharris
497230557Sjimharris      default:
498230557Sjimharris         //unsupported case, TBD
499230557Sjimharris         break;
500230557Sjimharris   } //end of switch
501230557Sjimharris
502230557Sjimharris   if (new_request_memory != NULL)
503230557Sjimharris   {
504230557Sjimharris      //set the retry count to new built smp request.
505230557Sjimharris      new_io = (SCIF_SAS_IO_REQUEST_T *) new_request_memory;
506230557Sjimharris      new_io->retry_count = ++retry_count;
507230557Sjimharris
508230557Sjimharris      //need to schedule the DPC here.
509230557Sjimharris      scif_cb_start_internal_io_task_schedule(
510230557Sjimharris            fw_controller,
511230557Sjimharris            scif_sas_controller_start_high_priority_io,
512230557Sjimharris            fw_controller
513230557Sjimharris         );
514230557Sjimharris
515230557Sjimharris      return SCI_SUCCESS;
516230557Sjimharris   }
517230557Sjimharris   else
518230557Sjimharris      return SCI_FAILURE_INSUFFICIENT_RESOURCES;
519230557Sjimharris
520230557Sjimharris}
521230557Sjimharris
522230557Sjimharris/**
523230557Sjimharris * @brief This method retry the external smp request.
524230557Sjimharris *
525230557Sjimharris * @param[in] fw_device This parameter specifies the remote device for
526230557Sjimharris *            which the internal IO request is destined.
527230557Sjimharris * @param[in] old_internal_io This parameter specifies the old smp request to be
528230557Sjimharris *            retried.
529230557Sjimharris *
530230557Sjimharris * @return none.
531230557Sjimharris */
532230557SjimharrisSCI_STATUS scif_sas_smp_external_request_retry(
533230557Sjimharris   SCIF_SAS_IO_REQUEST_T    * old_io
534230557Sjimharris)
535230557Sjimharris{
536230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T * fw_device = old_io->parent.device;
537230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller;
538230557Sjimharris   SCIF_SAS_IO_REQUEST_T * new_io;
539230557Sjimharris   void                  * new_request_memory = NULL;
540230557Sjimharris   U8                      retry_count = old_io->retry_count;
541230557Sjimharris
542230557Sjimharris   SCIF_LOG_TRACE((
543230557Sjimharris      sci_base_object_get_logger(fw_device),
544230557Sjimharris      SCIF_LOG_OBJECT_IO_REQUEST | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
545230557Sjimharris      "scif_sas_smp_external_request_retry(0x%x) time %d!\n",
546230557Sjimharris      old_io
547230557Sjimharris   ));
548230557Sjimharris
549230557Sjimharris   fw_controller = fw_device->domain->controller;
550230557Sjimharris
551230557Sjimharris   // Before we construct new io using the same memory, we need to
552230557Sjimharris   // remove the IO from the list of outstanding requests on the domain
553230557Sjimharris   // so that we don't damage the domain's fast list of request.
554230557Sjimharris   sci_fast_list_remove_element(&old_io->parent.list_element);
555230557Sjimharris
556230557Sjimharris   switch (fw_device->protocol_device.smp_device.current_smp_request)
557230557Sjimharris   {
558230557Sjimharris      case SMP_FUNCTION_DISCOVER:
559230557Sjimharris         //we are retrying an external io, we are going to reuse the
560230557Sjimharris         //old io's memory. new_request_memory is same as old_io.
561230557Sjimharris         new_request_memory = scif_sas_smp_request_construct_discover(
562230557Sjimharris            fw_controller, fw_device,
563230557Sjimharris            fw_device->protocol_device.smp_device.current_activity_phy_index,
564230557Sjimharris            (void *)sci_object_get_association(old_io),
565230557Sjimharris            (void *)old_io
566230557Sjimharris         );
567230557Sjimharris
568230557Sjimharris         break;
569230557Sjimharris
570230557Sjimharris      case SMP_FUNCTION_PHY_CONTROL:
571230557Sjimharris         //Phy Control command always uses external io memory.
572230557Sjimharris         new_request_memory = scif_sas_smp_request_construct_phy_control(
573230557Sjimharris            fw_controller, fw_device, PHY_OPERATION_HARD_RESET,
574230557Sjimharris            fw_device->protocol_device.smp_device.current_activity_phy_index,
575230557Sjimharris            (void *)sci_object_get_association(old_io),
576230557Sjimharris            (void *)old_io
577230557Sjimharris         );
578230557Sjimharris
579230557Sjimharris         break;
580230557Sjimharris
581230557Sjimharris      default:
582230557Sjimharris         //unsupported case, TBD
583231137Sjimharris         return SCI_FAILURE;
584230557Sjimharris   } //end of switch
585230557Sjimharris
586230557Sjimharris   //set the retry count to new built smp request.
587230557Sjimharris   new_io = (SCIF_SAS_IO_REQUEST_T *) new_request_memory;
588230557Sjimharris   new_io->retry_count = ++retry_count;
589230557Sjimharris
590230557Sjimharris   //put into the high priority queue.
591230557Sjimharris   sci_pool_put(fw_controller->hprq.pool, (POINTER_UINT) new_request_memory);
592230557Sjimharris
593230557Sjimharris   //schedule the DPC to start new io.
594230557Sjimharris   scif_cb_start_internal_io_task_schedule(
595230557Sjimharris      fw_controller, scif_sas_controller_start_high_priority_io, fw_controller
596230557Sjimharris   );
597230557Sjimharris
598230557Sjimharris   return SCI_SUCCESS;
599230557Sjimharris}
600230557Sjimharris
601