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 for the operations on an
62 * SCIC_SDS_IO_REQUEST object.
63 */
64
65 #include <dev/isci/scil/intel_sat.h>
66 #include <dev/isci/scil/intel_sata.h>
67 #include <dev/isci/scil/intel_sas.h>
68 #include <dev/isci/scil/sci_util.h>
69 #include <dev/isci/scil/sci_base_request.h>
70 #include <dev/isci/scil/scic_controller.h>
71 #include <dev/isci/scil/scic_io_request.h>
72 #include <dev/isci/scil/scic_remote_device.h>
73 #include <dev/isci/scil/scic_user_callback.h>
74 #include <dev/isci/scil/scic_sds_logger.h>
75 #include <dev/isci/scil/scic_sds_request.h>
76 #include <dev/isci/scil/scic_sds_pci.h>
77 #include <dev/isci/scil/scic_sds_stp_request.h>
78 #include <dev/isci/scil/scic_sds_controller.h>
79 #include <dev/isci/scil/scic_sds_controller_registers.h>
80 #include <dev/isci/scil/scic_sds_remote_device.h>
81 #include <dev/isci/scil/scic_sds_port.h>
82 #include <dev/isci/scil/scic_task_request.h>
83 #include <dev/isci/scil/scu_constants.h>
84 #include <dev/isci/scil/scu_task_context.h>
85 #include <dev/isci/scil/scic_sds_smp_request.h>
86 #include <dev/isci/sci_environment.h>
87 #include <dev/isci/scil/scic_sds_unsolicited_frame_control.h>
88 #include <dev/isci/scil/sci_types.h>
89 #include <dev/isci/scil/scu_completion_codes.h>
90 #include <dev/isci/scil/intel_scsi.h>
91
92 #if !defined(DISABLE_ATAPI)
93 #include <dev/isci/scil/scic_sds_stp_packet_request.h>
94 #endif
95
96 /**
97 * @struct SCI_SINGLE_LEVEL_LUN
98 *
99 * @brief this struct describes the single level LUN structure
100 * as per the SAM 4.
101 */
102 typedef struct SCI_SINGLE_LEVEL_LUN
103 {
104 U8 bus_id : 6;
105 U8 address_method : 2;
106 U8 lun_number;
107 U8 second_level_lun[2];
108 U8 third_level_lun[2];
109 U8 forth_level_lun[2];
110
111 } SCI_SINGLE_LEVEL_LUN_T;
112
113
114 //****************************************************************************
115 //* SCIC SDS IO REQUEST CONSTANTS
116 //****************************************************************************
117
118 /**
119 * We have no timer requirements for IO requests right now
120 */
121 #define SCIC_SDS_IO_REQUEST_MINIMUM_TIMER_COUNT (0)
122 #define SCIC_SDS_IO_REQUEST_MAXIMUM_TIMER_COUNT (0)
123
124 //****************************************************************************
125 //* SCIC SDS IO REQUEST MACROS
126 //****************************************************************************
127
128 /**
129 * This is a helper macro to return the os handle for this request object.
130 */
131 #define scic_sds_request_get_user_request(request) \
132 ((request)->user_request)
133
134
135 /**
136 * This macro returns the sizeof memory required to store the an SSP IO
137 * request. This does not include the size of the SGL or SCU Task Context
138 * memory.The sizeof(U32) are needed for DWORD alignment of the command IU
139 * and response IU
140 */
141 #define scic_ssp_io_request_get_object_size() \
142 ( \
143 sizeof(SCI_SSP_COMMAND_IU_T) \
144 + sizeof (U32) \
145 + sizeof(SCI_SSP_RESPONSE_IU_T) \
146 + sizeof (U32) \
147 )
148
149 /**
150 * This macro returns the address of the ssp command buffer in the io
151 * request memory
152 */
153 #define scic_sds_ssp_request_get_command_buffer_unaligned(memory) \
154 ((SCI_SSP_COMMAND_IU_T *)( \
155 ((char *)(memory)) + sizeof(SCIC_SDS_REQUEST_T) \
156 ))
157
158 /**
159 * This macro aligns the ssp command buffer in DWORD alignment
160 */
161 #define scic_sds_ssp_request_align_command_buffer(address) \
162 ((SCI_SSP_COMMAND_IU_T *)( \
163 (((POINTER_UINT)(address)) + (sizeof(U32) - 1)) \
164 & ~(sizeof(U32)- 1) \
165 ))
166
167 /**
168 * This macro returns the DWORD-aligned ssp command buffer
169 */
170 #define scic_sds_ssp_request_get_command_buffer(memory) \
171 ((SCI_SSP_COMMAND_IU_T *) \
172 ((char *)scic_sds_ssp_request_align_command_buffer( \
173 (char *) scic_sds_ssp_request_get_command_buffer_unaligned(memory) \
174 )))
175
176 /**
177 * This macro returns the address of the ssp response buffer in the io
178 * request memory
179 */
180 #define scic_sds_ssp_request_get_response_buffer_unaligned(memory) \
181 ((SCI_SSP_RESPONSE_IU_T *)( \
182 ((char *)(scic_sds_ssp_request_get_command_buffer(memory))) \
183 + sizeof(SCI_SSP_COMMAND_IU_T) \
184 ))
185
186 /**
187 * This macro aligns the ssp response buffer in DWORD-aligned fashion
188 */
189 #define scic_sds_ssp_request_align_response_buffer(memory) \
190 ((SCI_SSP_RESPONSE_IU_T *)( \
191 (((POINTER_UINT)(memory)) + (sizeof(U32) - 1)) \
192 & ~(sizeof(U32)- 1) \
193 ))
194
195 /**
196 * This macro returns the DWORD-aligned ssp response buffer
197 */
198 #define scic_sds_ssp_request_get_response_buffer(memory) \
199 ((SCI_SSP_RESPONSE_IU_T *) \
200 ((char *)scic_sds_ssp_request_align_response_buffer ( \
201 (char *)scic_sds_ssp_request_get_response_buffer_unaligned(memory) \
202 )))
203
204 /**
205 * This macro returns the address of the task context buffer in the io
206 * request memory
207 */
208 #define scic_sds_ssp_request_get_task_context_buffer_unaligned(memory) \
209 ((SCU_TASK_CONTEXT_T *)( \
210 ((char *)(scic_sds_ssp_request_get_response_buffer(memory))) \
211 + sizeof(SCI_SSP_RESPONSE_IU_T) \
212 ))
213
214 /**
215 * This macro returns the aligned task context buffer
216 */
217 #define scic_sds_ssp_request_get_task_context_buffer(memory) \
218 ((SCU_TASK_CONTEXT_T *)( \
219 ((char *)scic_sds_request_align_task_context_buffer( \
220 (char *)scic_sds_ssp_request_get_task_context_buffer_unaligned(memory)) \
221 )))
222
223 /**
224 * This macro returns the address of the sgl elment pairs in the io request
225 * memory buffer
226 */
227 #define scic_sds_ssp_request_get_sgl_element_buffer(memory) \
228 ((SCU_SGL_ELEMENT_PAIR_T *)( \
229 ((char *)(scic_sds_ssp_request_get_task_context_buffer(memory))) \
230 + sizeof(SCU_TASK_CONTEXT_T) \
231 ))
232
233 #if !defined(DISABLE_TASK_MANAGEMENT)
234
235 /**
236 * This macro returns the sizeof of memory required to store an SSP Task
237 * request. This does not include the size of the SCU Task Context memory.
238 */
239 #define scic_ssp_task_request_get_object_size() \
240 ( \
241 sizeof(SCI_SSP_TASK_IU_T) \
242 + sizeof(SCI_SSP_RESPONSE_IU_T) \
243 )
244
245 /**
246 * This macro returns the address of the ssp command buffer in the task
247 * request memory. Yes its the same as the above macro except for the
248 * name.
249 */
250 #define scic_sds_ssp_task_request_get_command_buffer(memory) \
251 ((SCI_SSP_TASK_IU_T *)( \
252 ((char *)(memory)) + sizeof(SCIC_SDS_REQUEST_T) \
253 ))
254
255 /**
256 * This macro returns the address of the ssp response buffer in the task
257 * request memory.
258 */
259 #define scic_sds_ssp_task_request_get_response_buffer(memory) \
260 ((SCI_SSP_RESPONSE_IU_T *)( \
261 ((char *)(scic_sds_ssp_task_request_get_command_buffer(memory))) \
262 + sizeof(SCI_SSP_TASK_IU_T) \
263 ))
264
265 /**
266 * This macro returs the task context buffer for the SSP task request.
267 */
268 #define scic_sds_ssp_task_request_get_task_context_buffer(memory) \
269 ((SCU_TASK_CONTEXT_T *)( \
270 ((char *)(scic_sds_ssp_task_request_get_response_buffer(memory))) \
271 + sizeof(SCI_SSP_RESPONSE_IU_T) \
272 ))
273
274 #endif // !defined(DISABLE_TASK_MANAGEMENT)
275
276
277 //****************************************************************************
278 //* SCIC SDS IO REQUEST PRIVATE METHODS
279 //****************************************************************************
280
281 #ifdef SCI_LOGGING
282 /**
283 * This method will initialize state transition logging for the task request
284 * object.
285 *
286 * @param[in] this_request This is the request for which to track state
287 * transitions.
288 */
289 void scic_sds_request_initialize_state_logging(
290 SCIC_SDS_REQUEST_T *this_request
291 )
292 {
293 sci_base_state_machine_logger_initialize(
294 &this_request->parent.state_machine_logger,
295 &this_request->parent.state_machine,
296 &this_request->parent.parent,
297 scic_cb_logger_log_states,
298 this_request->is_task_management_request ?
299 "SCIC_SDS_IO_REQUEST_T(Task)" : "SCIC_SDS_IO_REQUEST_T(IO)",
300 "base state machine",
301 SCIC_LOG_OBJECT_SMP_IO_REQUEST |
302 SCIC_LOG_OBJECT_STP_IO_REQUEST |
303 SCIC_LOG_OBJECT_SSP_IO_REQUEST
304 );
305
306 if (this_request->has_started_substate_machine)
307 {
308 sci_base_state_machine_logger_initialize(
309 &this_request->started_substate_machine_logger,
310 &this_request->started_substate_machine,
311 &this_request->parent.parent,
312 scic_cb_logger_log_states,
313 "SCIC_SDS_IO_REQUEST_T(Task)", "starting substate machine",
314 SCIC_LOG_OBJECT_SMP_IO_REQUEST |
315 SCIC_LOG_OBJECT_STP_IO_REQUEST |
316 SCIC_LOG_OBJECT_SSP_IO_REQUEST
317 );
318 }
319 }
320
321 /**
322 * This method will stop the state transition logging for the task request
323 * object.
324 *
325 * @param[in] this_request The task request object on which to stop state
326 * transition logging.
327 */
328 void scic_sds_request_deinitialize_state_logging(
329 SCIC_SDS_REQUEST_T *this_request
330 )
331 {
332 sci_base_state_machine_logger_deinitialize(
333 &this_request->parent.state_machine_logger,
334 &this_request->parent.state_machine
335 );
336
337 if (this_request->has_started_substate_machine)
338 {
339 sci_base_state_machine_logger_deinitialize(
340 &this_request->started_substate_machine_logger,
341 &this_request->started_substate_machine
342 );
343 }
344 }
345 #endif // SCI_LOGGING
346
347 /**
348 * This method returns the size required to store an SSP IO request object.
349 *
350 * @return U32
351 */
352 static
353 U32 scic_sds_ssp_request_get_object_size(void)
354 {
355 return sizeof(SCIC_SDS_REQUEST_T)
356 + scic_ssp_io_request_get_object_size()
357 + sizeof(SCU_TASK_CONTEXT_T)
358 + CACHE_LINE_SIZE
359 + sizeof(SCU_SGL_ELEMENT_PAIR_T) * SCU_MAX_SGL_ELEMENT_PAIRS;
360 }
361
362 /**
363 * @brief This method returns the sgl element pair for the specificed
364 * sgl_pair index.
365 *
366 * @param[in] this_request This parameter specifies the IO request for which
367 * to retrieve the Scatter-Gather List element pair.
368 * @param[in] sgl_pair_index This parameter specifies the index into the SGL
369 * element pair to be retrieved.
370 *
371 * @return This method returns a pointer to an SCU_SGL_ELEMENT_PAIR.
372 */
373 SCU_SGL_ELEMENT_PAIR_T *scic_sds_request_get_sgl_element_pair(
374 SCIC_SDS_REQUEST_T *this_request,
375 U32 sgl_pair_index
376 )
377 {
378 SCU_TASK_CONTEXT_T *task_context;
379
380 task_context = (SCU_TASK_CONTEXT_T *)this_request->task_context_buffer;
381
382 if (sgl_pair_index == 0)
383 {
384 return &task_context->sgl_pair_ab;
385 }
386 else if (sgl_pair_index == 1)
387 {
388 return &task_context->sgl_pair_cd;
389 }
390
391 return &this_request->sgl_element_pair_buffer[sgl_pair_index - 2];
392 }
393
394 /**
395 * @brief This function will build the SGL list for an IO request.
396 *
397 * @param[in] this_request This parameter specifies the IO request for which
398 * to build the Scatter-Gather List.
399 *
400 * @return none
401 */
402 void scic_sds_request_build_sgl(
403 SCIC_SDS_REQUEST_T *this_request
404 )
405 {
406 void *os_sge;
407 void *os_handle;
408 SCI_PHYSICAL_ADDRESS physical_address;
409 U32 sgl_pair_index = 0;
410 SCU_SGL_ELEMENT_PAIR_T *scu_sgl_list = NULL;
411 SCU_SGL_ELEMENT_PAIR_T *previous_pair = NULL;
412
413 os_handle = scic_sds_request_get_user_request(this_request);
414 scic_cb_io_request_get_next_sge(os_handle, NULL, &os_sge);
415
416 while (os_sge != NULL)
417 {
418 scu_sgl_list =
419 scic_sds_request_get_sgl_element_pair(this_request, sgl_pair_index);
420
421 SCU_SGL_COPY(os_handle, scu_sgl_list->A, os_sge);
422
423 scic_cb_io_request_get_next_sge(os_handle, os_sge, &os_sge);
424
425 if (os_sge != NULL)
426 {
427 SCU_SGL_COPY(os_handle, scu_sgl_list->B, os_sge);
428
429 scic_cb_io_request_get_next_sge(os_handle, os_sge, &os_sge);
430 }
431 else
432 {
433 SCU_SGL_ZERO(scu_sgl_list->B);
434 }
435
436 if (previous_pair != NULL)
437 {
438 scic_cb_io_request_get_physical_address(
439 scic_sds_request_get_controller(this_request),
440 this_request,
441 scu_sgl_list,
442 &physical_address
443 );
444
445 previous_pair->next_pair_upper =
446 sci_cb_physical_address_upper(physical_address);
447 previous_pair->next_pair_lower =
448 sci_cb_physical_address_lower(physical_address);
449 }
450
451 previous_pair = scu_sgl_list;
452 sgl_pair_index++;
453 }
454
455 if (scu_sgl_list != NULL)
456 {
457 scu_sgl_list->next_pair_upper = 0;
458 scu_sgl_list->next_pair_lower = 0;
459 }
460 }
461
462 /**
463 * @brief This method initializes common portions of the io request object.
464 * This includes construction of the SCI_BASE_REQUEST_T parent.
465 *
466 * @param[in] the_controller This parameter specifies the controller for which
467 * the request is being constructed.
468 * @param[in] the_target This parameter specifies the remote device for which
469 * the request is being constructed.
470 * @param[in] io_tag This parameter specifies the IO tag to be utilized for
471 * this request. This parameter can be set to
472 * SCI_CONTROLLER_INVALID_IO_TAG.
473 * @param[in] user_io_request_object This parameter specifies the user
474 * request object for which the request is being constructed.
475 * @param[in] this_request This parameter specifies the request being
476 * constructed.
477 *
478 * @return none
479 */
480 static
481 void scic_sds_general_request_construct(
482 SCIC_SDS_CONTROLLER_T * the_controller,
483 SCIC_SDS_REMOTE_DEVICE_T * the_target,
484 U16 io_tag,
485 void * user_io_request_object,
486 SCIC_SDS_REQUEST_T * this_request
487 )
488 {
489 sci_base_request_construct(
490 &this_request->parent,
491 sci_base_object_get_logger(the_controller),
492 scic_sds_request_state_table
493 );
494
495 this_request->io_tag = io_tag;
496 this_request->user_request = user_io_request_object;
497 this_request->owning_controller = the_controller;
498 this_request->target_device = the_target;
499 this_request->has_started_substate_machine = FALSE;
500 this_request->protocol = SCIC_NO_PROTOCOL;
501 this_request->sat_protocol = 0xFF;
502 this_request->saved_rx_frame_index = SCU_INVALID_FRAME_INDEX;
503 this_request->device_sequence = scic_sds_remote_device_get_sequence(the_target);
504
505 this_request->sci_status = SCI_SUCCESS;
506 this_request->scu_status = 0;
507 this_request->post_context = 0xFFFFFFFF;
508
509 this_request->is_task_management_request = FALSE;
510
511 if (io_tag == SCI_CONTROLLER_INVALID_IO_TAG)
512 {
513 this_request->was_tag_assigned_by_user = FALSE;
514 this_request->task_context_buffer = NULL;
515 }
516 else
517 {
518 this_request->was_tag_assigned_by_user = TRUE;
519
520 this_request->task_context_buffer =
521 scic_sds_controller_get_task_context_buffer(
522 this_request->owning_controller, io_tag);
523 }
524 }
525
526 /**
527 * @brief This method build the remainder of the IO request object.
528 *
529 * @pre The scic_sds_general_request_construct() must be called before this
530 * call is valid.
531 *
532 * @param[in] this_request This parameter specifies the request object being
533 * constructed.
534 *
535 * @return none
536 */
537 void scic_sds_ssp_io_request_assign_buffers(
538 SCIC_SDS_REQUEST_T *this_request
539 )
540 {
541 this_request->command_buffer =
542 scic_sds_ssp_request_get_command_buffer(this_request);
543 this_request->response_buffer =
544 scic_sds_ssp_request_get_response_buffer(this_request);
545 this_request->sgl_element_pair_buffer =
546 scic_sds_ssp_request_get_sgl_element_buffer(this_request);
547 this_request->sgl_element_pair_buffer =
548 scic_sds_request_align_sgl_element_buffer(this_request->sgl_element_pair_buffer);
549
550 if (this_request->was_tag_assigned_by_user == FALSE)
551 {
552 this_request->task_context_buffer =
553 scic_sds_ssp_request_get_task_context_buffer(this_request);
554 }
555 }
556
557 /**
558 * @brief This method constructs the SSP Command IU data for this io
559 * request object.
560 *
561 * @param[in] this_request This parameter specifies the request object for
562 * which the SSP command information unit is being built.
563 *
564 * @return none
565 */
566 static
567 void scic_sds_io_request_build_ssp_command_iu(
568 SCIC_SDS_REQUEST_T *this_request
569 )
570 {
571 SCI_SINGLE_LEVEL_LUN_T lun;
572 SCI_SSP_COMMAND_IU_T *command_frame;
573 void *os_handle;
574 U32 cdb_length;
575 U32 *cdb_buffer;
576
577 command_frame =
578 (SCI_SSP_COMMAND_IU_T *)this_request->command_buffer;
579
580 os_handle = scic_sds_request_get_user_request(this_request);
581
582 ((U32 *)&lun)[0] = 0;
583 ((U32 *)&lun)[1] = 0;
584 lun.lun_number = scic_cb_ssp_io_request_get_lun(os_handle) &0xff;
585 /// @todo Is it ok to leave junk at the end of the cdb buffer?
586 scic_word_copy_with_swap(
587 (U32 *)command_frame->lun,
588 (U32 *)&lun,
589 sizeof(lun));
590
591 ((U32 *)command_frame)[2] = 0;
592
593 cdb_length = scic_cb_ssp_io_request_get_cdb_length(os_handle);
594 cdb_buffer = (U32 *)scic_cb_ssp_io_request_get_cdb_address(os_handle);
595
596 if (cdb_length > 16)
597 {
598 command_frame->additional_cdb_length = cdb_length - 16;
599 }
600
601 /// @todo Is it ok to leave junk at the end of the cdb buffer?
602 scic_word_copy_with_swap(
603 (U32 *)(&command_frame->cdb),
604 (U32 *)(cdb_buffer),
605 (cdb_length + 3) / sizeof(U32)
606 );
607
608 command_frame->enable_first_burst = 0;
609 command_frame->task_priority =
610 scic_cb_ssp_io_request_get_command_priority(os_handle);
611 command_frame->task_attribute =
612 scic_cb_ssp_io_request_get_task_attribute(os_handle);
613 }
614
615 #if !defined(DISABLE_TASK_MANAGEMENT)
616
617 /**
618 * @brief This method constructs the SSP Task IU data for this io request
619 * object.
620 *
621 * @param[in] this_request
622 *
623 * @return none
624 */
625 static
626 void scic_sds_task_request_build_ssp_task_iu(
627 SCIC_SDS_REQUEST_T *this_request
628 )
629 {
630 SCI_SSP_TASK_IU_T *command_frame;
631 void *os_handle;
632
633 command_frame =
634 (SCI_SSP_TASK_IU_T *)this_request->command_buffer;
635
636 os_handle = scic_sds_request_get_user_request(this_request);
637
638 command_frame->lun_upper = 0;
639 command_frame->lun_lower = scic_cb_ssp_task_request_get_lun(os_handle);
640
641 ((U32 *)command_frame)[2] = 0;
642
643 command_frame->task_function =
644 scic_cb_ssp_task_request_get_function(os_handle);
645 command_frame->task_tag =
646 scic_cb_ssp_task_request_get_io_tag_to_manage(os_handle);
647 }
648
649 #endif // !defined(DISABLE_TASK_MANAGEMENT)
650
651 /**
652 * @brief This method is will fill in the SCU Task Context for any type of
653 * SSP request.
654 *
655 * @param[in] this_request
656 * @param[in] task_context
657 *
658 * @return none
659 */
660 static
661 void scu_ssp_reqeust_construct_task_context(
662 SCIC_SDS_REQUEST_T * this_request,
663 SCU_TASK_CONTEXT_T * task_context
664 )
665 {
666 SCI_PHYSICAL_ADDRESS physical_address;
667 SCIC_SDS_CONTROLLER_T *owning_controller;
668 SCIC_SDS_REMOTE_DEVICE_T *target_device;
669 SCIC_SDS_PORT_T *target_port;
670
671 owning_controller = scic_sds_request_get_controller(this_request);
672 target_device = scic_sds_request_get_device(this_request);
673 target_port = scic_sds_request_get_port(this_request);
674
675 // Fill in the TC with the its required data
676 task_context->abort = 0;
677 task_context->priority = 0;
678 task_context->initiator_request = 1;
679 task_context->connection_rate =
680 scic_remote_device_get_connection_rate(target_device);
681 task_context->protocol_engine_index =
682 scic_sds_controller_get_protocol_engine_group(owning_controller);
683 task_context->logical_port_index =
684 scic_sds_port_get_index(target_port);
685 task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SSP;
686 task_context->valid = SCU_TASK_CONTEXT_VALID;
687 task_context->context_type = SCU_TASK_CONTEXT_TYPE;
688
689 task_context->remote_node_index =
690 scic_sds_remote_device_get_index(this_request->target_device);
691 task_context->command_code = 0;
692
693 task_context->link_layer_control = 0;
694 task_context->do_not_dma_ssp_good_response = 1;
695 task_context->strict_ordering = 0;
696 task_context->control_frame = 0;
697 task_context->timeout_enable = 0;
698 task_context->block_guard_enable = 0;
699
700 task_context->address_modifier = 0;
701
702 //task_context->type.ssp.tag = this_request->io_tag;
703 task_context->task_phase = 0x01;
704
705 if (this_request->was_tag_assigned_by_user)
706 {
707 // Build the task context now since we have already read the data
708 this_request->post_context = (
709 SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC
710 | (
711 scic_sds_controller_get_protocol_engine_group(owning_controller)
712 << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT
713 )
714 | (
715 scic_sds_port_get_index(target_port)
716 << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT
717 )
718 | scic_sds_io_tag_get_index(this_request->io_tag)
719 );
720 }
721 else
722 {
723 // Build the task context now since we have already read the data
724 this_request->post_context = (
725 SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC
726 | (
727 scic_sds_controller_get_protocol_engine_group(owning_controller)
728 << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT
729 )
730 | (
731 scic_sds_port_get_index(target_port)
732 << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT
733 )
734 // This is not assigned because we have to wait until we get a TCi
735 );
736 }
737
738 // Copy the physical address for the command buffer to the SCU Task Context
739 scic_cb_io_request_get_physical_address(
740 scic_sds_request_get_controller(this_request),
741 this_request,
742 this_request->command_buffer,
743 &physical_address
744 );
745
746 task_context->command_iu_upper =
747 sci_cb_physical_address_upper(physical_address);
748 task_context->command_iu_lower =
749 sci_cb_physical_address_lower(physical_address);
750
751 // Copy the physical address for the response buffer to the SCU Task Context
752 scic_cb_io_request_get_physical_address(
753 scic_sds_request_get_controller(this_request),
754 this_request,
755 this_request->response_buffer,
756 &physical_address
757 );
758
759 task_context->response_iu_upper =
760 sci_cb_physical_address_upper(physical_address);
761 task_context->response_iu_lower =
762 sci_cb_physical_address_lower(physical_address);
763 }
764
765 /**
766 * @brief This method is will fill in the SCU Task Context for a SSP IO
767 * request.
768 *
769 * @param[in] this_request
770 *
771 * @return none
772 */
773 static
774 void scu_ssp_io_request_construct_task_context(
775 SCIC_SDS_REQUEST_T *this_request,
776 SCI_IO_REQUEST_DATA_DIRECTION data_direction,
777 U32 transfer_length_bytes
778 )
779 {
780 SCU_TASK_CONTEXT_T *task_context;
781
782 task_context = scic_sds_request_get_task_context(this_request);
783
784 scu_ssp_reqeust_construct_task_context(this_request, task_context);
785
786 task_context->ssp_command_iu_length = sizeof(SCI_SSP_COMMAND_IU_T) / sizeof(U32);
787 task_context->type.ssp.frame_type = SCI_SAS_COMMAND_FRAME;
788
789 switch (data_direction)
790 {
791 case SCI_IO_REQUEST_DATA_IN:
792 case SCI_IO_REQUEST_NO_DATA:
793 task_context->task_type = SCU_TASK_TYPE_IOREAD;
794 break;
795 case SCI_IO_REQUEST_DATA_OUT:
796 task_context->task_type = SCU_TASK_TYPE_IOWRITE;
797 break;
798 }
799
800 task_context->transfer_length_bytes = transfer_length_bytes;
801
802 if (task_context->transfer_length_bytes > 0)
803 {
804 scic_sds_request_build_sgl(this_request);
805 }
806 }
807
808 #if !defined(DISABLE_TASK_MANAGEMENT)
809
810 /**
811 * @brief This method will fill in the remainder of the io request object
812 * for SSP Task requests.
813 *
814 * @param[in] this_request
815 *
816 * @return none
817 */
818 void scic_sds_ssp_task_request_assign_buffers(
819 SCIC_SDS_REQUEST_T *this_request
820 )
821 {
822 // Assign all of the buffer pointers
823 this_request->command_buffer =
824 scic_sds_ssp_task_request_get_command_buffer(this_request);
825 this_request->response_buffer =
826 scic_sds_ssp_task_request_get_response_buffer(this_request);
827 this_request->sgl_element_pair_buffer = NULL;
828
829 if (this_request->was_tag_assigned_by_user == FALSE)
830 {
831 this_request->task_context_buffer =
832 scic_sds_ssp_task_request_get_task_context_buffer(this_request);
833 this_request->task_context_buffer =
834 scic_sds_request_align_task_context_buffer(this_request->task_context_buffer);
835 }
836 }
837
838 /**
839 * @brief This method will fill in the SCU Task Context for a SSP Task
840 * request. The following important settings are utilized:
841 * -# priority == SCU_TASK_PRIORITY_HIGH. This ensures that the
842 * task request is issued ahead of other task destined for the
843 * same Remote Node.
844 * -# task_type == SCU_TASK_TYPE_IOREAD. This simply indicates
845 * that a normal request type (i.e. non-raw frame) is being
846 * utilized to perform task management.
847 * -# control_frame == 1. This ensures that the proper endianness
848 * is set so that the bytes are transmitted in the right order
849 * for a task frame.
850 *
851 * @param[in] this_request This parameter specifies the task request object
852 * being constructed.
853 *
854 * @return none
855 */
856 static
857 void scu_ssp_task_request_construct_task_context(
858 SCIC_SDS_REQUEST_T *this_request
859 )
860 {
861 SCU_TASK_CONTEXT_T *task_context;
862
863 task_context = scic_sds_request_get_task_context(this_request);
864
865 scu_ssp_reqeust_construct_task_context(this_request, task_context);
866
867 task_context->control_frame = 1;
868 task_context->priority = SCU_TASK_PRIORITY_HIGH;
869 task_context->task_type = SCU_TASK_TYPE_RAW_FRAME;
870 task_context->transfer_length_bytes = 0;
871 task_context->type.ssp.frame_type = SCI_SAS_TASK_FRAME;
872 task_context->ssp_command_iu_length = sizeof(SCI_SSP_TASK_IU_T) / sizeof(U32);
873 }
874
875 #endif // !defined(DISABLE_TASK_MANAGEMENT)
876
877 #if !defined(DISABLE_PASS_THROUGH)
878 /**
879 * @brief This method constructs the SSP Command IU data for this
880 * ssp passthrough comand request object.
881 *
882 * @param[in] this_request This parameter specifies the request object for
883 * which the SSP command information unit is being built.
884 *
885 * @return SCI_STATUS, returns invalid parameter is cdb > 16
886 */
887 static
888 SCI_STATUS scic_sds_io_request_build_ssp_command_iu_pass_through(
889 SCIC_SDS_REQUEST_T *this_request,
890 SCIC_SSP_PASSTHRU_REQUEST_CALLBACKS_T *ssp_passthru_cb
891 )
892 {
893 SCI_SSP_COMMAND_IU_T *command_frame;
894 U32 cdb_length = 0, additional_cdb_length = 0;
895 U8 *cdb_buffer, *additional_cdb_buffer;
896 U8 *scsi_lun;
897 SCI_STATUS sci_status = SCI_SUCCESS;
898 SCI_SINGLE_LEVEL_LUN_T lun;
899
900 command_frame =
901 (SCI_SSP_COMMAND_IU_T *)this_request->command_buffer;
902
903 //get the lun
904 ssp_passthru_cb->scic_cb_ssp_passthru_get_lun (
905 this_request,
906 &scsi_lun
907 );
908 memset(&lun, 0, sizeof(lun));
909 lun.lun_number = *scsi_lun;
910 scic_word_copy_with_swap(
911 (U32 *)command_frame->lun,
912 (U32 *)&lun,
913 sizeof(lun));
914
915 ((U32 *)command_frame)[2] = 0;
916
917 ssp_passthru_cb->scic_cb_ssp_passthru_get_cdb(
918 this_request,
919 &cdb_length,
920 &cdb_buffer,
921 &additional_cdb_length,
922 &additional_cdb_buffer
923 );
924
925 command_frame->additional_cdb_length = additional_cdb_length;
926
927 // ----------- TODO
928 ///todo: what to do with additional cdb length and buffer as the current command buffer is
929 // 16 bytes in intel_sas.h
930 // ??? see the SAS command IU
931 if (additional_cdb_length > 0)
932 {
933 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
934 }
935
936 /// @todo Is it ok to leave junk at the end of the cdb buffer?
937 scic_word_copy_with_swap(
938 (U32 *)(&command_frame->cdb),
939 (U32 *)(cdb_buffer),
940 (cdb_length + 3) / sizeof(U32)
941 );
942
943 /////-------- End fo TODO
944
945 command_frame->enable_first_burst = 0;
946 command_frame->task_priority = 0; //todo: check with Richard ????
947
948 //get the task attribute
949 command_frame->task_attribute = ssp_passthru_cb->scic_cb_ssp_passthru_get_task_attribute (
950 this_request
951 );
952
953 return sci_status;
954 }
955 #endif // !defined(DISABLE_PASS_THROUGH)
956
957 //****************************************************************************
958 //* SCIC Interface Implementation
959 //****************************************************************************
960
961 #if !defined(DISABLE_TASK_MANAGEMENT)
962 /**
963 * This method returns the size required to store an SSP task request object.
964 *
965 * @return U32
966 */
967 static
968 U32 scic_sds_ssp_task_request_get_object_size(void)
969 {
970 return sizeof(SCIC_SDS_REQUEST_T)
971 + scic_ssp_task_request_get_object_size()
972 + sizeof(SCU_TASK_CONTEXT_T)
973 + CACHE_LINE_SIZE;
974 }
975
976
977 U32 scic_task_request_get_object_size(void)
978 {
979 U32 ssp_task_request_size;
980 U32 stp_task_request_size;
981
982 ssp_task_request_size = scic_sds_ssp_task_request_get_object_size();
983 stp_task_request_size = scic_sds_stp_task_request_get_object_size();
984
985 return MAX(ssp_task_request_size, stp_task_request_size);
986 }
987
988 #endif // !defined(DISABLE_TASK_MANAGEMENT)
989
990 // ---------------------------------------------------------------------------
991
992 U32 scic_io_request_get_object_size(void)
993 {
994 U32 ssp_request_size;
995 U32 stp_request_size;
996 U32 smp_request_size;
997
998 ssp_request_size = scic_sds_ssp_request_get_object_size();
999 stp_request_size = scic_sds_stp_request_get_object_size();
1000 smp_request_size = scic_sds_smp_request_get_object_size();
1001
1002 return MAX(ssp_request_size, MAX(stp_request_size, smp_request_size));
1003 }
1004
1005 // ---------------------------------------------------------------------------
1006
1007 SCIC_TRANSPORT_PROTOCOL scic_io_request_get_protocol(
1008 SCI_IO_REQUEST_HANDLE_T scic_io_request
1009 )
1010 {
1011 SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T * )scic_io_request;
1012 return this_request->protocol;
1013 }
1014
1015 // ---------------------------------------------------------------------------
1016
1017 U32 scic_sds_request_get_min_timer_count(void)
1018 {
1019 return SCIC_SDS_IO_REQUEST_MINIMUM_TIMER_COUNT;
1020 }
1021
1022 // ---------------------------------------------------------------------------
1023
1024 U32 scic_sds_request_get_max_timer_count(void)
1025 {
1026 return SCIC_SDS_IO_REQUEST_MAXIMUM_TIMER_COUNT;
1027 }
1028
1029 // ---------------------------------------------------------------------------
1030
1031 SCI_STATUS scic_io_request_construct(
1032 SCI_CONTROLLER_HANDLE_T scic_controller,
1033 SCI_REMOTE_DEVICE_HANDLE_T scic_remote_device,
1034 U16 io_tag,
1035 void * user_io_request_object,
1036 void * scic_io_request_memory,
1037 SCI_IO_REQUEST_HANDLE_T * new_scic_io_request_handle
1038 )
1039 {
1040 SCI_STATUS status = SCI_SUCCESS;
1041 SCIC_SDS_REQUEST_T * this_request;
1042 SMP_DISCOVER_RESPONSE_PROTOCOLS_T device_protocol;
1043
1044 this_request = (SCIC_SDS_REQUEST_T * )scic_io_request_memory;
1045
1046 SCIC_LOG_TRACE((
1047 sci_base_object_get_logger(scic_controller),
1048 (SCIC_LOG_OBJECT_SSP_IO_REQUEST
1049 |SCIC_LOG_OBJECT_SMP_IO_REQUEST
1050 |SCIC_LOG_OBJECT_STP_IO_REQUEST),
1051 "scic_io_request_construct(0x%x, 0x%x, 0x02x, 0x%x, 0x%x, 0x%x) enter\n",
1052 scic_controller, scic_remote_device,
1053 io_tag, user_io_request_object,
1054 this_request, new_scic_io_request_handle
1055 ));
1056
1057 // Build the common part of the request
1058 scic_sds_general_request_construct(
1059 (SCIC_SDS_CONTROLLER_T *)scic_controller,
1060 (SCIC_SDS_REMOTE_DEVICE_T *)scic_remote_device,
1061 io_tag,
1062 user_io_request_object,
1063 this_request
1064 );
1065
1066 if (
1067 scic_sds_remote_device_get_index((SCIC_SDS_REMOTE_DEVICE_T *)scic_remote_device)
1068 == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX
1069 )
1070 {
1071 return SCI_FAILURE_INVALID_REMOTE_DEVICE;
1072 }
1073
1074 scic_remote_device_get_protocols(scic_remote_device, &device_protocol);
1075
1076 if (device_protocol.u.bits.attached_ssp_target)
1077 {
1078 scic_sds_ssp_io_request_assign_buffers(this_request);
1079 }
1080 else if (device_protocol.u.bits.attached_stp_target)
1081 {
1082 scic_sds_stp_request_assign_buffers(this_request);
1083 memset(this_request->command_buffer, 0, sizeof(SATA_FIS_REG_H2D_T));
1084 }
1085 else if (device_protocol.u.bits.attached_smp_target)
1086 {
1087 scic_sds_smp_request_assign_buffers(this_request);
1088 memset(this_request->command_buffer, 0, sizeof(SMP_REQUEST_T));
1089 }
1090 else
1091 {
1092 status = SCI_FAILURE_UNSUPPORTED_PROTOCOL;
1093 }
1094
1095 if (status == SCI_SUCCESS)
1096 {
1097 memset(
1098 this_request->task_context_buffer,
1099 0,
1100 SCI_FIELD_OFFSET(SCU_TASK_CONTEXT_T, sgl_pair_ab)
1101 );
1102 *new_scic_io_request_handle = scic_io_request_memory;
1103 }
1104
1105 return status;
1106 }
1107
1108 // ---------------------------------------------------------------------------
1109
1110 #if !defined(DISABLE_TASK_MANAGEMENT)
1111
1112 SCI_STATUS scic_task_request_construct(
1113 SCI_CONTROLLER_HANDLE_T controller,
1114 SCI_REMOTE_DEVICE_HANDLE_T remote_device,
1115 U16 io_tag,
1116 void *user_io_request_object,
1117 void *scic_task_request_memory,
1118 SCI_TASK_REQUEST_HANDLE_T *new_scic_task_request_handle
1119 )
1120 {
1121 SCI_STATUS status = SCI_SUCCESS;
1122 SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T *)
1123 scic_task_request_memory;
1124 SMP_DISCOVER_RESPONSE_PROTOCOLS_T device_protocol;
1125
1126 SCIC_LOG_TRACE((
1127 sci_base_object_get_logger(controller),
1128 (SCIC_LOG_OBJECT_SSP_IO_REQUEST
1129 |SCIC_LOG_OBJECT_SMP_IO_REQUEST
1130 |SCIC_LOG_OBJECT_STP_IO_REQUEST),
1131 "scic_task_request_construct(0x%x, 0x%x, 0x02x, 0x%x, 0x%x, 0x%x) enter\n",
1132 controller, remote_device,
1133 io_tag, user_io_request_object,
1134 scic_task_request_memory, new_scic_task_request_handle
1135 ));
1136
1137 // Build the common part of the request
1138 scic_sds_general_request_construct(
1139 (SCIC_SDS_CONTROLLER_T *)controller,
1140 (SCIC_SDS_REMOTE_DEVICE_T *)remote_device,
1141 io_tag,
1142 user_io_request_object,
1143 this_request
1144 );
1145
1146 scic_remote_device_get_protocols(remote_device, &device_protocol);
1147
1148 if (device_protocol.u.bits.attached_ssp_target)
1149 {
1150 scic_sds_ssp_task_request_assign_buffers(this_request);
1151
1152 this_request->has_started_substate_machine = TRUE;
1153
1154 // Construct the started sub-state machine.
1155 sci_base_state_machine_construct(
1156 &this_request->started_substate_machine,
1157 &this_request->parent.parent,
1158 scic_sds_io_request_started_task_mgmt_substate_table,
1159 SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION
1160 );
1161 }
1162 else if (device_protocol.u.bits.attached_stp_target)
1163 {
1164 scic_sds_stp_request_assign_buffers(this_request);
1165 }
1166 else
1167 {
1168 status = SCI_FAILURE_UNSUPPORTED_PROTOCOL;
1169 }
1170
1171 if (status == SCI_SUCCESS)
1172 {
1173 this_request->is_task_management_request = TRUE;
1174 memset(this_request->task_context_buffer, 0x00, sizeof(SCU_TASK_CONTEXT_T));
1175 *new_scic_task_request_handle = scic_task_request_memory;
1176 }
1177
1178 return status;
1179 }
1180
1181 #endif // !defined(DISABLE_TASK_MANAGEMENT)
1182
1183 // ---------------------------------------------------------------------------
1184
1185 SCI_STATUS scic_io_request_construct_basic_ssp(
1186 SCI_IO_REQUEST_HANDLE_T scic_io_request
1187 )
1188 {
1189 void *os_handle;
1190 SCIC_SDS_REQUEST_T *this_request;
1191 this_request = (SCIC_SDS_REQUEST_T *)scic_io_request;
1192
1193 SCIC_LOG_TRACE((
1194 sci_base_object_get_logger(this_request),
1195 SCIC_LOG_OBJECT_SSP_IO_REQUEST,
1196 "scic_io_request_construct_basic_ssp(0x%x) enter\n",
1197 this_request
1198 ));
1199
1200 this_request->protocol = SCIC_SSP_PROTOCOL;
1201
1202 os_handle = scic_sds_request_get_user_request(this_request);
1203
1204 scu_ssp_io_request_construct_task_context(
1205 this_request,
1206 scic_cb_io_request_get_data_direction(os_handle),
1207 scic_cb_io_request_get_transfer_length(os_handle)
1208 );
1209
1210
1211 scic_sds_io_request_build_ssp_command_iu(this_request);
1212
1213 scic_sds_request_initialize_state_logging(this_request);
1214
1215 sci_base_state_machine_change_state(
1216 &this_request->parent.state_machine,
1217 SCI_BASE_REQUEST_STATE_CONSTRUCTED
1218 );
1219
1220 return SCI_SUCCESS;
1221 }
1222
1223 // ---------------------------------------------------------------------------
1224
1225 #if !defined(DISABLE_TASK_MANAGEMENT)
1226
1227 SCI_STATUS scic_task_request_construct_ssp(
1228 SCI_TASK_REQUEST_HANDLE_T scic_task_request
1229 )
1230 {
1231 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)
1232 scic_task_request;
1233
1234 SCIC_LOG_TRACE((
1235 sci_base_object_get_logger(this_request),
1236 SCIC_LOG_OBJECT_SSP_IO_REQUEST,
1237 "scic_task_request_construct_ssp(0x%x) enter\n",
1238 this_request
1239 ));
1240
1241 // Construct the SSP Task SCU Task Context
1242 scu_ssp_task_request_construct_task_context(this_request);
1243
1244 // Fill in the SSP Task IU
1245 scic_sds_task_request_build_ssp_task_iu(this_request);
1246
1247 scic_sds_request_initialize_state_logging(this_request);
1248
1249 sci_base_state_machine_change_state(
1250 &this_request->parent.state_machine,
1251 SCI_BASE_REQUEST_STATE_CONSTRUCTED
1252 );
1253
1254 return SCI_SUCCESS;
1255 }
1256
1257 #endif // !defined(DISABLE_TASK_MANAGEMENT)
1258
1259 // ---------------------------------------------------------------------------
1260
1261 SCI_STATUS scic_io_request_construct_advanced_ssp(
1262 SCI_IO_REQUEST_HANDLE_T scic_io_request,
1263 SCIC_IO_SSP_PARAMETERS_T * io_parameters
1264 )
1265 {
1266 SCIC_LOG_TRACE((
1267 sci_base_object_get_logger(scic_io_request),
1268 SCIC_LOG_OBJECT_SSP_IO_REQUEST,
1269 "scic_io_request_construct_advanced_ssp(0x%x, 0x%x) enter\n",
1270 io_parameters, scic_io_request
1271 ));
1272
1273 /// @todo Implement after 1.1
1274 return SCI_FAILURE;
1275 }
1276
1277 // ---------------------------------------------------------------------------
1278
1279 #if !defined(DISABLE_PASS_THROUGH)
1280 SCI_STATUS scic_io_request_construct_ssp_pass_through (
1281 void * scic_io_request,
1282 SCIC_SSP_PASSTHRU_REQUEST_CALLBACKS_T *ssp_passthru_cb
1283 )
1284 {
1285 SCI_STATUS status = SCI_SUCCESS;
1286 SCIC_SDS_REQUEST_T * this_request;
1287
1288 this_request = (SCIC_SDS_REQUEST_T * )scic_io_request;
1289
1290 SCIC_LOG_TRACE((
1291 sci_base_object_get_logger(scic_io_request),
1292 SCIC_LOG_OBJECT_STP_IO_REQUEST,
1293 "scic_io_request_construct_ssp_pass_through(0x%x) enter\n",
1294 scic_io_request
1295 ));
1296
1297 //build the task context from the pass through buffer
1298 scu_ssp_io_request_construct_task_context(
1299 this_request,
1300 ssp_passthru_cb->common_callbacks.scic_cb_passthru_get_data_direction (this_request),
1301 ssp_passthru_cb->common_callbacks.scic_cb_passthru_get_transfer_length(this_request)
1302 );
1303
1304 //build the ssp command iu from the pass through buffer
1305 status = scic_sds_io_request_build_ssp_command_iu_pass_through (
1306 this_request,
1307 ssp_passthru_cb
1308 );
1309 if (status != SCI_SUCCESS)
1310 {
1311 return status;
1312 }
1313
1314 /* initialize the logging */
1315 scic_sds_request_initialize_state_logging(this_request);
1316
1317 sci_base_state_machine_change_state(
1318 &this_request->parent.state_machine,
1319 SCI_BASE_REQUEST_STATE_CONSTRUCTED
1320 );
1321
1322 return status;
1323 }
1324 #endif // !defined(DISABLE_PASS_THROUGH)
1325
1326 // ---------------------------------------------------------------------------
1327
1328 #if !defined(DISABLE_TASK_MANAGEMENT)
1329
1330 SCI_STATUS scic_task_request_construct_sata(
1331 SCI_TASK_REQUEST_HANDLE_T scic_task_request
1332 )
1333 {
1334 SCI_STATUS status;
1335 SCIC_SDS_REQUEST_T * this_request;
1336 U8 sat_protocol;
1337
1338 this_request = (SCIC_SDS_REQUEST_T *)scic_task_request;
1339
1340 SCIC_LOG_TRACE((
1341 sci_base_object_get_logger(this_request),
1342 SCIC_LOG_OBJECT_STP_IO_REQUEST,
1343 "scic_task_request_construct_sata(0x%x) enter\n",
1344 this_request
1345 ));
1346
1347 sat_protocol =
1348 scic_cb_request_get_sat_protocol(this_request->user_request);
1349
1350 this_request->sat_protocol = sat_protocol;
1351
1352 switch (sat_protocol)
1353 {
1354 case SAT_PROTOCOL_ATA_HARD_RESET:
1355 case SAT_PROTOCOL_SOFT_RESET:
1356 status = scic_sds_stp_soft_reset_request_construct(this_request);
1357 break;
1358
1359 case SAT_PROTOCOL_PIO_DATA_IN:
1360 status = scic_sds_stp_pio_request_construct(this_request, sat_protocol, FALSE);
1361 break;
1362
1363 default:
1364 SCIC_LOG_ERROR((
1365 sci_base_object_get_logger(this_request),
1366 SCIC_LOG_OBJECT_STP_IO_REQUEST,
1367 "SCIC IO Request 0x%x received un-handled SAT Protocl %d.\n",
1368 this_request, sat_protocol
1369 ));
1370
1371 status = SCI_FAILURE;
1372 break;
1373 }
1374
1375 if (status == SCI_SUCCESS)
1376 {
1377 scic_sds_request_initialize_state_logging(this_request);
1378
1379 sci_base_state_machine_change_state(
1380 &this_request->parent.state_machine,
1381 SCI_BASE_REQUEST_STATE_CONSTRUCTED
1382 );
1383 }
1384
1385 return status;
1386 }
1387
1388 #endif // !defined(DISABLE_TASK_MANAGEMENT)
1389
1390 // ---------------------------------------------------------------------------
1391
1392 #if !defined(DISABLE_PASS_THROUGH)
1393 SCI_STATUS scic_io_request_construct_sata_pass_through(
1394 SCI_IO_REQUEST_HANDLE_T scic_io_request,
1395 SCIC_STP_PASSTHRU_REQUEST_CALLBACKS_T *passthru_cb
1396 )
1397 {
1398 SCI_STATUS status = SCI_SUCCESS;
1399 SCIC_SDS_REQUEST_T * this_request;
1400 U8 sat_protocol;
1401 U8 * reg_fis;
1402 U32 transfer_length;
1403 SCI_IO_REQUEST_DATA_DIRECTION data_direction;
1404
1405 this_request = (SCIC_SDS_REQUEST_T * )scic_io_request;
1406
1407 SCIC_LOG_TRACE((
1408 sci_base_object_get_logger(scic_io_request),
1409 SCIC_LOG_OBJECT_STP_IO_REQUEST,
1410 "scic_io_request_construct_sata_pass_through(0x%x) enter\n",
1411 scic_io_request
1412 ));
1413
1414 passthru_cb->scic_cb_stp_passthru_get_register_fis(this_request, ®_fis);
1415
1416 if (reg_fis == NULL)
1417 {
1418 status = SCI_FAILURE_INVALID_PARAMETER_VALUE;
1419 }
1420
1421 if (status == SCI_SUCCESS)
1422 {
1423 //copy the H2D Reg fis blindly from the request to the SCU command buffer
1424 memcpy ((U8 *)this_request->command_buffer, (U8 *)reg_fis, sizeof(SATA_FIS_REG_H2D_T));
1425
1426 //continue to create the request
1427 sat_protocol = passthru_cb->scic_cb_stp_passthru_get_protocol(this_request);
1428 transfer_length = passthru_cb->common_callbacks.scic_cb_passthru_get_transfer_length(this_request);
1429 data_direction = passthru_cb->common_callbacks.scic_cb_passthru_get_data_direction(this_request);
1430
1431 status = scic_sds_io_request_construct_sata(
1432 this_request,
1433 sat_protocol,
1434 transfer_length,
1435 data_direction,
1436 TRUE,
1437 TRUE
1438 );
1439
1440 this_request->protocol = SCIC_STP_PROTOCOL;
1441 }
1442
1443 return status;
1444 }
1445 #endif // !defined(DISABLE_PASS_THROUGH)
1446
1447 // ---------------------------------------------------------------------------
1448
1449 U16 scic_io_request_get_io_tag(
1450 SCI_IO_REQUEST_HANDLE_T scic_io_request
1451 )
1452 {
1453 SCIC_SDS_REQUEST_T *this_request;
1454 this_request = (SCIC_SDS_REQUEST_T *)scic_io_request;
1455
1456 SCIC_LOG_TRACE((
1457 sci_base_object_get_logger(scic_io_request),
1458 SCIC_LOG_OBJECT_SMP_IO_REQUEST,
1459 "scic_io_request_get_io_tag(0x%x) enter\n",
1460 scic_io_request
1461 ));
1462
1463 return this_request->io_tag;
1464 }
1465
1466 // ---------------------------------------------------------------------------
1467
1468 U32 scic_request_get_controller_status(
1469 SCI_IO_REQUEST_HANDLE_T io_request
1470 )
1471 {
1472 SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T*)io_request;
1473 return this_request->scu_status;
1474 }
1475
1476 U32 scic_request_get_sci_status(
1477 SCI_IO_REQUEST_HANDLE_T io_request
1478 )
1479 {
1480 SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T*)io_request;
1481 return this_request->sci_status;
1482 }
1483
1484 // ---------------------------------------------------------------------------
1485
1486 void * scic_io_request_get_rx_frame(
1487 SCI_IO_REQUEST_HANDLE_T scic_io_request,
1488 U32 offset
1489 )
1490 {
1491 void * frame_buffer = NULL;
1492 SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T *)scic_io_request;
1493
1494 ASSERT(offset < SCU_UNSOLICITED_FRAME_BUFFER_SIZE);
1495
1496 if (this_request->saved_rx_frame_index != SCU_INVALID_FRAME_INDEX)
1497 {
1498 scic_sds_unsolicited_frame_control_get_buffer(
1499 &(this_request->owning_controller->uf_control),
1500 this_request->saved_rx_frame_index,
1501 &frame_buffer
1502 );
1503 }
1504
1505 return frame_buffer;
1506 }
1507
1508 void * scic_io_request_get_command_iu_address(
1509 SCI_IO_REQUEST_HANDLE_T scic_io_request
1510 )
1511 {
1512 SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T *)scic_io_request;
1513
1514 return this_request->command_buffer;
1515 }
1516
1517 // ---------------------------------------------------------------------------
1518
1519 void * scic_io_request_get_response_iu_address(
1520 SCI_IO_REQUEST_HANDLE_T scic_io_request
1521 )
1522 {
1523 SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T *)scic_io_request;
1524
1525 return this_request->response_buffer;
1526 }
1527
1528 // ---------------------------------------------------------------------------
1529 #define SCU_TASK_CONTEXT_SRAM 0x200000
1530 U32 scic_io_request_get_number_of_bytes_transferred (
1531 SCI_IO_REQUEST_HANDLE_T scic_io_request
1532 )
1533 {
1534 U32 ret_val = 0;
1535 SCIC_SDS_REQUEST_T * scic_sds_request;
1536
1537 scic_sds_request = (SCIC_SDS_REQUEST_T *) scic_io_request;
1538
1539 if ( SMU_AMR_READ (scic_sds_request->owning_controller) == 0)
1540 {
1541 //get the bytes of data from the Address == BAR1 + 20002Ch + (256*TCi) where
1542 // BAR1 is the scu_registers
1543 // 0x20002C = 0x200000 + 0x2c
1544 // = start of task context SRAM + offset of (type.ssp.data_offset)
1545 // TCi is the io_tag of SCIC_SDS_REQUEST
1546 ret_val = scic_sds_pci_read_scu_dword(
1547 scic_sds_request->owning_controller,
1548 (
1549 (U8 *) scic_sds_request->owning_controller->scu_registers +
1550 ( SCU_TASK_CONTEXT_SRAM + SCI_FIELD_OFFSET(SCU_TASK_CONTEXT_T, type.ssp.data_offset) ) +
1551 ( ( sizeof (SCU_TASK_CONTEXT_T) ) * scic_sds_io_tag_get_index (scic_sds_request->io_tag))
1552 )
1553 );
1554 }
1555
1556 return ret_val;
1557 }
1558
1559 //****************************************************************************
1560 //* SCIC SDS Interface Implementation
1561 //****************************************************************************
1562
1563 /**
1564 * This method invokes the base state start request handler for the
1565 * SCIC_SDS_IO_REQUEST_T object.
1566 *
1567 * @param[in] this_request The SCIC_SDS_IO_REQUEST_T object for which the
1568 * start operation is to be executed.
1569 *
1570 * @return SCI_STATUS
1571 */
1572 SCI_STATUS scic_sds_request_start(
1573 SCIC_SDS_REQUEST_T *this_request
1574 )
1575 {
1576 if (
1577 this_request->device_sequence
1578 == scic_sds_remote_device_get_sequence(this_request->target_device)
1579 )
1580 {
1581 return this_request->state_handlers->parent.start_handler(
1582 &this_request->parent
1583 );
1584 }
1585
1586 return SCI_FAILURE;
1587 }
1588
1589 /**
1590 * This method invokes the base state terminate request handber for the
1591 * SCIC_SDS_IO_REQUEST_T object.
1592 *
1593 * @param[in] this_request The SCIC_SDS_IO_REQUEST_T object for which the
1594 * start operation is to be executed.
1595 *
1596 * @return SCI_STATUS
1597 */
1598 SCI_STATUS scic_sds_io_request_terminate(
1599 SCIC_SDS_REQUEST_T *this_request
1600 )
1601 {
1602 return this_request->state_handlers->parent.abort_handler(
1603 &this_request->parent);
1604 }
1605
1606 /**
1607 * This method invokes the base state request completion handler for the
1608 * SCIC_SDS_IO_REQUEST_T object.
1609 *
1610 * @param[in] this_request The SCIC_SDS_IO_REQUEST_T object for which the
1611 * start operation is to be executed.
1612 *
1613 * @return SCI_STATUS
1614 */
1615 SCI_STATUS scic_sds_io_request_complete(
1616 SCIC_SDS_REQUEST_T *this_request
1617 )
1618 {
1619 return this_request->state_handlers->parent.complete_handler(
1620 &this_request->parent);
1621 }
1622
1623 /**
1624 * This method invokes the core state handler for the SCIC_SDS_IO_REQUEST_T
1625 * object.
1626 *
1627 * @param[in] this_request The SCIC_SDS_IO_REQUEST_T object for which the
1628 * start operation is to be executed.
1629 * @param[in] event_code The event code returned by the hardware for the task
1630 * reqeust.
1631 *
1632 * @return SCI_STATUS
1633 */
1634 SCI_STATUS scic_sds_io_request_event_handler(
1635 SCIC_SDS_REQUEST_T * this_request,
1636 U32 event_code
1637 )
1638 {
1639 return this_request->state_handlers->event_handler(this_request, event_code);
1640 }
1641
1642 /**
1643 * This method invokes the core state frame handler for the
1644 * SCIC_SDS_IO_REQUEST_T object.
1645 *
1646 * @param[in] this_request The SCIC_SDS_IO_REQUEST_T object for which the
1647 * start operation is to be executed.
1648 * @param[in] frame_index The frame index returned by the hardware for the
1649 * reqeust object.
1650 *
1651 * @return SCI_STATUS
1652 */
1653 SCI_STATUS scic_sds_io_request_frame_handler(
1654 SCIC_SDS_REQUEST_T * this_request,
1655 U32 frame_index
1656 )
1657 {
1658 return this_request->state_handlers->frame_handler(this_request, frame_index);
1659 }
1660
1661 /**
1662 * This method invokes the core state task complete handler for the
1663 * SCIC_SDS_IO_REQUEST_T object.
1664 *
1665 * @param[in] this_request The SCIC_SDS_IO_REQUEST_T object for which the task
1666 * start operation is to be executed.
1667 *
1668 * @return SCI_STATUS
1669 */
1670 SCI_STATUS scic_sds_task_request_complete(
1671 SCIC_SDS_REQUEST_T *this_request
1672 )
1673 {
1674 return this_request->state_handlers->parent.complete_handler(&this_request->parent);
1675 }
1676
1677 //****************************************************************************
1678 //* SCIC SDS PROTECTED METHODS
1679 //****************************************************************************
1680
1681 /**
1682 * @brief This method copies response data for requests returning response
1683 * data instead of sense data.
1684 *
1685 * @param[in] this_request This parameter specifies the request object for
1686 * which to copy the response data.
1687 *
1688 * @return none
1689 */
1690 void scic_sds_io_request_copy_response(
1691 SCIC_SDS_REQUEST_T *this_request
1692 )
1693 {
1694 void * response_buffer;
1695 U32 user_response_length;
1696 U32 core_response_length;
1697 SCI_SSP_RESPONSE_IU_T * ssp_response;
1698
1699 ssp_response = (SCI_SSP_RESPONSE_IU_T *)this_request->response_buffer;
1700
1701 response_buffer = scic_cb_ssp_task_request_get_response_data_address(
1702 this_request->user_request
1703 );
1704
1705 user_response_length = scic_cb_ssp_task_request_get_response_data_length(
1706 this_request->user_request
1707 );
1708
1709 core_response_length = sci_ssp_get_response_data_length(
1710 ssp_response->response_data_length
1711 );
1712
1713 user_response_length = MIN(user_response_length, core_response_length);
1714
1715 memcpy(response_buffer, ssp_response->data, user_response_length);
1716 }
1717
1718 //******************************************************************************
1719 //* REQUEST STATE MACHINE
1720 //******************************************************************************
1721
1722 //*****************************************************************************
1723 //* DEFAULT STATE HANDLERS
1724 //*****************************************************************************
1725
1726 /**
1727 * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T
1728 * object receives a scic_sds_request_start() request. The default action is
1729 * to log a warning and return a failure status.
1730 *
1731 * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
1732 * the SCIC_SDS_IO_REQUEST_T object for which the start operation is
1733 * requested.
1734 *
1735 * @return SCI_STATUS
1736 * @retval SCI_FAILURE_INVALID_STATE
1737 */
1738 SCI_STATUS scic_sds_request_default_start_handler(
1739 SCI_BASE_REQUEST_T *request
1740 )
1741 {
1742 SCIC_LOG_WARNING((
1743 sci_base_object_get_logger((SCIC_SDS_REQUEST_T *)request),
1744 (
1745 SCIC_LOG_OBJECT_SSP_IO_REQUEST
1746 | SCIC_LOG_OBJECT_STP_IO_REQUEST
1747 | SCIC_LOG_OBJECT_SMP_IO_REQUEST
1748 ),
1749 "SCIC IO Request requested to start while in wrong state %d\n",
1750 sci_base_state_machine_get_state(
1751 &((SCIC_SDS_REQUEST_T *)request)->parent.state_machine)
1752 ));
1753
1754 return SCI_FAILURE_INVALID_STATE;
1755 }
1756
1757 /**
1758 * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T
1759 * object receives a scic_sds_request_terminate() request. The default action
1760 * is to log a warning and return a failure status.
1761 *
1762 * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
1763 * the SCIC_SDS_IO_REQUEST_T object for which the start operation is
1764 * requested.
1765 *
1766 * @return SCI_STATUS
1767 * @retval SCI_FAILURE_INVALID_STATE
1768 */
1769 SCI_STATUS scic_sds_request_default_abort_handler(
1770 SCI_BASE_REQUEST_T *request
1771 )
1772 {
1773 SCIC_LOG_WARNING((
1774 sci_base_object_get_logger((SCIC_SDS_REQUEST_T *)request),
1775 (
1776 SCIC_LOG_OBJECT_SSP_IO_REQUEST
1777 | SCIC_LOG_OBJECT_STP_IO_REQUEST
1778 | SCIC_LOG_OBJECT_SMP_IO_REQUEST
1779 ),
1780 "SCIC IO Request requested to abort while in wrong state %d\n",
1781 sci_base_state_machine_get_state(
1782 &((SCIC_SDS_REQUEST_T *)request)->parent.state_machine)
1783 ));
1784
1785 return SCI_FAILURE_INVALID_STATE;
1786 }
1787
1788 /**
1789 * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T
1790 * object receives a scic_sds_request_complete() request. The default action
1791 * is to log a warning and return a failure status.
1792 *
1793 * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
1794 * the SCIC_SDS_IO_REQUEST_T object for which the start operation is
1795 * requested.
1796 *
1797 * @return SCI_STATUS
1798 * @retval SCI_FAILURE_INVALID_STATE
1799 */
1800 SCI_STATUS scic_sds_request_default_complete_handler(
1801 SCI_BASE_REQUEST_T *request
1802 )
1803 {
1804 SCIC_LOG_WARNING((
1805 sci_base_object_get_logger((SCIC_SDS_REQUEST_T *)request),
1806 (
1807 SCIC_LOG_OBJECT_SSP_IO_REQUEST
1808 | SCIC_LOG_OBJECT_STP_IO_REQUEST
1809 | SCIC_LOG_OBJECT_SMP_IO_REQUEST
1810 ),
1811 "SCIC IO Request requested to complete while in wrong state %d\n",
1812 sci_base_state_machine_get_state(
1813 &((SCIC_SDS_REQUEST_T *)request)->parent.state_machine)
1814 ));
1815
1816 return SCI_FAILURE_INVALID_STATE;
1817 }
1818
1819 /**
1820 * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T
1821 * object receives a scic_sds_request_complete() request. The default action
1822 * is to log a warning and return a failure status.
1823 *
1824 * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
1825 * the SCIC_SDS_IO_REQUEST_T object for which the start operation is
1826 * requested.
1827 *
1828 * @return SCI_STATUS
1829 * @retval SCI_FAILURE_INVALID_STATE
1830 */
1831 SCI_STATUS scic_sds_request_default_destruct_handler(
1832 SCI_BASE_REQUEST_T *request
1833 )
1834 {
1835 SCIC_LOG_WARNING((
1836 sci_base_object_get_logger((SCIC_SDS_REQUEST_T *)request),
1837 (
1838 SCIC_LOG_OBJECT_SSP_IO_REQUEST
1839 | SCIC_LOG_OBJECT_STP_IO_REQUEST
1840 | SCIC_LOG_OBJECT_SMP_IO_REQUEST
1841 ),
1842 "SCIC IO Request requested to destroy while in wrong state %d\n",
1843 sci_base_state_machine_get_state(
1844 &((SCIC_SDS_REQUEST_T *)request)->parent.state_machine)
1845 ));
1846
1847 return SCI_FAILURE_INVALID_STATE;
1848 }
1849
1850 /**
1851 * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T
1852 * object receives a scic_sds_task_request_complete() request. The default
1853 * action is to log a warning and return a failure status.
1854 *
1855 * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
1856 * the SCIC_SDS_IO_REQUEST_T object for which the start operation is
1857 * requested.
1858 *
1859 * @return SCI_STATUS
1860 * @retval SCI_FAILURE_INVALID_STATE
1861 */
1862 SCI_STATUS scic_sds_request_default_tc_completion_handler(
1863 SCIC_SDS_REQUEST_T * this_request,
1864 U32 completion_code
1865 )
1866 {
1867 SCIC_LOG_WARNING((
1868 sci_base_object_get_logger(this_request),
1869 (
1870 SCIC_LOG_OBJECT_SSP_IO_REQUEST
1871 | SCIC_LOG_OBJECT_STP_IO_REQUEST
1872 | SCIC_LOG_OBJECT_SMP_IO_REQUEST
1873 ),
1874 "SCIC IO Request given task completion notification %x while in wrong state %d\n",
1875 completion_code,
1876 sci_base_state_machine_get_state(&this_request->parent.state_machine)
1877 ));
1878
1879 return SCI_FAILURE_INVALID_STATE;
1880
1881 }
1882
1883 /**
1884 * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T
1885 * object receives a scic_sds_request_event_handler() request. The default
1886 * action is to log a warning and return a failure status.
1887 *
1888 * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
1889 * the SCIC_SDS_IO_REQUEST_T object for which the start operation is
1890 * requested.
1891 *
1892 * @return SCI_STATUS
1893 * @retval SCI_FAILURE_INVALID_STATE
1894 */
1895 SCI_STATUS scic_sds_request_default_event_handler(
1896 SCIC_SDS_REQUEST_T * this_request,
1897 U32 event_code
1898 )
1899 {
1900 SCIC_LOG_WARNING((
1901 sci_base_object_get_logger(this_request),
1902 (
1903 SCIC_LOG_OBJECT_SSP_IO_REQUEST
1904 | SCIC_LOG_OBJECT_STP_IO_REQUEST
1905 | SCIC_LOG_OBJECT_SMP_IO_REQUEST
1906 ),
1907 "SCIC IO Request given event code notification %x while in wrong state %d\n",
1908 event_code,
1909 sci_base_state_machine_get_state(&this_request->parent.state_machine)
1910 ));
1911
1912 return SCI_FAILURE_INVALID_STATE;
1913 }
1914
1915 /**
1916 * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T
1917 * object receives a scic_sds_request_event_handler() request. The default
1918 * action is to log a warning and return a failure status.
1919 *
1920 * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
1921 * the SCIC_SDS_IO_REQUEST_T object for which the start operation is
1922 * requested.
1923 *
1924 * @return SCI_STATUS
1925 * @retval SCI_FAILURE_INVALID_STATE
1926 */
1927 SCI_STATUS scic_sds_request_default_frame_handler(
1928 SCIC_SDS_REQUEST_T * this_request,
1929 U32 frame_index
1930 )
1931 {
1932 SCIC_LOG_WARNING((
1933 sci_base_object_get_logger(this_request),
1934 (
1935 SCIC_LOG_OBJECT_SSP_IO_REQUEST
1936 | SCIC_LOG_OBJECT_STP_IO_REQUEST
1937 | SCIC_LOG_OBJECT_SMP_IO_REQUEST
1938 ),
1939 "SCIC IO Request given unexpected frame %x while in state %d\n",
1940 frame_index,
1941 sci_base_state_machine_get_state(&this_request->parent.state_machine)
1942 ));
1943
1944 scic_sds_controller_release_frame(
1945 this_request->owning_controller, frame_index);
1946
1947 return SCI_FAILURE_INVALID_STATE;
1948 }
1949
1950 //*****************************************************************************
1951 //* CONSTRUCTED STATE HANDLERS
1952 //*****************************************************************************
1953
1954 /**
1955 * This method implements the action taken when a constructed
1956 * SCIC_SDS_IO_REQUEST_T object receives a scic_sds_request_start() request.
1957 *
1958 * This method will, if necessary, allocate a TCi for the io request object
1959 * and then will, if necessary, copy the constructed TC data into the actual
1960 * TC buffer. If everything is successful the post context field is updated
1961 * with the TCi so the controller can post the request to the hardware.
1962 *
1963 * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
1964 * the SCIC_SDS_IO_REQUEST_T object for which the start operation is
1965 * requested.
1966 *
1967 * @return SCI_STATUS
1968 * @retval SCI_SUCCESS
1969 * @retval SCI_FAILURE_INSUFFICIENT_RESOURCES
1970 */
1971 static
1972 SCI_STATUS scic_sds_request_constructed_state_start_handler(
1973 SCI_BASE_REQUEST_T *request
1974 )
1975 {
1976 SCU_TASK_CONTEXT_T *task_context;
1977 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)request;
1978
1979 if (this_request->io_tag == SCI_CONTROLLER_INVALID_IO_TAG)
1980 {
1981 this_request->io_tag =
1982 scic_controller_allocate_io_tag(this_request->owning_controller);
1983 }
1984
1985 // Record the IO Tag in the request
1986 if (this_request->io_tag != SCI_CONTROLLER_INVALID_IO_TAG)
1987 {
1988 task_context = this_request->task_context_buffer;
1989
1990 task_context->task_index = scic_sds_io_tag_get_index(this_request->io_tag);
1991
1992 switch (task_context->protocol_type)
1993 {
1994 case SCU_TASK_CONTEXT_PROTOCOL_SMP:
1995 case SCU_TASK_CONTEXT_PROTOCOL_SSP:
1996 // SSP/SMP Frame
1997 task_context->type.ssp.tag = this_request->io_tag;
1998 task_context->type.ssp.target_port_transfer_tag = 0xFFFF;
1999 break;
2000
2001 case SCU_TASK_CONTEXT_PROTOCOL_STP:
2002 // STP/SATA Frame
2003 //task_context->type.stp.ncq_tag = this_request->ncq_tag;
2004 break;
2005
2006 case SCU_TASK_CONTEXT_PROTOCOL_NONE:
2007 /// @todo When do we set no protocol type?
2008 break;
2009
2010 default:
2011 // This should never happen since we build the IO requests
2012 break;
2013 }
2014
2015 // Check to see if we need to copy the task context buffer
2016 // or have been building into the task context buffer
2017 if (this_request->was_tag_assigned_by_user == FALSE)
2018 {
2019 scic_sds_controller_copy_task_context(
2020 this_request->owning_controller, this_request
2021 );
2022 }
2023
2024 // Add to the post_context the io tag value
2025 this_request->post_context |= scic_sds_io_tag_get_index(this_request->io_tag);
2026
2027 // Everything is good go ahead and change state
2028 sci_base_state_machine_change_state(
2029 &this_request->parent.state_machine,
2030 SCI_BASE_REQUEST_STATE_STARTED
2031 );
2032
2033 return SCI_SUCCESS;
2034 }
2035
2036 return SCI_FAILURE_INSUFFICIENT_RESOURCES;
2037 }
2038
2039 /**
2040 * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T
2041 * object receives a scic_sds_request_terminate() request.
2042 *
2043 * Since the request has not yet been posted to the hardware the request
2044 * transitions to the completed state.
2045 *
2046 * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
2047 * the SCIC_SDS_IO_REQUEST_T object for which the start operation is
2048 * requested.
2049 *
2050 * @return SCI_STATUS
2051 * @retval SCI_SUCCESS
2052 */
2053 static
2054 SCI_STATUS scic_sds_request_constructed_state_abort_handler(
2055 SCI_BASE_REQUEST_T *request
2056 )
2057 {
2058 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)request;
2059
2060 // This request has been terminated by the user make sure that the correct
2061 // status code is returned
2062 scic_sds_request_set_status(
2063 this_request,
2064 SCU_TASK_DONE_TASK_ABORT,
2065 SCI_FAILURE_IO_TERMINATED
2066 );
2067
2068 sci_base_state_machine_change_state(
2069 &this_request->parent.state_machine,
2070 SCI_BASE_REQUEST_STATE_COMPLETED
2071 );
2072
2073 return SCI_SUCCESS;
2074 }
2075
2076 //*****************************************************************************
2077 //* STARTED STATE HANDLERS
2078 //*****************************************************************************
2079
2080 /**
2081 * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T
2082 * object receives a scic_sds_request_terminate() request.
2083 *
2084 * Since the request has been posted to the hardware the io request state is
2085 * changed to the aborting state.
2086 *
2087 * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
2088 * the SCIC_SDS_IO_REQUEST_T object for which the start operation is
2089 * requested.
2090 *
2091 * @return SCI_STATUS
2092 * @retval SCI_SUCCESS
2093 */
2094 SCI_STATUS scic_sds_request_started_state_abort_handler(
2095 SCI_BASE_REQUEST_T *request
2096 )
2097 {
2098 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)request;
2099
2100 if (this_request->has_started_substate_machine)
2101 {
2102 sci_base_state_machine_stop(&this_request->started_substate_machine);
2103 }
2104
2105 sci_base_state_machine_change_state(
2106 &this_request->parent.state_machine,
2107 SCI_BASE_REQUEST_STATE_ABORTING
2108 );
2109
2110 return SCI_SUCCESS;
2111 }
2112
2113 /**
2114 * @brief This method process TC (task context) completions for normal IO
2115 * request (i.e. Task/Abort Completions of type 0). This method will
2116 * update the SCIC_SDS_IO_REQUEST_T::status field.
2117 *
2118 * @param[in] this_request This parameter specifies the request for which
2119 * a completion occurred.
2120 * @param[in] completion_code This parameter specifies the completion code
2121 * received from the SCU.
2122 *
2123 * @return none
2124 */
2125 SCI_STATUS scic_sds_request_started_state_tc_completion_handler(
2126 SCIC_SDS_REQUEST_T * this_request,
2127 U32 completion_code
2128 )
2129 {
2130 U8 data_present;
2131 SCI_SSP_RESPONSE_IU_T * response_buffer;
2132
2133 /**
2134 * @todo Any SDMA return code of other than 0 is bad
2135 * decode 0x003C0000 to determine SDMA status
2136 */
2137 switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
2138 {
2139 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
2140 scic_sds_request_set_status(
2141 this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
2142 );
2143 break;
2144
2145 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_EARLY_RESP):
2146 {
2147 // There are times when the SCU hardware will return an early response
2148 // because the io request specified more data than is returned by the
2149 // target device (mode pages, inquiry data, etc.). We must check the
2150 // response stats to see if this is truly a failed request or a good
2151 // request that just got completed early.
2152 SCI_SSP_RESPONSE_IU_T *response = (SCI_SSP_RESPONSE_IU_T *)
2153 this_request->response_buffer;
2154 scic_word_copy_with_swap(
2155 this_request->response_buffer,
2156 this_request->response_buffer,
2157 sizeof(SCI_SSP_RESPONSE_IU_T) / sizeof(U32)
2158 );
2159
2160 if (response->status == 0)
2161 {
2162 scic_sds_request_set_status(
2163 this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS_IO_DONE_EARLY
2164 );
2165 }
2166 else
2167 {
2168 scic_sds_request_set_status(
2169 this_request,
2170 SCU_TASK_DONE_CHECK_RESPONSE,
2171 SCI_FAILURE_IO_RESPONSE_VALID
2172 );
2173 }
2174 }
2175 break;
2176
2177 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CHECK_RESPONSE):
2178 scic_word_copy_with_swap(
2179 this_request->response_buffer,
2180 this_request->response_buffer,
2181 sizeof(SCI_SSP_RESPONSE_IU_T) / sizeof(U32)
2182 );
2183
2184 scic_sds_request_set_status(
2185 this_request,
2186 SCU_TASK_DONE_CHECK_RESPONSE,
2187 SCI_FAILURE_IO_RESPONSE_VALID
2188 );
2189 break;
2190
2191 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_RESP_LEN_ERR):
2192 /// @todo With TASK_DONE_RESP_LEN_ERR is the response frame guaranteed
2193 /// to be received before this completion status is posted?
2194 response_buffer =
2195 (SCI_SSP_RESPONSE_IU_T *)this_request->response_buffer;
2196 data_present =
2197 response_buffer->data_present & SCI_SSP_RESPONSE_IU_DATA_PRESENT_MASK;
2198
2199 if ((data_present == 0x01) || (data_present == 0x02))
2200 {
2201 scic_sds_request_set_status(
2202 this_request,
2203 SCU_TASK_DONE_CHECK_RESPONSE,
2204 SCI_FAILURE_IO_RESPONSE_VALID
2205 );
2206 }
2207 else
2208 {
2209 scic_sds_request_set_status(
2210 this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
2211 );
2212 }
2213 break;
2214
2215 //only stp device gets suspended.
2216 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_ACK_NAK_TO):
2217 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_PERR):
2218 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_NAK_ERR):
2219 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_DATA_LEN_ERR):
2220 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_ABORT_ERR):
2221 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_XR_WD_LEN):
2222 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_MAX_PLD_ERR):
2223 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_RESP):
2224 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_SDBFIS):
2225 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_REG_ERR):
2226 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SDB_ERR):
2227 if (this_request->protocol == SCIC_STP_PROTOCOL)
2228 {
2229 SCIC_LOG_ERROR((
2230 sci_base_object_get_logger(this_request),
2231 SCIC_LOG_OBJECT_STP_IO_REQUEST,
2232 "SCIC IO Request 0x%x returning REMOTE_DEVICE_RESET_REQUIRED for completion code 0x%x\n",
2233 this_request, completion_code
2234 ));
2235 scic_sds_request_set_status(
2236 this_request,
2237 SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT,
2238 SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED
2239 );
2240 }
2241 else
2242 {
2243 SCIC_LOG_ERROR((
2244 sci_base_object_get_logger(this_request),
2245 SCIC_LOG_OBJECT_SSP_IO_REQUEST,
2246 "SCIC IO Request 0x%x returning CONTROLLER_SPECIFIC_IO_ERR for completion code 0x%x\n",
2247 this_request, completion_code
2248 ));
2249 scic_sds_request_set_status(
2250 this_request,
2251 SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT,
2252 SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
2253 );
2254 }
2255 break;
2256
2257 //both stp/ssp device gets suspended
2258 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LF_ERR):
2259 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_WRONG_DESTINATION):
2260 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_1):
2261 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_2):
2262 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_3):
2263 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_BAD_DESTINATION):
2264 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_ZONE_VIOLATION):
2265 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_STP_RESOURCES_BUSY):
2266 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED):
2267 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_CONNECTION_RATE_NOT_SUPPORTED):
2268 scic_sds_request_set_status(
2269 this_request,
2270 SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT,
2271 SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED
2272 );
2273 break;
2274
2275 //neither ssp nor stp gets suspended.
2276 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_NAK_CMD_ERR):
2277 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_XR):
2278 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_XR_IU_LEN_ERR):
2279 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SDMA_ERR):
2280 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_OFFSET_ERR):
2281 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_EXCESS_DATA):
2282 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_RESP_TO_ERR):
2283 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_UFI_ERR):
2284 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_FRM_TYPE_ERR):
2285 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_LL_RX_ERR):
2286 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_DATA):
2287 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_OPEN_FAIL):
2288 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_VIIT_ENTRY_NV):
2289 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_IIT_ENTRY_NV):
2290 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_RNCNV_OUTBOUND):
2291 default:
2292 SCIC_LOG_ERROR((
2293 sci_base_object_get_logger(this_request),
2294 SCIC_LOG_OBJECT_SSP_IO_REQUEST | SCIC_LOG_OBJECT_STP_IO_REQUEST,
2295 "SCIC IO Request 0x%x returning CONTROLLER_SPECIFIC_IO_ERR for completion code 0x%x\n",
2296 this_request, completion_code
2297 ));
2298 scic_sds_request_set_status(
2299 this_request,
2300 SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT,
2301 SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
2302 );
2303 break;
2304 }
2305
2306 /**
2307 * @todo This is probably wrong for ACK/NAK timeout conditions
2308 */
2309
2310 // In all cases we will treat this as the completion of the IO request.
2311 sci_base_state_machine_change_state(
2312 &this_request->parent.state_machine,
2313 SCI_BASE_REQUEST_STATE_COMPLETED
2314 );
2315
2316 return SCI_SUCCESS;
2317 }
2318
2319 /**
2320 * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T
2321 * object receives a scic_sds_request_frame_handler() request.
2322 *
2323 * This method first determines the frame type received. If this is a
2324 * response frame then the response data is copied to the io request response
2325 * buffer for processing at completion time.
2326 *
2327 * If the frame type is not a response buffer an error is logged.
2328 *
2329 * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
2330 * the SCIC_SDS_IO_REQUEST_T object for which the start operation is
2331 * requested.
2332 * @param[in] frame_index This is the index of the unsolicited frame to be
2333 * processed.
2334 *
2335 * @return SCI_STATUS
2336 * @retval SCI_SUCCESS
2337 * @retval SCI_FAILURE_INVALID_PARAMETER_VALUE
2338 */
2339 static
2340 SCI_STATUS scic_sds_request_started_state_frame_handler(
2341 SCIC_SDS_REQUEST_T * this_request,
2342 U32 frame_index
2343 )
2344 {
2345 SCI_STATUS status;
2346 SCI_SSP_FRAME_HEADER_T *frame_header;
2347
2348 /// @todo If this is a response frame we must record that we received it
2349 status = scic_sds_unsolicited_frame_control_get_header(
2350 &(scic_sds_request_get_controller(this_request)->uf_control),
2351 frame_index,
2352 (void**) &frame_header
2353 );
2354
2355 if (frame_header->frame_type == SCI_SAS_RESPONSE_FRAME)
2356 {
2357 SCI_SSP_RESPONSE_IU_T *response_buffer;
2358
2359 status = scic_sds_unsolicited_frame_control_get_buffer(
2360 &(scic_sds_request_get_controller(this_request)->uf_control),
2361 frame_index,
2362 (void**) &response_buffer
2363 );
2364
2365 scic_word_copy_with_swap(
2366 this_request->response_buffer,
2367 (U32 *)response_buffer,
2368 sizeof(SCI_SSP_RESPONSE_IU_T)
2369 );
2370
2371 response_buffer = (SCI_SSP_RESPONSE_IU_T *)this_request->response_buffer;
2372
2373 if (
2374 (response_buffer->data_present == 0x01)
2375 || (response_buffer->data_present == 0x02)
2376 )
2377 {
2378 scic_sds_request_set_status(
2379 this_request,
2380 SCU_TASK_DONE_CHECK_RESPONSE,
2381 SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
2382 );
2383 }
2384 else
2385 {
2386 scic_sds_request_set_status(
2387 this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
2388 );
2389 }
2390
2391 }
2392 else
2393 {
2394 // This was not a response frame why did it get forwarded?
2395 SCIC_LOG_ERROR((
2396 sci_base_object_get_logger(this_request),
2397 SCIC_LOG_OBJECT_SSP_IO_REQUEST,
2398 "SCIC IO Request 0x%x received unexpected frame %d type 0x%02x\n",
2399 this_request, frame_index, frame_header->frame_type
2400 ));
2401 }
2402
2403 // In any case we are done with this frame buffer return it to the
2404 // controller
2405 scic_sds_controller_release_frame(
2406 this_request->owning_controller, frame_index
2407 );
2408
2409 return SCI_SUCCESS;
2410 }
2411
2412 //*****************************************************************************
2413 //* COMPLETED STATE HANDLERS
2414 //*****************************************************************************
2415
2416
2417 /**
2418 * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T
2419 * object receives a scic_sds_request_complete() request.
2420 *
2421 * This method frees up any io request resources that have been allocated and
2422 * transitions the request to its final state.
2423 *
2424 * @todo Consider stopping the state machine instead of transitioning to the
2425 * final state?
2426 *
2427 * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
2428 * the SCIC_SDS_IO_REQUEST_T object for which the start operation is
2429 * requested.
2430 *
2431 * @return SCI_STATUS
2432 * @retval SCI_SUCCESS
2433 */
2434 static
2435 SCI_STATUS scic_sds_request_completed_state_complete_handler(
2436 SCI_BASE_REQUEST_T *request
2437 )
2438 {
2439 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)request;
2440
2441 if (this_request->was_tag_assigned_by_user != TRUE)
2442 {
2443 scic_controller_free_io_tag(
2444 this_request->owning_controller, this_request->io_tag
2445 );
2446 }
2447
2448 if (this_request->saved_rx_frame_index != SCU_INVALID_FRAME_INDEX)
2449 {
2450 scic_sds_controller_release_frame(
2451 this_request->owning_controller, this_request->saved_rx_frame_index);
2452 }
2453
2454 sci_base_state_machine_change_state(
2455 &this_request->parent.state_machine,
2456 SCI_BASE_REQUEST_STATE_FINAL
2457 );
2458
2459 scic_sds_request_deinitialize_state_logging(this_request);
2460
2461 return SCI_SUCCESS;
2462 }
2463
2464 //*****************************************************************************
2465 //* ABORTING STATE HANDLERS
2466 //*****************************************************************************
2467
2468 /**
2469 * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T
2470 * object receives a scic_sds_request_terminate() request.
2471 *
2472 * This method is the io request aborting state abort handlers. On receipt of
2473 * a multiple terminate requests the io request will transition to the
2474 * completed state. This should not happen in normal operation.
2475 *
2476 * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
2477 * the SCIC_SDS_IO_REQUEST_T object for which the start operation is
2478 * requested.
2479 *
2480 * @return SCI_STATUS
2481 * @retval SCI_SUCCESS
2482 */
2483 static
2484 SCI_STATUS scic_sds_request_aborting_state_abort_handler(
2485 SCI_BASE_REQUEST_T *request
2486 )
2487 {
2488 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)request;
2489
2490 sci_base_state_machine_change_state(
2491 &this_request->parent.state_machine,
2492 SCI_BASE_REQUEST_STATE_COMPLETED
2493 );
2494
2495 return SCI_SUCCESS;
2496 }
2497
2498 /**
2499 * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T
2500 * object receives a scic_sds_request_task_completion() request.
2501 *
2502 * This method decodes the completion type waiting for the abort task complete
2503 * notification. When the abort task complete is received the io request
2504 * transitions to the completed state.
2505 *
2506 * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
2507 * the SCIC_SDS_IO_REQUEST_T object for which the start operation is
2508 * requested.
2509 *
2510 * @return SCI_STATUS
2511 * @retval SCI_SUCCESS
2512 */
2513 static
2514 SCI_STATUS scic_sds_request_aborting_state_tc_completion_handler(
2515 SCIC_SDS_REQUEST_T * this_request,
2516 U32 completion_code
2517 )
2518 {
2519 SCIC_LOG_TRACE((
2520 sci_base_object_get_logger(this_request),
2521 SCIC_LOG_OBJECT_TASK_MANAGEMENT,
2522 "scic_sds_request_aborting_state_tc_completion_handler(0x%x,0x%x) enter\n",
2523 this_request, completion_code
2524 ));
2525
2526 switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
2527 {
2528 case (SCU_TASK_DONE_GOOD << SCU_COMPLETION_TL_STATUS_SHIFT):
2529 case (SCU_TASK_DONE_TASK_ABORT << SCU_COMPLETION_TL_STATUS_SHIFT):
2530 scic_sds_request_set_status(
2531 this_request, SCU_TASK_DONE_TASK_ABORT, SCI_FAILURE_IO_TERMINATED
2532 );
2533
2534 sci_base_state_machine_change_state(
2535 &this_request->parent.state_machine,
2536 SCI_BASE_REQUEST_STATE_COMPLETED
2537 );
2538 break;
2539
2540 default:
2541 // Unless we get some strange error wait for the task abort to complete
2542 // TODO: Should there be a state change for this completion?
2543 break;
2544 }
2545
2546 return SCI_SUCCESS;
2547 }
2548
2549 /**
2550 * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T
2551 * object receives a scic_sds_request_frame_handler() request.
2552 *
2553 * This method discards the unsolicited frame since we are waiting for the
2554 * abort task completion.
2555 *
2556 * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
2557 * the SCIC_SDS_IO_REQUEST_T object for which the start operation is
2558 * requested.
2559 *
2560 * @return SCI_STATUS
2561 * @retval SCI_SUCCESS
2562 */
2563 static
2564 SCI_STATUS scic_sds_request_aborting_state_frame_handler(
2565 SCIC_SDS_REQUEST_T * this_request,
2566 U32 frame_index
2567 )
2568 {
2569 // TODO: Is it even possible to get an unsolicited frame in the aborting state?
2570
2571 scic_sds_controller_release_frame(
2572 this_request->owning_controller, frame_index);
2573
2574 return SCI_SUCCESS;
2575 }
2576
2577 // ---------------------------------------------------------------------------
2578
2579 SCIC_SDS_IO_REQUEST_STATE_HANDLER_T
2580 scic_sds_request_state_handler_table[SCI_BASE_REQUEST_MAX_STATES] =
2581 {
2582 // SCI_BASE_REQUEST_STATE_INITIAL
2583 {
2584 {
2585 scic_sds_request_default_start_handler,
2586 scic_sds_request_default_abort_handler,
2587 scic_sds_request_default_complete_handler,
2588 scic_sds_request_default_destruct_handler
2589 },
2590 scic_sds_request_default_tc_completion_handler,
2591 scic_sds_request_default_event_handler,
2592 scic_sds_request_default_frame_handler
2593 },
2594 // SCI_BASE_REQUEST_STATE_CONSTRUCTED
2595 {
2596 {
2597 scic_sds_request_constructed_state_start_handler,
2598 scic_sds_request_constructed_state_abort_handler,
2599 scic_sds_request_default_complete_handler,
2600 scic_sds_request_default_destruct_handler
2601 },
2602 scic_sds_request_default_tc_completion_handler,
2603 scic_sds_request_default_event_handler,
2604 scic_sds_request_default_frame_handler
2605 },
2606 // SCI_BASE_REQUEST_STATE_STARTED
2607 {
2608 {
2609 scic_sds_request_default_start_handler,
2610 scic_sds_request_started_state_abort_handler,
2611 scic_sds_request_default_complete_handler,
2612 scic_sds_request_default_destruct_handler
2613 },
2614 scic_sds_request_started_state_tc_completion_handler,
2615 scic_sds_request_default_event_handler,
2616 scic_sds_request_started_state_frame_handler
2617 },
2618 // SCI_BASE_REQUEST_STATE_COMPLETED
2619 {
2620 {
2621 scic_sds_request_default_start_handler,
2622 scic_sds_request_default_abort_handler,
2623 scic_sds_request_completed_state_complete_handler,
2624 scic_sds_request_default_destruct_handler
2625 },
2626 scic_sds_request_default_tc_completion_handler,
2627 scic_sds_request_default_event_handler,
2628 scic_sds_request_default_frame_handler
2629 },
2630 // SCI_BASE_REQUEST_STATE_ABORTING
2631 {
2632 {
2633 scic_sds_request_default_start_handler,
2634 scic_sds_request_aborting_state_abort_handler,
2635 scic_sds_request_default_complete_handler,
2636 scic_sds_request_default_destruct_handler
2637 },
2638 scic_sds_request_aborting_state_tc_completion_handler,
2639 scic_sds_request_default_event_handler,
2640 scic_sds_request_aborting_state_frame_handler,
2641 },
2642 // SCI_BASE_REQUEST_STATE_FINAL
2643 {
2644 {
2645 scic_sds_request_default_start_handler,
2646 scic_sds_request_default_abort_handler,
2647 scic_sds_request_default_complete_handler,
2648 scic_sds_request_default_destruct_handler
2649 },
2650 scic_sds_request_default_tc_completion_handler,
2651 scic_sds_request_default_event_handler,
2652 scic_sds_request_default_frame_handler
2653 }
2654 };
2655
2656 /**
2657 * This method implements the actions taken when entering the
2658 * SCI_BASE_REQUEST_STATE_INITIAL state. This state is entered when the
2659 * initial base request is constructed. Entry into the initial state sets all
2660 * handlers for the io request object to their default handlers.
2661 *
2662 * @param[in] object This parameter specifies the base object for which the
2663 * state transition is occurring.
2664 *
2665 * @return none
2666 */
2667 static
2668 void scic_sds_request_initial_state_enter(
2669 SCI_BASE_OBJECT_T *object
2670 )
2671 {
2672 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
2673
2674 SET_STATE_HANDLER(
2675 this_request,
2676 scic_sds_request_state_handler_table,
2677 SCI_BASE_REQUEST_STATE_INITIAL
2678 );
2679 }
2680
2681 /**
2682 * This method implements the actions taken when entering the
2683 * SCI_BASE_REQUEST_STATE_CONSTRUCTED state.
2684 * The method sets the state handlers for the constructed state.
2685 *
2686 * @param[in] object The io request object that is to enter the constructed
2687 * state.
2688 *
2689 * @return none
2690 */
2691 static
2692 void scic_sds_request_constructed_state_enter(
2693 SCI_BASE_OBJECT_T *object
2694 )
2695 {
2696 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
2697
2698 SET_STATE_HANDLER(
2699 this_request,
2700 scic_sds_request_state_handler_table,
2701 SCI_BASE_REQUEST_STATE_CONSTRUCTED
2702 );
2703 }
2704
2705 /**
2706 * This method implements the actions taken when entering the
2707 * SCI_BASE_REQUEST_STATE_STARTED state. If the io request object type is a
2708 * SCSI Task request we must enter the started substate machine.
2709 *
2710 * @param[in] object This parameter specifies the base object for which the
2711 * state transition is occurring. This is cast into a
2712 * SCIC_SDS_IO_REQUEST object.
2713 *
2714 * @return none
2715 */
2716 static
2717 void scic_sds_request_started_state_enter(
2718 SCI_BASE_OBJECT_T *object
2719 )
2720 {
2721 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
2722
2723 SET_STATE_HANDLER(
2724 this_request,
2725 scic_sds_request_state_handler_table,
2726 SCI_BASE_REQUEST_STATE_STARTED
2727 );
2728
2729 // Most of the request state machines have a started substate machine so
2730 // start its execution on the entry to the started state.
2731 if (this_request->has_started_substate_machine == TRUE)
2732 sci_base_state_machine_start(&this_request->started_substate_machine);
2733 }
2734
2735 /**
2736 * This method implements the actions taken when exiting the
2737 * SCI_BASE_REQUEST_STATE_STARTED state. For task requests the action will be
2738 * to stop the started substate machine.
2739 *
2740 * @param[in] object This parameter specifies the base object for which the
2741 * state transition is occurring. This object is cast into a
2742 * SCIC_SDS_IO_REQUEST object.
2743 *
2744 * @return none
2745 */
2746 static
2747 void scic_sds_request_started_state_exit(
2748 SCI_BASE_OBJECT_T *object
2749 )
2750 {
2751 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
2752
2753 if (this_request->has_started_substate_machine == TRUE)
2754 sci_base_state_machine_stop(&this_request->started_substate_machine);
2755 }
2756
2757 /**
2758 * This method implements the actions taken when entering the
2759 * SCI_BASE_REQUEST_STATE_COMPLETED state. This state is entered when the
2760 * SCIC_SDS_IO_REQUEST has completed. The method will decode the request
2761 * completion status and convert it to an SCI_STATUS to return in the
2762 * completion callback function.
2763 *
2764 * @param[in] object This parameter specifies the base object for which the
2765 * state transition is occurring. This object is cast into a
2766 * SCIC_SDS_IO_REQUEST object.
2767 *
2768 * @return none
2769 */
2770 static
2771 void scic_sds_request_completed_state_enter(
2772 SCI_BASE_OBJECT_T *object
2773 )
2774 {
2775 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
2776
2777 SET_STATE_HANDLER(
2778 this_request,
2779 scic_sds_request_state_handler_table,
2780 SCI_BASE_REQUEST_STATE_COMPLETED
2781 );
2782
2783 // Tell the SCI_USER that the IO request is complete
2784 if (this_request->is_task_management_request == FALSE)
2785 {
2786 scic_cb_io_request_complete(
2787 scic_sds_request_get_controller(this_request),
2788 scic_sds_request_get_device(this_request),
2789 this_request,
2790 this_request->sci_status
2791 );
2792 }
2793 else
2794 {
2795 scic_cb_task_request_complete(
2796 scic_sds_request_get_controller(this_request),
2797 scic_sds_request_get_device(this_request),
2798 this_request,
2799 this_request->sci_status
2800 );
2801 }
2802 }
2803
2804 /**
2805 * This method implements the actions taken when entering the
2806 * SCI_BASE_REQUEST_STATE_ABORTING state.
2807 *
2808 * @param[in] object This parameter specifies the base object for which the
2809 * state transition is occurring. This object is cast into a
2810 * SCIC_SDS_IO_REQUEST object.
2811 *
2812 * @return none
2813 */
2814 static
2815 void scic_sds_request_aborting_state_enter(
2816 SCI_BASE_OBJECT_T *object
2817 )
2818 {
2819 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
2820
2821 // Setting the abort bit in the Task Context is required by the silicon.
2822 this_request->task_context_buffer->abort = 1;
2823
2824 SET_STATE_HANDLER(
2825 this_request,
2826 scic_sds_request_state_handler_table,
2827 SCI_BASE_REQUEST_STATE_ABORTING
2828 );
2829 }
2830
2831 /**
2832 * This method implements the actions taken when entering the
2833 * SCI_BASE_REQUEST_STATE_FINAL state. The only action required is to put the
2834 * state handlers in place.
2835 *
2836 * @param[in] object This parameter specifies the base object for which the
2837 * state transition is occurring. This is cast into a
2838 * SCIC_SDS_IO_REQUEST object.
2839 *
2840 * @return none
2841 */
2842 static
2843 void scic_sds_request_final_state_enter(
2844 SCI_BASE_OBJECT_T *object
2845 )
2846 {
2847 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
2848
2849 SET_STATE_HANDLER(
2850 this_request,
2851 scic_sds_request_state_handler_table,
2852 SCI_BASE_REQUEST_STATE_FINAL
2853 );
2854 }
2855
2856 // ---------------------------------------------------------------------------
2857
2858 SCI_BASE_STATE_T
2859 scic_sds_request_state_table[SCI_BASE_REQUEST_MAX_STATES] =
2860 {
2861 {
2862 SCI_BASE_REQUEST_STATE_INITIAL,
2863 scic_sds_request_initial_state_enter,
2864 NULL
2865 },
2866 {
2867 SCI_BASE_REQUEST_STATE_CONSTRUCTED,
2868 scic_sds_request_constructed_state_enter,
2869 NULL
2870 },
2871 {
2872 SCI_BASE_REQUEST_STATE_STARTED,
2873 scic_sds_request_started_state_enter,
2874 scic_sds_request_started_state_exit
2875 },
2876 {
2877 SCI_BASE_REQUEST_STATE_COMPLETED,
2878 scic_sds_request_completed_state_enter,
2879 NULL
2880 },
2881 {
2882 SCI_BASE_REQUEST_STATE_ABORTING,
2883 scic_sds_request_aborting_state_enter,
2884 NULL
2885 },
2886 {
2887 SCI_BASE_REQUEST_STATE_FINAL,
2888 scic_sds_request_final_state_enter,
2889 NULL
2890 }
2891 };
2892
Cache object: 6177d62b37957c4de2887b05bd33093f
|