xref: /freebsd/sys/dev/isci/scil/scif_sas_smp_io_request.c (revision 685dc743dc3b5645e34836464128e1c0558b404b)
1f11c7f63SJim Harris /*-
2*718cf2ccSPedro F. Giffuni  * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0
3*718cf2ccSPedro F. Giffuni  *
4f11c7f63SJim Harris  * This file is provided under a dual BSD/GPLv2 license.  When using or
5f11c7f63SJim Harris  * redistributing this file, you may do so under either license.
6f11c7f63SJim Harris  *
7f11c7f63SJim Harris  * GPL LICENSE SUMMARY
8f11c7f63SJim Harris  *
9f11c7f63SJim Harris  * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
10f11c7f63SJim Harris  *
11f11c7f63SJim Harris  * This program is free software; you can redistribute it and/or modify
12f11c7f63SJim Harris  * it under the terms of version 2 of the GNU General Public License as
13f11c7f63SJim Harris  * published by the Free Software Foundation.
14f11c7f63SJim Harris  *
15f11c7f63SJim Harris  * This program is distributed in the hope that it will be useful, but
16f11c7f63SJim Harris  * WITHOUT ANY WARRANTY; without even the implied warranty of
17f11c7f63SJim Harris  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18f11c7f63SJim Harris  * General Public License for more details.
19f11c7f63SJim Harris  *
20f11c7f63SJim Harris  * You should have received a copy of the GNU General Public License
21f11c7f63SJim Harris  * along with this program; if not, write to the Free Software
22f11c7f63SJim Harris  * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
23f11c7f63SJim Harris  * The full GNU General Public License is included in this distribution
24f11c7f63SJim Harris  * in the file called LICENSE.GPL.
25f11c7f63SJim Harris  *
26f11c7f63SJim Harris  * BSD LICENSE
27f11c7f63SJim Harris  *
28f11c7f63SJim Harris  * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
29f11c7f63SJim Harris  * All rights reserved.
30f11c7f63SJim Harris  *
31f11c7f63SJim Harris  * Redistribution and use in source and binary forms, with or without
32f11c7f63SJim Harris  * modification, are permitted provided that the following conditions
33f11c7f63SJim Harris  * are met:
34f11c7f63SJim Harris  *
35f11c7f63SJim Harris  *   * Redistributions of source code must retain the above copyright
36f11c7f63SJim Harris  *     notice, this list of conditions and the following disclaimer.
37f11c7f63SJim Harris  *   * Redistributions in binary form must reproduce the above copyright
38f11c7f63SJim Harris  *     notice, this list of conditions and the following disclaimer in
39f11c7f63SJim Harris  *     the documentation and/or other materials provided with the
40f11c7f63SJim Harris  *     distribution.
41f11c7f63SJim Harris  *
42f11c7f63SJim Harris  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
43f11c7f63SJim Harris  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
44f11c7f63SJim Harris  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
45f11c7f63SJim Harris  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
46f11c7f63SJim Harris  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
47f11c7f63SJim Harris  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
48f11c7f63SJim Harris  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
49f11c7f63SJim Harris  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
50f11c7f63SJim Harris  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
51f11c7f63SJim Harris  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
52f11c7f63SJim Harris  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53f11c7f63SJim Harris  */
54f11c7f63SJim Harris 
55f11c7f63SJim Harris #include <sys/cdefs.h>
56f11c7f63SJim Harris /**
57f11c7f63SJim Harris  * @file
58f11c7f63SJim Harris  *
59f11c7f63SJim Harris  * @brief This file contains the method implementations for the
60f11c7f63SJim Harris  *        SCIF_SAS_SMP_IO_REQUEST object.  The contents will implement SMP
61f11c7f63SJim Harris  *        specific functionality.
62f11c7f63SJim Harris  */
63f11c7f63SJim Harris 
64f11c7f63SJim Harris #include <dev/isci/scil/scif_sas_smp_io_request.h>
65f11c7f63SJim Harris #include <dev/isci/scil/scif_sas_logger.h>
66f11c7f63SJim Harris #include <dev/isci/scil/scif_sas_controller.h>
67f11c7f63SJim Harris #include <dev/isci/scil/sci_controller.h>
68f11c7f63SJim Harris 
69f11c7f63SJim Harris #include <dev/isci/scil/sci_status.h>
70f11c7f63SJim Harris #include <dev/isci/scil/scic_io_request.h>
71f11c7f63SJim Harris #include <dev/isci/scil/scic_user_callback.h>
72f11c7f63SJim Harris 
73f11c7f63SJim Harris #include <dev/isci/scil/intel_sas.h>
74f11c7f63SJim Harris 
75f11c7f63SJim Harris /**
76f11c7f63SJim Harris  * @brief This routine is to fill in the space given by core the SMP command
77f11c7f63SJim Harris  *        frame. Then it calls core's construction.
78f11c7f63SJim Harris  *
79f11c7f63SJim Harris  * @param[in] fw_io The smp io request to be constructed.
80f11c7f63SJim Harris  * @param[in] smp_command The SMP request filled according to SAS spec.
81f11c7f63SJim Harris  *
82f11c7f63SJim Harris  * @return none
83f11c7f63SJim Harris  */
scif_sas_smp_request_construct(SCIF_SAS_REQUEST_T * fw_request,SMP_REQUEST_T * smp_command)84f11c7f63SJim Harris void scif_sas_smp_request_construct(
85f11c7f63SJim Harris    SCIF_SAS_REQUEST_T * fw_request,
86f11c7f63SJim Harris    SMP_REQUEST_T * smp_command
87f11c7f63SJim Harris )
88f11c7f63SJim Harris {
89f11c7f63SJim Harris    void * command_iu_address =
90f11c7f63SJim Harris       scic_io_request_get_command_iu_address(fw_request->core_object);
91f11c7f63SJim Harris 
92f11c7f63SJim Harris    //copy the smp_command to the address;
93f11c7f63SJim Harris    memcpy( (char*) command_iu_address,
94f11c7f63SJim Harris            smp_command,
95f11c7f63SJim Harris            sizeof(SMP_REQUEST_T)
96f11c7f63SJim Harris           );
97f11c7f63SJim Harris 
98f11c7f63SJim Harris    scic_io_request_construct_smp(fw_request->core_object);
99f11c7f63SJim Harris 
100f11c7f63SJim Harris    fw_request->protocol_complete_handler
101f11c7f63SJim Harris       = NULL;
102f11c7f63SJim Harris }
103f11c7f63SJim Harris 
104f11c7f63SJim Harris /**
105f11c7f63SJim Harris  * @brief This method will perform all of the construction common to all
106f11c7f63SJim Harris  *        SMP requests (e.g. filling in the frame type, zero-out memory,
107f11c7f63SJim Harris  *        etc.).
108f11c7f63SJim Harris  *
109f11c7f63SJim Harris  * @param[out] smp_request This parameter specifies the SMP request
110f11c7f63SJim Harris  *             structure containing the SMP request to be sent to the
111f11c7f63SJim Harris  *             SMP target.
112f11c7f63SJim Harris  * @param[in]  smp_function This parameter specifies the SMP function to
113f11c7f63SJim Harris  *             sent.
114f11c7f63SJim Harris  * @param[in]  smp_response_length This parameter specifies the length of
115f11c7f63SJim Harris  *             the response (in DWORDs) that will be returned for this
116f11c7f63SJim Harris  *             SMP request.
117f11c7f63SJim Harris  * @param[in]  smp_request_length This parameter specifies the length of
118f11c7f63SJim Harris  *             the request (in DWORDs) that will be sent.
119f11c7f63SJim Harris  */
120f11c7f63SJim Harris static
scif_sas_smp_protocol_request_construct(SMP_REQUEST_T * smp_request,U8 smp_function,U8 smp_response_length,U8 smp_request_length)121f11c7f63SJim Harris void scif_sas_smp_protocol_request_construct(
122f11c7f63SJim Harris    SMP_REQUEST_T * smp_request,
123f11c7f63SJim Harris    U8              smp_function,
124f11c7f63SJim Harris    U8              smp_response_length,
125f11c7f63SJim Harris    U8              smp_request_length
126f11c7f63SJim Harris )
127f11c7f63SJim Harris {
128f11c7f63SJim Harris    memset((char*)smp_request, 0, sizeof(SMP_REQUEST_T));
129f11c7f63SJim Harris 
130f11c7f63SJim Harris    smp_request->header.smp_frame_type            = SMP_FRAME_TYPE_REQUEST;
131f11c7f63SJim Harris    smp_request->header.function                  = smp_function;
132f11c7f63SJim Harris    smp_request->header.allocated_response_length = smp_response_length;
133f11c7f63SJim Harris    smp_request->header.request_length            = smp_request_length;
134f11c7f63SJim Harris }
135f11c7f63SJim Harris 
136f11c7f63SJim Harris 
137f11c7f63SJim Harris /**
138f11c7f63SJim Harris  * @brief This method will allocate the internal IO request object and
139f11c7f63SJim Harris  *        construct its contents based upon the supplied SMP request.
140f11c7f63SJim Harris  *
141f11c7f63SJim Harris  * @param[in] fw_controller This parameter specifies the controller object
142f11c7f63SJim Harris  *            from which to allocate the internal IO request.
143f11c7f63SJim Harris  * @param[in] fw_device This parameter specifies the remote device for
144f11c7f63SJim Harris  *            which the internal IO request is destined.
145f11c7f63SJim Harris  * @param[in] smp_request This parameter specifies the SMP request contents
146f11c7f63SJim Harris  *            to be sent to the SMP target.
147f11c7f63SJim Harris  *
148f11c7f63SJim Harris  * @return void * The address of built scif sas smp request.
149f11c7f63SJim Harris  */
150f11c7f63SJim Harris static
scif_sas_smp_request_build(SCIF_SAS_CONTROLLER_T * fw_controller,SCIF_SAS_REMOTE_DEVICE_T * fw_device,SMP_REQUEST_T * smp_request,void * external_request_object,void * external_memory)151f11c7f63SJim Harris void * scif_sas_smp_request_build(
152f11c7f63SJim Harris    SCIF_SAS_CONTROLLER_T    * fw_controller,
153f11c7f63SJim Harris    SCIF_SAS_REMOTE_DEVICE_T * fw_device,
154f11c7f63SJim Harris    SMP_REQUEST_T            * smp_request,
155f11c7f63SJim Harris    void                     * external_request_object,
156f11c7f63SJim Harris    void                     * external_memory
157f11c7f63SJim Harris )
158f11c7f63SJim Harris {
159f11c7f63SJim Harris    if (external_memory != NULL && external_request_object != NULL)
160f11c7f63SJim Harris    {
161f11c7f63SJim Harris       scif_sas_io_request_construct_smp(
162f11c7f63SJim Harris          fw_controller,
163f11c7f63SJim Harris          fw_device,
164f11c7f63SJim Harris          external_memory,
165f11c7f63SJim Harris          (char *)external_memory + sizeof(SCIF_SAS_IO_REQUEST_T),
166f11c7f63SJim Harris          SCI_CONTROLLER_INVALID_IO_TAG,
167f11c7f63SJim Harris          smp_request,
168f11c7f63SJim Harris          external_request_object
169f11c7f63SJim Harris       );
170f11c7f63SJim Harris 
171f11c7f63SJim Harris       return external_memory;
172f11c7f63SJim Harris    }
173f11c7f63SJim Harris    else
174f11c7f63SJim Harris    {
175f11c7f63SJim Harris       void * internal_io_memory;
176f11c7f63SJim Harris       internal_io_memory = scif_sas_controller_allocate_internal_request(fw_controller);
177f11c7f63SJim Harris       ASSERT(internal_io_memory != NULL);
178f11c7f63SJim Harris 
179f11c7f63SJim Harris       if (internal_io_memory != NULL)
180f11c7f63SJim Harris       {
181f11c7f63SJim Harris          //construct, only when we got valid io memory.
182f11c7f63SJim Harris          scif_sas_internal_io_request_construct_smp(
183f11c7f63SJim Harris             fw_controller,
184f11c7f63SJim Harris             fw_device,
185f11c7f63SJim Harris             internal_io_memory,
186f11c7f63SJim Harris             SCI_CONTROLLER_INVALID_IO_TAG,
187f11c7f63SJim Harris             smp_request
188f11c7f63SJim Harris          );
189f11c7f63SJim Harris       }
190f11c7f63SJim Harris       else
191f11c7f63SJim Harris       {
192f11c7f63SJim Harris          SCIF_LOG_ERROR((
193f11c7f63SJim Harris             sci_base_object_get_logger(fw_controller),
194f11c7f63SJim Harris             SCIF_LOG_OBJECT_IO_REQUEST,
195f11c7f63SJim Harris             "scif_sas_smp_request_build, no memory available!\n"
196f11c7f63SJim Harris          ));
197f11c7f63SJim Harris       }
198f11c7f63SJim Harris 
199f11c7f63SJim Harris       return internal_io_memory;
200f11c7f63SJim Harris    }
201f11c7f63SJim Harris }
202f11c7f63SJim Harris 
203f11c7f63SJim Harris /**
204f11c7f63SJim Harris  * @brief construct a smp Report Genernal command to the fw_device.
205f11c7f63SJim Harris  *
206f11c7f63SJim Harris  * @param[in] fw_controller The framework controller object.
207f11c7f63SJim Harris  * @param[in] fw_device the framework device that the REPORT GENERAL command
208f11c7f63SJim Harris  *       targets to.
209f11c7f63SJim Harris  *
210f11c7f63SJim Harris  * @return void * address to the built scif sas smp request.
211f11c7f63SJim Harris  */
scif_sas_smp_request_construct_report_general(SCIF_SAS_CONTROLLER_T * fw_controller,SCIF_SAS_REMOTE_DEVICE_T * fw_device)212f11c7f63SJim Harris void * scif_sas_smp_request_construct_report_general(
213f11c7f63SJim Harris    SCIF_SAS_CONTROLLER_T    * fw_controller,
214f11c7f63SJim Harris    SCIF_SAS_REMOTE_DEVICE_T * fw_device
215f11c7f63SJim Harris )
216f11c7f63SJim Harris {
217f11c7f63SJim Harris    SMP_REQUEST_T smp_report_general;
218f11c7f63SJim Harris 
219f11c7f63SJim Harris    // Build the REPORT GENERAL request.
220f11c7f63SJim Harris    scif_sas_smp_protocol_request_construct(
221f11c7f63SJim Harris       &smp_report_general,
222f11c7f63SJim Harris       SMP_FUNCTION_REPORT_GENERAL,
223f11c7f63SJim Harris       sizeof(SMP_RESPONSE_REPORT_GENERAL_T) / sizeof(U32),
224f11c7f63SJim Harris       0
225f11c7f63SJim Harris    );
226f11c7f63SJim Harris 
227f11c7f63SJim Harris    smp_report_general.request.report_general.crc = 0;
228f11c7f63SJim Harris 
229f11c7f63SJim Harris    SCIF_LOG_INFO((
230f11c7f63SJim Harris       sci_base_object_get_logger(fw_device),
231f11c7f63SJim Harris       SCIF_LOG_OBJECT_IO_REQUEST | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
232f11c7f63SJim Harris       "SMP REPORT GENERAL -  Device:0x%x\n",
233f11c7f63SJim Harris       fw_device
234f11c7f63SJim Harris    ));
235f11c7f63SJim Harris 
236f11c7f63SJim Harris    return scif_sas_smp_request_build(
237f11c7f63SJim Harris              fw_controller, fw_device, &smp_report_general, NULL, NULL);
238f11c7f63SJim Harris }
239f11c7f63SJim Harris 
240f11c7f63SJim Harris /**
241f11c7f63SJim Harris  * @brief construct a SMP Report Manufacturer Info request to the fw_device.
242f11c7f63SJim Harris  *
243f11c7f63SJim Harris  * @param[in] fw_controller The framework controller object.
244f11c7f63SJim Harris  * @param[in] fw_device the framework device that the REPORT MANUFACTURER
245f11c7f63SJim Harris  *            INFO targets to.
246f11c7f63SJim Harris  *
247f11c7f63SJim Harris  * @return void * address to the built scif sas smp request.
248f11c7f63SJim Harris  */
scif_sas_smp_request_construct_report_manufacturer_info(SCIF_SAS_CONTROLLER_T * fw_controller,SCIF_SAS_REMOTE_DEVICE_T * fw_device)249f11c7f63SJim Harris void * scif_sas_smp_request_construct_report_manufacturer_info(
250f11c7f63SJim Harris    SCIF_SAS_CONTROLLER_T    * fw_controller,
251f11c7f63SJim Harris    SCIF_SAS_REMOTE_DEVICE_T * fw_device
252f11c7f63SJim Harris )
253f11c7f63SJim Harris {
254f11c7f63SJim Harris    SMP_REQUEST_T smp_report_manufacturer_info;
255f11c7f63SJim Harris 
256f11c7f63SJim Harris    scif_sas_smp_protocol_request_construct(
257f11c7f63SJim Harris       &smp_report_manufacturer_info,
258f11c7f63SJim Harris       SMP_FUNCTION_REPORT_MANUFACTURER_INFORMATION,
259f11c7f63SJim Harris       sizeof(SMP_RESPONSE_REPORT_MANUFACTURER_INFORMATION_T) / sizeof(U32),
260f11c7f63SJim Harris       0
261f11c7f63SJim Harris    );
262f11c7f63SJim Harris 
263f11c7f63SJim Harris    smp_report_manufacturer_info.request.report_general.crc = 0;
264f11c7f63SJim Harris 
265f11c7f63SJim Harris    SCIF_LOG_INFO((
266f11c7f63SJim Harris       sci_base_object_get_logger(fw_device),
267f11c7f63SJim Harris       SCIF_LOG_OBJECT_IO_REQUEST | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
268f11c7f63SJim Harris       "SMP REPORT MANUFACTURER_INFO -  Device:0x%x\n",
269f11c7f63SJim Harris       fw_device
270f11c7f63SJim Harris    ));
271f11c7f63SJim Harris 
272f11c7f63SJim Harris    return scif_sas_smp_request_build(
273f11c7f63SJim Harris              fw_controller, fw_device, &smp_report_manufacturer_info, NULL, NULL
274f11c7f63SJim Harris           );
275f11c7f63SJim Harris }
276f11c7f63SJim Harris 
277f11c7f63SJim Harris /**
278f11c7f63SJim Harris  * @brief construct a smp Discover command to the fw_device.
279f11c7f63SJim Harris  * @param[in] fw_controller The framework controller object.
280f11c7f63SJim Harris  * @param[in] fw_device the framework smp device that DISCOVER command targets
281f11c7f63SJim Harris  *       to.
282f11c7f63SJim Harris  * @param[in] phy_identifier The phy index the DISCOVER command targets to.
283f11c7f63SJim Harris  *
284f11c7f63SJim Harris  * @return void * address to the built scif sas smp request.
285f11c7f63SJim Harris  */
scif_sas_smp_request_construct_discover(SCIF_SAS_CONTROLLER_T * fw_controller,SCIF_SAS_REMOTE_DEVICE_T * fw_device,U8 phy_identifier,void * external_request_object,void * external_memory)286f11c7f63SJim Harris void * scif_sas_smp_request_construct_discover(
287f11c7f63SJim Harris    SCIF_SAS_CONTROLLER_T    * fw_controller,
288f11c7f63SJim Harris    SCIF_SAS_REMOTE_DEVICE_T * fw_device,
289f11c7f63SJim Harris    U8                         phy_identifier,
290f11c7f63SJim Harris    void                     * external_request_object,
291f11c7f63SJim Harris    void                     * external_memory
292f11c7f63SJim Harris )
293f11c7f63SJim Harris {
294f11c7f63SJim Harris    SMP_REQUEST_T smp_discover;
295f11c7f63SJim Harris 
296f11c7f63SJim Harris    scif_sas_smp_protocol_request_construct(
297f11c7f63SJim Harris       &smp_discover,
298f11c7f63SJim Harris       SMP_FUNCTION_DISCOVER,
299f11c7f63SJim Harris       sizeof(SMP_RESPONSE_DISCOVER_T) / sizeof(U32),
300f11c7f63SJim Harris       sizeof(SMP_REQUEST_PHY_IDENTIFIER_T) / sizeof(U32)
301f11c7f63SJim Harris    );
302f11c7f63SJim Harris 
303f11c7f63SJim Harris    smp_discover.request.discover.phy_identifier = phy_identifier;
304f11c7f63SJim Harris 
305f11c7f63SJim Harris    SCIF_LOG_INFO((
306f11c7f63SJim Harris       sci_base_object_get_logger(fw_device),
307f11c7f63SJim Harris       SCIF_LOG_OBJECT_IO_REQUEST | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
308f11c7f63SJim Harris       "SMP DISCOVER - Device:0x%x PhyId:0x%x\n",
309f11c7f63SJim Harris       fw_device, phy_identifier
310f11c7f63SJim Harris    ));
311f11c7f63SJim Harris 
312f11c7f63SJim Harris    return scif_sas_smp_request_build(
313f11c7f63SJim Harris              fw_controller, fw_device, &smp_discover,
314f11c7f63SJim Harris              external_request_object, external_memory
315f11c7f63SJim Harris           );
316f11c7f63SJim Harris }
317f11c7f63SJim Harris 
318f11c7f63SJim Harris 
319f11c7f63SJim Harris /**
320f11c7f63SJim Harris  * @brief construct a smp REPORT PHY SATA command to the fw_device.
321f11c7f63SJim Harris  * @param[in] fw_controller The framework controller object.
322f11c7f63SJim Harris  * @param[in] fw_device the framework smp device that DISCOVER command targets
323f11c7f63SJim Harris  *       to.
324f11c7f63SJim Harris  * @param[in] phy_identifier The phy index the DISCOVER command targets to.
325f11c7f63SJim Harris  *
326f11c7f63SJim Harris  * @return void * address to the built scif sas smp request.
327f11c7f63SJim Harris  */
scif_sas_smp_request_construct_report_phy_sata(SCIF_SAS_CONTROLLER_T * fw_controller,SCIF_SAS_REMOTE_DEVICE_T * fw_device,U8 phy_identifier)328f11c7f63SJim Harris void * scif_sas_smp_request_construct_report_phy_sata(
329f11c7f63SJim Harris    SCIF_SAS_CONTROLLER_T    * fw_controller,
330f11c7f63SJim Harris    SCIF_SAS_REMOTE_DEVICE_T * fw_device,
331f11c7f63SJim Harris    U8                         phy_identifier
332f11c7f63SJim Harris )
333f11c7f63SJim Harris {
334f11c7f63SJim Harris    SMP_REQUEST_T report_phy_sata;
335f11c7f63SJim Harris 
336f11c7f63SJim Harris    scif_sas_smp_protocol_request_construct(
337f11c7f63SJim Harris       &report_phy_sata,
338f11c7f63SJim Harris       SMP_FUNCTION_REPORT_PHY_SATA,
339f11c7f63SJim Harris       sizeof(SMP_RESPONSE_REPORT_PHY_SATA_T) / sizeof(U32),
340f11c7f63SJim Harris       sizeof(SMP_REQUEST_PHY_IDENTIFIER_T) / sizeof(U32)
341f11c7f63SJim Harris    );
342f11c7f63SJim Harris 
343f11c7f63SJim Harris    report_phy_sata.request.report_phy_sata.phy_identifier = phy_identifier;
344f11c7f63SJim Harris 
345f11c7f63SJim Harris    SCIF_LOG_INFO((
346f11c7f63SJim Harris       sci_base_object_get_logger(fw_device),
347f11c7f63SJim Harris       SCIF_LOG_OBJECT_IO_REQUEST | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
348f11c7f63SJim Harris       "SMP REPORT PHY SATA - Device:0x%x PhyId:0x%x\n",
349f11c7f63SJim Harris       fw_device, phy_identifier
350f11c7f63SJim Harris    ));
351f11c7f63SJim Harris 
352f11c7f63SJim Harris    return scif_sas_smp_request_build(
353f11c7f63SJim Harris              fw_controller, fw_device, &report_phy_sata, NULL, NULL);
354f11c7f63SJim Harris }
355f11c7f63SJim Harris 
356f11c7f63SJim Harris 
357f11c7f63SJim Harris /**
358f11c7f63SJim Harris  * @brief construct a smp REPORT PHY SATA command to the fw_device.
359f11c7f63SJim Harris  * @param[in] fw_controller The framework controller object.
360f11c7f63SJim Harris  * @param[in] fw_device the framework smp device that PHY CONTROL command
361f11c7f63SJim Harris  *       targets to.
362f11c7f63SJim Harris  * @param[in] phy_identifier The phy index the DISCOVER command targets to.
363f11c7f63SJim Harris  *
364f11c7f63SJim Harris  * @return void * address to the built scif sas smp request.
365f11c7f63SJim Harris  */
scif_sas_smp_request_construct_phy_control(SCIF_SAS_CONTROLLER_T * fw_controller,SCIF_SAS_REMOTE_DEVICE_T * fw_device,U8 phy_operation,U8 phy_identifier,void * external_request_object,void * external_memory)366f11c7f63SJim Harris void * scif_sas_smp_request_construct_phy_control(
367f11c7f63SJim Harris    SCIF_SAS_CONTROLLER_T    * fw_controller,
368f11c7f63SJim Harris    SCIF_SAS_REMOTE_DEVICE_T * fw_device,
369f11c7f63SJim Harris    U8                         phy_operation,
370f11c7f63SJim Harris    U8                         phy_identifier,
371f11c7f63SJim Harris    void                     * external_request_object,
372f11c7f63SJim Harris    void                     * external_memory
373f11c7f63SJim Harris )
374f11c7f63SJim Harris {
375f11c7f63SJim Harris    SMP_REQUEST_T phy_control;
376f11c7f63SJim Harris 
377f11c7f63SJim Harris    scif_sas_smp_protocol_request_construct(
378f11c7f63SJim Harris       &phy_control,
379f11c7f63SJim Harris       SMP_FUNCTION_PHY_CONTROL,
380f11c7f63SJim Harris       0,
381f11c7f63SJim Harris       sizeof(SMP_REQUEST_PHY_CONTROL_T) / sizeof(U32)
382f11c7f63SJim Harris    );
383f11c7f63SJim Harris 
384f11c7f63SJim Harris    phy_control.request.phy_control.phy_operation = phy_operation;
385f11c7f63SJim Harris    phy_control.request.phy_control.phy_identifier = phy_identifier;
386f11c7f63SJim Harris 
387f11c7f63SJim Harris    return scif_sas_smp_request_build(
388f11c7f63SJim Harris              fw_controller, fw_device, &phy_control,
389f11c7f63SJim Harris              external_request_object, external_memory
390f11c7f63SJim Harris           );
391f11c7f63SJim Harris }
392f11c7f63SJim Harris 
393f11c7f63SJim Harris 
394f11c7f63SJim Harris /**
395f11c7f63SJim Harris  * @brief construct a smp CONFIG ROUTE INFO command to the fw_device.
396f11c7f63SJim Harris  *
397f11c7f63SJim Harris  * @param[in] fw_controller The framework controller object.
398f11c7f63SJim Harris  * @param[in] fw_device the framework smp device that PHY CONTROL command
399f11c7f63SJim Harris  *       targets to.
400f11c7f63SJim Harris  * @param[in] phy_id The phy, whose route entry at route_index is to be configured.
401f11c7f63SJim Harris  * @param[in] route_index The index of a phy's route entry that is to be configured.
402f11c7f63SJim Harris  * @param[in] destination_sas_address A sas address for an route table entry
403f11c7f63SJim Harris  *
404f11c7f63SJim Harris  * @return void * address to the built scif sas smp request.
405f11c7f63SJim Harris  */
scif_sas_smp_request_construct_config_route_info(struct SCIF_SAS_CONTROLLER * fw_controller,struct SCIF_SAS_REMOTE_DEVICE * fw_device,U8 phy_id,U16 route_index,SCI_SAS_ADDRESS_T destination_sas_address,BOOL disable_expander_route_entry)406f11c7f63SJim Harris void * scif_sas_smp_request_construct_config_route_info(
407f11c7f63SJim Harris    struct SCIF_SAS_CONTROLLER    * fw_controller,
408f11c7f63SJim Harris    struct SCIF_SAS_REMOTE_DEVICE * fw_device,
409f11c7f63SJim Harris    U8                              phy_id,
410f11c7f63SJim Harris    U16                             route_index,
411f11c7f63SJim Harris    SCI_SAS_ADDRESS_T               destination_sas_address,
412f11c7f63SJim Harris    BOOL                            disable_expander_route_entry
413f11c7f63SJim Harris )
414f11c7f63SJim Harris {
415f11c7f63SJim Harris    SMP_REQUEST_T config_route_info;
416f11c7f63SJim Harris 
417f11c7f63SJim Harris    scif_sas_smp_protocol_request_construct(
418f11c7f63SJim Harris       &config_route_info,
419f11c7f63SJim Harris       SMP_FUNCTION_CONFIGURE_ROUTE_INFORMATION,
420f11c7f63SJim Harris       0,
421f11c7f63SJim Harris       sizeof(SMP_REQUEST_CONFIGURE_ROUTE_INFORMATION_T) / sizeof(U32)
422f11c7f63SJim Harris    );
423f11c7f63SJim Harris 
424f11c7f63SJim Harris    config_route_info.request.configure_route_information.phy_identifier = phy_id;
425f11c7f63SJim Harris    config_route_info.request.configure_route_information.expander_route_index_high =
426f11c7f63SJim Harris       ((route_index & 0xff00) >> 8);
427f11c7f63SJim Harris    config_route_info.request.configure_route_information.expander_route_index =
428f11c7f63SJim Harris       route_index & 0xff;
429f11c7f63SJim Harris    config_route_info.request.configure_route_information.routed_sas_address[0] =
430f11c7f63SJim Harris       destination_sas_address.high;
431f11c7f63SJim Harris    config_route_info.request.configure_route_information.routed_sas_address[1] =
432f11c7f63SJim Harris       destination_sas_address.low;
433f11c7f63SJim Harris 
434f11c7f63SJim Harris    if (disable_expander_route_entry == TRUE)
435f11c7f63SJim Harris       config_route_info.request.configure_route_information.disable_route_entry = 1;
436f11c7f63SJim Harris 
437f11c7f63SJim Harris    return scif_sas_smp_request_build(
438f11c7f63SJim Harris              fw_controller, fw_device, &config_route_info,
439f11c7f63SJim Harris              NULL, NULL
440f11c7f63SJim Harris           );
441f11c7f63SJim Harris }
442f11c7f63SJim Harris 
443f11c7f63SJim Harris /**
444f11c7f63SJim Harris  * @brief This method retry the internal smp request.
445f11c7f63SJim Harris  *
446f11c7f63SJim Harris  * @param[in] fw_device This parameter specifies the remote device for
447f11c7f63SJim Harris  *            which the internal IO request is destined.
448f11c7f63SJim Harris  * @param[in] retry_count This parameter specifies how many times the
449f11c7f63SJim Harris  *            old smp request has been retried.
450f11c7f63SJim Harris  *
451f11c7f63SJim Harris  * @return none.
452f11c7f63SJim Harris  */
scif_sas_smp_internal_request_retry(SCIF_SAS_REMOTE_DEVICE_T * fw_device)453f11c7f63SJim Harris SCI_STATUS scif_sas_smp_internal_request_retry(
454f11c7f63SJim Harris    SCIF_SAS_REMOTE_DEVICE_T * fw_device
455f11c7f63SJim Harris )
456f11c7f63SJim Harris {
457f11c7f63SJim Harris    SCIF_SAS_CONTROLLER_T * fw_controller;
458f11c7f63SJim Harris    SCIF_SAS_IO_REQUEST_T * new_io;
459f11c7f63SJim Harris    void                  * new_request_memory = NULL;
460f11c7f63SJim Harris    U8 retry_count = fw_device->protocol_device.smp_device.io_retry_count;
461f11c7f63SJim Harris 
462f11c7f63SJim Harris    SCIF_LOG_TRACE((
463f11c7f63SJim Harris       sci_base_object_get_logger(fw_device),
464f11c7f63SJim Harris       SCIF_LOG_OBJECT_IO_REQUEST | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
465f11c7f63SJim Harris       "scif_sas_smp_internal_request_retry(0x%x, 0x%x) time %d!\n",
466f11c7f63SJim Harris       fw_device, retry_count
467f11c7f63SJim Harris    ));
468f11c7f63SJim Harris 
469f11c7f63SJim Harris    fw_controller = fw_device->domain->controller;
470f11c7f63SJim Harris 
471f11c7f63SJim Harris    switch (fw_device->protocol_device.smp_device.current_smp_request)
472f11c7f63SJim Harris    {
473f11c7f63SJim Harris       case SMP_FUNCTION_REPORT_GENERAL:
474f11c7f63SJim Harris          new_request_memory = scif_sas_smp_request_construct_report_general(
475f11c7f63SJim Harris             fw_controller, fw_device
476f11c7f63SJim Harris          );
477f11c7f63SJim Harris          break;
478f11c7f63SJim Harris 
479f11c7f63SJim Harris       case SMP_FUNCTION_DISCOVER:
480f11c7f63SJim Harris          //We are retrying an internal io. So we are going to allocate
481f11c7f63SJim Harris          //a new memory from internal io memory pool.
482f11c7f63SJim Harris          new_request_memory = scif_sas_smp_request_construct_discover(
483f11c7f63SJim Harris             fw_controller, fw_device,
484f11c7f63SJim Harris             fw_device->protocol_device.smp_device.current_activity_phy_index,
485f11c7f63SJim Harris             NULL, NULL
486f11c7f63SJim Harris          );
487f11c7f63SJim Harris 
488f11c7f63SJim Harris          break;
489f11c7f63SJim Harris 
490f11c7f63SJim Harris       case SMP_FUNCTION_REPORT_PHY_SATA:
491f11c7f63SJim Harris          new_request_memory = scif_sas_smp_request_construct_report_phy_sata(
492f11c7f63SJim Harris             fw_controller, fw_device,
493f11c7f63SJim Harris             fw_device->protocol_device.smp_device.current_activity_phy_index
494f11c7f63SJim Harris          );
495f11c7f63SJim Harris          break;
496f11c7f63SJim Harris 
497f11c7f63SJim Harris       default:
498f11c7f63SJim Harris          //unsupported case, TBD
499f11c7f63SJim Harris          break;
500f11c7f63SJim Harris    } //end of switch
501f11c7f63SJim Harris 
502f11c7f63SJim Harris    if (new_request_memory != NULL)
503f11c7f63SJim Harris    {
504f11c7f63SJim Harris       //set the retry count to new built smp request.
505f11c7f63SJim Harris       new_io = (SCIF_SAS_IO_REQUEST_T *) new_request_memory;
506f11c7f63SJim Harris       new_io->retry_count = ++retry_count;
507f11c7f63SJim Harris 
508f11c7f63SJim Harris       //need to schedule the DPC here.
509f11c7f63SJim Harris       scif_cb_start_internal_io_task_schedule(
510f11c7f63SJim Harris             fw_controller,
511f11c7f63SJim Harris             scif_sas_controller_start_high_priority_io,
512f11c7f63SJim Harris             fw_controller
513f11c7f63SJim Harris          );
514f11c7f63SJim Harris 
515f11c7f63SJim Harris       return SCI_SUCCESS;
516f11c7f63SJim Harris    }
517f11c7f63SJim Harris    else
518f11c7f63SJim Harris       return SCI_FAILURE_INSUFFICIENT_RESOURCES;
519f11c7f63SJim Harris 
520f11c7f63SJim Harris }
521f11c7f63SJim Harris 
522f11c7f63SJim Harris /**
523f11c7f63SJim Harris  * @brief This method retry the external smp request.
524f11c7f63SJim Harris  *
525f11c7f63SJim Harris  * @param[in] fw_device This parameter specifies the remote device for
526f11c7f63SJim Harris  *            which the internal IO request is destined.
527f11c7f63SJim Harris  * @param[in] old_internal_io This parameter specifies the old smp request to be
528f11c7f63SJim Harris  *            retried.
529f11c7f63SJim Harris  *
530f11c7f63SJim Harris  * @return none.
531f11c7f63SJim Harris  */
scif_sas_smp_external_request_retry(SCIF_SAS_IO_REQUEST_T * old_io)532f11c7f63SJim Harris SCI_STATUS scif_sas_smp_external_request_retry(
533f11c7f63SJim Harris    SCIF_SAS_IO_REQUEST_T    * old_io
534f11c7f63SJim Harris )
535f11c7f63SJim Harris {
536f11c7f63SJim Harris    SCIF_SAS_REMOTE_DEVICE_T * fw_device = old_io->parent.device;
537f11c7f63SJim Harris    SCIF_SAS_CONTROLLER_T * fw_controller;
538f11c7f63SJim Harris    SCIF_SAS_IO_REQUEST_T * new_io;
539f11c7f63SJim Harris    void                  * new_request_memory = NULL;
540f11c7f63SJim Harris    U8                      retry_count = old_io->retry_count;
541f11c7f63SJim Harris 
542f11c7f63SJim Harris    SCIF_LOG_TRACE((
543f11c7f63SJim Harris       sci_base_object_get_logger(fw_device),
544f11c7f63SJim Harris       SCIF_LOG_OBJECT_IO_REQUEST | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
545f11c7f63SJim Harris       "scif_sas_smp_external_request_retry(0x%x) time %d!\n",
546f11c7f63SJim Harris       old_io
547f11c7f63SJim Harris    ));
548f11c7f63SJim Harris 
549f11c7f63SJim Harris    fw_controller = fw_device->domain->controller;
550f11c7f63SJim Harris 
551f11c7f63SJim Harris    // Before we construct new io using the same memory, we need to
552f11c7f63SJim Harris    // remove the IO from the list of outstanding requests on the domain
553f11c7f63SJim Harris    // so that we don't damage the domain's fast list of request.
554f11c7f63SJim Harris    sci_fast_list_remove_element(&old_io->parent.list_element);
555f11c7f63SJim Harris 
556f11c7f63SJim Harris    switch (fw_device->protocol_device.smp_device.current_smp_request)
557f11c7f63SJim Harris    {
558f11c7f63SJim Harris       case SMP_FUNCTION_DISCOVER:
559f11c7f63SJim Harris          //we are retrying an external io, we are going to reuse the
560f11c7f63SJim Harris          //old io's memory. new_request_memory is same as old_io.
561f11c7f63SJim Harris          new_request_memory = scif_sas_smp_request_construct_discover(
562f11c7f63SJim Harris             fw_controller, fw_device,
563f11c7f63SJim Harris             fw_device->protocol_device.smp_device.current_activity_phy_index,
564f11c7f63SJim Harris             (void *)sci_object_get_association(old_io),
565f11c7f63SJim Harris             (void *)old_io
566f11c7f63SJim Harris          );
567f11c7f63SJim Harris 
568f11c7f63SJim Harris          break;
569f11c7f63SJim Harris 
570f11c7f63SJim Harris       case SMP_FUNCTION_PHY_CONTROL:
571f11c7f63SJim Harris          //Phy Control command always uses external io memory.
572f11c7f63SJim Harris          new_request_memory = scif_sas_smp_request_construct_phy_control(
573f11c7f63SJim Harris             fw_controller, fw_device, PHY_OPERATION_HARD_RESET,
574f11c7f63SJim Harris             fw_device->protocol_device.smp_device.current_activity_phy_index,
575f11c7f63SJim Harris             (void *)sci_object_get_association(old_io),
576f11c7f63SJim Harris             (void *)old_io
577f11c7f63SJim Harris          );
578f11c7f63SJim Harris 
579f11c7f63SJim Harris          break;
580f11c7f63SJim Harris 
581f11c7f63SJim Harris       default:
582f11c7f63SJim Harris          //unsupported case, TBD
5832d57bb86SJim Harris          return SCI_FAILURE;
584f11c7f63SJim Harris    } //end of switch
585f11c7f63SJim Harris 
586f11c7f63SJim Harris    //set the retry count to new built smp request.
587f11c7f63SJim Harris    new_io = (SCIF_SAS_IO_REQUEST_T *) new_request_memory;
588f11c7f63SJim Harris    new_io->retry_count = ++retry_count;
589f11c7f63SJim Harris 
590f11c7f63SJim Harris    //put into the high priority queue.
591f11c7f63SJim Harris    sci_pool_put(fw_controller->hprq.pool, (POINTER_UINT) new_request_memory);
592f11c7f63SJim Harris 
593f11c7f63SJim Harris    //schedule the DPC to start new io.
594f11c7f63SJim Harris    scif_cb_start_internal_io_task_schedule(
595f11c7f63SJim Harris       fw_controller, scif_sas_controller_start_high_priority_io, fw_controller
596f11c7f63SJim Harris    );
597f11c7f63SJim Harris 
598f11c7f63SJim Harris    return SCI_SUCCESS;
599f11c7f63SJim Harris }
600f11c7f63SJim Harris 
601