1/*-
2 * This file is provided under a dual BSD/GPLv2 license.  When using or
3 * redistributing this file, you may do so under either license.
4 *
5 * GPL LICENSE SUMMARY
6 *
7 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of version 2 of the GNU General Public License as
11 * published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
21 * The full GNU General Public License is included in this distribution
22 * in the file called LICENSE.GPL.
23 *
24 * BSD LICENSE
25 *
26 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
27 * All rights reserved.
28 *
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
31 * are met:
32 *
33 *   * Redistributions of source code must retain the above copyright
34 *     notice, this list of conditions and the following disclaimer.
35 *   * Redistributions in binary form must reproduce the above copyright
36 *     notice, this list of conditions and the following disclaimer in
37 *     the documentation and/or other materials provided with the
38 *     distribution.
39 *
40 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
41 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
42 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
43 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
44 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
46 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
47 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
48 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
49 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
50 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51 *
52 * $FreeBSD$
53 */
54#ifndef _SCIC_SDS_IO_REQUEST_H_
55#define _SCIC_SDS_IO_REQUEST_H_
56
57/**
58 * @file
59 *
60 * @brief This file contains the structures, constants and prototypes for the
61 *        SCIC_SDS_IO_REQUEST object.
62 */
63
64#ifdef __cplusplus
65extern "C" {
66#endif // __cplusplus
67
68#include <dev/isci/scil/scic_io_request.h>
69
70#include <dev/isci/scil/sci_base_request.h>
71#include <dev/isci/scil/sci_base_state_machine_logger.h>
72#include <dev/isci/scil/scu_task_context.h>
73#include <dev/isci/scil/intel_sas.h>
74
75struct SCIC_SDS_CONTROLLER;
76struct SCIC_SDS_REMOTE_DEVICE;
77struct SCIC_SDS_IO_REQUEST_STATE_HANDLER;
78
79/**
80 * @enum _SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATES
81 *
82 * @brief This enumeration depicts all of the substates for a task
83 *        management request to be performed in the STARTED super-state.
84 */
85typedef enum _SCIC_SDS_RAW_REQUEST_STARTED_TASK_MGMT_SUBSTATES
86{
87   /**
88    * The AWAIT_TC_COMPLETION sub-state indicates that the started raw
89    * task management request is waiting for the transmission of the
90    * initial frame (i.e. command, task, etc.).
91    */
92   SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION,
93
94   /**
95    * This sub-state indicates that the started task management request
96    * is waiting for the reception of an unsolicited frame
97    * (i.e. response IU).
98    */
99   SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE,
100
101   SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_MAX_SUBSTATES
102
103} SCIC_SDS_RAW_REQUEST_STARTED_TASK_MGMT_SUBSTATES;
104
105
106/**
107 * @enum _SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATES
108 *
109 * @brief This enumeration depicts all of the substates for a SMP
110 *        request to be performed in the STARTED super-state.
111 */
112typedef enum _SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATES
113{
114   /**
115    * This sub-state indicates that the started task management request
116    * is waiting for the reception of an unsolicited frame
117    * (i.e. response IU).
118    */
119   SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE,
120
121   /**
122    * The AWAIT_TC_COMPLETION sub-state indicates that the started SMP request is
123    * waiting for the transmission of the initial frame (i.e. command, task, etc.).
124    */
125   SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION,
126
127   SCIC_SDS_SMP_REQUEST_STARTED_MAX_SUBSTATES
128
129} SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATES;
130
131/**
132 * @struct SCIC_SDS_IO_REQUEST
133 *
134 * @brief This structure contains or references all of the data necessary
135 *        to process a task management or normal IO request.
136 */
137typedef struct SCIC_SDS_REQUEST
138{
139   /**
140    * This field indictes the parent object of the request.
141    */
142   SCI_BASE_REQUEST_T parent;
143
144   void *user_request;
145
146   /**
147    * This field simply points to the controller to which this IO request
148    * is associated.
149    */
150   struct SCIC_SDS_CONTROLLER    *owning_controller;
151
152   /**
153    * This field simply points to the remote device to which this IO request
154    * is associated.
155    */
156   struct SCIC_SDS_REMOTE_DEVICE *target_device;
157
158   /**
159    * This field is utilized to determine if the SCI user is managing
160    * the IO tag for this request or if the core is managing it.
161    */
162   BOOL was_tag_assigned_by_user;
163
164   /**
165    * This field indicates the IO tag for this request.  The IO tag is
166    * comprised of the task_index and a sequence count. The sequence count
167    * is utilized to help identify tasks from one life to another.
168    */
169   U16 io_tag;
170
171   /**
172   * This field specifies the sat protocol being utilized for this
173   * IO request, such as SAT_PROTOCOL_PIO_DATA_IN, SAT_PROTOCOL_FPDMA etc.
174   */
175   U8 sat_protocol;
176
177   /**
178    * This field specifies the protocol being utilized for this
179    * IO request.
180    */
181   SCIC_TRANSPORT_PROTOCOL protocol;
182
183   /**
184    * This field indicates the completion status taken from the SCUs
185    * completion code.  It indicates the completion result for the SCU hardware.
186    */
187   U32 scu_status;
188
189   /**
190    * This field indicates the completion status returned to the SCI user.  It
191    * indicates the users view of the io request completion.
192    */
193   U32 sci_status;
194
195   /**
196    * This field contains the value to be utilized when posting (e.g. Post_TC,
197    * Post_TC_Abort) this request to the silicon.
198    */
199   U32 post_context;
200
201   void                   *command_buffer;
202   void                   *response_buffer;
203   SCU_TASK_CONTEXT_T     *task_context_buffer;
204   SCU_SGL_ELEMENT_PAIR_T *sgl_element_pair_buffer;
205
206   /**
207    * This field indicates if this request is a task management request or
208    * normal IO request.
209    */
210   BOOL is_task_management_request;
211
212   /**
213    * This field indicates that this request contains an initialized started
214    * substate machine.
215    */
216   BOOL has_started_substate_machine;
217
218   /**
219    * This field is a pointer to the stored rx frame data.  It is used in STP
220    * internal requests and SMP response frames.  If this field is non-NULL the
221    * saved frame must be released on IO request completion.
222    *
223    * @todo In the future do we want to keep a list of RX frame buffers?
224    */
225   U32 saved_rx_frame_index;
226
227   /**
228    * This field specifies the data necessary to manage the sub-state
229    * machine executed while in the SCI_BASE_REQUEST_STATE_STARTED state.
230    */
231   SCI_BASE_STATE_MACHINE_T started_substate_machine;
232
233   /**
234    * This field specifies the current state handlers in place for this
235    * IO Request object.  This field is updated each time the request
236    * changes state.
237    */
238   struct SCIC_SDS_IO_REQUEST_STATE_HANDLER *state_handlers;
239
240   #ifdef SCI_LOGGING
241   /**
242    * This field is the observer of the started subsate machine
243    */
244   SCI_BASE_STATE_MACHINE_LOGGER_T started_substate_machine_logger;
245   #endif
246
247   /**
248    * This field in the recorded device sequence for the io request.  This is
249    * recorded during the build operation and is compared in the start
250    * operation.  If the sequence is different then there was a change of
251    * devices from the build to start operations.
252    */
253   U8  device_sequence;
254
255} SCIC_SDS_REQUEST_T;
256
257
258typedef SCI_STATUS (*SCIC_SDS_IO_REQUEST_FRAME_HANDLER_T)(
259                         SCIC_SDS_REQUEST_T * this_request,
260                         U32                  frame_index);
261
262typedef SCI_STATUS (*SCIC_SDS_IO_REQUEST_EVENT_HANDLER_T)(
263                         SCIC_SDS_REQUEST_T * this_request,
264                         U32                  event_code);
265
266typedef SCI_STATUS (*SCIC_SDS_IO_REQUEST_TASK_COMPLETION_HANDLER_T)(
267                         SCIC_SDS_REQUEST_T * this_request,
268                         U32                  completion_code);
269
270/**
271 * @struct SCIC_SDS_IO_REQUEST_STATE_HANDLER
272 *
273 * @brief This is the SDS core definition of the state handlers.
274 */
275typedef struct SCIC_SDS_IO_REQUEST_STATE_HANDLER
276{
277   SCI_BASE_REQUEST_STATE_HANDLER_T parent;
278
279   SCIC_SDS_IO_REQUEST_TASK_COMPLETION_HANDLER_T  tc_completion_handler;
280   SCIC_SDS_IO_REQUEST_EVENT_HANDLER_T            event_handler;
281   SCIC_SDS_IO_REQUEST_FRAME_HANDLER_T            frame_handler;
282
283} SCIC_SDS_IO_REQUEST_STATE_HANDLER_T;
284
285extern SCI_BASE_STATE_T scic_sds_request_state_table[];
286extern SCIC_SDS_IO_REQUEST_STATE_HANDLER_T
287       scic_sds_request_state_handler_table[];
288
289extern SCI_BASE_STATE_T scic_sds_io_request_started_task_mgmt_substate_table[];
290extern SCIC_SDS_IO_REQUEST_STATE_HANDLER_T
291       scic_sds_ssp_task_request_started_substate_handler_table[];
292
293extern SCI_BASE_STATE_T scic_sds_smp_request_started_substate_table[];
294extern SCIC_SDS_IO_REQUEST_STATE_HANDLER_T
295       scic_sds_smp_request_started_substate_handler_table[];
296
297/**
298 * This macro returns the maximum number of SGL element paris that we will
299 * support in a single IO request.
300 */
301#define SCU_MAX_SGL_ELEMENT_PAIRS ((SCU_IO_REQUEST_SGE_COUNT + 1) / 2)
302
303/**
304 * This macro will return the controller for this io request object
305 */
306#define scic_sds_request_get_controller(this_request) \
307   ((this_request)->owning_controller)
308
309/**
310 * This macro will return the device for this io request object
311 */
312#define scic_sds_request_get_device(this_request) \
313   ((this_request)->target_device)
314
315/**
316 * This macro will return the port for this io request object
317 */
318#define scic_sds_request_get_port(this_request) \
319   scic_sds_remote_device_get_port(scic_sds_request_get_device(this_request))
320
321/**
322 * This macro returns the constructed post context result for the io
323 * request.
324 */
325#define scic_sds_request_get_post_context(this_request) \
326   ((this_request)->post_context)
327
328/**
329 * This is a helper macro to return the os handle for this request object.
330 */
331#define scic_sds_request_get_task_context(request) \
332   ((request)->task_context_buffer)
333
334#define CACHE_LINE_SIZE (64)
335#define scic_sds_request_align_task_context_buffer(address) \
336   ((SCU_TASK_CONTEXT_T *)( \
337       (((POINTER_UINT)(address)) + (CACHE_LINE_SIZE - 1)) \
338     & ~(CACHE_LINE_SIZE - 1) \
339   ))
340
341/**
342 * This macro will align the memory address so that it is correct for the SCU
343 * hardware to DMA the SGL element pairs.
344 */
345#define scic_sds_request_align_sgl_element_buffer(address) \
346   ((SCU_SGL_ELEMENT_PAIR_T *)( \
347     ((char *)(address)) \
348   + ( \
349         ((~(POINTER_UINT)(address)) + 1) \
350       & (sizeof(SCU_SGL_ELEMENT_PAIR_T) - 1) \
351     ) \
352   ))
353
354/**
355 * This macro will set the scu hardware status and sci request completion
356 * status for an io request.
357 */
358#define scic_sds_request_set_status(request, scu_status_code, sci_status_code) \
359{ \
360   (request)->scu_status = (scu_status_code); \
361   (request)->sci_status = (sci_status_code); \
362}
363
364#define scic_sds_request_complete(a_request) \
365   ((a_request)->state_handlers->parent.complete_handler(&(a_request)->parent))
366
367U32 scic_sds_request_get_min_timer_count(void);
368
369U32 scic_sds_request_get_max_timer_count(void);
370
371
372/**
373 * This macro invokes the core state task completion handler for the
374 * SCIC_SDS_IO_REQUEST_T object.
375 */
376#define scic_sds_io_request_tc_completion(this_request, completion_code) \
377{ \
378   if (this_request->parent.state_machine.current_state_id  \
379          == SCI_BASE_REQUEST_STATE_STARTED \
380       && this_request->has_started_substate_machine \
381          == FALSE) \
382      scic_sds_request_started_state_tc_completion_handler(this_request, completion_code); \
383   else \
384      this_request->state_handlers->tc_completion_handler(this_request, completion_code); \
385}
386
387/**
388 * This macro zeros the hardware SGL element data
389 */
390#define SCU_SGL_ZERO(scu_sge) \
391{ \
392   (scu_sge).length = 0; \
393   (scu_sge).address_lower = 0; \
394   (scu_sge).address_upper = 0; \
395   (scu_sge).address_modifier = 0; \
396}
397
398/**
399 * This macro copys the SGL Element data from the host os to the hardware SGL
400 * elment data
401 */
402#define SCU_SGL_COPY(os_handle, scu_sge, os_sge) \
403{ \
404   (scu_sge).length = \
405      scic_cb_sge_get_length_field(os_handle, os_sge); \
406   (scu_sge).address_upper = \
407      sci_cb_physical_address_upper(scic_cb_sge_get_address_field(os_handle, os_sge)); \
408   (scu_sge).address_lower = \
409      sci_cb_physical_address_lower(scic_cb_sge_get_address_field(os_handle, os_sge)); \
410   (scu_sge).address_modifier = 0; \
411}
412
413//*****************************************************************************
414//* CORE REQUEST PROTOTYPES
415//*****************************************************************************
416
417SCU_SGL_ELEMENT_PAIR_T *scic_sds_request_get_sgl_element_pair(
418   SCIC_SDS_REQUEST_T *this_request,
419   U32                 sgl_pair_index
420);
421
422void scic_sds_request_build_sgl(
423   SCIC_SDS_REQUEST_T *this_request
424);
425
426void scic_sds_ssp_io_request_assign_buffers(
427   SCIC_SDS_REQUEST_T *this_request
428);
429
430void scic_sds_ssp_task_request_assign_buffers(
431   SCIC_SDS_REQUEST_T *this_request
432);
433
434void scic_sds_stp_request_assign_buffers(
435   SCIC_SDS_REQUEST_T * this_request
436);
437
438void scic_sds_smp_request_assign_buffers(
439   SCIC_SDS_REQUEST_T * this_request
440);
441
442// ---------------------------------------------------------------------------
443
444SCI_STATUS scic_sds_request_start(
445   SCIC_SDS_REQUEST_T *this_request
446);
447
448SCI_STATUS scic_sds_io_request_terminate(
449   SCIC_SDS_REQUEST_T *this_request
450);
451
452SCI_STATUS scic_sds_io_request_complete(
453   SCIC_SDS_REQUEST_T *this_request
454);
455
456void scic_sds_io_request_copy_response(
457   SCIC_SDS_REQUEST_T *this_request
458);
459
460SCI_STATUS scic_sds_io_request_event_handler(
461   SCIC_SDS_REQUEST_T *this_request,
462   U32                    event_code
463);
464
465SCI_STATUS scic_sds_io_request_frame_handler(
466   SCIC_SDS_REQUEST_T *this_request,
467   U32                    frame_index
468);
469
470SCI_STATUS scic_sds_task_request_complete(
471   SCIC_SDS_REQUEST_T *this_request
472);
473
474SCI_STATUS scic_sds_task_request_terminate(
475   SCIC_SDS_REQUEST_T *this_request
476);
477
478#ifdef SCI_LOGGING
479void scic_sds_request_initialize_state_logging(
480   SCIC_SDS_REQUEST_T *this_request
481);
482
483void scic_sds_request_deinitialize_state_logging(
484   SCIC_SDS_REQUEST_T *this_request
485);
486#else // SCI_LOGGING
487#define scic_sds_request_initialize_state_logging(x)
488#define scic_sds_request_deinitialize_state_logging(x)
489#endif // SCI_LOGGING
490
491//*****************************************************************************
492//* DEFAULT STATE HANDLERS
493//*****************************************************************************
494
495SCI_STATUS scic_sds_request_default_start_handler(
496   SCI_BASE_REQUEST_T *this_request
497);
498
499SCI_STATUS scic_sds_request_default_abort_handler(
500   SCI_BASE_REQUEST_T *this_request
501);
502
503SCI_STATUS scic_sds_request_default_complete_handler(
504   SCI_BASE_REQUEST_T *this_request
505);
506
507SCI_STATUS scic_sds_request_default_destruct_handler(
508   SCI_BASE_REQUEST_T *this_request
509);
510
511SCI_STATUS scic_sds_request_default_tc_completion_handler(
512   SCIC_SDS_REQUEST_T * this_request,
513   U32                  completion_code
514);
515
516SCI_STATUS scic_sds_request_default_event_handler(
517   SCIC_SDS_REQUEST_T * this_request,
518   U32                  event_code
519);
520
521SCI_STATUS scic_sds_request_default_frame_handler(
522   SCIC_SDS_REQUEST_T * this_request,
523   U32                  frame_index
524);
525
526//*****************************************************************************
527//* STARTED STATE HANDLERS
528//*****************************************************************************
529
530SCI_STATUS scic_sds_request_started_state_abort_handler(
531   SCI_BASE_REQUEST_T *this_request
532);
533
534SCI_STATUS scic_sds_request_started_state_tc_completion_handler(
535   SCIC_SDS_REQUEST_T * this_request,
536   U32                  completion_code
537);
538
539#ifdef __cplusplus
540}
541#endif // __cplusplus
542
543#endif // _SCIC_SDS_IO_REQUEST_H_
544