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#include <dev/isci/scil/scic_sds_smp_request.h>
57230557Sjimharris#include <dev/isci/scil/scic_sds_logger.h>
58230557Sjimharris#include <dev/isci/scil/scic_sds_controller.h>
59230557Sjimharris#include <dev/isci/scil/scic_sds_remote_device.h>
60230557Sjimharris#include <dev/isci/scil/scic_remote_device.h>
61230557Sjimharris#include <dev/isci/scil/sci_util.h>
62230557Sjimharris#include <dev/isci/sci_environment.h>
63230557Sjimharris#include <dev/isci/scil/intel_sas.h>
64230557Sjimharris#include <dev/isci/scil/scic_sds_request.h>
65230557Sjimharris#include <dev/isci/scil/scic_controller.h>
66230557Sjimharris#include <dev/isci/scil/scu_completion_codes.h>
67230557Sjimharris#include <dev/isci/scil/scu_task_context.h>
68230557Sjimharris#include <dev/isci/scil/sci_base_state_machine.h>
69230557Sjimharris
70230557Sjimharris/**
71230557Sjimharris * This method return the memory space required for STP PIO requests.
72230557Sjimharris *
73230557Sjimharris * @return U32
74230557Sjimharris */
75230557SjimharrisU32 scic_sds_smp_request_get_object_size(void)
76230557Sjimharris{
77230557Sjimharris   return   sizeof(SCIC_SDS_REQUEST_T)
78230557Sjimharris          + sizeof(SMP_REQUEST_T)
79230557Sjimharris          + sizeof(U32)
80230557Sjimharris          + sizeof(SMP_RESPONSE_T)
81230557Sjimharris          + sizeof(U32)
82230557Sjimharris          + sizeof(SCU_TASK_CONTEXT_T)
83230557Sjimharris          + CACHE_LINE_SIZE;
84230557Sjimharris}
85230557Sjimharris
86230557Sjimharris/**
87230557Sjimharris * This macro returns the address of the smp command buffer in the smp request
88230557Sjimharris * memory. No need to cast to SMP request type.
89230557Sjimharris */
90230557Sjimharris#define scic_sds_smp_request_get_command_buffer_unaligned(memory) \
91230557Sjimharris   ( ((char *)(memory)) + sizeof(SCIC_SDS_REQUEST_T) )
92230557Sjimharris
93230557Sjimharris/**
94230557Sjimharris * This macro aligns the smp command buffer in DWORD alignment
95230557Sjimharris*/
96230557Sjimharris#define scic_sds_smp_request_align_command_buffer(address) \
97230557Sjimharris   ((char *)( \
98230557Sjimharris      (((POINTER_UINT)(address)) + (sizeof(U32) - 1)) \
99230557Sjimharris         & ~(sizeof(U32)- 1) \
100230557Sjimharris   ))
101230557Sjimharris
102230557Sjimharris/**
103230557Sjimharris * This macro returns the DWORD-aligned smp command buffer
104230557Sjimharris*/
105230557Sjimharris#define scic_sds_smp_request_get_command_buffer(memory) \
106230557Sjimharris   ((char *)  \
107230557Sjimharris      ((char *)scic_sds_smp_request_align_command_buffer( \
108230557Sjimharris         (char *) scic_sds_smp_request_get_command_buffer_unaligned(memory) \
109230557Sjimharris   )))
110230557Sjimharris
111230557Sjimharris/**
112230557Sjimharris * This macro returns the address of the smp response buffer in the smp request
113230557Sjimharris * memory.
114230557Sjimharris */
115230557Sjimharris#define scic_sds_smp_request_get_response_buffer_unaligned(memory) \
116230557Sjimharris   ( ((char *)(scic_sds_smp_request_get_command_buffer(memory))) \
117230557Sjimharris      + sizeof(SMP_REQUEST_T) )
118230557Sjimharris
119230557Sjimharris/**
120230557Sjimharris * This macro aligns the smp command buffer in DWORD alignment
121230557Sjimharris*/
122230557Sjimharris#define scic_sds_smp_request_align_response_buffer(address) \
123230557Sjimharris   ((char *)( \
124230557Sjimharris      (((POINTER_UINT)(address)) + (sizeof(U32) - 1)) \
125230557Sjimharris         & ~(sizeof(U32)- 1) \
126230557Sjimharris   ))
127230557Sjimharris
128230557Sjimharris/**
129230557Sjimharris * This macro returns the DWORD-aligned smp resposne buffer
130230557Sjimharris*/
131230557Sjimharris#define scic_sds_smp_request_get_response_buffer(memory) \
132230557Sjimharris   ((char *)  \
133230557Sjimharris      ((char *)scic_sds_smp_request_align_response_buffer( \
134230557Sjimharris         (char *) scic_sds_smp_request_get_response_buffer_unaligned(memory) \
135230557Sjimharris   )))
136230557Sjimharris
137230557Sjimharris/**
138230557Sjimharris * This macro returs the task context buffer for the SMP request.
139230557Sjimharris */
140230557Sjimharris#define scic_sds_smp_request_get_task_context_buffer_unaligned(memory) \
141230557Sjimharris   ((SCU_TASK_CONTEXT_T *)( \
142230557Sjimharris        ((char *)(scic_sds_smp_request_get_response_buffer(memory))) \
143230557Sjimharris      + sizeof(SMP_RESPONSE_T) \
144230557Sjimharris   ))
145230557Sjimharris
146230557Sjimharris/**
147230557Sjimharris * This macro returns the dword-aligned smp task context buffer
148230557Sjimharris */
149230557Sjimharris#define scic_sds_smp_request_get_task_context_buffer(memory) \
150230557Sjimharris   ((SCU_TASK_CONTEXT_T *)( \
151230557Sjimharris      ((char *)scic_sds_request_align_task_context_buffer( \
152230557Sjimharris         (char *)scic_sds_smp_request_get_task_context_buffer_unaligned(memory)) \
153230557Sjimharris   )))
154230557Sjimharris
155230557Sjimharris/**
156230557Sjimharris * @brief This method build the remainder of the IO request object.
157230557Sjimharris *
158230557Sjimharris * @pre The scic_sds_general_request_construct() must be called before this
159230557Sjimharris *      call is valid.
160230557Sjimharris *
161230557Sjimharris * @param[in] this_request This parameter specifies the request object being
162230557Sjimharris *            constructed.
163230557Sjimharris *
164230557Sjimharris * @return none
165230557Sjimharris */
166230557Sjimharris
167230557Sjimharrisvoid scic_sds_smp_request_assign_buffers(
168230557Sjimharris   SCIC_SDS_REQUEST_T *this_request
169230557Sjimharris)
170230557Sjimharris{
171230557Sjimharris   // Assign all of the buffer pointers
172230557Sjimharris   this_request->command_buffer =
173230557Sjimharris      scic_sds_smp_request_get_command_buffer(this_request);
174230557Sjimharris   this_request->response_buffer =
175230557Sjimharris      scic_sds_smp_request_get_response_buffer(this_request);
176230557Sjimharris   this_request->sgl_element_pair_buffer = NULL;
177230557Sjimharris
178230557Sjimharris   if (this_request->was_tag_assigned_by_user == FALSE)
179230557Sjimharris   {
180230557Sjimharris      this_request->task_context_buffer =
181230557Sjimharris         scic_sds_smp_request_get_task_context_buffer(this_request);
182230557Sjimharris   }
183230557Sjimharris
184230557Sjimharris}
185230557Sjimharris/**
186230557Sjimharris * @brief This method is called by the SCI user to build an SMP
187230557Sjimharris *        IO request.
188230557Sjimharris *
189230557Sjimharris * @pre
190230557Sjimharris *        - The user must have previously called scic_io_request_construct()
191230557Sjimharris *          on the supplied IO request.
192230557Sjimharris *
193230557Sjimharris * @param[in]  scic_io_request This parameter specifies the handle to the
194230557Sjimharris *             io request object to be built.
195230557Sjimharris *
196230557Sjimharris * @return Indicate if the controller successfully built the IO request.
197230557Sjimharris * @retval SCI_SUCCESS This value is returned if the IO request was
198230557Sjimharris *         successfully built.
199230557Sjimharris * @retval SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned if the
200230557Sjimharris *         remote_device does not support the SMP protocol.
201230557Sjimharris * @retval SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the
202230557Sjimharris *         user did not properly set the association between the SCIC IO
203230557Sjimharris *         request and the user's IO request.  Please refer to the
204230557Sjimharris *         sci_object_set_association() routine for more
205230557Sjimharris *         information.
206230557Sjimharris */
207230557SjimharrisSCI_STATUS scic_io_request_construct_smp(
208230557Sjimharris   SCI_IO_REQUEST_HANDLE_T  scic_smp_request
209230557Sjimharris)
210230557Sjimharris{
211230557Sjimharris   SMP_REQUEST_T smp_request;
212230557Sjimharris
213230557Sjimharris   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *) scic_smp_request;
214230557Sjimharris   SCIC_LOG_TRACE((
215230557Sjimharris      sci_base_object_get_logger(this_request),
216230557Sjimharris      SCIC_LOG_OBJECT_SMP_IO_REQUEST,
217230557Sjimharris      "scic_io_request_construct_smp(0x%x) enter\n",
218230557Sjimharris      this_request
219230557Sjimharris   ));
220230557Sjimharris
221230557Sjimharris   this_request->protocol                     = SCIC_SMP_PROTOCOL;
222230557Sjimharris   this_request->has_started_substate_machine = TRUE;
223230557Sjimharris
224230557Sjimharris   // Construct the started sub-state machine.
225230557Sjimharris   sci_base_state_machine_construct(
226230557Sjimharris      &this_request->started_substate_machine,
227230557Sjimharris      &this_request->parent.parent,
228230557Sjimharris      scic_sds_smp_request_started_substate_table,
229230557Sjimharris      SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE
230230557Sjimharris   );
231230557Sjimharris
232230557Sjimharris   // Construct the SMP SCU Task Context
233230557Sjimharris   memcpy((char *)&smp_request,
234230557Sjimharris        this_request->command_buffer,
235230557Sjimharris        sizeof(SMP_REQUEST_T));
236230557Sjimharris
237230557Sjimharris   // Look at the SMP requests' header fields; for certain SAS 1.x SMP
238230557Sjimharris   // functions under SAS 2.0, a zero request length really indicates
239230557Sjimharris   // a non-zero default length.
240230557Sjimharris   if( smp_request.header.request_length == 0 )
241230557Sjimharris   {
242230557Sjimharris       switch( smp_request.header.function )
243230557Sjimharris       {
244230557Sjimharris       case SMP_FUNCTION_DISCOVER:
245230557Sjimharris       case SMP_FUNCTION_REPORT_PHY_ERROR_LOG:
246230557Sjimharris       case SMP_FUNCTION_REPORT_PHY_SATA:
247230557Sjimharris       case SMP_FUNCTION_REPORT_ROUTE_INFORMATION:
248230557Sjimharris           smp_request.header.request_length = 2;
249230557Sjimharris           break;
250230557Sjimharris       case SMP_FUNCTION_CONFIGURE_ROUTE_INFORMATION:
251230557Sjimharris       case SMP_FUNCTION_PHY_CONTROL:
252230557Sjimharris       case SMP_FUNCTION_PHY_TEST:
253230557Sjimharris           smp_request.header.request_length = 9;
254230557Sjimharris           break;
255230557Sjimharris       // Default - zero is a valid default for 2.0.
256230557Sjimharris       }
257230557Sjimharris   }
258230557Sjimharris
259230557Sjimharris   scu_smp_request_construct_task_context(
260230557Sjimharris      this_request,
261230557Sjimharris      &smp_request
262230557Sjimharris   );
263230557Sjimharris
264230557Sjimharris   sci_base_state_machine_change_state(
265230557Sjimharris      &this_request->parent.state_machine,
266230557Sjimharris      SCI_BASE_REQUEST_STATE_CONSTRUCTED
267230557Sjimharris   );
268230557Sjimharris
269230557Sjimharris   return SCI_SUCCESS;
270230557Sjimharris}
271230557Sjimharris
272230557Sjimharris/**
273230557Sjimharris * @brief This method is called by the SCI user to build an SMP pass-through
274230557Sjimharris *        IO request.
275230557Sjimharris *
276230557Sjimharris * @pre
277230557Sjimharris *        - The user must have previously called scic_io_request_construct()
278230557Sjimharris *          on the supplied IO request.
279230557Sjimharris *
280230557Sjimharris * @param[in]  scic_smp_request This parameter specifies the handle to the
281230557Sjimharris *             io request object to be built.
282230557Sjimharris *
283230557Sjimharris * @param[in]  passthru_cb This parameter specifies the pointer to the callback
284230557Sjimharris *             structure that contains the function pointers
285230557Sjimharris *
286230557Sjimharris * @return Indicate if the controller successfully built the IO request.
287230557Sjimharris */
288230557SjimharrisSCI_STATUS scic_io_request_construct_smp_pass_through(
289230557Sjimharris   SCI_IO_REQUEST_HANDLE_T  scic_smp_request,
290230557Sjimharris   SCIC_SMP_PASSTHRU_REQUEST_CALLBACKS_T *passthru_cb
291230557Sjimharris)
292230557Sjimharris{
293230557Sjimharris   SMP_REQUEST_T smp_request;
294230557Sjimharris   U8 * request_buffer;
295230557Sjimharris   U32 request_buffer_length_in_bytes;
296230557Sjimharris
297230557Sjimharris   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *) scic_smp_request;
298230557Sjimharris   SCIC_LOG_TRACE((
299230557Sjimharris      sci_base_object_get_logger(this_request),
300230557Sjimharris      SCIC_LOG_OBJECT_SMP_IO_REQUEST,
301230557Sjimharris      "scic_io_request_construct_smp_pass_through(0x%x) enter\n",
302230557Sjimharris      this_request
303230557Sjimharris   ));
304230557Sjimharris
305230557Sjimharris   this_request->protocol                     = SCIC_SMP_PROTOCOL;
306230557Sjimharris   this_request->has_started_substate_machine = TRUE;
307230557Sjimharris
308230557Sjimharris   // Call the callback function to retrieve the SMP passthrough request
309230557Sjimharris   request_buffer_length_in_bytes = passthru_cb->scic_cb_smp_passthru_get_request (
310230557Sjimharris                                       (void *)this_request,
311230557Sjimharris                                       &request_buffer
312230557Sjimharris                                    );
313230557Sjimharris
314230557Sjimharris   //copy the request to smp request
315230557Sjimharris   memcpy((char *)&smp_request.request.vendor_specific_request,
316230557Sjimharris        request_buffer,
317230557Sjimharris        request_buffer_length_in_bytes);
318230557Sjimharris
319230557Sjimharris   //the header length in smp_request is in dwords - the sas spec has similar way,
320230557Sjimharris   //but the csmi header contains the number of bytes, so we need to convert the
321230557Sjimharris   //number of bytes to number of dwords
322230557Sjimharris   smp_request.header.request_length = (U8) (request_buffer_length_in_bytes / sizeof (U32));
323230557Sjimharris
324230557Sjimharris   //Grab the other needed fields from the smp request using callbacks
325230557Sjimharris   smp_request.header.smp_frame_type = passthru_cb->scic_cb_smp_passthru_get_frame_type ((void *)this_request);
326230557Sjimharris   smp_request.header.function = passthru_cb->scic_cb_smp_passthru_get_function ((void *)this_request);
327230557Sjimharris   smp_request.header.allocated_response_length = passthru_cb->scic_cb_smp_passthru_get_allocated_response_length((void *)this_request);
328230557Sjimharris
329230557Sjimharris   // Construct the started sub-state machine.
330230557Sjimharris   sci_base_state_machine_construct(
331230557Sjimharris      &this_request->started_substate_machine,
332230557Sjimharris      &this_request->parent.parent,
333230557Sjimharris      scic_sds_smp_request_started_substate_table,
334230557Sjimharris      SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE
335230557Sjimharris   );
336230557Sjimharris
337230557Sjimharris   // Construct the SMP SCU Task Context
338230557Sjimharris   scu_smp_request_construct_task_context (this_request, &smp_request);
339230557Sjimharris
340230557Sjimharris   sci_base_state_machine_change_state(
341230557Sjimharris      &this_request->parent.state_machine,
342230557Sjimharris      SCI_BASE_REQUEST_STATE_CONSTRUCTED
343230557Sjimharris   );
344230557Sjimharris
345230557Sjimharris   return SCI_SUCCESS;
346230557Sjimharris}
347230557Sjimharris
348230557Sjimharris/**
349230557Sjimharris * @brief This method will fill in the SCU Task Context for a SMP request. The
350230557Sjimharris *        following important settings are utilized:
351230557Sjimharris *
352230557Sjimharris *          -# task_type == SCU_TASK_TYPE_SMP.  This simply indicates
353230557Sjimharris *             that a normal request type (i.e. non-raw frame) is being
354230557Sjimharris *             utilized to perform task management.
355230557Sjimharris *          -# control_frame == 1.  This ensures that the proper endianess
356230557Sjimharris *             is set so that the bytes are transmitted in the right order
357230557Sjimharris *             for a smp request frame.
358230557Sjimharris *
359230557Sjimharris * @param[in] this_request This parameter specifies the smp request object
360230557Sjimharris *            being constructed.
361230557Sjimharris *
362230557Sjimharris * @return none
363230557Sjimharris */
364230557Sjimharrisvoid scu_smp_request_construct_task_context(
365230557Sjimharris   SCIC_SDS_REQUEST_T *this_request,
366230557Sjimharris   SMP_REQUEST_T      *smp_request
367230557Sjimharris)
368230557Sjimharris{
369230557Sjimharris   SCI_PHYSICAL_ADDRESS      physical_address;
370230557Sjimharris   SCIC_SDS_CONTROLLER_T    *owning_controller;
371230557Sjimharris   SCIC_SDS_REMOTE_DEVICE_T *target_device;
372230557Sjimharris   SCIC_SDS_PORT_T          *target_port;
373230557Sjimharris   SCU_TASK_CONTEXT_T *task_context;
374230557Sjimharris
375230557Sjimharris   //byte swap the smp request.
376230557Sjimharris   scic_word_copy_with_swap(
377230557Sjimharris      this_request->command_buffer,
378230557Sjimharris      (U32*) smp_request,
379230557Sjimharris      sizeof(SMP_REQUEST_T)/sizeof(U32)
380230557Sjimharris   );
381230557Sjimharris
382230557Sjimharris   task_context = scic_sds_request_get_task_context(this_request);
383230557Sjimharris
384230557Sjimharris   owning_controller = scic_sds_request_get_controller(this_request);
385230557Sjimharris   target_device = scic_sds_request_get_device(this_request);
386230557Sjimharris   target_port = scic_sds_request_get_port(this_request);
387230557Sjimharris
388230557Sjimharris   SCIC_LOG_TRACE((
389230557Sjimharris      sci_base_object_get_logger(this_request),
390230557Sjimharris      SCIC_LOG_OBJECT_SMP_IO_REQUEST,
391230557Sjimharris      "scu_smp_request_construct_task_context(0x%x) contents\n"
392230557Sjimharris      "   reqlen=%x; function=%x;\n",
393230557Sjimharris      this_request,
394230557Sjimharris      smp_request->header.request_length,
395230557Sjimharris      smp_request->header.function
396230557Sjimharris   ));
397230557Sjimharris
398230557Sjimharris   // Fill in the TC with the its required data
399230557Sjimharris   // 00h
400230557Sjimharris   task_context->priority = 0;
401230557Sjimharris   task_context->initiator_request = 1;
402230557Sjimharris   task_context->connection_rate =
403230557Sjimharris      scic_remote_device_get_connection_rate(target_device);
404230557Sjimharris   task_context->protocol_engine_index =
405230557Sjimharris      scic_sds_controller_get_protocol_engine_group(owning_controller);
406230557Sjimharris   task_context->logical_port_index =
407230557Sjimharris      scic_sds_port_get_index(target_port);
408230557Sjimharris   task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SMP;
409230557Sjimharris   task_context->abort = 0;
410230557Sjimharris   task_context->valid = SCU_TASK_CONTEXT_VALID;
411230557Sjimharris   task_context->context_type = SCU_TASK_CONTEXT_TYPE;
412230557Sjimharris
413230557Sjimharris   //04h
414230557Sjimharris   task_context->remote_node_index = this_request->target_device->rnc->remote_node_index;
415230557Sjimharris   task_context->command_code = 0;
416230557Sjimharris   task_context->task_type = SCU_TASK_TYPE_SMP_REQUEST;
417230557Sjimharris
418230557Sjimharris   //08h
419230557Sjimharris   task_context->link_layer_control = 0;
420230557Sjimharris   task_context->do_not_dma_ssp_good_response = 1;
421230557Sjimharris   task_context->strict_ordering = 0;
422230557Sjimharris   task_context->control_frame = 1;
423230557Sjimharris   task_context->timeout_enable = 0;
424230557Sjimharris   task_context->block_guard_enable = 0;
425230557Sjimharris
426230557Sjimharris   //0ch
427230557Sjimharris   task_context->address_modifier = 0;
428230557Sjimharris
429230557Sjimharris   //10h
430230557Sjimharris   task_context->ssp_command_iu_length = smp_request->header.request_length;
431230557Sjimharris
432230557Sjimharris   //14h
433230557Sjimharris   task_context->transfer_length_bytes = 0;
434230557Sjimharris
435230557Sjimharris   //18h ~ 30h, protocol specific
436230557Sjimharris   // since commandIU has been build by framework at this point, we just
437230557Sjimharris   // copy the frist DWord from command IU to this location.
438230557Sjimharris   memcpy((void *)(&task_context->type.smp), this_request->command_buffer, sizeof(U32) );
439230557Sjimharris
440230557Sjimharris   //40h
441230557Sjimharris   // "For SMP you could program it to zero. We would prefer that way so that
442230557Sjimharris   // done code will be consistent." - Venki
443230557Sjimharris   task_context->task_phase = 0;
444230557Sjimharris
445230557Sjimharris   if (this_request->was_tag_assigned_by_user)
446230557Sjimharris   {
447230557Sjimharris      // Build the task context now since we have already read the data
448230557Sjimharris      this_request->post_context = (
449230557Sjimharris           SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC
450230557Sjimharris         | (
451230557Sjimharris                scic_sds_controller_get_protocol_engine_group(owning_controller)
452230557Sjimharris             << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT
453230557Sjimharris           )
454230557Sjimharris         | (
455230557Sjimharris                 scic_sds_port_get_index(target_port)
456230557Sjimharris              << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT
457230557Sjimharris           )
458230557Sjimharris         | scic_sds_io_tag_get_index(this_request->io_tag)
459230557Sjimharris      );
460230557Sjimharris   }
461230557Sjimharris   else
462230557Sjimharris   {
463230557Sjimharris      // Build the task context now since we have already read the data
464230557Sjimharris      this_request->post_context = (
465230557Sjimharris           SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC
466230557Sjimharris         | (
467230557Sjimharris               scic_sds_controller_get_protocol_engine_group(owning_controller)
468230557Sjimharris            << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT
469230557Sjimharris           )
470230557Sjimharris         | (
471230557Sjimharris                scic_sds_port_get_index(target_port)
472230557Sjimharris             << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT
473230557Sjimharris           )
474230557Sjimharris         // This is not assigned because we have to wait until we get a TCi
475230557Sjimharris      );
476230557Sjimharris   }
477230557Sjimharris
478230557Sjimharris   // Copy the physical address for the command buffer to the SCU Task Context
479230557Sjimharris   // command buffer should not contain command header.
480230557Sjimharris   scic_cb_io_request_get_physical_address(
481230557Sjimharris         scic_sds_request_get_controller(this_request),
482230557Sjimharris         this_request,
483230557Sjimharris         ((char *)(this_request->command_buffer) + sizeof(U32)),
484230557Sjimharris         &physical_address
485230557Sjimharris      );
486230557Sjimharris
487230557Sjimharris   task_context->command_iu_upper =
488230557Sjimharris      sci_cb_physical_address_upper(physical_address);
489230557Sjimharris   task_context->command_iu_lower =
490230557Sjimharris      sci_cb_physical_address_lower(physical_address);
491230557Sjimharris
492230557Sjimharris
493230557Sjimharris   //SMP response comes as UF, so no need to set response IU address.
494230557Sjimharris   task_context->response_iu_upper = 0;
495230557Sjimharris   task_context->response_iu_lower = 0;
496230557Sjimharris}
497230557Sjimharris
498230557Sjimharris//******************************************************************************
499230557Sjimharris//* SMP REQUEST STATE MACHINE
500230557Sjimharris//******************************************************************************
501230557Sjimharris
502230557Sjimharris/**
503230557Sjimharris * @brief This method processes an unsolicited frame while the SMP request is
504230557Sjimharris *        waiting for a response frame.  It will copy the response data, release
505230557Sjimharris *        the unsolicited frame, and transition the request to the
506230557Sjimharris *        SCI_BASE_REQUEST_STATE_COMPLETED state.
507230557Sjimharris *
508230557Sjimharris * @param[in] this_request This parameter specifies the request for which
509230557Sjimharris *            the unsolicited frame was received.
510230557Sjimharris * @param[in] frame_index This parameter indicates the unsolicited frame
511230557Sjimharris *            index that should contain the response.
512230557Sjimharris *
513230557Sjimharris * @return This method returns an indication of whether the response
514230557Sjimharris *         frame was handled successfully or not.
515230557Sjimharris * @retval SCI_SUCCESS Currently this value is always returned and indicates
516230557Sjimharris *         successful processing of the TC response.
517230557Sjimharris */
518230557Sjimharrisstatic
519230557SjimharrisSCI_STATUS scic_sds_smp_request_await_response_frame_handler(
520230557Sjimharris   SCIC_SDS_REQUEST_T * this_request,
521230557Sjimharris   U32                  frame_index
522230557Sjimharris)
523230557Sjimharris{
524230557Sjimharris   SCI_STATUS              status;
525230557Sjimharris   void                  * frame_header;
526230557Sjimharris   SMP_RESPONSE_HEADER_T * this_frame_header;
527230557Sjimharris   U8                    * user_smp_buffer = this_request->response_buffer;
528230557Sjimharris
529230557Sjimharris   // Save off the controller, so that we do not touch the request after it
530230557Sjimharris   //  is completed.
531230557Sjimharris   SCIC_SDS_CONTROLLER_T * controller = scic_sds_request_get_controller(this_request);
532230557Sjimharris
533230557Sjimharris   SCIC_LOG_TRACE((
534230557Sjimharris      sci_base_object_get_logger(this_request),
535230557Sjimharris      SCIC_LOG_OBJECT_SMP_IO_REQUEST,
536230557Sjimharris      "scic_sds_smp_request_await_response_frame_handler(0x%x, 0x%x) enter\n",
537230557Sjimharris      this_request, frame_index
538230557Sjimharris   ));
539230557Sjimharris
540230557Sjimharris   status = scic_sds_unsolicited_frame_control_get_header(
541230557Sjimharris      &(controller->uf_control),
542230557Sjimharris      frame_index,
543230557Sjimharris      &frame_header
544230557Sjimharris   );
545230557Sjimharris
546230557Sjimharris   //byte swap the header.
547230557Sjimharris   scic_word_copy_with_swap(
548230557Sjimharris      (U32*) user_smp_buffer,
549230557Sjimharris      frame_header,
550230557Sjimharris      sizeof(SMP_RESPONSE_HEADER_T)/sizeof(U32)
551230557Sjimharris   );
552230557Sjimharris   this_frame_header = (SMP_RESPONSE_HEADER_T*) user_smp_buffer;
553230557Sjimharris
554230557Sjimharris   if (this_frame_header->smp_frame_type == SMP_FRAME_TYPE_RESPONSE)
555230557Sjimharris   {
556230557Sjimharris      void * smp_response_buffer;
557230557Sjimharris
558230557Sjimharris      status = scic_sds_unsolicited_frame_control_get_buffer(
559230557Sjimharris         &(controller->uf_control),
560230557Sjimharris         frame_index,
561230557Sjimharris         &smp_response_buffer
562230557Sjimharris      );
563230557Sjimharris
564230557Sjimharris      scic_word_copy_with_swap(
565230557Sjimharris         (U32*) (user_smp_buffer + sizeof(SMP_RESPONSE_HEADER_T)),
566230557Sjimharris         smp_response_buffer,
567230557Sjimharris         sizeof(SMP_RESPONSE_BODY_T)/sizeof(U32)
568230557Sjimharris      );
569230557Sjimharris      if (this_frame_header->function == SMP_FUNCTION_DISCOVER)
570230557Sjimharris      {
571230557Sjimharris          SMP_RESPONSE_T * this_smp_response;
572230557Sjimharris
573230557Sjimharris          this_smp_response = (SMP_RESPONSE_T *)user_smp_buffer;
574230557Sjimharris
575230557Sjimharris          // Some expanders only report an attached SATA device, and
576230557Sjimharris          // not an STP target.  Since the core depends on the STP
577230557Sjimharris          // target attribute to correctly build I/O, set the bit now
578230557Sjimharris          // if necessary.
579230557Sjimharris          if (this_smp_response->response.discover.protocols.u.bits.attached_sata_device
580230557Sjimharris           && !this_smp_response->response.discover.protocols.u.bits.attached_stp_target)
581230557Sjimharris          {
582230557Sjimharris              this_smp_response->response.discover.protocols.u.bits.attached_stp_target = 1;
583230557Sjimharris
584230557Sjimharris              SCIC_LOG_TRACE((
585230557Sjimharris                  sci_base_object_get_logger(this_request),
586230557Sjimharris                 SCIC_LOG_OBJECT_SMP_IO_REQUEST,
587230557Sjimharris                 "scic_sds_smp_request_await_response_frame_handler(0x%x) Found SATA dev, setting STP bit.\n",
588230557Sjimharris                 this_request
589230557Sjimharris              ));
590230557Sjimharris          }
591230557Sjimharris      }
592230557Sjimharris
593230557Sjimharris     //Don't need to copy to user space. User instead will refer to
594230557Sjimharris     //core request's response buffer.
595230557Sjimharris
596230557Sjimharris     //copy the smp response to framework smp request's response buffer.
597230557Sjimharris     //scic_sds_smp_request_copy_response(this_request);
598230557Sjimharris
599230557Sjimharris      scic_sds_request_set_status(
600230557Sjimharris         this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
601230557Sjimharris      );
602230557Sjimharris
603230557Sjimharris      sci_base_state_machine_change_state(
604230557Sjimharris         &this_request->started_substate_machine,
605230557Sjimharris         SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION
606230557Sjimharris      );
607230557Sjimharris   }
608230557Sjimharris   else
609230557Sjimharris   {
610230557Sjimharris      // This was not a response frame why did it get forwarded?
611230557Sjimharris      SCIC_LOG_ERROR((
612230557Sjimharris         sci_base_object_get_logger(this_request),
613230557Sjimharris         SCIC_LOG_OBJECT_SMP_IO_REQUEST,
614230557Sjimharris         "SCIC SMP Request 0x%08x received unexpected frame %d type 0x%02x\n",
615230557Sjimharris         this_request, frame_index, this_frame_header->smp_frame_type
616230557Sjimharris      ));
617230557Sjimharris
618230557Sjimharris     scic_sds_request_set_status(
619230557Sjimharris        this_request,
620230557Sjimharris        SCU_TASK_DONE_SMP_FRM_TYPE_ERR,
621230557Sjimharris        SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
622230557Sjimharris     );
623230557Sjimharris
624230557Sjimharris     sci_base_state_machine_change_state(
625230557Sjimharris         &this_request->parent.state_machine,
626230557Sjimharris         SCI_BASE_REQUEST_STATE_COMPLETED
627230557Sjimharris      );
628230557Sjimharris   }
629230557Sjimharris
630230557Sjimharris   scic_sds_controller_release_frame(
631230557Sjimharris      controller, frame_index
632230557Sjimharris   );
633230557Sjimharris
634230557Sjimharris   return SCI_SUCCESS;
635230557Sjimharris}
636230557Sjimharris
637230557Sjimharris
638230557Sjimharris/**
639230557Sjimharris * @brief This method processes an abnormal TC completion while the SMP
640230557Sjimharris *        request is waiting for a response frame.  It decides what
641230557Sjimharris *        happened to the IO based on TC completion status.
642230557Sjimharris *
643230557Sjimharris * @param[in] this_request This parameter specifies the request for which
644230557Sjimharris *            the TC completion was received.
645230557Sjimharris * @param[in] completion_code This parameter indicates the completion status
646230557Sjimharris *            information for the TC.
647230557Sjimharris *
648230557Sjimharris * @return Indicate if the tc completion handler was successful.
649230557Sjimharris * @retval SCI_SUCCESS currently this method always returns success.
650230557Sjimharris */
651230557Sjimharrisstatic
652230557SjimharrisSCI_STATUS scic_sds_smp_request_await_response_tc_completion_handler(
653230557Sjimharris   SCIC_SDS_REQUEST_T * this_request,
654230557Sjimharris   U32                  completion_code
655230557Sjimharris)
656230557Sjimharris{
657230557Sjimharris   SCIC_LOG_TRACE((
658230557Sjimharris      sci_base_object_get_logger(this_request),
659230557Sjimharris      SCIC_LOG_OBJECT_SMP_IO_REQUEST,
660230557Sjimharris      "scic_sds_smp_request_await_response_tc_completion_handler(0x%x, 0x%x) enter\n",
661230557Sjimharris      this_request, completion_code
662230557Sjimharris   ));
663230557Sjimharris
664230557Sjimharris   switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
665230557Sjimharris   {
666230557Sjimharris   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
667230557Sjimharris      //In the AWAIT RESPONSE state, any TC completion is unexpected.
668230557Sjimharris      //but if the TC has success status, we complete the IO anyway.
669230557Sjimharris      scic_sds_request_set_status(
670230557Sjimharris         this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
671230557Sjimharris      );
672230557Sjimharris
673230557Sjimharris      sci_base_state_machine_change_state(
674230557Sjimharris         &this_request->parent.state_machine,
675230557Sjimharris         SCI_BASE_REQUEST_STATE_COMPLETED
676230557Sjimharris      );
677230557Sjimharris   break;
678230557Sjimharris
679230557Sjimharris   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_RESP_TO_ERR):
680230557Sjimharris   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_UFI_ERR):
681230557Sjimharris   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_FRM_TYPE_ERR):
682230557Sjimharris   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_LL_RX_ERR):
683230557Sjimharris      //These status has been seen in a specific LSI expander, which sometimes
684230557Sjimharris      //is not able to send smp response within 2 ms. This causes our hardware
685230557Sjimharris      //break the connection and set TC completion with one of these SMP_XXX_XX_ERR
686230557Sjimharris      //status. For these type of error, we ask scic user to retry the request.
687230557Sjimharris      scic_sds_request_set_status(
688230557Sjimharris         this_request, SCU_TASK_DONE_SMP_RESP_TO_ERR, SCI_FAILURE_RETRY_REQUIRED
689230557Sjimharris      );
690230557Sjimharris
691230557Sjimharris      sci_base_state_machine_change_state(
692230557Sjimharris         &this_request->parent.state_machine,
693230557Sjimharris         SCI_BASE_REQUEST_STATE_COMPLETED
694230557Sjimharris      );
695230557Sjimharris   break;
696230557Sjimharris
697230557Sjimharris   default:
698230557Sjimharris      // All other completion status cause the IO to be complete.  If a NAK
699230557Sjimharris      // was received, then it is up to the user to retry the request.
700230557Sjimharris      scic_sds_request_set_status(
701230557Sjimharris         this_request,
702230557Sjimharris         SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
703230557Sjimharris         SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
704230557Sjimharris      );
705230557Sjimharris
706230557Sjimharris      sci_base_state_machine_change_state(
707230557Sjimharris         &this_request->parent.state_machine,
708230557Sjimharris         SCI_BASE_REQUEST_STATE_COMPLETED
709230557Sjimharris      );
710230557Sjimharris   break;
711230557Sjimharris   }
712230557Sjimharris
713230557Sjimharris   return SCI_SUCCESS;
714230557Sjimharris}
715230557Sjimharris
716230557Sjimharris
717230557Sjimharris/**
718230557Sjimharris * @brief This method processes the completions transport layer (TL) status
719230557Sjimharris *        to determine if the SMP request was sent successfully. If the SMP
720230557Sjimharris *        request was sent successfully, then the state for the SMP request
721230557Sjimharris *        transits to waiting for a response frame.
722230557Sjimharris *
723230557Sjimharris * @param[in] this_request This parameter specifies the request for which
724230557Sjimharris *            the TC completion was received.
725230557Sjimharris * @param[in] completion_code This parameter indicates the completion status
726230557Sjimharris *            information for the TC.
727230557Sjimharris *
728230557Sjimharris * @return Indicate if the tc completion handler was successful.
729230557Sjimharris * @retval SCI_SUCCESS currently this method always returns success.
730230557Sjimharris */
731230557Sjimharrisstatic
732230557SjimharrisSCI_STATUS scic_sds_smp_request_await_tc_completion_tc_completion_handler(
733230557Sjimharris   SCIC_SDS_REQUEST_T * this_request,
734230557Sjimharris   U32                  completion_code
735230557Sjimharris)
736230557Sjimharris{
737230557Sjimharris   SCIC_LOG_TRACE((
738230557Sjimharris      sci_base_object_get_logger(this_request),
739230557Sjimharris      SCIC_LOG_OBJECT_SMP_IO_REQUEST,
740230557Sjimharris      "scic_sds_smp_request_await_tc_completion_tc_completion_handler(0x%x, 0x%x) enter\n",
741230557Sjimharris      this_request, completion_code
742230557Sjimharris   ));
743230557Sjimharris
744230557Sjimharris   switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
745230557Sjimharris   {
746230557Sjimharris   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
747230557Sjimharris      scic_sds_request_set_status(
748230557Sjimharris         this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
749230557Sjimharris      );
750230557Sjimharris
751230557Sjimharris      sci_base_state_machine_change_state(
752230557Sjimharris         &this_request->parent.state_machine,
753230557Sjimharris         SCI_BASE_REQUEST_STATE_COMPLETED
754230557Sjimharris      );
755230557Sjimharris   break;
756230557Sjimharris
757230557Sjimharris   default:
758230557Sjimharris      // All other completion status cause the IO to be complete.  If a NAK
759230557Sjimharris      // was received, then it is up to the user to retry the request.
760230557Sjimharris      scic_sds_request_set_status(
761230557Sjimharris         this_request,
762230557Sjimharris         SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
763230557Sjimharris         SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
764230557Sjimharris      );
765230557Sjimharris
766230557Sjimharris      sci_base_state_machine_change_state(
767230557Sjimharris         &this_request->parent.state_machine,
768230557Sjimharris         SCI_BASE_REQUEST_STATE_COMPLETED
769230557Sjimharris      );
770230557Sjimharris   break;
771230557Sjimharris   }
772230557Sjimharris
773230557Sjimharris   return SCI_SUCCESS;
774230557Sjimharris}
775230557Sjimharris
776230557Sjimharris
777230557SjimharrisSCIC_SDS_IO_REQUEST_STATE_HANDLER_T
778230557Sjimharrisscic_sds_smp_request_started_substate_handler_table
779230557Sjimharris[SCIC_SDS_SMP_REQUEST_STARTED_MAX_SUBSTATES] =
780230557Sjimharris{
781230557Sjimharris   // SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE
782230557Sjimharris   {
783230557Sjimharris      {
784230557Sjimharris         scic_sds_request_default_start_handler,
785230557Sjimharris         scic_sds_request_started_state_abort_handler,
786230557Sjimharris         scic_sds_request_default_complete_handler,
787230557Sjimharris         scic_sds_request_default_destruct_handler
788230557Sjimharris      },
789230557Sjimharris      scic_sds_smp_request_await_response_tc_completion_handler,
790230557Sjimharris      scic_sds_request_default_event_handler,
791230557Sjimharris      scic_sds_smp_request_await_response_frame_handler
792230557Sjimharris   },
793230557Sjimharris   // SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION
794230557Sjimharris   {
795230557Sjimharris      {
796230557Sjimharris         scic_sds_request_default_start_handler,
797230557Sjimharris         scic_sds_request_started_state_abort_handler,
798230557Sjimharris         scic_sds_request_default_complete_handler,
799230557Sjimharris         scic_sds_request_default_destruct_handler
800230557Sjimharris      },
801230557Sjimharris      scic_sds_smp_request_await_tc_completion_tc_completion_handler,
802230557Sjimharris      scic_sds_request_default_event_handler,
803230557Sjimharris      scic_sds_request_default_frame_handler
804230557Sjimharris   }
805230557Sjimharris};
806230557Sjimharris
807230557Sjimharris/**
808230557Sjimharris * @brief This method performs the actions required when entering the
809230557Sjimharris *        SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_RESPONSE sub-state.
810230557Sjimharris *        This includes setting the IO request state handlers for this
811230557Sjimharris *        sub-state.
812230557Sjimharris *
813230557Sjimharris * @param[in]  object This parameter specifies the request object for which
814230557Sjimharris *             the sub-state change is occuring.
815230557Sjimharris *
816230557Sjimharris * @return none.
817230557Sjimharris */
818230557Sjimharrisstatic
819230557Sjimharrisvoid scic_sds_smp_request_started_await_response_substate_enter(
820230557Sjimharris   SCI_BASE_OBJECT_T *object
821230557Sjimharris)
822230557Sjimharris{
823230557Sjimharris   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
824230557Sjimharris
825230557Sjimharris   SET_STATE_HANDLER(
826230557Sjimharris      this_request,
827230557Sjimharris      scic_sds_smp_request_started_substate_handler_table,
828230557Sjimharris      SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE
829230557Sjimharris   );
830230557Sjimharris}
831230557Sjimharris
832230557Sjimharris/**
833230557Sjimharris * @brief This method performs the actions required when entering the
834230557Sjimharris *        SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION
835230557Sjimharris *        sub-state.  This includes setting the SMP request state handlers for
836230557Sjimharris *        this sub-state.
837230557Sjimharris *
838230557Sjimharris * @param[in]  object This parameter specifies the request object for which
839230557Sjimharris *             the sub-state change is occuring.
840230557Sjimharris *
841230557Sjimharris * @return none.
842230557Sjimharris */
843230557Sjimharrisstatic
844230557Sjimharrisvoid scic_sds_smp_request_started_await_tc_completion_substate_enter(
845230557Sjimharris   SCI_BASE_OBJECT_T *object
846230557Sjimharris)
847230557Sjimharris{
848230557Sjimharris   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
849230557Sjimharris
850230557Sjimharris   SET_STATE_HANDLER(
851230557Sjimharris      this_request,
852230557Sjimharris      scic_sds_smp_request_started_substate_handler_table,
853230557Sjimharris      SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION
854230557Sjimharris   );
855230557Sjimharris}
856230557Sjimharris
857230557SjimharrisSCI_BASE_STATE_T scic_sds_smp_request_started_substate_table
858230557Sjimharris[SCIC_SDS_SMP_REQUEST_STARTED_MAX_SUBSTATES] =
859230557Sjimharris{
860230557Sjimharris   {
861230557Sjimharris      SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE,
862230557Sjimharris      scic_sds_smp_request_started_await_response_substate_enter,
863230557Sjimharris      NULL
864230557Sjimharris   },
865230557Sjimharris   {
866230557Sjimharris      SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION,
867230557Sjimharris      scic_sds_smp_request_started_await_tc_completion_substate_enter,
868230557Sjimharris      NULL
869230557Sjimharris   }
870230557Sjimharris};
871230557Sjimharris
872230557Sjimharris
873