1/*-
2 * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0
3 *
4 * This file is provided under a dual BSD/GPLv2 license.  When using or
5 * redistributing this file, you may do so under either license.
6 *
7 * GPL LICENSE SUMMARY
8 *
9 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of version 2 of the GNU General Public License as
13 * published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
23 * The full GNU General Public License is included in this distribution
24 * in the file called LICENSE.GPL.
25 *
26 * BSD LICENSE
27 *
28 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
29 * All rights reserved.
30 *
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
33 * are met:
34 *
35 *   * Redistributions of source code must retain the above copyright
36 *     notice, this list of conditions and the following disclaimer.
37 *   * Redistributions in binary form must reproduce the above copyright
38 *     notice, this list of conditions and the following disclaimer in
39 *     the documentation and/or other materials provided with the
40 *     distribution.
41 *
42 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
43 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
44 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
45 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
46 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
47 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
48 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
49 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
50 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
51 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
52 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53 */
54
55#include <sys/cdefs.h>
56__FBSDID("$FreeBSD$");
57
58/**
59 * @file
60 *
61 * @brief This file contains the implementation of the SCIF_SAS_IO_REQUEST
62 *        object.
63 */
64
65
66#include <dev/isci/scil/scic_io_request.h>
67#include <dev/isci/scil/scic_remote_device.h>
68#include <dev/isci/scil/scic_user_callback.h>
69#include <dev/isci/scil/scic_controller.h>
70#include <dev/isci/scil/scif_user_callback.h>
71
72#include <dev/isci/scil/scif_sas_controller.h>
73#include <dev/isci/scil/scif_sas_domain.h>
74#include <dev/isci/scil/scif_sas_remote_device.h>
75#include <dev/isci/scil/scif_sas_io_request.h>
76#include <dev/isci/scil/scif_sas_task_request.h>
77#include <dev/isci/scil/scif_sas_stp_io_request.h>
78#include <dev/isci/scil/scif_sas_logger.h>
79#include <dev/isci/scil/scif_sas_smp_io_request.h>
80#include <dev/isci/scil/sci_fast_list.h>
81#include <dev/isci/scil/sati.h>
82#include <dev/isci/scil/intel_sat.h>
83#include <dev/isci/scil/sati_translator_sequence.h>
84
85/**
86 * @brief This method represents common functionality for the
87 *        scif_io_request_construct() and scif_sas_io_request_continue()
88 *        methods.
89 *
90 * @return This method returns an indication as to whether the
91 *         construction succeeded.
92 */
93static
94SCI_STATUS scif_sas_io_request_construct(
95   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
96   SCIF_SAS_IO_REQUEST_T    * fw_io,
97   U16                        io_tag,
98   void                     * user_io_request_object,
99   SCI_IO_REQUEST_HANDLE_T  * scif_io_request,
100   BOOL                       is_initial_construction
101)
102{
103   SCI_STATUS                         status;
104   SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;
105
106   scic_remote_device_get_protocols(fw_device->core_object, &dev_protocols);
107
108   //Currently, all the io requests sent to smp target are internal.
109   //so we fail all the external io toward to it.
110   //Todo: is there a better way to handle external io to smp target?
111   if (dev_protocols.u.bits.attached_smp_target)
112      return SCI_FAILURE_INVALID_REMOTE_DEVICE;
113
114   SCIF_LOG_TRACE((
115      sci_base_object_get_logger(fw_device),
116      SCIF_LOG_OBJECT_IO_REQUEST,
117      "scif_sas_io_request_construct(0x%x,0x%x,0x%x,0x%x,0x%x,0x%x) enter\n",
118      fw_device, fw_io, io_tag, user_io_request_object, scif_io_request,
119      is_initial_construction
120   ));
121
122   // Initialize the users handle to the framework IO request.
123   *scif_io_request = fw_io;
124
125   // Construct the parent object first in order to ensure logging can
126   // function.
127   scif_sas_request_construct(
128      &fw_io->parent,
129      fw_device,
130      sci_base_object_get_logger(fw_device),
131      scif_sas_io_request_state_table
132   );
133
134   status = scic_io_request_construct(
135               fw_device->domain->controller->core_object,
136               fw_device->core_object,
137               io_tag,
138               fw_io,
139               ((U8 *)fw_io) + sizeof(SCIF_SAS_IO_REQUEST_T),
140               &fw_io->parent.core_object
141            );
142
143   if (status == SCI_SUCCESS)
144   {
145      // These associations must be set early for the core io request
146      // object construction to complete correctly as there will be
147      // callbacks into the user driver framework during core construction
148      sci_object_set_association(fw_io, user_io_request_object);
149      sci_object_set_association(fw_io->parent.core_object, fw_io);
150
151      // Perform protocol specific core IO request construction.
152      if (dev_protocols.u.bits.attached_ssp_target)
153         status = scic_io_request_construct_basic_ssp(fw_io->parent.core_object);
154      else if (dev_protocols.u.bits.attached_stp_target)
155      {
156         if (is_initial_construction == TRUE)
157               sati_sequence_construct(&fw_io->parent.stp.sequence);
158
159#if !defined(DISABLE_ATAPI)
160         if (!scic_remote_device_is_atapi(fw_device->core_object))
161         {
162#endif
163            status = scif_sas_stp_io_request_construct(fw_io);
164
165#if !defined(DISABLE_ATAPI)
166         }
167         else
168            status = scif_sas_stp_packet_io_request_construct(fw_io);
169#endif
170      }
171
172      sci_base_state_machine_logger_initialize(
173         &fw_io->parent.parent.state_machine_logger,
174         &fw_io->parent.parent.state_machine,
175         &fw_io->parent.parent.parent,
176         scif_cb_logger_log_states,
177         "SCIF_IO_REQUEST_T", "base_state_machine",
178         SCIF_LOG_OBJECT_IO_REQUEST
179      );
180   }
181
182   return status;
183}
184
185//******************************************************************************
186//* P U B L I C   M E T H O D S
187//******************************************************************************
188
189U32 scif_io_request_get_object_size(
190   void
191)
192{
193   return (sizeof(SCIF_SAS_IO_REQUEST_T) + scic_io_request_get_object_size());
194}
195
196// ----------------------------------------------------------------------------
197U32 scif_io_request_get_number_of_bytes_transferred(
198   SCI_IO_REQUEST_HANDLE_T  scif_io_request
199)
200{
201   SCIF_SAS_IO_REQUEST_T * fw_request = (SCIF_SAS_IO_REQUEST_T*) scif_io_request;
202
203   if(scic_io_request_get_protocol(scif_io_request_get_scic_handle(scif_io_request))
204       == SCIC_STP_PROTOCOL)
205   {
206      U16 sati_data_bytes_set =
207             sati_get_number_data_bytes_set(&(fw_request->parent.stp.sequence));
208
209      if (sati_data_bytes_set != 0)
210         return sati_data_bytes_set;
211      else
212      {
213#if !defined(DISABLE_ATAPI)
214         U8 sat_protocol = fw_request->parent.stp.sequence.protocol;
215         if ( sat_protocol & SAT_PROTOCOL_PACKET)
216            return
217               scif_sas_stp_packet_io_request_get_number_of_bytes_transferred(fw_request);
218         else
219#endif
220            return scic_io_request_get_number_of_bytes_transferred(
221                      scif_io_request_get_scic_handle(scif_io_request));
222      }
223   }
224   else
225   {
226      return scic_io_request_get_number_of_bytes_transferred(
227                scif_io_request_get_scic_handle(scif_io_request));
228   }
229}
230
231// ---------------------------------------------------------------------------
232
233SCI_STATUS scif_io_request_construct(
234   SCI_CONTROLLER_HANDLE_T      scif_controller,
235   SCI_REMOTE_DEVICE_HANDLE_T   scif_remote_device,
236   U16                          io_tag,
237   void                       * user_io_request_object,
238   void                       * io_request_memory,
239   SCI_IO_REQUEST_HANDLE_T    * scif_io_request
240)
241{
242   SCIF_SAS_IO_REQUEST_T    * fw_io     = (SCIF_SAS_IO_REQUEST_T*)
243                                          io_request_memory;
244   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
245                                          scif_remote_device;
246
247   return scif_sas_io_request_construct(
248             fw_device,
249             fw_io,
250             io_tag,
251             user_io_request_object,
252             scif_io_request,
253             TRUE
254          );
255}
256
257// ---------------------------------------------------------------------------
258
259SCI_STATUS scif_request_construct(
260   SCI_CONTROLLER_HANDLE_T      scif_controller,
261   SCI_REMOTE_DEVICE_HANDLE_T   scif_remote_device,
262   U16                          io_tag,
263   void                       * user_io_request_object,
264   void                       * io_request_memory,
265   SCI_IO_REQUEST_HANDLE_T    * scif_io_request
266)
267{
268   SCIF_SAS_IO_REQUEST_T    * fw_io     = (SCIF_SAS_IO_REQUEST_T*)
269                                          io_request_memory;
270   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
271                                          scif_remote_device;
272   SCI_STATUS                 status;
273
274   SCIF_LOG_TRACE((
275      sci_base_object_get_logger(fw_device),
276      SCIF_LOG_OBJECT_IO_REQUEST,
277      "scif_io_request_construct(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x) enter\n",
278      scif_controller, scif_remote_device, io_tag, user_io_request_object,
279      io_request_memory, scif_io_request
280   ));
281
282   // Step 1: Create the scif io request.
283   // Initialize the users handle to the framework IO request.
284   *scif_io_request = fw_io;
285
286   // Construct the parent object first in order to ensure logging can
287   // function.
288   scif_sas_request_construct(
289      &fw_io->parent,
290      fw_device,
291      sci_base_object_get_logger(fw_device),
292      scif_sas_io_request_state_table
293   );
294
295   status = scic_io_request_construct(
296               (void *) ((SCIF_SAS_CONTROLLER_T *)scif_controller)->core_object,
297               (void *) fw_device->core_object,
298               io_tag,
299               fw_io,
300               (U8 *)io_request_memory + sizeof(SCIF_SAS_IO_REQUEST_T),
301               &fw_io->parent.core_object
302            );
303
304   if (status == SCI_SUCCESS)
305   {
306      // These associations must be set early for the core io request
307      // object construction to complete correctly as there will be
308      // callbacks into the user driver framework during core construction
309      sci_object_set_association(fw_io, user_io_request_object);
310      sci_object_set_association(fw_io->parent.core_object, fw_io);
311
312      sci_base_state_machine_logger_initialize(
313         &fw_io->parent.parent.state_machine_logger,
314         &fw_io->parent.parent.state_machine,
315         &fw_io->parent.parent.parent,
316         scif_cb_logger_log_states,
317         "SCIF_IO_REQUEST_T", "base_state_machine",
318         SCIF_LOG_OBJECT_IO_REQUEST
319      );
320   }
321
322   return status;
323}
324
325// ----------------------------------------------------------------------------
326
327SCI_STATUS scif_io_request_construct_with_core (
328   SCI_CONTROLLER_HANDLE_T      scif_controller,
329   SCI_REMOTE_DEVICE_HANDLE_T   scif_remote_device,
330   void                       * scic_io_request,
331   void                       * user_io_request_object,
332   void                       * io_request_memory,
333   SCI_IO_REQUEST_HANDLE_T    * scif_io_request
334)
335{
336   SCIF_SAS_IO_REQUEST_T    * fw_io     = (SCIF_SAS_IO_REQUEST_T*)
337                                          io_request_memory;
338   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
339                                          scif_remote_device;
340   SCI_STATUS                 status = SCI_SUCCESS;
341
342   SCIF_LOG_TRACE((
343      sci_base_object_get_logger(fw_device),
344      SCIF_LOG_OBJECT_IO_REQUEST,
345      "scif_io_request_construct_pass_through(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
346      scif_remote_device, user_io_request_object,
347      io_request_memory, scif_io_request
348   ));
349
350   // Initialize the users handle to the framework IO request.
351   *scif_io_request = fw_io;
352
353   // Construct the parent object first in order to ensure logging can
354   // function.
355   scif_sas_request_construct(
356      &fw_io->parent,
357      fw_device,
358      sci_base_object_get_logger(fw_device),
359      scif_sas_io_request_state_table
360   );
361
362   fw_io->parent.core_object = scic_io_request;
363
364   //set association
365   sci_object_set_association(fw_io, user_io_request_object);
366   sci_object_set_association(fw_io->parent.core_object, fw_io);
367
368
369   sci_base_state_machine_logger_initialize(
370      &fw_io->parent.parent.state_machine_logger,
371      &fw_io->parent.parent.state_machine,
372      &fw_io->parent.parent.parent,
373      scif_cb_logger_log_states,
374      "SCIF_IO_REQUEST_T", "base_state_machine",
375      SCIF_LOG_OBJECT_IO_REQUEST
376   );
377
378   return status;
379}
380
381// ---------------------------------------------------------------------------
382
383void * scif_io_request_get_response_iu_address(
384   SCI_IO_REQUEST_HANDLE_T scif_io_request
385)
386{
387   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*)scif_io_request;
388
389   return (scic_io_request_get_response_iu_address(fw_io->parent.core_object ));
390}
391
392// ---------------------------------------------------------------------------
393
394SCI_IO_REQUEST_HANDLE_T scif_io_request_get_scic_handle(
395   SCI_IO_REQUEST_HANDLE_T scif_io_request
396)
397{
398   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*) scif_io_request;
399   return fw_io->parent.core_object;
400}
401
402// ---------------------------------------------------------------------------
403
404void scic_cb_io_request_complete(
405   SCI_CONTROLLER_HANDLE_T     controller,
406   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
407   SCI_IO_REQUEST_HANDLE_T     io_request,
408   SCI_IO_STATUS               completion_status
409)
410{
411   SCI_STATUS                 status;
412   SCIF_SAS_CONTROLLER_T    * fw_controller = (SCIF_SAS_CONTROLLER_T*)
413                                      sci_object_get_association(controller);
414   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
415                                      sci_object_get_association(remote_device);
416   SCIF_SAS_REQUEST_T       * fw_request = (SCIF_SAS_REQUEST_T*)
417                                      sci_object_get_association(io_request);
418
419   SCIF_LOG_TRACE((
420      sci_base_object_get_logger(controller),
421      SCIF_LOG_OBJECT_IO_REQUEST,
422      "scic_cb_io_request_complete(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
423      controller, remote_device, io_request, completion_status
424   ));
425
426   // Invoke the common completion handler routine.
427   // A non-successful return indicates we are not in a correct state to
428   // receive a completion notification for this request.
429   status = fw_request->state_handlers->complete_handler(&fw_request->parent);
430
431   // If the status indicates the completion handler was successful, then
432   // allow protocol specific completion processing to occur.
433   if (status == SCI_SUCCESS)
434   {
435      if (fw_request->protocol_complete_handler != NULL)
436      {
437         status = fw_request->protocol_complete_handler(
438                     fw_controller, fw_device, fw_request, (SCI_STATUS *)&completion_status
439                  );
440      }
441
442      // If this isn't an internal framework IO request, then simply pass the
443      // notification up to the SCIF user.
444      if ( status == SCI_SUCCESS )
445      {
446         if (fw_request->is_high_priority == FALSE)
447         {
448            if (fw_request->is_waiting_for_abort_task_set == FALSE)
449            {
450               scif_cb_io_request_complete(
451                  fw_controller, fw_device, fw_request, completion_status);
452            }
453            else
454            {
455               // do nothing - will complete the I/O when the abort task
456               //  set completes
457            }
458         }
459         else
460            scif_sas_controller_complete_high_priority_io(
461               fw_controller, fw_device, fw_request);
462      }
463      else if ( status == SCI_WARNING_SEQUENCE_INCOMPLETE )
464      {
465         scif_sas_io_request_continue(fw_controller, fw_device, fw_request);
466      }
467   }
468}
469
470// ---------------------------------------------------------------------------
471
472U32 scic_cb_io_request_get_transfer_length(
473   void * scic_user_io_request
474)
475{
476   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*)
477                                   scic_user_io_request;
478
479   return (scif_cb_io_request_get_transfer_length(
480             fw_io->parent.parent.parent.associated_object
481           ));
482}
483
484// ---------------------------------------------------------------------------
485
486SCI_IO_REQUEST_DATA_DIRECTION scic_cb_io_request_get_data_direction(
487   void * scic_user_io_request
488)
489{
490   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*)
491                                   scic_user_io_request;
492
493   return (scif_cb_io_request_get_data_direction(
494             fw_io->parent.parent.parent.associated_object
495          ));
496}
497
498// ---------------------------------------------------------------------------
499#ifndef SCI_SGL_OPTIMIZATION_ENABLED
500void scic_cb_io_request_get_next_sge(
501   void * scic_user_io_request,
502   void * current_sge_address,
503   void **next_sge
504)
505{
506   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*)
507                                   scic_user_io_request;
508
509   scif_cb_io_request_get_next_sge(
510      fw_io->parent.parent.parent.associated_object,
511      current_sge_address,
512      next_sge
513   );
514}
515#endif
516
517// ---------------------------------------------------------------------------
518
519SCI_PHYSICAL_ADDRESS scic_cb_sge_get_address_field(
520   void * scic_user_io_request,
521   void * sge_address
522)
523{
524   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*)
525                                   scic_user_io_request;
526   return scif_cb_sge_get_address_field(
527             fw_io->parent.parent.parent.associated_object, sge_address
528          );
529}
530
531// ---------------------------------------------------------------------------
532
533U32 scic_cb_sge_get_length_field(
534   void * scic_user_io_request,
535   void * sge_address
536)
537{
538   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*)
539                                   scic_user_io_request;
540
541   return scif_cb_sge_get_length_field(
542             fw_io->parent.parent.parent.associated_object,
543             sge_address
544          );
545}
546
547// ---------------------------------------------------------------------------
548
549void * scic_cb_ssp_io_request_get_cdb_address(
550   void * scic_user_io_request
551)
552{
553   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*)
554                                   scic_user_io_request;
555
556   return scif_cb_io_request_get_cdb_address(
557             fw_io->parent.parent.parent.associated_object
558          );
559}
560
561// ---------------------------------------------------------------------------
562
563U32 scic_cb_ssp_io_request_get_cdb_length(
564   void * scic_user_io_request
565)
566{
567   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*)
568                                   scic_user_io_request;
569
570   return scif_cb_io_request_get_cdb_length(
571             fw_io->parent.parent.parent.associated_object
572          );
573}
574
575// ---------------------------------------------------------------------------
576
577#if !defined(DISABLE_ATAPI)
578void * scic_cb_stp_packet_io_request_get_cdb_address(
579   void * scic_user_io_request
580)
581{
582   SCIF_SAS_REQUEST_T * fw_request = (SCIF_SAS_REQUEST_T*)scic_user_io_request;
583
584   SATI_TRANSLATOR_SEQUENCE_T * sati_sequence = &fw_request->stp.sequence;
585
586   if (sati_sequence->state != SATI_SEQUENCE_STATE_INCOMPLETE)
587      return scif_cb_io_request_get_cdb_address(
588                fw_request->parent.parent.associated_object
589             );
590   else
591      return
592      &(sati_sequence->command_specific_data.sati_atapi_data.request_sense_cdb);
593}
594#endif
595
596// ---------------------------------------------------------------------------
597
598#if !defined(DISABLE_ATAPI)
599U32 scic_cb_stp_packet_io_request_get_cdb_length(
600   void * scic_user_io_request
601)
602{
603   SCIF_SAS_REQUEST_T * fw_request = (SCIF_SAS_REQUEST_T*)
604                                   scic_user_io_request;
605
606   SATI_TRANSLATOR_SEQUENCE_T * sati_sequence = &fw_request->stp.sequence;
607
608   if (sati_sequence->state != SATI_SEQUENCE_STATE_INCOMPLETE)
609      return scif_cb_io_request_get_cdb_length(
610                fw_request->parent.parent.associated_object
611             );
612   else
613      return SATI_ATAPI_REQUEST_SENSE_CDB_LENGTH;
614}
615#endif
616
617// ---------------------------------------------------------------------------
618
619U32 scic_cb_ssp_io_request_get_lun(
620   void * scic_user_io_request
621)
622{
623   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*)
624                                   scic_user_io_request;
625
626   return scif_cb_io_request_get_lun(
627             fw_io->parent.parent.parent.associated_object
628          );
629}
630
631// ---------------------------------------------------------------------------
632
633U32 scic_cb_ssp_io_request_get_task_attribute(
634   void * scic_user_io_request
635)
636{
637   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*)
638                                   scic_user_io_request;
639
640   return scif_cb_io_request_get_task_attribute(
641             fw_io->parent.parent.parent.associated_object
642          );
643}
644
645// ---------------------------------------------------------------------------
646
647U32 scic_cb_ssp_io_request_get_command_priority(
648   void * scic_user_io_request
649)
650{
651   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*)
652                                   scic_user_io_request;
653
654   return scif_cb_io_request_get_command_priority(
655             fw_io->parent.parent.parent.associated_object
656          );
657}
658
659// ---------------------------------------------------------------------------
660
661BOOL scic_cb_request_is_initial_construction(
662   void * scic_user_io_request
663)
664{
665   SCIF_SAS_REQUEST_T * fw_request = (SCIF_SAS_REQUEST_T*)
666                                   scic_user_io_request;
667   SCIF_SAS_REMOTE_DEVICE_T* fw_device = fw_request->device;
668
669   SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;
670   scic_remote_device_get_protocols(fw_device->core_object, &dev_protocols);
671
672   if (dev_protocols.u.bits.attached_stp_target
673       && fw_request->stp.sequence.state == SATI_SEQUENCE_STATE_INCOMPLETE)
674      return FALSE;
675
676   return TRUE;
677}
678
679
680//******************************************************************************
681//* P R O T E C T E D   M E T H O D S
682//******************************************************************************
683/**
684 * @brief This method constructs an scif sas smp request.
685 *
686 * @param[in] fw_controller The framework controller
687 * @param[in] fw_device The smp device that the smp request targets to.
688 * @param[in] fw_io_memory The memory space for the smp request.
689 * @param[in] core_io_memory The memory space for the core request.
690 * @param[in] io_tag The io tag for the internl io to be constructed.
691 * @param[in] smp_command A pointer to the smp request data structure according
692 *       to SAS protocol.
693 *
694 * @return Indicate if the internal io was successfully constructed.
695 * @retval SCI_SUCCESS This value is returned if the internal io was
696 *         successfully constructed.
697 * @retval SCI_FAILURE This value is returned if the internal io was failed to
698 *         be constructed.
699 */
700SCI_STATUS scif_sas_io_request_construct_smp(
701   SCIF_SAS_CONTROLLER_T       * fw_controller,
702   SCIF_SAS_REMOTE_DEVICE_T    * fw_device,
703   void                        * fw_io_memory,
704   void                        * core_io_memory,
705   U16                           io_tag,
706   SMP_REQUEST_T               * smp_command,
707   void                        * user_request_object
708)
709{
710   SCIF_SAS_IO_REQUEST_T * fw_io =
711     (SCIF_SAS_IO_REQUEST_T*)fw_io_memory;
712
713   SCI_STATUS status = SCI_SUCCESS;
714
715   SCIF_LOG_TRACE((
716      sci_base_object_get_logger(fw_device),
717      SCIF_LOG_OBJECT_IO_REQUEST,
718      "scif_sas_io_request_construct_smp(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x) enter\n",
719      fw_controller,
720      fw_device,
721      fw_io_memory,
722      core_io_memory,
723      io_tag,
724      smp_command,
725      user_request_object
726   ));
727
728   // Construct the parent object first in order to ensure logging can
729   // function.
730   scif_sas_request_construct(
731      &fw_io->parent,
732      fw_device,
733      sci_base_object_get_logger(fw_controller),
734      scif_sas_io_request_state_table
735   );
736
737   status = scic_io_request_construct(
738               fw_device->domain->controller->core_object,
739               fw_device->core_object,
740               io_tag,
741               (void*)fw_io,
742               (U8 *)core_io_memory,
743               &fw_io->parent.core_object
744            );
745
746   if (status == SCI_SUCCESS)
747   {
748      //set object association.
749      sci_object_set_association(fw_io, user_request_object);
750      sci_object_set_association(fw_io->parent.core_object, fw_io);
751
752      scif_sas_smp_request_construct(&fw_io->parent, smp_command);
753
754      fw_io->parent.is_high_priority = TRUE;
755
756      sci_base_state_machine_logger_initialize(
757         &fw_io->parent.parent.state_machine_logger,
758         &fw_io->parent.parent.state_machine,
759         &fw_io->parent.parent.parent,
760         scif_cb_logger_log_states,
761         "SCIF_IO_REQUEST_T", "base_state_machine",
762         SCIF_LOG_OBJECT_IO_REQUEST
763      );
764   }
765
766   return status;
767}
768
769
770/**
771 * @brief This method continues a scif sas request.
772 *
773 * @param[in] fw_controller The framework controller
774 * @param[in] fw_device The device that the IO request targets to.
775 * @param[in] fw_request The IO request to be continued.
776 *
777 * @return Indicate if the internal io was successfully constructed.
778 * @retval SCI_SUCCESS This value is returned if the internal io was
779 *         successfully continued.
780 * @retval SCI_FAILURE This value is returned if the io was failed to
781 *         be continued.
782 */
783SCI_STATUS scif_sas_io_request_continue(
784   SCIF_SAS_CONTROLLER_T       * fw_controller,
785   SCIF_SAS_REMOTE_DEVICE_T    * fw_device,
786   SCIF_SAS_REQUEST_T          * fw_request
787)
788{
789   SCI_IO_REQUEST_HANDLE_T dummy_handle;
790
791   SCIF_LOG_TRACE((
792      sci_base_object_get_logger(fw_request),
793      SCIF_LOG_OBJECT_IO_REQUEST,
794      "scif_sas_io_request_continue(0x%x, 0x%x, 0x%x) enter\n",
795      fw_controller,
796      fw_device,
797      fw_request
798   ));
799
800   //complete this io request in framework and core.
801   scif_controller_complete_io(fw_controller, fw_device, fw_request);
802
803   //construct next command in the sequence using the same memory. We pass
804   //a dummy pointer to let the framework user keep the pointer to this IO
805   //request untouched.
806   scif_sas_io_request_construct(
807      fw_device,
808      (SCIF_SAS_IO_REQUEST_T*)fw_request,
809      SCI_CONTROLLER_INVALID_IO_TAG,
810      (void *)sci_object_get_association(fw_request),
811      &dummy_handle,
812      FALSE
813   );
814
815   //start the new constructed IO.
816   return (SCI_STATUS)scif_controller_start_io(
817             (SCI_CONTROLLER_HANDLE_T) fw_controller,
818             (SCI_REMOTE_DEVICE_HANDLE_T) fw_device,
819             (SCI_IO_REQUEST_HANDLE_T) fw_request,
820             SCI_CONTROLLER_INVALID_IO_TAG
821          );
822}
823