[Zrouter-src-freebsd] ZRouter.org: push to FreeBSD HEAD tree

zrouter-src-freebsd at zrouter.org zrouter-src-freebsd at zrouter.org
Wed Feb 1 10:56:08 UTC 2012


details:   http://zrouter.org/hg/FreeBSD/head//rev/f370dd4be562
changeset: 297:f370dd4be562
user:      ray at terran.dlink.ua
date:      Wed Feb 01 11:27:03 2012 +0200
description:
Add isci driver

diffstat:

 head/sys/dev/isci/README                                                   |    14 +
 head/sys/dev/isci/environment.h                                            |   100 +
 head/sys/dev/isci/isci.c                                                   |   650 +
 head/sys/dev/isci/isci.h                                                   |   302 +
 head/sys/dev/isci/isci_controller.c                                        |   653 +
 head/sys/dev/isci/isci_domain.c                                            |   318 +
 head/sys/dev/isci/isci_interrupt.c                                         |   229 +
 head/sys/dev/isci/isci_io_request.c                                        |   923 +
 head/sys/dev/isci/isci_logger.c                                            |   351 +
 head/sys/dev/isci/isci_oem_parameters.c                                    |   176 +
 head/sys/dev/isci/isci_remote_device.c                                     |   298 +
 head/sys/dev/isci/isci_sysctl.c                                            |   229 +
 head/sys/dev/isci/isci_task_request.c                                      |   258 +
 head/sys/dev/isci/isci_timer.c                                             |   166 +
 head/sys/dev/isci/sci_environment.h                                        |     1 +
 head/sys/dev/isci/scil/intel_ata.h                                         |   654 +
 head/sys/dev/isci/scil/intel_pci.h                                         |    90 +
 head/sys/dev/isci/scil/intel_sas.h                                         |   977 +
 head/sys/dev/isci/scil/intel_sat.h                                         |    94 +
 head/sys/dev/isci/scil/intel_sata.h                                        |   284 +
 head/sys/dev/isci/scil/intel_scsi.h                                        |   540 +
 head/sys/dev/isci/scil/sati.c                                              |  1250 +
 head/sys/dev/isci/scil/sati.h                                              |   271 +
 head/sys/dev/isci/scil/sati_abort_task_set.c                               |   177 +
 head/sys/dev/isci/scil/sati_abort_task_set.h                               |    83 +
 head/sys/dev/isci/scil/sati_atapi.c                                        |   257 +
 head/sys/dev/isci/scil/sati_atapi.h                                        |   177 +
 head/sys/dev/isci/scil/sati_callbacks.h                                    |   481 +
 head/sys/dev/isci/scil/sati_design.h                                       |   169 +
 head/sys/dev/isci/scil/sati_device.c                                       |   245 +
 head/sys/dev/isci/scil/sati_device.h                                       |   203 +
 head/sys/dev/isci/scil/sati_inquiry.c                                      |   799 +
 head/sys/dev/isci/scil/sati_inquiry.h                                      |   114 +
 head/sys/dev/isci/scil/sati_log_sense.c                                    |   807 +
 head/sys/dev/isci/scil/sati_log_sense.h                                    |    87 +
 head/sys/dev/isci/scil/sati_lun_reset.c                                    |   122 +
 head/sys/dev/isci/scil/sati_lun_reset.h                                    |    79 +
 head/sys/dev/isci/scil/sati_mode_pages.c                                   |   372 +
 head/sys/dev/isci/scil/sati_mode_pages.h                                   |   144 +
 head/sys/dev/isci/scil/sati_mode_select.c                                  |  1115 +
 head/sys/dev/isci/scil/sati_mode_select.h                                  |    84 +
 head/sys/dev/isci/scil/sati_mode_sense.c                                   |   837 +
 head/sys/dev/isci/scil/sati_mode_sense.h                                   |   146 +
 head/sys/dev/isci/scil/sati_mode_sense_10.c                                |   509 +
 head/sys/dev/isci/scil/sati_mode_sense_10.h                                |   114 +
 head/sys/dev/isci/scil/sati_mode_sense_6.c                                 |   429 +
 head/sys/dev/isci/scil/sati_mode_sense_6.h                                 |   114 +
 head/sys/dev/isci/scil/sati_move.c                                         |   616 +
 head/sys/dev/isci/scil/sati_move.h                                         |   121 +
 head/sys/dev/isci/scil/sati_passthrough.c                                  |   465 +
 head/sys/dev/isci/scil/sati_passthrough.h                                  |    88 +
 head/sys/dev/isci/scil/sati_read.c                                         |   323 +
 head/sys/dev/isci/scil/sati_read.h                                         |    91 +
 head/sys/dev/isci/scil/sati_read_buffer.c                                  |   235 +
 head/sys/dev/isci/scil/sati_read_buffer.h                                  |    82 +
 head/sys/dev/isci/scil/sati_read_capacity.c                                |   366 +
 head/sys/dev/isci/scil/sati_read_capacity.h                                |    91 +
 head/sys/dev/isci/scil/sati_reassign_blocks.c                              |   622 +
 head/sys/dev/isci/scil/sati_reassign_blocks.h                              |    80 +
 head/sys/dev/isci/scil/sati_report_luns.c                                  |   124 +
 head/sys/dev/isci/scil/sati_report_luns.h                                  |    75 +
 head/sys/dev/isci/scil/sati_request_sense.c                                |   353 +
 head/sys/dev/isci/scil/sati_request_sense.h                                |    86 +
 head/sys/dev/isci/scil/sati_start_stop_unit.c                              |   404 +
 head/sys/dev/isci/scil/sati_start_stop_unit.h                              |   102 +
 head/sys/dev/isci/scil/sati_synchronize_cache.c                            |   119 +
 head/sys/dev/isci/scil/sati_synchronize_cache.h                            |    71 +
 head/sys/dev/isci/scil/sati_test_unit_ready.c                              |   186 +
 head/sys/dev/isci/scil/sati_test_unit_ready.h                              |    79 +
 head/sys/dev/isci/scil/sati_translator_sequence.h                          |   361 +
 head/sys/dev/isci/scil/sati_types.h                                        |   152 +
 head/sys/dev/isci/scil/sati_unmap.c                                        |   609 +
 head/sys/dev/isci/scil/sati_unmap.h                                        |   135 +
 head/sys/dev/isci/scil/sati_util.c                                         |  2005 ++
 head/sys/dev/isci/scil/sati_util.h                                         |   393 +
 head/sys/dev/isci/scil/sati_verify.c                                       |   273 +
 head/sys/dev/isci/scil/sati_verify.h                                       |    83 +
 head/sys/dev/isci/scil/sati_write.c                                        |   321 +
 head/sys/dev/isci/scil/sati_write.h                                        |    91 +
 head/sys/dev/isci/scil/sati_write_and_verify.c                             |   243 +
 head/sys/dev/isci/scil/sati_write_and_verify.h                             |    90 +
 head/sys/dev/isci/scil/sati_write_buffer.c                                 |   254 +
 head/sys/dev/isci/scil/sati_write_buffer.h                                 |    78 +
 head/sys/dev/isci/scil/sati_write_long.c                                   |   259 +
 head/sys/dev/isci/scil/sati_write_long.h                                   |    83 +
 head/sys/dev/isci/scil/sci_abstract_list.c                                 |   599 +
 head/sys/dev/isci/scil/sci_abstract_list.h                                 |   871 +
 head/sys/dev/isci/scil/sci_base_controller.c                               |   105 +
 head/sys/dev/isci/scil/sci_base_controller.h                               |   347 +
 head/sys/dev/isci/scil/sci_base_domain.c                                   |    89 +
 head/sys/dev/isci/scil/sci_base_domain.h                                   |   309 +
 head/sys/dev/isci/scil/sci_base_iterator.c                                 |   182 +
 head/sys/dev/isci/scil/sci_base_iterator.h                                 |   134 +
 head/sys/dev/isci/scil/sci_base_library.c                                  |   103 +
 head/sys/dev/isci/scil/sci_base_library.h                                  |   197 +
 head/sys/dev/isci/scil/sci_base_logger.c                                   |   291 +
 head/sys/dev/isci/scil/sci_base_logger.h                                   |   131 +
 head/sys/dev/isci/scil/sci_base_memory_descriptor_list.c                   |   168 +
 head/sys/dev/isci/scil/sci_base_memory_descriptor_list.h                   |   168 +
 head/sys/dev/isci/scil/sci_base_memory_descriptor_list_decorator.c         |   149 +
 head/sys/dev/isci/scil/sci_base_object.c                                   |   118 +
 head/sys/dev/isci/scil/sci_base_object.h                                   |   142 +
 head/sys/dev/isci/scil/sci_base_observer.c                                 |   107 +
 head/sys/dev/isci/scil/sci_base_observer.h                                 |   167 +
 head/sys/dev/isci/scil/sci_base_phy.c                                      |    89 +
 head/sys/dev/isci/scil/sci_base_phy.h                                      |   213 +
 head/sys/dev/isci/scil/sci_base_port.c                                     |    88 +
 head/sys/dev/isci/scil/sci_base_port.h                                     |   233 +
 head/sys/dev/isci/scil/sci_base_remote_device.c                            |    80 +
 head/sys/dev/isci/scil/sci_base_remote_device.h                            |   298 +
 head/sys/dev/isci/scil/sci_base_request.c                                  |    79 +
 head/sys/dev/isci/scil/sci_base_request.h                                  |   209 +
 head/sys/dev/isci/scil/sci_base_state.h                                    |   110 +
 head/sys/dev/isci/scil/sci_base_state_machine.c                            |   212 +
 head/sys/dev/isci/scil/sci_base_state_machine.h                            |   157 +
 head/sys/dev/isci/scil/sci_base_state_machine_logger.c                     |   217 +
 head/sys/dev/isci/scil/sci_base_state_machine_logger.h                     |   137 +
 head/sys/dev/isci/scil/sci_base_state_machine_observer.c                   |    99 +
 head/sys/dev/isci/scil/sci_base_state_machine_observer.h                   |   138 +
 head/sys/dev/isci/scil/sci_base_subject.c                                  |   149 +
 head/sys/dev/isci/scil/sci_base_subject.h                                  |   157 +
 head/sys/dev/isci/scil/sci_controller.h                                    |   113 +
 head/sys/dev/isci/scil/sci_controller_constants.h                          |   217 +
 head/sys/dev/isci/scil/sci_fast_list.h                                     |   339 +
 head/sys/dev/isci/scil/sci_iterator.h                                      |   129 +
 head/sys/dev/isci/scil/sci_library.h                                       |   111 +
 head/sys/dev/isci/scil/sci_logger.h                                        |   250 +
 head/sys/dev/isci/scil/sci_memory_descriptor_list.h                        |   181 +
 head/sys/dev/isci/scil/sci_memory_descriptor_list_decorator.h              |   129 +
 head/sys/dev/isci/scil/sci_object.h                                        |   139 +
 head/sys/dev/isci/scil/sci_overview.h                                      |   251 +
 head/sys/dev/isci/scil/sci_pool.h                                          |   188 +
 head/sys/dev/isci/scil/sci_simple_list.h                                   |   350 +
 head/sys/dev/isci/scil/sci_status.h                                        |   418 +
 head/sys/dev/isci/scil/sci_types.h                                         |   280 +
 head/sys/dev/isci/scil/sci_util.c                                          |    72 +
 head/sys/dev/isci/scil/sci_util.h                                          |   164 +
 head/sys/dev/isci/scil/scic_config_parameters.h                            |   346 +
 head/sys/dev/isci/scil/scic_controller.h                                   |   856 +
 head/sys/dev/isci/scil/scic_io_request.h                                   |   761 +
 head/sys/dev/isci/scil/scic_library.h                                      |   275 +
 head/sys/dev/isci/scil/scic_logger.h                                       |   136 +
 head/sys/dev/isci/scil/scic_overview.h                                     |    88 +
 head/sys/dev/isci/scil/scic_phy.h                                          |   462 +
 head/sys/dev/isci/scil/scic_port.h                                         |   239 +
 head/sys/dev/isci/scil/scic_remote_device.h                                |   442 +
 head/sys/dev/isci/scil/scic_sds_controller.c                               |  7042 ++++++++++
 head/sys/dev/isci/scil/scic_sds_controller.h                               |   840 +
 head/sys/dev/isci/scil/scic_sds_controller_registers.h                     |   598 +
 head/sys/dev/isci/scil/scic_sds_library.c                                  |   287 +
 head/sys/dev/isci/scil/scic_sds_library.h                                  |   118 +
 head/sys/dev/isci/scil/scic_sds_logger.h                                   |    93 +
 head/sys/dev/isci/scil/scic_sds_pci.c                                      |   247 +
 head/sys/dev/isci/scil/scic_sds_pci.h                                      |   138 +
 head/sys/dev/isci/scil/scic_sds_phy.c                                      |  4036 +++++
 head/sys/dev/isci/scil/scic_sds_phy.h                                      |   531 +
 head/sys/dev/isci/scil/scic_sds_phy_registers.h                            |   270 +
 head/sys/dev/isci/scil/scic_sds_port.c                                     |  3662 +++++
 head/sys/dev/isci/scil/scic_sds_port.h                                     |   595 +
 head/sys/dev/isci/scil/scic_sds_port_configuration_agent.c                 |  1133 +
 head/sys/dev/isci/scil/scic_sds_port_configuration_agent.h                 |   128 +
 head/sys/dev/isci/scil/scic_sds_port_registers.h                           |   139 +
 head/sys/dev/isci/scil/scic_sds_remote_device.c                            |  2727 +++
 head/sys/dev/isci/scil/scic_sds_remote_device.h                            |   646 +
 head/sys/dev/isci/scil/scic_sds_remote_node_context.c                      |  1500 ++
 head/sys/dev/isci/scil/scic_sds_remote_node_context.h                      |   382 +
 head/sys/dev/isci/scil/scic_sds_remote_node_table.c                        |   660 +
 head/sys/dev/isci/scil/scic_sds_remote_node_table.h                        |   190 +
 head/sys/dev/isci/scil/scic_sds_request.c                                  |  2890 ++++
 head/sys/dev/isci/scil/scic_sds_request.h                                  |   543 +
 head/sys/dev/isci/scil/scic_sds_sgpio.c                                    |   298 +
 head/sys/dev/isci/scil/scic_sds_smp_remote_device.c                        |   371 +
 head/sys/dev/isci/scil/scic_sds_smp_request.c                              |   872 +
 head/sys/dev/isci/scil/scic_sds_smp_request.h                              |    83 +
 head/sys/dev/isci/scil/scic_sds_ssp_request.c                              |   340 +
 head/sys/dev/isci/scil/scic_sds_stp_packet_request.c                       |   978 +
 head/sys/dev/isci/scil/scic_sds_stp_packet_request.h                       |   171 +
 head/sys/dev/isci/scil/scic_sds_stp_pio_request.h                          |   131 +
 head/sys/dev/isci/scil/scic_sds_stp_remote_device.c                        |  1098 +
 head/sys/dev/isci/scil/scic_sds_stp_request.c                              |  2583 +++
 head/sys/dev/isci/scil/scic_sds_stp_request.h                              |   280 +
 head/sys/dev/isci/scil/scic_sds_unsolicited_frame_control.c                |   402 +
 head/sys/dev/isci/scil/scic_sds_unsolicited_frame_control.h                |   305 +
 head/sys/dev/isci/scil/scic_sgpio.h                                        |   299 +
 head/sys/dev/isci/scil/scic_task_request.h                                 |   181 +
 head/sys/dev/isci/scil/scic_user_callback.h                                |  1146 +
 head/sys/dev/isci/scil/scif_config_parameters.h                            |   181 +
 head/sys/dev/isci/scil/scif_controller.h                                   |   454 +
 head/sys/dev/isci/scil/scif_domain.h                                       |   185 +
 head/sys/dev/isci/scil/scif_io_request.h                                   |   243 +
 head/sys/dev/isci/scil/scif_library.h                                      |   196 +
 head/sys/dev/isci/scil/scif_logger.h                                       |   118 +
 head/sys/dev/isci/scil/scif_overview.h                                     |   116 +
 head/sys/dev/isci/scil/scif_remote_device.h                                |   295 +
 head/sys/dev/isci/scil/scif_sas_constants.h                                |    79 +
 head/sys/dev/isci/scil/scif_sas_controller.c                               |  1249 +
 head/sys/dev/isci/scil/scif_sas_controller.h                               |   308 +
 head/sys/dev/isci/scil/scif_sas_controller_state_handlers.c                |  1845 ++
 head/sys/dev/isci/scil/scif_sas_controller_states.c                        |   460 +
 head/sys/dev/isci/scil/scif_sas_design.h                                   |   348 +
 head/sys/dev/isci/scil/scif_sas_domain.c                                   |  1536 ++
 head/sys/dev/isci/scil/scif_sas_domain.h                                   |   328 +
 head/sys/dev/isci/scil/scif_sas_domain_state_handlers.c                    |  1630 ++
 head/sys/dev/isci/scil/scif_sas_domain_states.c                            |   612 +
 head/sys/dev/isci/scil/scif_sas_high_priority_request_queue.c              |   161 +
 head/sys/dev/isci/scil/scif_sas_high_priority_request_queue.h              |   123 +
 head/sys/dev/isci/scil/scif_sas_internal_io_request.c                      |   282 +
 head/sys/dev/isci/scil/scif_sas_internal_io_request.h                      |   157 +
 head/sys/dev/isci/scil/scif_sas_io_request.c                               |   820 +
 head/sys/dev/isci/scil/scif_sas_io_request.h                               |   152 +
 head/sys/dev/isci/scil/scif_sas_io_request_state_handlers.c                |   417 +
 head/sys/dev/isci/scil/scif_sas_io_request_states.c                        |   286 +
 head/sys/dev/isci/scil/scif_sas_library.c                                  |   270 +
 head/sys/dev/isci/scil/scif_sas_library.h                                  |   105 +
 head/sys/dev/isci/scil/scif_sas_logger.h                                   |    94 +
 head/sys/dev/isci/scil/scif_sas_remote_device.c                            |   794 +
 head/sys/dev/isci/scil/scif_sas_remote_device.h                            |   502 +
 head/sys/dev/isci/scil/scif_sas_remote_device_ready_substate_handlers.c    |   779 +
 head/sys/dev/isci/scil/scif_sas_remote_device_ready_substates.c            |   290 +
 head/sys/dev/isci/scil/scif_sas_remote_device_starting_substate_handlers.c |   317 +
 head/sys/dev/isci/scil/scif_sas_remote_device_starting_substates.c         |   143 +
 head/sys/dev/isci/scil/scif_sas_remote_device_state_handlers.c             |  1161 +
 head/sys/dev/isci/scil/scif_sas_remote_device_states.c                     |   549 +
 head/sys/dev/isci/scil/scif_sas_request.c                                  |   183 +
 head/sys/dev/isci/scil/scif_sas_request.h                                  |   221 +
 head/sys/dev/isci/scil/scif_sas_sati_binding.h                             |   253 +
 head/sys/dev/isci/scil/scif_sas_smp_activity_clear_affiliation.c           |   252 +
 head/sys/dev/isci/scil/scif_sas_smp_io_request.c                           |   600 +
 head/sys/dev/isci/scil/scif_sas_smp_io_request.h                           |   138 +
 head/sys/dev/isci/scil/scif_sas_smp_phy.c                                  |   335 +
 head/sys/dev/isci/scil/scif_sas_smp_phy.h                                  |   186 +
 head/sys/dev/isci/scil/scif_sas_smp_remote_device.c                        |  2632 +++
 head/sys/dev/isci/scil/scif_sas_smp_remote_device.h                        |   431 +
 head/sys/dev/isci/scil/scif_sas_stp_io_request.c                           |   623 +
 head/sys/dev/isci/scil/scif_sas_stp_io_request.h                           |   101 +
 head/sys/dev/isci/scil/scif_sas_stp_remote_device.c                        |   215 +
 head/sys/dev/isci/scil/scif_sas_stp_remote_device.h                        |   119 +
 head/sys/dev/isci/scil/scif_sas_stp_task_request.c                         |   265 +
 head/sys/dev/isci/scil/scif_sas_stp_task_request.h                         |   106 +
 head/sys/dev/isci/scil/scif_sas_task_request.c                             |   481 +
 head/sys/dev/isci/scil/scif_sas_task_request.h                             |   143 +
 head/sys/dev/isci/scil/scif_sas_task_request_state_handlers.c              |   404 +
 head/sys/dev/isci/scil/scif_sas_task_request_states.c                      |   287 +
 head/sys/dev/isci/scil/scif_sas_timer.c                                    |   123 +
 head/sys/dev/isci/scil/scif_task_request.h                                 |   129 +
 head/sys/dev/isci/scil/scif_user_callback.h                                |  1049 +
 head/sys/dev/isci/scil/scu_bios_definitions.h                              |  1002 +
 head/sys/dev/isci/scil/scu_completion_codes.h                              |   263 +
 head/sys/dev/isci/scil/scu_constants.h                                     |   154 +
 head/sys/dev/isci/scil/scu_event_codes.h                                   |   343 +
 head/sys/dev/isci/scil/scu_registers.h                                     |  2121 +++
 head/sys/dev/isci/scil/scu_remote_node_context.h                           |   242 +
 head/sys/dev/isci/scil/scu_task_context.h                                  |   965 +
 head/sys/dev/isci/scil/scu_unsolicited_frame.h                             |   122 +
 head/sys/dev/isci/scil/scu_viit_data.h                                     |   186 +
 head/sys/dev/isci/types.h                                                  |    53 +
 256 files changed, 111924 insertions(+), 0 deletions(-)

diffs (112948 lines):

diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/README
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/README	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,14 @@
+FreeBSD Driver for Intel(R) C600 SAS Controller
+===============================================
+
+This driver has been developed for use with FreeBSD, version 9.0 and later.
+
+This driver uses an OS-agnostic abstraction layer library named SCIL that is
+published by Intel specifically for the C600 SAS controller.  The SAS
+controller has no firmware, so the driver is extensive and using SCIL
+minimizes the development and maintenance cost of the driver.
+
+The FreeBSD implementation files are in the isci directory, and SCIL files
+are in the isci/scil subdirectory.  As Intel publishes new versions of SCIL
+(to add features or fix bugs), the isci/scil subdirectory will be updated
+appropriately.
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/environment.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/environment.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,100 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef ENVIRONMENT_H_
+#define ENVIRONMENT_H_
+
+/**
+ * @file
+ *
+ * @brief Types and macros specific to the FreeBSD environment.
+ */
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/libkern.h>
+#include <machine/bus.h>
+#include <opt_isci.h>
+
+typedef int8_t 		S8;
+typedef uint8_t		U8;
+
+typedef int16_t		S16;
+typedef uint16_t	U16;
+
+typedef int32_t		S32;
+typedef uint32_t	U32;
+
+typedef int64_t		S64;
+typedef uint64_t	U64;
+
+/* Technically, this should be defined as bus_addr_t, but SCIL makes some
+ *  incorrect assumptions in some of its physical address calculations which
+ *  necessitate using uint64_t here to avoid compiler warnings.  This is
+ *  easier for now than modifying SCIL, and works just as well.
+ */
+typedef uint64_t	SCI_PHYSICAL_ADDRESS;
+
+typedef U64		SATI_LBA;
+typedef void *		FUNCPTR;
+
+#define sci_cb_physical_address_upper(address) ((uint32_t)((address)>>32))
+#define sci_cb_physical_address_lower(address) ((uint32_t)((address)&0xFFFFFFFF))
+#define sci_cb_make_physical_address(physical_address, address_upper, address_lower) \
+	((physical_address) = ((U64)(address_upper))<<32 | (address_lower))
+
+#define INLINE __inline
+
+#define PLACEMENT_HINTS(...)
+
+#define SCIC_SDS_4_ENABLED 1
+#define PBG_BUILD 1
+#define PHY_MAX_LINK_SPEED_GENERATION 3
+
+/* SCIL defines logging as SCI_LOGGING, but the FreeBSD driver name is ISCI.
+	So we define ISCI_LOGGING as the option exported to the kernel, and
+	translate it here. */
+#ifdef ISCI_LOGGING
+#define SCI_LOGGING
+#endif
+
+#define __SCI_LIBRARY_MAJOR_VERSION__ 3
+#define __SCI_LIBRARY_MINOR_VERSION__ 1
+#define __SCI_LIBRARY_BUILD_VERSION__ 7142
+
+#define SATI_TRANSPORT_SUPPORTS_SATA
+#define SATI_TRANSPORT_SUPPORTS_SAS
+#define USE_ABSTRACT_LIST_FUNCTIONS
+
+#define ASSERT(cond)
+#define assert(cond)
+
+#endif /* ENVIRONMENT_H_ */
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/isci.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/isci.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,650 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <dev/isci/isci.h>
+
+#include <sys/sysctl.h>
+#include <sys/malloc.h>
+
+#include <cam/cam_periph.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+
+#include <dev/isci/scil/scic_logger.h>
+#include <dev/isci/scil/scic_library.h>
+#include <dev/isci/scil/scic_user_callback.h>
+
+#include <dev/isci/scil/scif_controller.h>
+#include <dev/isci/scil/scif_library.h>
+#include <dev/isci/scil/scif_logger.h>
+#include <dev/isci/scil/scif_user_callback.h>
+
+MALLOC_DEFINE(M_ISCI, "isci", "isci driver memory allocations");
+
+struct isci_softc *g_isci;
+uint32_t g_isci_debug_level = 0;
+
+static int isci_probe(device_t);
+static int isci_attach(device_t);
+static int isci_detach(device_t);
+
+int isci_initialize(struct isci_softc *isci);
+
+void isci_allocate_dma_buffer_callback(void *arg, bus_dma_segment_t *seg,
+    int nseg, int error);
+
+static devclass_t isci_devclass;
+
+static device_method_t isci_pci_methods[] = {
+	 /* Device interface */
+	 DEVMETHOD(device_probe,  isci_probe),
+	 DEVMETHOD(device_attach, isci_attach),
+	 DEVMETHOD(device_detach, isci_detach),
+	 { 0, 0 }
+};
+
+static driver_t isci_pci_driver = {
+	 "isci",
+	 isci_pci_methods,
+	 sizeof(struct isci_softc),
+};
+
+DRIVER_MODULE(isci, pci, isci_pci_driver, isci_devclass, 0, 0);
+
+static struct _pcsid
+{
+	 u_int32_t	type;
+	 const char	*desc;
+} pci_ids[] = {
+	 { 0x1d608086,	"Intel(R) C600 Series Chipset SAS Controller"  },
+	 { 0x1d618086,	"Intel(R) C600 Series Chipset SAS Controller (SATA mode)"  },
+	 { 0x1d628086,	"Intel(R) C600 Series Chipset SAS Controller"  },
+	 { 0x1d638086,	"Intel(R) C600 Series Chipset SAS Controller"  },
+	 { 0x1d648086,	"Intel(R) C600 Series Chipset SAS Controller"  },
+	 { 0x1d658086,	"Intel(R) C600 Series Chipset SAS Controller"  },
+	 { 0x1d668086,	"Intel(R) C600 Series Chipset SAS Controller"  },
+	 { 0x1d678086,	"Intel(R) C600 Series Chipset SAS Controller"  },
+	 { 0x1d688086,	"Intel(R) C600 Series Chipset SAS Controller"  },
+	 { 0x1d698086,	"Intel(R) C600 Series Chipset SAS Controller"  },
+	 { 0x1d6a8086,	"Intel(R) C600 Series Chipset SAS Controller (SATA mode)"  },
+	 { 0x1d6b8086,	"Intel(R) C600 Series Chipset SAS Controller (SATA mode)"  },
+	 { 0x00000000,	NULL				}
+};
+
+static int
+isci_probe (device_t device)
+{
+	u_int32_t	type = pci_get_devid(device);
+	struct _pcsid	*ep = pci_ids;
+
+	while (ep->type && ep->type != type)
+		++ep;
+
+	if (ep->desc)
+	{
+		device_set_desc(device, ep->desc);
+		return (0);
+	}
+	else
+		return (ENXIO);
+}
+
+static int
+isci_allocate_pci_memory(struct isci_softc *isci)
+{
+	int i;
+
+	for (i = 0; i < ISCI_NUM_PCI_BARS; i++)
+	{
+		struct ISCI_PCI_BAR *pci_bar = &isci->pci_bar[i];
+
+		pci_bar->resource_id = PCIR_BAR(i*2);
+		pci_bar->resource = bus_alloc_resource(isci->device,
+		    SYS_RES_MEMORY, &pci_bar->resource_id, 0, ~0, 1,
+		    RF_ACTIVE);
+
+		if(pci_bar->resource == NULL)
+			isci_log_message(0, "ISCI",
+			    "unable to allocate pci resource\n");
+		else {
+			pci_bar->bus_tag = rman_get_bustag(pci_bar->resource);
+			pci_bar->bus_handle =
+			    rman_get_bushandle(pci_bar->resource);
+		}
+	}
+
+	return (0);
+}
+
+static int
+isci_attach(device_t device)
+{
+	int error;
+	struct isci_softc *isci = DEVICE2SOFTC(device);
+
+	g_isci = isci;
+	isci->device = device;
+
+	isci_allocate_pci_memory(isci);
+
+	error = isci_initialize(isci);
+
+	if (error)
+	{
+		isci_detach(device);
+		return (error);
+	}
+
+	isci_interrupt_setup(isci);
+	isci_sysctl_initialize(isci);
+
+	return (0);
+}
+
+static int
+isci_detach(device_t device)
+{
+	struct isci_softc *isci = DEVICE2SOFTC(device);
+	int i;
+
+	for (i = 0; i < isci->controller_count; i++) {
+		struct ISCI_CONTROLLER *controller = &isci->controllers[i];
+		SCI_STATUS status;
+
+		if (controller->scif_controller_handle != NULL) {
+			scic_controller_disable_interrupts(
+			    scif_controller_get_scic_handle(controller->scif_controller_handle));
+
+			mtx_lock(&controller->lock);
+			status = scif_controller_stop(controller->scif_controller_handle, 0);
+			mtx_unlock(&controller->lock);
+
+			while (controller->is_started == TRUE) {
+				/* Now poll for interrupts until the controller stop complete
+				 *  callback is received.
+				 */
+				mtx_lock(&controller->lock);
+				isci_interrupt_poll_handler(controller);
+				mtx_unlock(&controller->lock);
+				pause("isci", 1);
+			}
+
+			if(controller->sim != NULL) {
+				mtx_lock(&controller->lock);
+				xpt_free_path(controller->path);
+				xpt_bus_deregister(cam_sim_path(controller->sim));
+				cam_sim_free(controller->sim, TRUE);
+				mtx_unlock(&controller->lock);
+			}
+		}
+
+		if (controller->timer_memory != NULL)
+			free(controller->timer_memory, M_ISCI);
+
+		if (controller->remote_device_memory != NULL)
+			free(controller->remote_device_memory, M_ISCI);
+	}
+
+	/* The SCIF controllers have been stopped, so we can now
+	 *  free the SCI library memory.
+	 */
+	if (isci->sci_library_memory != NULL)
+		free(isci->sci_library_memory, M_ISCI);
+
+	for (i = 0; i < ISCI_NUM_PCI_BARS; i++)
+	{
+		struct ISCI_PCI_BAR *pci_bar = &isci->pci_bar[i];
+
+		if (pci_bar->resource != NULL)
+			bus_release_resource(device, SYS_RES_MEMORY,
+			    pci_bar->resource_id, pci_bar->resource);
+	}
+
+	for (i = 0; i < isci->num_interrupts; i++)
+	{
+		struct ISCI_INTERRUPT_INFO *interrupt_info;
+
+		interrupt_info = &isci->interrupt_info[i];
+
+		if(interrupt_info->tag != NULL)
+			bus_teardown_intr(device, interrupt_info->res,
+			    interrupt_info->tag);
+
+		if(interrupt_info->res != NULL)
+			bus_release_resource(device, SYS_RES_IRQ,
+			    rman_get_rid(interrupt_info->res),
+			    interrupt_info->res);
+
+		pci_release_msi(device);
+	}
+
+	return (0);
+}
+
+int
+isci_initialize(struct isci_softc *isci)
+{
+	int error;
+	uint32_t status = 0;
+	uint32_t library_object_size;
+	uint32_t verbosity_mask;
+	uint32_t scic_log_object_mask;
+	uint32_t scif_log_object_mask;
+	uint8_t *header_buffer;
+
+	library_object_size = scif_library_get_object_size(SCI_MAX_CONTROLLERS);
+
+	isci->sci_library_memory =
+	    malloc(library_object_size, M_ISCI, M_NOWAIT | M_ZERO );
+
+	isci->sci_library_handle = scif_library_construct(
+	    isci->sci_library_memory, SCI_MAX_CONTROLLERS);
+
+	sci_object_set_association( isci->sci_library_handle, (void *)isci);
+
+	verbosity_mask = (1<<SCI_LOG_VERBOSITY_ERROR) |
+	    (1<<SCI_LOG_VERBOSITY_WARNING) | (1<<SCI_LOG_VERBOSITY_INFO) |
+	    (1<<SCI_LOG_VERBOSITY_TRACE);
+
+	scic_log_object_mask = 0xFFFFFFFF;
+	scic_log_object_mask &= ~SCIC_LOG_OBJECT_COMPLETION_QUEUE;
+	scic_log_object_mask &= ~SCIC_LOG_OBJECT_SSP_IO_REQUEST;
+	scic_log_object_mask &= ~SCIC_LOG_OBJECT_STP_IO_REQUEST;
+	scic_log_object_mask &= ~SCIC_LOG_OBJECT_SMP_IO_REQUEST;
+	scic_log_object_mask &= ~SCIC_LOG_OBJECT_CONTROLLER;
+
+	scif_log_object_mask = 0xFFFFFFFF;
+	scif_log_object_mask &= ~SCIF_LOG_OBJECT_CONTROLLER;
+	scif_log_object_mask &= ~SCIF_LOG_OBJECT_IO_REQUEST;
+
+	TUNABLE_INT_FETCH("hw.isci.debug_level", &g_isci_debug_level);
+
+	sci_logger_enable(sci_object_get_logger(isci->sci_library_handle),
+	    scif_log_object_mask, verbosity_mask);
+
+	sci_logger_enable(sci_object_get_logger(
+	    scif_library_get_scic_handle(isci->sci_library_handle)),
+	    scic_log_object_mask, verbosity_mask);
+
+	header_buffer = (uint8_t *)&isci->pci_common_header;
+	for (uint8_t i = 0; i < sizeof(isci->pci_common_header); i++)
+		header_buffer[i] = pci_read_config(isci->device, i, 1);
+
+	scic_library_set_pci_info(
+	    scif_library_get_scic_handle(isci->sci_library_handle),
+	    &isci->pci_common_header);
+
+	isci->oem_parameters_found = FALSE;
+
+	isci_get_oem_parameters(isci);
+
+	/* trigger interrupt if 32 completions occur before timeout expires */
+	isci->coalesce_number = 32;
+
+	/* trigger interrupt if 2 microseconds elapse after a completion occurs,
+	 *  regardless if "coalesce_number" completions have occurred
+	 */
+	isci->coalesce_timeout = 2;
+
+	isci->controller_count = scic_library_get_pci_device_controller_count(
+	    scif_library_get_scic_handle(isci->sci_library_handle));
+
+	for (int index = 0; index < isci->controller_count; index++) {
+		struct ISCI_CONTROLLER *controller = &isci->controllers[index];
+		SCI_CONTROLLER_HANDLE_T scif_controller_handle;
+
+		controller->index = index;
+		isci_controller_construct(controller, isci);
+
+		scif_controller_handle = controller->scif_controller_handle;
+
+		status = isci_controller_initialize(controller);
+
+		if(status != SCI_SUCCESS) {
+			isci_log_message(0, "ISCI",
+			    "isci_controller_initialize FAILED: %x\n",
+			    status);
+			return (status);
+		}
+
+		error = isci_controller_allocate_memory(controller);
+
+		if (error != 0)
+			return (error);
+
+		scif_controller_set_interrupt_coalescence(
+		    scif_controller_handle, isci->coalesce_number,
+		    isci->coalesce_timeout);
+	}
+
+	/* FreeBSD provides us a hook to ensure we get a chance to start
+	 *  our controllers and complete initial domain discovery before
+	 *  it searches for the boot device.  Once we're done, we'll
+	 *  disestablish the hook, signaling the kernel that is can proceed
+	 *  with the boot process.
+	 */
+	isci->config_hook.ich_func = &isci_controller_start;
+	isci->config_hook.ich_arg = &isci->controllers[0];
+
+	if (config_intrhook_establish(&isci->config_hook) != 0)
+		isci_log_message(0, "ISCI",
+		    "config_intrhook_establish failed!\n");
+
+	return (status);
+}
+
+void
+isci_allocate_dma_buffer_callback(void *arg, bus_dma_segment_t *seg,
+    int nseg, int error)
+{
+	struct ISCI_MEMORY *memory = (struct ISCI_MEMORY *)arg;
+
+	memory->error = error;
+
+	if (nseg != 1 || error != 0)
+		isci_log_message(0, "ISCI",
+		    "Failed to allocate physically contiguous memory!\n");
+	else
+		memory->physical_address = seg->ds_addr;
+}
+
+int
+isci_allocate_dma_buffer(device_t device, struct ISCI_MEMORY *memory)
+{
+	uint32_t status;
+
+	status = bus_dma_tag_create(bus_get_dma_tag(device),
+	    0x40 /* cacheline alignment */, 0x0, BUS_SPACE_MAXADDR,
+	    BUS_SPACE_MAXADDR, NULL, NULL, memory->size,
+	    0x1 /* we want physically contiguous */,
+	    memory->size, 0, NULL, NULL, &memory->dma_tag);
+
+	if(status == ENOMEM) {
+		isci_log_message(0, "ISCI", "bus_dma_tag_create failed\n");
+		return (status);
+	}
+
+	status = bus_dmamem_alloc(memory->dma_tag,
+	    (void **)&memory->virtual_address, BUS_DMA_ZERO, &memory->dma_map);
+
+	if(status == ENOMEM)
+	{
+		isci_log_message(0, "ISCI", "bus_dmamem_alloc failed\n");
+		return (status);
+	}
+
+	status = bus_dmamap_load(memory->dma_tag, memory->dma_map,
+	    (void *)memory->virtual_address, memory->size,
+	    isci_allocate_dma_buffer_callback, memory, 0);
+
+	if(status == EINVAL)
+	{
+		isci_log_message(0, "ISCI", "bus_dmamap_load failed\n");
+		return (status);
+	}
+
+	return (0);
+}
+
+/**
+ * @brief This callback method asks the user to associate the supplied
+ *        lock with an operating environment specific locking construct.
+ *
+ * @param[in]  controller This parameter specifies the controller with
+ *             which this lock is to be associated.
+ * @param[in]  lock This parameter specifies the lock for which the
+ *             user should associate an operating environment specific
+ *             locking object.
+ *
+ * @see The SCI_LOCK_LEVEL enumeration for more information.
+ *
+ * @return none.
+ */
+void
+scif_cb_lock_associate(SCI_CONTROLLER_HANDLE_T controller,
+    SCI_LOCK_HANDLE_T lock)
+{
+
+}
+
+/**
+ * @brief This callback method asks the user to de-associate the supplied
+ *        lock with an operating environment specific locking construct.
+ *
+ * @param[in]  controller This parameter specifies the controller with
+ *             which this lock is to be de-associated.
+ * @param[in]  lock This parameter specifies the lock for which the
+ *             user should de-associate an operating environment specific
+ *             locking object.
+ *
+ * @see The SCI_LOCK_LEVEL enumeration for more information.
+ *
+ * @return none.
+ */
+void
+scif_cb_lock_disassociate(SCI_CONTROLLER_HANDLE_T controller,
+    SCI_LOCK_HANDLE_T lock)
+{
+
+}
+
+
+/**
+ * @brief This callback method asks the user to acquire/get the lock.
+ *        This method should pend until the lock has been acquired.
+ *
+ * @param[in]  controller This parameter specifies the controller with
+ *             which this lock is associated.
+ * @param[in]  lock This parameter specifies the lock to be acquired.
+ *
+ * @return none
+ */
+void
+scif_cb_lock_acquire(SCI_CONTROLLER_HANDLE_T controller,
+    SCI_LOCK_HANDLE_T lock)
+{
+
+}
+
+/**
+ * @brief This callback method asks the user to release a lock.
+ *
+ * @param[in]  controller This parameter specifies the controller with
+ *             which this lock is associated.
+ * @param[in]  lock This parameter specifies the lock to be released.
+ *
+ * @return none
+ */
+void
+scif_cb_lock_release(SCI_CONTROLLER_HANDLE_T controller,
+    SCI_LOCK_HANDLE_T lock)
+{
+}
+
+/**
+ * @brief This callback method creates an OS specific deferred task
+ *        for internal usage. The handler to deferred task is stored by OS
+ *        driver.
+ *
+ * @param[in] controller This parameter specifies the controller object
+ *            with which this callback is associated.
+ *
+ * @return none
+ */
+void
+scif_cb_start_internal_io_task_create(SCI_CONTROLLER_HANDLE_T controller)
+{
+
+}
+
+/**
+ * @brief This callback method schedules a OS specific deferred task.
+ *
+ * @param[in] controller This parameter specifies the controller
+ *            object with which this callback is associated.
+ * @param[in] start_internal_io_task_routine This parameter specifies the
+ *            sci start_internal_io routine.
+ * @param[in] context This parameter specifies a handle to a parameter
+ *            that will be passed into the "start_internal_io_task_routine"
+ *            when it is invoked.
+ *
+ * @return none
+ */
+void
+scif_cb_start_internal_io_task_schedule(SCI_CONTROLLER_HANDLE_T scif_controller,
+    FUNCPTR start_internal_io_task_routine, void *context)
+{
+	/** @todo Use FreeBSD tasklet to defer this routine to a later time,
+	 *  rather than calling the routine inline.
+	 */
+	SCI_START_INTERNAL_IO_ROUTINE sci_start_internal_io_routine =
+	    (SCI_START_INTERNAL_IO_ROUTINE)start_internal_io_task_routine;
+
+	sci_start_internal_io_routine(context);
+}
+
+/**
+ * @brief In this method the user must write to PCI memory via access.
+ *        This method is used for access to memory space and IO space.
+ *
+ * @param[in]  controller The controller for which to read a DWORD.
+ * @param[in]  address This parameter depicts the address into
+ *             which to write.
+ * @param[out] write_value This parameter depicts the value being written
+ *             into the PCI memory location.
+ *
+ * @todo These PCI memory access calls likely needs to be optimized into macros?
+ */
+void
+scic_cb_pci_write_dword(SCI_CONTROLLER_HANDLE_T scic_controller,
+    void *address, uint32_t write_value)
+{
+	SCI_CONTROLLER_HANDLE_T scif_controller =
+	    (SCI_CONTROLLER_HANDLE_T) sci_object_get_association(scic_controller);
+	struct ISCI_CONTROLLER *isci_controller =
+	    (struct ISCI_CONTROLLER *) sci_object_get_association(scif_controller);
+	struct isci_softc *isci = isci_controller->isci;
+	uint32_t bar = (uint32_t)(((POINTER_UINT)address & 0xF0000000) >> 28);
+	bus_size_t offset = (bus_size_t)((POINTER_UINT)address & 0x0FFFFFFF);
+
+	bus_space_write_4(isci->pci_bar[bar].bus_tag,
+	    isci->pci_bar[bar].bus_handle, offset, write_value);
+}
+
+/**
+ * @brief In this method the user must read from PCI memory via access.
+ *        This method is used for access to memory space and IO space.
+ *
+ * @param[in]  controller The controller for which to read a DWORD.
+ * @param[in]  address This parameter depicts the address from
+ *             which to read.
+ *
+ * @return The value being returned from the PCI memory location.
+ *
+ * @todo This PCI memory access calls likely need to be optimized into macro?
+ */
+uint32_t
+scic_cb_pci_read_dword(SCI_CONTROLLER_HANDLE_T scic_controller, void *address)
+{
+	SCI_CONTROLLER_HANDLE_T scif_controller =
+		(SCI_CONTROLLER_HANDLE_T)sci_object_get_association(scic_controller);
+	struct ISCI_CONTROLLER *isci_controller =
+		(struct ISCI_CONTROLLER *)sci_object_get_association(scif_controller);
+	struct isci_softc *isci = isci_controller->isci;
+	uint32_t bar = (uint32_t)(((POINTER_UINT)address & 0xF0000000) >> 28);
+	bus_size_t offset = (bus_size_t)((POINTER_UINT)address & 0x0FFFFFFF);
+
+	return (bus_space_read_4(isci->pci_bar[bar].bus_tag,
+	    isci->pci_bar[bar].bus_handle, offset));
+}
+
+/**
+ * @brief This method is called when the core requires the OS driver
+ *        to stall execution.  This method is utilized during initialization
+ *        or non-performance paths only.
+ *
+ * @param[in]  microseconds This parameter specifies the number of
+ *             microseconds for which to stall.  The operating system driver
+ *             is allowed to round this value up where necessary.
+ *
+ * @return none.
+ */
+void
+scic_cb_stall_execution(uint32_t microseconds)
+{
+
+	DELAY(microseconds);
+}
+
+/**
+ * @brief In this method the user must return the base address register (BAR)
+ *        value for the supplied base address register number.
+ *
+ * @param[in] controller The controller for which to retrieve the bar number.
+ * @param[in] bar_number This parameter depicts the BAR index/number to be read.
+ *
+ * @return Return a pointer value indicating the contents of the BAR.
+ * @retval NULL indicates an invalid BAR index/number was specified.
+ * @retval All other values indicate a valid VIRTUAL address from the BAR.
+ */
+void *
+scic_cb_pci_get_bar(SCI_CONTROLLER_HANDLE_T controller,
+    uint16_t bar_number)
+{
+
+	return ((void *)(POINTER_UINT)((uint32_t)bar_number << 28));
+}
+
+/**
+ * @brief This method informs the SCI Core user that a phy/link became
+ *        ready, but the phy is not allowed in the port.  In some
+ *        situations the underlying hardware only allows for certain phy
+ *        to port mappings.  If these mappings are violated, then this
+ *        API is invoked.
+ *
+ * @param[in] controller This parameter represents the controller which
+ *            contains the port.
+ * @param[in] port This parameter specifies the SCI port object for which
+ *            the callback is being invoked.
+ * @param[in] phy This parameter specifies the phy that came ready, but the
+ *            phy can't be a valid member of the port.
+ *
+ * @return none
+ */
+void
+scic_cb_port_invalid_link_up(SCI_CONTROLLER_HANDLE_T controller,
+    SCI_PORT_HANDLE_T port, SCI_PHY_HANDLE_T phy)
+{
+
+}
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/isci.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/isci.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,302 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/types.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <cam/cam.h>
+#include <cam/cam_ccb.h>
+#include <cam/cam_sim.h>
+#include <cam/cam_xpt_sim.h>
+
+#include <dev/isci/environment.h>
+#include <dev/isci/scil/intel_pci.h>
+
+#include <dev/isci/scil/sci_types.h>
+#include <dev/isci/scil/sci_object.h>
+#include <dev/isci/scil/sci_status.h>
+#include <dev/isci/scil/sci_pool.h>
+#include <dev/isci/scil/sci_fast_list.h>
+
+#include <dev/isci/scil/sci_controller_constants.h>
+
+#include <dev/isci/scil/scic_controller.h>
+#include <dev/isci/scil/scic_config_parameters.h>
+
+#define DEVICE2SOFTC(dev) ((struct isci_softc *) device_get_softc(dev))
+
+#define DEVICE_TIMEOUT 1000
+#define SCI_MAX_TIMERS  32
+
+#define ISCI_NUM_PCI_BARS  2
+#define ISCI_MAX_LUN		 8
+
+MALLOC_DECLARE(M_ISCI);
+
+struct ISCI_TIMER {
+	struct callout		callout;
+	SCI_TIMER_CALLBACK_T	callback;
+	void			*cookie;
+	BOOL			is_started;
+};
+
+struct ISCI_REMOTE_DEVICE {
+	uint32_t			index;
+	struct ISCI_DOMAIN 		*domain;
+	SCI_REMOTE_DEVICE_HANDLE_T	sci_object;
+	BOOL				is_resetting;
+	uint32_t			frozen_lun_mask;
+	SCI_FAST_LIST_ELEMENT_T		pending_device_reset_element;
+};
+
+struct ISCI_DOMAIN {
+	struct ISCI_CONTROLLER	*controller;
+	SCI_DOMAIN_HANDLE_T	sci_object;
+	uint8_t			index;
+
+};
+
+struct ISCI_MEMORY
+{
+	bus_addr_t	physical_address;
+	bus_dma_tag_t	dma_tag;
+	bus_dmamap_t	dma_map;
+	POINTER_UINT	virtual_address;
+	uint32_t	size;
+	int		error;
+};
+
+struct ISCI_INTERRUPT_INFO
+{
+	SCIC_CONTROLLER_HANDLER_METHODS_T 	*handlers;
+	void					*interrupt_target_handle;
+	struct resource				*res;
+	int					rid;
+	void					*tag;
+
+};
+
+struct ISCI_CONTROLLER
+{
+	struct isci_softc 	*isci;
+	uint8_t			index;
+	SCI_CONTROLLER_HANDLE_T	scif_controller_handle;
+	struct ISCI_DOMAIN	domain[SCI_MAX_DOMAINS];
+	BOOL			is_started;
+	uint32_t		initial_discovery_mask;
+	BOOL			is_frozen;
+	uint8_t			*remote_device_memory;
+	struct ISCI_MEMORY	cached_controller_memory;
+	struct ISCI_MEMORY	uncached_controller_memory;
+	struct ISCI_MEMORY	request_memory;
+	bus_dma_tag_t		buffer_dma_tag;
+	struct mtx		lock;
+	struct cam_sim		*sim;
+	struct cam_path		*path;
+	struct ISCI_REMOTE_DEVICE *remote_device[SCI_MAX_REMOTE_DEVICES];
+	void 			*timer_memory;
+	SCIC_OEM_PARAMETERS_T	oem_parameters;
+	uint32_t		oem_parameters_version;
+	uint32_t		queue_depth;
+	uint32_t		sim_queue_depth;
+	SCI_FAST_LIST_T		pending_device_reset_list;
+
+	SCI_MEMORY_DESCRIPTOR_LIST_HANDLE_T mdl;
+
+	SCI_POOL_CREATE(remote_device_pool, struct ISCI_REMOTE_DEVICE *, SCI_MAX_REMOTE_DEVICES);
+	SCI_POOL_CREATE(request_pool, struct ISCI_REQUEST *, SCI_MAX_IO_REQUESTS);
+	SCI_POOL_CREATE(timer_pool, struct ISCI_TIMER *, SCI_MAX_TIMERS);
+};
+
+struct ISCI_REQUEST
+{
+	SCI_CONTROLLER_HANDLE_T		controller_handle;
+	SCI_REMOTE_DEVICE_HANDLE_T	remote_device_handle;
+	bus_dma_tag_t			dma_tag;
+	bus_dmamap_t			dma_map;
+	SCI_PHYSICAL_ADDRESS		physical_address;
+	struct callout			timer;
+};
+
+struct ISCI_IO_REQUEST
+{
+	struct ISCI_REQUEST	parent;
+	SCI_STATUS		status;
+	SCI_IO_REQUEST_HANDLE_T	sci_object;
+	union ccb		*ccb;
+	uint32_t		num_segments;
+	uint32_t		current_sge_index;
+	bus_dma_segment_t	*sge;
+};
+
+struct ISCI_TASK_REQUEST
+{
+	struct ISCI_REQUEST		parent;
+	struct scsi_sense_data		sense_data;
+	SCI_TASK_REQUEST_HANDLE_T	sci_object;
+	union ccb			*ccb;
+
+};
+
+struct ISCI_PCI_BAR {
+
+	bus_space_tag_t		bus_tag;
+	bus_space_handle_t	bus_handle;
+	int			resource_id;
+	struct resource		*resource;
+
+};
+
+/*
+ * One of these per allocated PCI device.
+ */
+struct isci_softc {
+
+	struct ISCI_PCI_BAR			pci_bar[ISCI_NUM_PCI_BARS];
+	struct ISCI_CONTROLLER			controllers[SCI_MAX_CONTROLLERS];
+	SCI_LIBRARY_HANDLE_T			sci_library_handle;
+	void *					sci_library_memory;
+	SCIC_CONTROLLER_HANDLER_METHODS_T	handlers[4];
+	struct ISCI_INTERRUPT_INFO		interrupt_info[4];
+	uint32_t				controller_count;
+	uint32_t				num_interrupts;
+	uint32_t				coalesce_number;
+	uint32_t				coalesce_timeout;
+	device_t				device;
+	SCI_PCI_COMMON_HEADER_T			pci_common_header;
+	BOOL					oem_parameters_found;
+	struct intr_config_hook			config_hook;
+};
+
+int isci_allocate_resources(device_t device);
+
+int isci_allocate_dma_buffer(device_t device, struct ISCI_MEMORY *memory);
+
+void isci_remote_device_reset(struct ISCI_REMOTE_DEVICE *remote_device,
+    union ccb *ccb);
+
+/**
+ *  Returns the negotiated link rate (in KB/s) for the associated
+ *	remote device.  Used to fill out bitrate field for GET_TRANS_SETTINGS.
+ *	Will match the negotiated link rate for the lowest numbered local phy
+ *	in the port/domain containing this remote device.
+ */
+uint32_t isci_remote_device_get_bitrate(
+    struct ISCI_REMOTE_DEVICE *remote_device);
+
+void isci_remote_device_freeze_lun_queue(
+    struct ISCI_REMOTE_DEVICE *remote_device, lun_id_t lun);
+
+void isci_remote_device_release_lun_queue(
+    struct ISCI_REMOTE_DEVICE *remote_device, lun_id_t lun);
+
+void isci_remote_device_release_device_queue(
+    struct ISCI_REMOTE_DEVICE * remote_device);
+
+void isci_request_construct(struct ISCI_REQUEST *request,
+    SCI_CONTROLLER_HANDLE_T scif_controller_handle,
+    bus_dma_tag_t io_buffer_dma_tag, bus_addr_t physical_address);
+
+#define isci_io_request_get_max_io_size() \
+	((SCI_MAX_SCATTER_GATHER_ELEMENTS - 1) * PAGE_SIZE)
+
+#define isci_task_request_get_object_size() \
+	(sizeof(struct ISCI_TASK_REQUEST) + scif_task_request_get_object_size())
+
+#define isci_io_request_get_object_size() \
+	(sizeof(struct ISCI_IO_REQUEST) + scif_io_request_get_object_size())
+
+#define isci_request_get_object_size() \
+	max( \
+	    isci_task_request_get_object_size(), \
+	    isci_io_request_get_object_size() \
+	)
+
+
+void isci_io_request_execute_scsi_io(union ccb *ccb,
+    struct ISCI_CONTROLLER *controller);
+
+#if __FreeBSD_version >= 900026
+void isci_io_request_execute_smp_io(
+    union ccb *ccb, struct ISCI_CONTROLLER *controller);
+#endif
+
+void isci_io_request_timeout(void *);
+
+void isci_get_oem_parameters(struct isci_softc *isci);
+
+void isci_io_request_complete(
+    SCI_CONTROLLER_HANDLE_T scif_controller,
+    SCI_REMOTE_DEVICE_HANDLE_T remote_device,
+    struct ISCI_IO_REQUEST * isci_request, SCI_IO_STATUS completion_status);
+
+void isci_task_request_complete(
+    SCI_CONTROLLER_HANDLE_T scif_controller,
+    SCI_REMOTE_DEVICE_HANDLE_T remote_device,
+    SCI_TASK_REQUEST_HANDLE_T io_request, SCI_TASK_STATUS completion_status);
+
+void isci_sysctl_initialize(struct isci_softc *isci);
+
+void isci_controller_construct(struct ISCI_CONTROLLER *controller,
+    struct isci_softc *isci);
+
+SCI_STATUS isci_controller_initialize(struct ISCI_CONTROLLER *controller);
+
+int isci_controller_allocate_memory(struct ISCI_CONTROLLER *controller);
+
+void isci_controller_domain_discovery_complete(
+    struct ISCI_CONTROLLER *isci_controller, struct ISCI_DOMAIN *isci_domain);
+
+int isci_controller_attach_to_cam(struct ISCI_CONTROLLER *controller);
+
+void isci_controller_start(void *controller);
+
+void isci_domain_construct(struct ISCI_DOMAIN *domain, uint32_t domain_index,
+    struct ISCI_CONTROLLER *controller);
+
+void isci_interrupt_setup(struct isci_softc *isci);
+void isci_interrupt_poll_handler(struct ISCI_CONTROLLER *controller);
+
+void isci_log_message(uint32_t	verbosity, char *log_message_prefix,
+    char *log_message, ...);
+
+extern uint32_t g_isci_debug_level;
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/isci_controller.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/isci_controller.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,653 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <dev/isci/isci.h>
+
+#include <sys/conf.h>
+#include <sys/malloc.h>
+
+#include <dev/isci/scil/sci_memory_descriptor_list.h>
+#include <dev/isci/scil/sci_memory_descriptor_list_decorator.h>
+
+#include <dev/isci/scil/scif_controller.h>
+#include <dev/isci/scil/scif_library.h>
+#include <dev/isci/scil/scif_io_request.h>
+#include <dev/isci/scil/scif_task_request.h>
+#include <dev/isci/scil/scif_remote_device.h>
+#include <dev/isci/scil/scif_domain.h>
+#include <dev/isci/scil/scif_user_callback.h>
+
+void isci_action(struct cam_sim *sim, union ccb *ccb);
+void isci_poll(struct cam_sim *sim);
+
+#define ccb_sim_ptr sim_priv.entries[0].ptr
+
+/**
+ * @brief This user callback will inform the user that the controller has
+ *        had a serious unexpected error.  The user should not the error,
+ *        disable interrupts, and wait for current ongoing processing to
+ *        complete.  Subsequently, the user should reset the controller.
+ *
+ * @param[in]  controller This parameter specifies the controller that had
+ *                        an error.
+ *
+ * @return none
+ */
+void scif_cb_controller_error(SCI_CONTROLLER_HANDLE_T controller,
+    SCI_CONTROLLER_ERROR error)
+{
+
+	isci_log_message(0, "ISCI", "scif_cb_controller_error: 0x%x\n",
+	    error);
+}
+
+/**
+ * @brief This user callback will inform the user that the controller has
+ *        finished the start process.
+ *
+ * @param[in]  controller This parameter specifies the controller that was
+ *             started.
+ * @param[in]  completion_status This parameter specifies the results of
+ *             the start operation.  SCI_SUCCESS indicates successful
+ *             completion.
+ *
+ * @return none
+ */
+void scif_cb_controller_start_complete(SCI_CONTROLLER_HANDLE_T controller,
+    SCI_STATUS completion_status)
+{
+	uint32_t index;
+	struct ISCI_CONTROLLER *isci_controller = (struct ISCI_CONTROLLER *)
+	    sci_object_get_association(controller);
+
+	isci_controller->is_started = TRUE;
+
+	/* Set bits for all domains.  We will clear them one-by-one once
+	 *  the domains complete discovery, or return error when calling
+	 *  scif_domain_discover.  Once all bits are clear, we will register
+	 *  the controller with CAM.
+	 */
+	isci_controller->initial_discovery_mask = (1 << SCI_MAX_DOMAINS) - 1;
+
+	for(index = 0; index < SCI_MAX_DOMAINS; index++) {
+		SCI_STATUS status;
+		SCI_DOMAIN_HANDLE_T domain =
+		    isci_controller->domain[index].sci_object;
+
+		status = scif_domain_discover(
+			domain,
+			scif_domain_get_suggested_discover_timeout(domain),
+			DEVICE_TIMEOUT
+		);
+
+		if (status != SCI_SUCCESS)
+		{
+			isci_controller_domain_discovery_complete(
+			    isci_controller, &isci_controller->domain[index]);
+		}
+	}
+}
+
+/**
+ * @brief This user callback will inform the user that the controller has
+ *        finished the stop process. Note, after user calls
+ *        scif_controller_stop(), before user receives this controller stop
+ *        complete callback, user should not expect any callback from
+ *        framework, such like scif_cb_domain_change_notification().
+ *
+ * @param[in]  controller This parameter specifies the controller that was
+ *             stopped.
+ * @param[in]  completion_status This parameter specifies the results of
+ *             the stop operation.  SCI_SUCCESS indicates successful
+ *             completion.
+ *
+ * @return none
+ */
+void scif_cb_controller_stop_complete(SCI_CONTROLLER_HANDLE_T controller,
+    SCI_STATUS completion_status)
+{
+	struct ISCI_CONTROLLER *isci_controller = (struct ISCI_CONTROLLER *)
+	    sci_object_get_association(controller);
+
+	isci_controller->is_started = FALSE;
+}
+
+/**
+ * @brief This method will be invoked to allocate memory dynamically.
+ *
+ * @param[in]  controller This parameter represents the controller
+ *             object for which to allocate memory.
+ * @param[out] mde This parameter represents the memory descriptor to
+ *             be filled in by the user that will reference the newly
+ *             allocated memory.
+ *
+ * @return none
+ */
+void scif_cb_controller_allocate_memory(SCI_CONTROLLER_HANDLE_T controller,
+    SCI_PHYSICAL_MEMORY_DESCRIPTOR_T *mde)
+{
+
+}
+
+/**
+ * @brief This method will be invoked to allocate memory dynamically.
+ *
+ * @param[in]  controller This parameter represents the controller
+ *             object for which to allocate memory.
+ * @param[out] mde This parameter represents the memory descriptor to
+ *             be filled in by the user that will reference the newly
+ *             allocated memory.
+ *
+ * @return none
+ */
+void scif_cb_controller_free_memory(SCI_CONTROLLER_HANDLE_T controller,
+    SCI_PHYSICAL_MEMORY_DESCRIPTOR_T * mde)
+{
+
+}
+
+void isci_controller_construct(struct ISCI_CONTROLLER *controller,
+    struct isci_softc *isci)
+{
+	SCI_CONTROLLER_HANDLE_T scif_controller_handle;
+
+	scif_library_allocate_controller(isci->sci_library_handle,
+	    &scif_controller_handle);
+
+	scif_controller_construct(isci->sci_library_handle,
+	    scif_controller_handle, NULL);
+
+	controller->isci = isci;
+	controller->scif_controller_handle = scif_controller_handle;
+
+	/* This allows us to later use
+	 *  sci_object_get_association(scif_controller_handle)
+	 * inside of a callback routine to get our struct ISCI_CONTROLLER object
+	 */
+	sci_object_set_association(scif_controller_handle, (void *)controller);
+
+	controller->is_started = FALSE;
+	controller->is_frozen = FALSE;
+	controller->sim = NULL;
+	controller->initial_discovery_mask = 0;
+
+	sci_fast_list_init(&controller->pending_device_reset_list);
+
+	mtx_init(&controller->lock, "isci", NULL, MTX_DEF);
+
+	uint32_t domain_index;
+
+	for(domain_index = 0; domain_index < SCI_MAX_DOMAINS; domain_index++) {
+		isci_domain_construct( &controller->domain[domain_index],
+		    domain_index, controller);
+	}
+
+	controller->timer_memory = malloc(
+	    sizeof(struct ISCI_TIMER) * SCI_MAX_TIMERS, M_ISCI,
+	    M_NOWAIT | M_ZERO);
+
+	sci_pool_initialize(controller->timer_pool);
+
+	struct ISCI_TIMER *timer = (struct ISCI_TIMER *)
+	    controller->timer_memory;
+
+	for ( int i = 0; i < SCI_MAX_TIMERS; i++ ) {
+		sci_pool_put(controller->timer_pool, timer++);
+	}
+}
+
+SCI_STATUS isci_controller_initialize(struct ISCI_CONTROLLER *controller)
+{
+	SCIC_USER_PARAMETERS_T scic_user_parameters;
+	SCI_CONTROLLER_HANDLE_T scic_controller_handle;
+	unsigned long tunable;
+	int i;
+
+	scic_controller_handle =
+	    scif_controller_get_scic_handle(controller->scif_controller_handle);
+
+	if (controller->isci->oem_parameters_found == TRUE)
+	{
+		scic_oem_parameters_set(
+		    scic_controller_handle,
+		    &controller->oem_parameters,
+		    (uint8_t)(controller->oem_parameters_version));
+	}
+
+	scic_user_parameters_get(scic_controller_handle, &scic_user_parameters);
+
+	if (TUNABLE_ULONG_FETCH("hw.isci.no_outbound_task_timeout", &tunable))
+		scic_user_parameters.sds1.no_outbound_task_timeout =
+		    (uint8_t)tunable;
+
+	if (TUNABLE_ULONG_FETCH("hw.isci.ssp_max_occupancy_timeout", &tunable))
+		scic_user_parameters.sds1.ssp_max_occupancy_timeout =
+		    (uint16_t)tunable;
+
+	if (TUNABLE_ULONG_FETCH("hw.isci.stp_max_occupancy_timeout", &tunable))
+		scic_user_parameters.sds1.stp_max_occupancy_timeout =
+		    (uint16_t)tunable;
+
+	if (TUNABLE_ULONG_FETCH("hw.isci.ssp_inactivity_timeout", &tunable))
+		scic_user_parameters.sds1.ssp_inactivity_timeout =
+		    (uint16_t)tunable;
+
+	if (TUNABLE_ULONG_FETCH("hw.isci.stp_inactivity_timeout", &tunable))
+		scic_user_parameters.sds1.stp_inactivity_timeout =
+		    (uint16_t)tunable;
+
+	if (TUNABLE_ULONG_FETCH("hw.isci.max_speed_generation", &tunable))
+		for (i = 0; i < SCI_MAX_PHYS; i++)
+			scic_user_parameters.sds1.phys[i].max_speed_generation =
+			    (uint8_t)tunable;
+
+	scic_user_parameters_set(scic_controller_handle, &scic_user_parameters);
+
+	/* Scheduler bug in SCU requires SCIL to reserve some task contexts as a
+	 *  a workaround - one per domain.
+	 */
+	controller->queue_depth = SCI_MAX_IO_REQUESTS - SCI_MAX_DOMAINS;
+
+	if (TUNABLE_INT_FETCH("hw.isci.controller_queue_depth",
+	    &controller->queue_depth)) {
+		controller->queue_depth = max(1, min(controller->queue_depth,
+		    SCI_MAX_IO_REQUESTS - SCI_MAX_DOMAINS));
+	}
+
+	/* Reserve one request so that we can ensure we have one available TC
+	 *  to do internal device resets.
+	 */
+	controller->sim_queue_depth = controller->queue_depth - 1;
+
+	/* Although we save one TC to do internal device resets, it is possible
+	 *  we could end up using several TCs for simultaneous device resets
+	 *  while at the same time having CAM fill our controller queue.  To
+	 *  simulate this condition, and how our driver handles it, we can set
+	 *  this io_shortage parameter, which will tell CAM that we have a
+	 *  large queue depth than we really do.
+	 */
+	uint32_t io_shortage = 0;
+	TUNABLE_INT_FETCH("hw.isci.io_shortage", &io_shortage);
+	controller->sim_queue_depth += io_shortage;
+
+	return (scif_controller_initialize(controller->scif_controller_handle));
+}
+
+int isci_controller_allocate_memory(struct ISCI_CONTROLLER *controller)
+{
+	int error;
+	device_t device =  controller->isci->device;
+	uint32_t max_segment_size = isci_io_request_get_max_io_size();
+	uint32_t status = 0;
+	struct ISCI_MEMORY *uncached_controller_memory =
+	    &controller->uncached_controller_memory;
+	struct ISCI_MEMORY *cached_controller_memory =
+	    &controller->cached_controller_memory;
+	struct ISCI_MEMORY *request_memory =
+	    &controller->request_memory;
+	POINTER_UINT virtual_address;
+	bus_addr_t physical_address;
+
+	controller->mdl = sci_controller_get_memory_descriptor_list_handle(
+	    controller->scif_controller_handle);
+
+	uncached_controller_memory->size = sci_mdl_decorator_get_memory_size(
+	    controller->mdl, SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS);
+
+	error = isci_allocate_dma_buffer(device, uncached_controller_memory);
+
+	if (error != 0)
+	    return (error);
+
+	sci_mdl_decorator_assign_memory( controller->mdl,
+	    SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS,
+	    uncached_controller_memory->virtual_address,
+	    uncached_controller_memory->physical_address);
+
+	cached_controller_memory->size = sci_mdl_decorator_get_memory_size(
+	    controller->mdl,
+	    SCI_MDE_ATTRIBUTE_CACHEABLE | SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
+	);
+
+	error = isci_allocate_dma_buffer(device, cached_controller_memory);
+
+	if (error != 0)
+	    return (error);
+
+	sci_mdl_decorator_assign_memory(controller->mdl,
+	    SCI_MDE_ATTRIBUTE_CACHEABLE | SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS,
+	    cached_controller_memory->virtual_address,
+	    cached_controller_memory->physical_address);
+
+	request_memory->size =
+	    controller->queue_depth * isci_io_request_get_object_size();
+
+	error = isci_allocate_dma_buffer(device, request_memory);
+
+	if (error != 0)
+	    return (error);
+
+	/* For STP PIO testing, we want to ensure we can force multiple SGLs
+	 *  since this has been a problem area in SCIL.  This tunable parameter
+	 *  will allow us to force DMA segments to a smaller size, ensuring
+	 *  that even if a physically contiguous buffer is attached to this
+	 *  I/O, the DMA subsystem will pass us multiple segments in our DMA
+	 *  load callback.
+	 */
+	TUNABLE_INT_FETCH("hw.isci.max_segment_size", &max_segment_size);
+
+	/* Create DMA tag for our I/O requests.  Then we can create DMA maps based off
+	 *  of this tag and store them in each of our ISCI_IO_REQUEST objects.  This
+	 *  will enable better performance than creating the DMA maps everytime we get
+	 *  an I/O.
+	 */
+	status = bus_dma_tag_create(bus_get_dma_tag(device), 0x1, 0x0,
+	    BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
+	    isci_io_request_get_max_io_size(),
+	    SCI_MAX_SCATTER_GATHER_ELEMENTS, max_segment_size, 0, NULL, NULL,
+	    &controller->buffer_dma_tag);
+
+	sci_pool_initialize(controller->request_pool);
+
+	virtual_address = request_memory->virtual_address;
+	physical_address = request_memory->physical_address;
+
+	for (int i = 0; i < controller->queue_depth; i++) {
+		struct ISCI_REQUEST *request =
+		    (struct ISCI_REQUEST *)virtual_address;
+
+		isci_request_construct(request,
+		    controller->scif_controller_handle,
+		    controller->buffer_dma_tag, physical_address);
+
+		sci_pool_put(controller->request_pool, request);
+
+		virtual_address += isci_request_get_object_size();
+		physical_address += isci_request_get_object_size();
+	}
+
+	uint32_t remote_device_size = sizeof(struct ISCI_REMOTE_DEVICE) +
+	    scif_remote_device_get_object_size();
+
+	controller->remote_device_memory = (uint8_t *) malloc(
+	    remote_device_size * SCI_MAX_REMOTE_DEVICES, M_ISCI,
+	    M_NOWAIT | M_ZERO);
+
+	sci_pool_initialize(controller->remote_device_pool);
+
+	uint8_t *remote_device_memory_ptr = controller->remote_device_memory;
+
+	for (int i = 0; i < SCI_MAX_REMOTE_DEVICES; i++) {
+		struct ISCI_REMOTE_DEVICE *remote_device =
+		    (struct ISCI_REMOTE_DEVICE *)remote_device_memory_ptr;
+
+		controller->remote_device[i] = NULL;
+		remote_device->index = i;
+		remote_device->is_resetting = FALSE;
+		remote_device->frozen_lun_mask = 0;
+		sci_fast_list_element_init(remote_device,
+		    &remote_device->pending_device_reset_element);
+		sci_pool_put(controller->remote_device_pool, remote_device);
+		remote_device_memory_ptr += remote_device_size;
+	}
+
+	return (0);
+}
+
+void isci_controller_start(void *controller_handle)
+{
+	struct ISCI_CONTROLLER *controller =
+	    (struct ISCI_CONTROLLER *)controller_handle;
+	SCI_CONTROLLER_HANDLE_T scif_controller_handle =
+	    controller->scif_controller_handle;
+
+	scif_controller_start(scif_controller_handle,
+	    scif_controller_get_suggested_start_timeout(scif_controller_handle));
+
+	scic_controller_enable_interrupts(
+	    scif_controller_get_scic_handle(controller->scif_controller_handle));
+}
+
+void isci_controller_domain_discovery_complete(
+    struct ISCI_CONTROLLER *isci_controller, struct ISCI_DOMAIN *isci_domain)
+{
+	if (isci_controller->sim == NULL)
+	{
+		/* Controller has not been attached to CAM yet.  We'll clear
+		 *  the discovery bit for this domain, then check if all bits
+		 *  are now clear.  That would indicate that all domains are
+		 *  done with discovery and we can then attach the controller
+		 *  to CAM.
+		 */
+
+		isci_controller->initial_discovery_mask &=
+		    ~(1 << isci_domain->index);
+
+		if (isci_controller->initial_discovery_mask == 0) {
+			struct isci_softc *driver = isci_controller->isci;
+			uint8_t next_index = isci_controller->index + 1;
+
+			isci_controller_attach_to_cam(isci_controller);
+
+			if (next_index < driver->controller_count) {
+				/*  There are more controllers that need to
+				 *   start.  So start the next one.
+				 */
+				isci_controller_start(
+				    &driver->controllers[next_index]);
+			}
+			else
+			{
+				/* All controllers have been started and completed discovery.
+				 *  Disestablish the config hook while will signal to the
+				 *  kernel during boot that it is safe to try to find and
+				 *  mount the root partition.
+				 */
+				config_intrhook_disestablish(
+				    &driver->config_hook);
+			}
+		}
+	}
+}
+
+int isci_controller_attach_to_cam(struct ISCI_CONTROLLER *controller)
+{
+	struct isci_softc *isci = controller->isci;
+	device_t parent = device_get_parent(isci->device);
+	int unit = device_get_unit(isci->device);
+	struct cam_devq *isci_devq = cam_simq_alloc(controller->sim_queue_depth);
+
+	if(isci_devq == NULL) {
+		isci_log_message(0, "ISCI", "isci_devq is NULL \n");
+		return (-1);
+	}
+
+	controller->sim = cam_sim_alloc(isci_action, isci_poll, "isci",
+	    controller, unit, &controller->lock, controller->sim_queue_depth,
+	    controller->sim_queue_depth, isci_devq);
+
+	if(controller->sim == NULL) {
+		isci_log_message(0, "ISCI", "cam_sim_alloc... fails\n");
+		cam_simq_free(isci_devq);
+		return (-1);
+	}
+
+	if(xpt_bus_register(controller->sim, parent, controller->index)
+	    != CAM_SUCCESS) {
+		isci_log_message(0, "ISCI", "xpt_bus_register...fails \n");
+		cam_sim_free(controller->sim, TRUE);
+		mtx_unlock(&controller->lock);
+		return (-1);
+	}
+
+	if(xpt_create_path(&controller->path, NULL,
+	    cam_sim_path(controller->sim), CAM_TARGET_WILDCARD,
+	    CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
+		isci_log_message(0, "ISCI", "xpt_create_path....fails\n");
+		xpt_bus_deregister(cam_sim_path(controller->sim));
+		cam_sim_free(controller->sim, TRUE);
+		mtx_unlock(&controller->lock);
+		return (-1);
+	}
+
+	return (0);
+}
+
+void isci_poll(struct cam_sim *sim)
+{
+	struct ISCI_CONTROLLER *controller =
+	    (struct ISCI_CONTROLLER *)cam_sim_softc(sim);
+
+	isci_interrupt_poll_handler(controller);
+}
+
+void isci_action(struct cam_sim *sim, union ccb *ccb)
+{
+	struct ISCI_CONTROLLER *controller =
+	    (struct ISCI_CONTROLLER *)cam_sim_softc(sim);
+
+	switch ( ccb->ccb_h.func_code ) {
+	case XPT_PATH_INQ:
+		{
+			struct ccb_pathinq *cpi = &ccb->cpi;
+			int bus = cam_sim_bus(sim);
+			ccb->ccb_h.ccb_sim_ptr = sim;
+			cpi->version_num = 1;
+			cpi->hba_inquiry = PI_TAG_ABLE;
+			cpi->target_sprt = 0;
+			cpi->hba_misc = PIM_NOBUSRESET | PIM_SEQSCAN;
+			cpi->hba_eng_cnt = 0;
+			cpi->max_target = SCI_MAX_REMOTE_DEVICES - 1;
+			cpi->max_lun = ISCI_MAX_LUN;
+#if __FreeBSD_version >= 704100
+			cpi->maxio = isci_io_request_get_max_io_size();
+#endif
+			cpi->unit_number = cam_sim_unit(sim);
+			cpi->bus_id = bus;
+			cpi->initiator_id = SCI_MAX_REMOTE_DEVICES;
+			cpi->base_transfer_speed = 300000;
+			strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
+			strncpy(cpi->hba_vid, "Intel Corp.", HBA_IDLEN);
+			strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
+			cpi->transport = XPORT_SAS;
+			cpi->transport_version = 0;
+			cpi->protocol = PROTO_SCSI;
+			cpi->protocol_version = SCSI_REV_SPC2;
+			cpi->ccb_h.status = CAM_REQ_CMP;
+			xpt_done(ccb);
+		}
+		break;
+	case XPT_GET_TRAN_SETTINGS:
+		{
+			struct ccb_trans_settings *general_settings = &ccb->cts;
+			struct ccb_trans_settings_sas *sas_settings =
+			    &general_settings->xport_specific.sas;
+			struct ccb_trans_settings_scsi *scsi_settings =
+			    &general_settings->proto_specific.scsi;
+			struct ISCI_REMOTE_DEVICE *remote_device;
+
+			remote_device = controller->remote_device[ccb->ccb_h.target_id];
+
+			if (remote_device == NULL) {
+				ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
+				ccb->ccb_h.status &= ~CAM_STATUS_MASK;
+				ccb->ccb_h.status |= CAM_DEV_NOT_THERE;
+				xpt_done(ccb);
+				break;
+			}
+
+			general_settings->protocol = PROTO_SCSI;
+			general_settings->transport = XPORT_SAS;
+			general_settings->protocol_version = SCSI_REV_SPC2;
+			general_settings->transport_version = 0;
+			scsi_settings->valid = CTS_SCSI_VALID_TQ;
+			scsi_settings->flags = CTS_SCSI_FLAGS_TAG_ENB;
+			ccb->ccb_h.status &= ~CAM_STATUS_MASK;
+			ccb->ccb_h.status |= CAM_REQ_CMP;
+
+			sas_settings->bitrate =
+			    isci_remote_device_get_bitrate(remote_device);
+
+			if (sas_settings->bitrate != 0)
+				sas_settings->valid = CTS_SAS_VALID_SPEED;
+
+			xpt_done(ccb);
+		}
+		break;
+	case XPT_SCSI_IO:
+		isci_io_request_execute_scsi_io(ccb, controller);
+		break;
+#if __FreeBSD_version >= 900026
+	case XPT_SMP_IO:
+		isci_io_request_execute_smp_io(ccb, controller);
+		break;
+#endif
+	case XPT_SET_TRAN_SETTINGS:
+		ccb->ccb_h.status &= ~CAM_STATUS_MASK;
+		ccb->ccb_h.status |= CAM_REQ_CMP;
+		xpt_done(ccb);
+		break;
+	case XPT_CALC_GEOMETRY:
+		cam_calc_geometry(&ccb->ccg, /*extended*/1);
+		xpt_done(ccb);
+		break;
+	case XPT_RESET_DEV:
+		{
+			struct ISCI_REMOTE_DEVICE *remote_device =
+			    controller->remote_device[ccb->ccb_h.target_id];
+
+			if (remote_device != NULL)
+				isci_remote_device_reset(remote_device, ccb);
+			else {
+				ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
+				ccb->ccb_h.status &= ~CAM_STATUS_MASK;
+				ccb->ccb_h.status |= CAM_DEV_NOT_THERE;
+				xpt_done(ccb);
+			}
+		}
+		break;
+	case XPT_RESET_BUS:
+		ccb->ccb_h.status = CAM_REQ_CMP;
+		xpt_done(ccb);
+		break;
+	default:
+		isci_log_message(0, "ISCI", "Unhandled func_code 0x%x\n",
+		    ccb->ccb_h.func_code);
+		ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
+		ccb->ccb_h.status &= ~CAM_STATUS_MASK;
+		ccb->ccb_h.status |= CAM_REQ_INVALID;
+		xpt_done(ccb);
+		break;
+	}
+}
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/isci_domain.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/isci_domain.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,318 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <dev/isci/isci.h>
+
+#include <cam/cam_periph.h>
+#include <cam/cam_xpt_periph.h>
+
+#include <dev/isci/scil/scif_domain.h>
+#include <dev/isci/scil/scif_remote_device.h>
+#include <dev/isci/scil/scif_controller.h>
+#include <dev/isci/scil/scif_user_callback.h>
+
+/**
+ * @brief This callback method informs the framework user that something
+ *        in the supplied domain has changed (e.g. a device was added or
+ *        removed).
+ *
+ * This callback is called by the framework outside of discovery or
+ * target reset processes.  Specifically, domain changes occurring
+ * during these processes are handled by the framework.  For example,
+ * in the case of Serial Attached SCSI, reception of a BROADCAST (CHANGE)
+ * during discovery will cause discovery to restart.  Thus, discovery
+ * does not complete until all BCNs are processed. Note, during controller
+ * stopping/reset process, the framework user should not expect this call
+ * back.
+ *
+ * @param[in]  controller This parameter specifies the controller object
+ *             with which this callback is associated.
+ * @param[in]  domain This parameter specifies the domain object with
+ *             which this callback is associated.
+ *
+ * @return none
+ */
+void
+scif_cb_domain_change_notification(SCI_CONTROLLER_HANDLE_T controller,
+    SCI_DOMAIN_HANDLE_T domain)
+{
+	struct ISCI_CONTROLLER *isci_controller =
+	    (struct ISCI_CONTROLLER *)sci_object_get_association(controller);
+
+	/* When the controller start is complete, we will explicitly discover
+	 *  all of the domains then.  This is because SCIF will not allow
+	 *  any I/O to start until the controller is ready, meaning internal SMP
+	 *  requests triggered by domain discovery won't work until the controller
+	 *  is ready.
+	 */
+	if (isci_controller->is_started == TRUE)
+	    scif_domain_discover(domain,
+	        scif_domain_get_suggested_discover_timeout(domain),
+	        DEVICE_TIMEOUT);
+}
+
+/**
+ * @brief This callback method informs the framework user that a previously
+ *        requested discovery operation on the domain has completed.
+ *
+ * @param[in]  controller This parameter specifies the controller object
+ *             with which this callback is associated.
+ * @param[in]  domain This parameter specifies the domain object with
+ *             which this callback is associated.
+ * @param[in]  completion_status This parameter indicates the results of the
+ *             discovery operation.
+ *
+ * @return none
+ */
+void
+scif_cb_domain_discovery_complete(SCI_CONTROLLER_HANDLE_T controller,
+    SCI_DOMAIN_HANDLE_T domain, SCI_STATUS completion_status)
+{
+
+	if(completion_status != SCI_SUCCESS)
+		isci_log_message(0, "ISCI",
+		    "scif_cb_domain_discovery_complete status = 0x%x\n",
+		    completion_status);
+
+	isci_controller_domain_discovery_complete(
+	    (struct ISCI_CONTROLLER *)sci_object_get_association(controller),
+	    (struct ISCI_DOMAIN *) sci_object_get_association(domain));
+}
+
+/**
+ * @brief This callback method informs the framework user that a previously
+ *        requested reset operation on the domain has completed.
+ *
+ * @param[in]  controller This parameter specifies the controller object
+ *             with which this callback is associated.
+ * @param[in]  domain This parameter specifies the domain object with
+ *             which this callback is associated.
+ * @param[in]  completion_status This parameter indicates the results of the
+ *             reset operation.
+ *
+ * @return none
+ */
+void
+scif_cb_domain_reset_complete(SCI_CONTROLLER_HANDLE_T controller,
+    SCI_DOMAIN_HANDLE_T domain, SCI_STATUS completion_status)
+{
+
+}
+
+/**
+ * @brief This callback method informs the framework user that the domain
+ *        is ready and capable of processing IO requests for devices found
+ *        inside it.
+ *
+ * @param[in]  controller This parameter specifies the controller object
+ *             with which this callback is associated.
+ * @param[in]  domain This parameter specifies the domain object with
+ *             which this callback is associated.
+ *
+ * @return none
+ */
+void
+scif_cb_domain_ready(SCI_CONTROLLER_HANDLE_T controller,
+    SCI_DOMAIN_HANDLE_T domain)
+{
+	uint32_t i;
+	struct ISCI_DOMAIN *isci_domain = sci_object_get_association(domain);
+	struct ISCI_CONTROLLER *isci_controller =
+	    sci_object_get_association(controller);
+
+	for (i = 0; i < SCI_MAX_REMOTE_DEVICES; i++) {
+		struct ISCI_REMOTE_DEVICE *remote_device =
+		    isci_controller->remote_device[i];
+
+		if (remote_device != NULL &&
+		    remote_device->domain == isci_domain)
+			isci_remote_device_release_device_queue(remote_device);
+	}
+}
+
+/**
+ * @brief This callback method informs the framework user that the domain
+ *        is no longer ready. Thus, it is incapable of processing IO
+ *        requests for devices found inside it.
+ *
+ * @param[in]  controller This parameter specifies the controller object
+ *             with which this callback is associated.
+ * @param[in]  domain This parameter specifies the domain object with
+ *             which this callback is associated.
+ *
+ * @return none
+ */
+void
+scif_cb_domain_not_ready(SCI_CONTROLLER_HANDLE_T controller,
+    SCI_DOMAIN_HANDLE_T domain)
+{
+
+}
+
+/**
+ * @brief This callback method informs the framework user that a new
+ *        direct attached device was found in the domain.
+ *
+ * @param[in]  controller This parameter specifies the controller object
+ *             with which this callback is associated.
+ * @param[in]  domain This parameter specifies the domain object with
+ *             which this callback is associated.
+ * @param[in]  sas_address This parameter specifies the SAS address of
+ *             the new device.
+ * @param[in]  protocols This parameter specifies the protocols
+ *             supported by the newly discovered device.
+ *
+ * @return none
+ */
+void
+scif_cb_domain_da_device_added(SCI_CONTROLLER_HANDLE_T controller,
+    SCI_DOMAIN_HANDLE_T domain, SCI_SAS_ADDRESS_T *sas_address,
+    SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T *protocols)
+{
+	struct ISCI_REMOTE_DEVICE *remote_device;
+	struct ISCI_DOMAIN *isci_domain =
+	    (struct ISCI_DOMAIN *)sci_object_get_association(domain);
+	struct ISCI_CONTROLLER *isci_controller =
+	    (struct ISCI_CONTROLLER *)sci_object_get_association(controller);
+
+	sci_pool_get(isci_controller->remote_device_pool, remote_device);
+
+	scif_remote_device_construct(domain,
+	    (uint8_t*)remote_device + sizeof(struct ISCI_REMOTE_DEVICE),
+	    &(remote_device->sci_object));
+
+	sci_object_set_association(remote_device->sci_object, remote_device);
+
+	scif_remote_device_da_construct(remote_device->sci_object, sas_address,
+	    protocols);
+
+	/* We do not put the device in the ISCI_CONTROLLER's device array yet.
+	 *  That will happen once the device becomes ready (see
+	 *  scif_cb_remote_device_ready).
+	 */
+
+	remote_device->domain = isci_domain;
+}
+
+/**
+ * @brief This callback method informs the framework user that a new
+ *        expander attached device was found in the domain.
+ *
+ * @param[in]  controller This parameter specifies the controller object
+ *             with which this callback is associated.
+ * @param[in]  domain This parameter specifies the domain object with
+ *             which this callback is associated.
+ * @param[in]  containing_device This parameter specifies the remote
+ *             device that contains the device that was added.
+ * @param[in]  smp_response This parameter specifies the SMP response
+ *             data associated with the newly discovered device.
+ *
+ * @return none
+ */
+void
+scif_cb_domain_ea_device_added(SCI_CONTROLLER_HANDLE_T controller,
+    SCI_DOMAIN_HANDLE_T domain, SCI_REMOTE_DEVICE_HANDLE_T containing_device,
+    SMP_RESPONSE_DISCOVER_T *smp_response)
+{
+	struct ISCI_REMOTE_DEVICE *remote_device;
+	struct ISCI_DOMAIN *isci_domain =
+		(struct ISCI_DOMAIN *)sci_object_get_association(domain);
+	struct ISCI_CONTROLLER *isci_controller =
+		(struct ISCI_CONTROLLER *)sci_object_get_association(controller);
+
+	sci_pool_get(isci_controller->remote_device_pool, remote_device);
+
+	scif_remote_device_construct( domain,
+	    (uint8_t*)remote_device + sizeof(struct ISCI_REMOTE_DEVICE),
+	    &(remote_device->sci_object));
+
+	sci_object_set_association(remote_device->sci_object, remote_device);
+
+	scif_remote_device_ea_construct(remote_device->sci_object,
+	    containing_device, smp_response);
+
+	/* We do not put the device in the ISCI_CONTROLLER's device array yet.
+	 *  That will happen once the device becomes ready (see
+	 *  scif_cb_remote_device_ready).
+	 */
+	remote_device->domain = isci_domain;
+}
+
+/**
+ * @brief This callback method informs the framework user that a device
+ *        has been removed from the domain.
+ *
+ * @param[in]  controller This parameter specifies the controller object
+ *             with which this callback is associated.
+ * @param[in]  domain This parameter specifies the domain object with
+ *             which this callback is associated.
+ * @param[in]  remote_device This parameter specifies the device object with
+ *             which this callback is associated.
+ *
+ * @return none
+ */
+void
+scif_cb_domain_device_removed(SCI_CONTROLLER_HANDLE_T controller,
+    SCI_DOMAIN_HANDLE_T domain, SCI_REMOTE_DEVICE_HANDLE_T remote_device)
+{
+	struct ISCI_REMOTE_DEVICE *isci_remote_device =
+	    (struct ISCI_REMOTE_DEVICE *)sci_object_get_association(remote_device);
+	struct ISCI_CONTROLLER *isci_controller =
+	    (struct ISCI_CONTROLLER *)sci_object_get_association(controller);
+	uint32_t path = cam_sim_path(isci_controller->sim);
+	union ccb *ccb = xpt_alloc_ccb_nowait();
+
+	isci_controller->remote_device[isci_remote_device->index] = NULL;
+
+	xpt_create_path(&ccb->ccb_h.path, xpt_periph, path,
+	    isci_remote_device->index, CAM_LUN_WILDCARD);
+
+	xpt_rescan(ccb);
+
+	scif_remote_device_destruct(remote_device);
+
+	sci_pool_put(isci_controller->remote_device_pool, isci_remote_device);
+}
+
+void
+isci_domain_construct(struct ISCI_DOMAIN *domain, uint32_t domain_index,
+    struct ISCI_CONTROLLER *controller)
+{
+
+	scif_controller_get_domain_handle( controller->scif_controller_handle,
+	    domain_index, &domain->sci_object);
+
+	domain->index = domain_index;
+	domain->controller = controller;
+	sci_object_set_association(domain->sci_object, (void *)domain);
+}
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/isci_interrupt.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/isci_interrupt.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,229 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <dev/isci/isci.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+
+#include <dev/isci/scil/scif_controller.h>
+
+void isci_interrupt_legacy_handler(void *arg);
+void isci_interrupt_msix_handler(void *arg);
+
+static int
+isci_interrupt_setup_legacy(struct isci_softc *isci)
+{
+	struct ISCI_INTERRUPT_INFO *interrupt_info = &isci->interrupt_info[0];
+
+	isci->num_interrupts = 1;
+
+	scic_controller_get_handler_methods(SCIC_LEGACY_LINE_INTERRUPT_TYPE,
+	    0, &isci->handlers[0]);
+
+	interrupt_info->handlers = &isci->handlers[0];
+	interrupt_info->rid = 0;
+	interrupt_info->interrupt_target_handle = (void *)isci;
+
+	interrupt_info->res = bus_alloc_resource_any(isci->device, SYS_RES_IRQ,
+	    &interrupt_info->rid, RF_SHAREABLE|RF_ACTIVE);
+
+	if (interrupt_info->res == NULL) {
+		isci_log_message(0, "ISCI", "bus_alloc_resource failed\n");
+		return (-1);
+	}
+
+	interrupt_info->tag = NULL;
+	if (bus_setup_intr(isci->device, interrupt_info->res,
+	    INTR_TYPE_CAM | INTR_MPSAFE, NULL, isci_interrupt_legacy_handler,
+	    interrupt_info, &interrupt_info->tag)) {
+		isci_log_message(0, "ISCI", "bus_setup_intr failed\n");
+		return (-1);
+	}
+
+	return (0);
+}
+
+static int
+isci_interrupt_setup_msix(struct isci_softc *isci)
+{
+	uint32_t controller_index;
+
+	scic_controller_get_handler_methods(SCIC_MSIX_INTERRUPT_TYPE,
+	    SCI_MAX_MSIX_MESSAGES_PER_CONTROLLER, &isci->handlers[0]);
+
+	for (controller_index = 0; controller_index < isci->controller_count;
+	    controller_index++) {
+		uint32_t msix_index;
+		uint8_t base_index = controller_index *
+		    SCI_MAX_MSIX_MESSAGES_PER_CONTROLLER;
+
+		for (msix_index = 0; msix_index < SCI_MAX_MSIX_MESSAGES_PER_CONTROLLER;
+		    msix_index++) {
+			struct ISCI_INTERRUPT_INFO *info =
+			    &isci->interrupt_info[base_index+msix_index];
+
+			info->handlers = &isci->handlers[msix_index];
+			info->interrupt_target_handle =
+			    &isci->controllers[controller_index];
+
+			info->rid = base_index+msix_index+1;
+
+			info->res = bus_alloc_resource_any(isci->device,
+			    SYS_RES_IRQ, &info->rid, RF_ACTIVE);
+			if (info->res == NULL) {
+				isci_log_message(0, "ISCI",
+				    "bus_alloc_resource failed\n");
+				return (-1);
+			}
+
+			info->tag = NULL;
+			if (bus_setup_intr(isci->device, info->res,
+			    INTR_TYPE_CAM | INTR_MPSAFE, NULL,
+			    isci_interrupt_msix_handler, info, &info->tag)) {
+				isci_log_message(0, "ISCI",
+				    "bus_setup_intr failed\n");
+				return (-1);
+			}
+		}
+	}
+
+	return (0);
+}
+
+void
+isci_interrupt_setup(struct isci_softc *isci)
+{
+	uint8_t max_msix_messages = SCI_MAX_MSIX_MESSAGES_PER_CONTROLLER *
+	    isci->controller_count;
+	BOOL use_msix = FALSE;
+	uint32_t force_legacy_interrupts = 0;
+
+	TUNABLE_INT_FETCH("hw.isci.force_legacy_interrupts",
+	    &force_legacy_interrupts);
+
+	if (!force_legacy_interrupts &&
+	    pci_msix_count(isci->device) >= max_msix_messages) {
+
+		isci->num_interrupts = max_msix_messages;
+		pci_alloc_msix(isci->device, &isci->num_interrupts);
+		if (isci->num_interrupts == max_msix_messages)
+			use_msix = TRUE;
+	}
+
+	if (use_msix == TRUE)
+		isci_interrupt_setup_msix(isci);
+	else
+		isci_interrupt_setup_legacy(isci);
+}
+
+void
+isci_interrupt_legacy_handler(void *arg)
+{
+	struct ISCI_INTERRUPT_INFO *interrupt_info =
+	    (struct ISCI_INTERRUPT_INFO *)arg;
+	struct isci_softc *isci =
+	    (struct isci_softc *)interrupt_info->interrupt_target_handle;
+	SCIC_CONTROLLER_INTERRUPT_HANDLER  interrupt_handler;
+	SCIC_CONTROLLER_COMPLETION_HANDLER completion_handler;
+	int index;
+
+	interrupt_handler =  interrupt_info->handlers->interrupt_handler;
+	completion_handler = interrupt_info->handlers->completion_handler;
+
+	for (index = 0; index < isci->controller_count; index++) {
+		struct ISCI_CONTROLLER *controller = &isci->controllers[index];
+
+		/* If controller_count > 0, we will get interrupts here for
+		 *  controller 0 before controller 1 has even started.  So
+		 *  we need to make sure we don't call the completion handler
+		 *  for a non-started controller.
+		 */
+		if (controller->is_started == TRUE) {
+			SCI_CONTROLLER_HANDLE_T scic_controller_handle =
+			    scif_controller_get_scic_handle(
+				controller->scif_controller_handle);
+
+			if (interrupt_handler(scic_controller_handle)) {
+				mtx_lock(&controller->lock);
+				completion_handler(scic_controller_handle);
+				mtx_unlock(&controller->lock);
+			}
+		}
+	}
+}
+
+void
+isci_interrupt_msix_handler(void *arg)
+{
+	struct ISCI_INTERRUPT_INFO *interrupt_info =
+	    (struct ISCI_INTERRUPT_INFO *)arg;
+	struct ISCI_CONTROLLER *controller =
+	    (struct ISCI_CONTROLLER *)interrupt_info->interrupt_target_handle;
+	SCIC_CONTROLLER_INTERRUPT_HANDLER  interrupt_handler;
+	SCIC_CONTROLLER_COMPLETION_HANDLER completion_handler;
+
+	interrupt_handler =  interrupt_info->handlers->interrupt_handler;
+	completion_handler = interrupt_info->handlers->completion_handler;
+
+	SCI_CONTROLLER_HANDLE_T scic_controller_handle;
+
+	scic_controller_handle = scif_controller_get_scic_handle(
+	    controller->scif_controller_handle);
+
+	if (interrupt_handler(scic_controller_handle)) {
+		mtx_lock(&controller->lock);
+		completion_handler(scic_controller_handle);
+		mtx_unlock(&controller->lock);
+	}
+}
+
+void
+isci_interrupt_poll_handler(struct ISCI_CONTROLLER *controller)
+{
+	SCI_CONTROLLER_HANDLE_T scic_controller =
+	    scif_controller_get_scic_handle(controller->scif_controller_handle);
+	SCIC_CONTROLLER_HANDLER_METHODS_T handlers;
+
+	scic_controller_get_handler_methods(SCIC_NO_INTERRUPTS, 0x0, &handlers);
+
+	if(handlers.interrupt_handler(scic_controller) == TRUE) {
+		/* Do not acquire controller lock in this path. xpt
+		 *  poll routine will get called with this lock already
+		 *  held, so we can't acquire it again here.  Other users
+		 *  of this function must acquire the lock explicitly
+		 *  before calling this handler.
+		 */
+		handlers.completion_handler(scic_controller);
+	}
+}
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/isci_io_request.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/isci_io_request.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,923 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <dev/isci/isci.h>
+
+#include <cam/scsi/scsi_all.h>
+#include <cam/scsi/scsi_message.h>
+
+#include <dev/isci/scil/intel_sas.h>
+
+#include <dev/isci/scil/sci_util.h>
+
+#include <dev/isci/scil/scif_io_request.h>
+#include <dev/isci/scil/scif_controller.h>
+#include <dev/isci/scil/scif_remote_device.h>
+#include <dev/isci/scil/scif_user_callback.h>
+
+#include <dev/isci/scil/scic_io_request.h>
+#include <dev/isci/scil/scic_user_callback.h>
+
+/**
+ * @brief This user callback will inform the user that an IO request has
+ *        completed.
+ *
+ * @param[in]  controller This parameter specifies the controller on
+ *             which the IO request is completing.
+ * @param[in]  remote_device This parameter specifies the remote device on
+ *             which this request is completing.
+ * @param[in]  io_request This parameter specifies the IO request that has
+ *             completed.
+ * @param[in]  completion_status This parameter specifies the results of
+ *             the IO request operation.  SCI_IO_SUCCESS indicates
+ *             successful completion.
+ *
+ * @return none
+ */
+void
+scif_cb_io_request_complete(SCI_CONTROLLER_HANDLE_T scif_controller,
+    SCI_REMOTE_DEVICE_HANDLE_T remote_device,
+    SCI_IO_REQUEST_HANDLE_T io_request, SCI_IO_STATUS completion_status)
+{
+	struct ISCI_IO_REQUEST *isci_request =
+	    (struct ISCI_IO_REQUEST *)sci_object_get_association(io_request);
+
+	scif_controller_complete_io(scif_controller, remote_device, io_request);
+	isci_io_request_complete(scif_controller, remote_device, isci_request,
+	    completion_status);
+}
+
+void
+isci_io_request_complete(SCI_CONTROLLER_HANDLE_T scif_controller,
+    SCI_REMOTE_DEVICE_HANDLE_T remote_device,
+    struct ISCI_IO_REQUEST *isci_request, SCI_IO_STATUS completion_status)
+{
+	struct ISCI_CONTROLLER *isci_controller;
+	struct ISCI_REMOTE_DEVICE *isci_remote_device;
+	union ccb *ccb;
+
+	isci_controller = (struct ISCI_CONTROLLER *) sci_object_get_association(scif_controller);
+	isci_remote_device =
+		(struct ISCI_REMOTE_DEVICE *) sci_object_get_association(remote_device);
+
+	ccb = isci_request->ccb;
+
+	ccb->ccb_h.status &= ~CAM_STATUS_MASK;
+
+	switch (completion_status) {
+	case SCI_IO_SUCCESS:
+	case SCI_IO_SUCCESS_COMPLETE_BEFORE_START:
+#if __FreeBSD_version >= 900026
+		if (ccb->ccb_h.func_code == XPT_SMP_IO) {
+			void *smp_response =
+			    scif_io_request_get_response_iu_address(
+			        isci_request->sci_object);
+
+			memcpy(ccb->smpio.smp_response, smp_response,
+			    ccb->smpio.smp_response_len);
+		}
+#endif
+		ccb->ccb_h.status |= CAM_REQ_CMP;
+		break;
+
+	case SCI_IO_SUCCESS_IO_DONE_EARLY:
+		ccb->ccb_h.status |= CAM_REQ_CMP;
+		ccb->csio.resid = ccb->csio.dxfer_len -
+		    scif_io_request_get_number_of_bytes_transferred(
+		        isci_request->sci_object);
+		break;
+
+	case SCI_IO_FAILURE_RESPONSE_VALID:
+	{
+		SCI_SSP_RESPONSE_IU_T * response_buffer;
+		uint32_t sense_length;
+		int error_code, sense_key, asc, ascq;
+		struct ccb_scsiio *csio = &ccb->csio;
+
+		response_buffer = (SCI_SSP_RESPONSE_IU_T *)
+		    scif_io_request_get_response_iu_address(
+		        isci_request->sci_object);
+
+		sense_length = sci_ssp_get_sense_data_length(
+		    response_buffer->sense_data_length);
+
+		sense_length = MIN(csio->sense_len, sense_length);
+
+		memcpy(&csio->sense_data, response_buffer->data, sense_length);
+
+		csio->sense_resid = csio->sense_len - sense_length;
+		csio->scsi_status = response_buffer->status;
+		ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
+		ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
+		scsi_extract_sense( &csio->sense_data, &error_code, &sense_key,
+		    &asc, &ascq );
+		isci_log_message(1, "ISCI",
+		    "isci: bus=%x target=%x lun=%x cdb[0]=%x status=%x key=%x asc=%x ascq=%x\n",
+		    ccb->ccb_h.path_id, ccb->ccb_h.target_id,
+		    ccb->ccb_h.target_lun, csio->cdb_io.cdb_bytes[0],
+		    csio->scsi_status, sense_key, asc, ascq);
+		break;
+	}
+
+	case SCI_IO_FAILURE_REMOTE_DEVICE_RESET_REQUIRED:
+		isci_remote_device_reset(isci_remote_device, NULL);
+
+		/* drop through */
+	case SCI_IO_FAILURE_TERMINATED:
+		ccb->ccb_h.status |= CAM_REQ_TERMIO;
+		isci_log_message(1, "ISCI",
+		    "isci: bus=%x target=%x lun=%x cdb[0]=%x terminated\n",
+		    ccb->ccb_h.path_id, ccb->ccb_h.target_id,
+		    ccb->ccb_h.target_lun, ccb->csio.cdb_io.cdb_bytes[0]);
+		break;
+
+	case SCI_IO_FAILURE_INVALID_STATE:
+	case SCI_IO_FAILURE_INSUFFICIENT_RESOURCES:
+		ccb->ccb_h.status |= CAM_REQUEUE_REQ;
+		isci_remote_device_freeze_lun_queue(isci_remote_device,
+		    ccb->ccb_h.target_lun);
+		break;
+
+	case SCI_IO_FAILURE_INVALID_REMOTE_DEVICE:
+		ccb->ccb_h.status |= CAM_DEV_NOT_THERE;
+		break;
+
+	case SCI_IO_FAILURE_NO_NCQ_TAG_AVAILABLE:
+		{
+			struct ccb_relsim ccb_relsim;
+			struct cam_path *path;
+
+			xpt_create_path(&path, NULL,
+			    cam_sim_path(isci_controller->sim),
+			    isci_remote_device->index, 0);
+
+			xpt_setup_ccb(&ccb_relsim.ccb_h, path, 5);
+			ccb_relsim.ccb_h.func_code = XPT_REL_SIMQ;
+			ccb_relsim.ccb_h.flags = CAM_DEV_QFREEZE;
+			ccb_relsim.release_flags = RELSIM_ADJUST_OPENINGS;
+			ccb_relsim.openings =
+			    scif_remote_device_get_max_queue_depth(remote_device);
+			xpt_action((union ccb *)&ccb_relsim);
+			xpt_free_path(path);
+			ccb->ccb_h.status |= CAM_REQUEUE_REQ;
+		}
+		break;
+
+	case SCI_IO_FAILURE:
+	case SCI_IO_FAILURE_REQUIRES_SCSI_ABORT:
+	case SCI_IO_FAILURE_UNSUPPORTED_PROTOCOL:
+	case SCI_IO_FAILURE_PROTOCOL_VIOLATION:
+	case SCI_IO_FAILURE_INVALID_PARAMETER_VALUE:
+	case SCI_IO_FAILURE_CONTROLLER_SPECIFIC_ERR:
+	default:
+		isci_log_message(1, "ISCI",
+		    "isci: bus=%x target=%x lun=%x cdb[0]=%x completion status=%x\n",
+		    ccb->ccb_h.path_id, ccb->ccb_h.target_id,
+		    ccb->ccb_h.target_lun, ccb->csio.cdb_io.cdb_bytes[0],
+		    completion_status);
+		ccb->ccb_h.status |= CAM_REQ_CMP_ERR;
+		break;
+	}
+
+	if (ccb->ccb_h.status != CAM_REQ_CMP) {
+		/* ccb will be completed with some type of non-success
+		 *  status.  So temporarily freeze the queue until the
+		 *  upper layers can act on the status.  The CAM_DEV_QFRZN
+		 *  flag will then release the queue after the status is
+		 *  acted upon.
+		 */
+		ccb->ccb_h.status |= CAM_DEV_QFRZN;
+		xpt_freeze_devq(ccb->ccb_h.path, 1);
+	}
+
+	callout_stop(&isci_request->parent.timer);
+	bus_dmamap_sync(isci_request->parent.dma_tag,
+	    isci_request->parent.dma_map,
+	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+
+	bus_dmamap_unload(isci_request->parent.dma_tag,
+	    isci_request->parent.dma_map);
+
+	if (isci_remote_device->frozen_lun_mask != 0 &&
+	    !(ccb->ccb_h.status & CAM_REQUEUE_REQ))
+		isci_remote_device_release_device_queue(isci_remote_device);
+
+	xpt_done(ccb);
+	isci_request->ccb = NULL;
+
+	if (isci_controller->is_frozen == TRUE) {
+		isci_controller->is_frozen = FALSE;
+		xpt_release_simq(isci_controller->sim, TRUE);
+	}
+
+	sci_pool_put(isci_controller->request_pool,
+	    (struct ISCI_REQUEST *)isci_request);
+}
+
+/**
+ * @brief This callback method asks the user to provide the physical
+ *        address for the supplied virtual address when building an
+ *        io request object.
+ *
+ * @param[in] controller This parameter is the core controller object
+ *            handle.
+ * @param[in] io_request This parameter is the io request object handle
+ *            for which the physical address is being requested.
+ * @param[in] virtual_address This paramter is the virtual address which
+ *            is to be returned as a physical address.
+ * @param[out] physical_address The physical address for the supplied virtual
+ *             address.
+ *
+ * @return None.
+ */
+void
+scic_cb_io_request_get_physical_address(SCI_CONTROLLER_HANDLE_T	controller,
+    SCI_IO_REQUEST_HANDLE_T io_request, void *virtual_address,
+    SCI_PHYSICAL_ADDRESS *physical_address)
+{
+	SCI_IO_REQUEST_HANDLE_T scif_request =
+	    sci_object_get_association(io_request);
+	struct ISCI_REQUEST *isci_request =
+	    sci_object_get_association(scif_request);
+
+	if(isci_request != NULL) {
+		/* isci_request is not NULL, meaning this is a request initiated
+		 *  by CAM or the isci layer (i.e. device reset for I/O
+		 *  timeout).  Therefore we can calculate the physical address
+		 *  based on the address we stored in the struct ISCI_REQUEST
+		 *  object.
+		 */
+		*physical_address = isci_request->physical_address +
+		    (uintptr_t)virtual_address -
+		    (uintptr_t)isci_request;
+	} else {
+		/* isci_request is NULL, meaning this is a request generated
+		 *  internally by SCIL (i.e. for SMP requests or NCQ error
+		 *  recovery).  Therefore we calculate the physical address
+		 *  based on the controller's uncached controller memory buffer,
+		 *  since we know that this is what SCIL uses for internal
+		 *  framework requests.
+		 */
+		SCI_CONTROLLER_HANDLE_T scif_controller =
+		    (SCI_CONTROLLER_HANDLE_T) sci_object_get_association(controller);
+		struct ISCI_CONTROLLER *isci_controller =
+		    (struct ISCI_CONTROLLER *)sci_object_get_association(scif_controller);
+		U64 virt_addr_offset = (uintptr_t)virtual_address -
+		    (U64)isci_controller->uncached_controller_memory.virtual_address;
+
+		*physical_address =
+		    isci_controller->uncached_controller_memory.physical_address
+		    + virt_addr_offset;
+	}
+}
+
+/**
+ * @brief This callback method asks the user to provide the address for
+ *        the command descriptor block (CDB) associated with this IO request.
+ *
+ * @param[in] scif_user_io_request This parameter points to the user's
+ *            IO request object.  It is a cookie that allows the user to
+ *            provide the necessary information for this callback.
+ *
+ * @return This method returns the virtual address of the CDB.
+ */
+void *
+scif_cb_io_request_get_cdb_address(void * scif_user_io_request)
+{
+	struct ISCI_IO_REQUEST *isci_request =
+	    (struct ISCI_IO_REQUEST *)scif_user_io_request;
+
+	return (isci_request->ccb->csio.cdb_io.cdb_bytes);
+}
+
+/**
+ * @brief This callback method asks the user to provide the length of
+ *        the command descriptor block (CDB) associated with this IO request.
+ *
+ * @param[in] scif_user_io_request This parameter points to the user's
+ *            IO request object.  It is a cookie that allows the user to
+ *            provide the necessary information for this callback.
+ *
+ * @return This method returns the length of the CDB.
+ */
+uint32_t
+scif_cb_io_request_get_cdb_length(void * scif_user_io_request)
+{
+	struct ISCI_IO_REQUEST *isci_request =
+	    (struct ISCI_IO_REQUEST *)scif_user_io_request;
+
+	return (isci_request->ccb->csio.cdb_len);
+}
+
+/**
+ * @brief This callback method asks the user to provide the Logical Unit (LUN)
+ *        associated with this IO request.
+ *
+ * @note The contents of the value returned from this callback are defined
+ *       by the protocol standard (e.g. T10 SAS specification).  Please
+ *       refer to the transport command information unit description
+ *       in the associated standard.
+ *
+ * @param[in] scif_user_io_request This parameter points to the user's
+ *            IO request object.  It is a cookie that allows the user to
+ *            provide the necessary information for this callback.
+ *
+ * @return This method returns the LUN associated with this request.
+ */
+uint32_t
+scif_cb_io_request_get_lun(void * scif_user_io_request)
+{
+	struct ISCI_IO_REQUEST *isci_request =
+	    (struct ISCI_IO_REQUEST *)scif_user_io_request;
+
+	return (isci_request->ccb->ccb_h.target_lun);
+}
+
+/**
+ * @brief This callback method asks the user to provide the task attribute
+ *        associated with this IO request.
+ *
+ * @note The contents of the value returned from this callback are defined
+ *       by the protocol standard (e.g. T10 SAS specification).  Please
+ *       refer to the transport command information unit description
+ *       in the associated standard.
+ *
+ * @param[in] scif_user_io_request This parameter points to the user's
+ *            IO request object.  It is a cookie that allows the user to
+ *            provide the necessary information for this callback.
+ *
+ * @return This method returns the task attribute associated with this
+ *         IO request.
+ */
+uint32_t
+scif_cb_io_request_get_task_attribute(void * scif_user_io_request)
+{
+	struct ISCI_IO_REQUEST *isci_request =
+	    (struct ISCI_IO_REQUEST *)scif_user_io_request;
+	uint32_t task_attribute;
+
+	if((isci_request->ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) != 0)
+		switch(isci_request->ccb->csio.tag_action) {
+		case MSG_HEAD_OF_Q_TAG:
+			task_attribute = SCI_SAS_HEAD_OF_QUEUE_ATTRIBUTE;
+			break;
+
+		case MSG_ORDERED_Q_TAG:
+			task_attribute = SCI_SAS_ORDERED_ATTRIBUTE;
+			break;
+
+		case MSG_ACA_TASK:
+			task_attribute = SCI_SAS_ACA_ATTRIBUTE;
+			break;
+
+		default:
+			task_attribute = SCI_SAS_SIMPLE_ATTRIBUTE;
+			break;
+		}
+	else
+		task_attribute = SCI_SAS_SIMPLE_ATTRIBUTE;
+
+	return (task_attribute);
+}
+
+/**
+ * @brief This callback method asks the user to provide the command priority
+ *        associated with this IO request.
+ *
+ * @note The contents of the value returned from this callback are defined
+ *       by the protocol standard (e.g. T10 SAS specification).  Please
+ *       refer to the transport command information unit description
+ *       in the associated standard.
+ *
+ * @param[in] scif_user_io_request This parameter points to the user's
+ *            IO request object.  It is a cookie that allows the user to
+ *            provide the necessary information for this callback.
+ *
+ * @return This method returns the command priority associated with this
+ *         IO request.
+ */
+uint32_t
+scif_cb_io_request_get_command_priority(void * scif_user_io_request)
+{
+	return (0);
+}
+
+/**
+ * @brief This method simply returns the virtual address associated
+ *        with the scsi_io and byte_offset supplied parameters.
+ *
+ * @note This callback is not utilized in the fast path.  The expectation
+ *       is that this method is utilized for items such as SCSI to ATA
+ *       translation for commands like INQUIRY, READ CAPACITY, etc.
+ *
+ * @param[in] scif_user_io_request This parameter points to the user's
+ *            IO request object.  It is a cookie that allows the user to
+ *            provide the necessary information for this callback.
+ * @param[in] byte_offset This parameter specifies the offset into the data
+ *            buffers pointed to by the SGL.  The byte offset starts at 0
+ *            and continues until the last byte pointed to be the last SGL
+ *            element.
+ *
+ * @return A virtual address pointer to the location specified by the
+ *         parameters.
+ */
+uint8_t *
+scif_cb_io_request_get_virtual_address_from_sgl(void * scif_user_io_request,
+    uint32_t byte_offset)
+{
+	struct ISCI_IO_REQUEST *isci_request =
+	    (struct ISCI_IO_REQUEST *)scif_user_io_request;
+
+	return (isci_request->ccb->csio.data_ptr + byte_offset);
+}
+
+/**
+ * @brief This callback method asks the user to provide the number of
+ *        bytes to be transfered as part of this request.
+ *
+ * @param[in] scif_user_io_request This parameter points to the user's
+ *            IO request object.  It is a cookie that allows the user to
+ *            provide the necessary information for this callback.
+ *
+ * @return This method returns the number of payload data bytes to be
+ *         transfered for this IO request.
+ */
+uint32_t
+scif_cb_io_request_get_transfer_length(void * scif_user_io_request)
+{
+	struct ISCI_IO_REQUEST *isci_request =
+	    (struct ISCI_IO_REQUEST *)scif_user_io_request;
+
+	return (isci_request->ccb->csio.dxfer_len);
+
+}
+
+/**
+ * @brief This callback method asks the user to provide the data direction
+ *        for this request.
+ *
+ * @param[in] scif_user_io_request This parameter points to the user's
+ *            IO request object.  It is a cookie that allows the user to
+ *            provide the necessary information for this callback.
+ *
+ * @return This method returns the value of SCI_IO_REQUEST_DATA_OUT,
+ *         SCI_IO_REQUEST_DATA_IN, or SCI_IO_REQUEST_NO_DATA.
+ */
+SCI_IO_REQUEST_DATA_DIRECTION
+scif_cb_io_request_get_data_direction(void * scif_user_io_request)
+{
+	struct ISCI_IO_REQUEST *isci_request =
+	    (struct ISCI_IO_REQUEST *)scif_user_io_request;
+
+	switch (isci_request->ccb->ccb_h.flags & CAM_DIR_MASK) {
+	case CAM_DIR_IN:
+		return (SCI_IO_REQUEST_DATA_IN);
+	case CAM_DIR_OUT:
+		return (SCI_IO_REQUEST_DATA_OUT);
+	default:
+		return (SCI_IO_REQUEST_NO_DATA);
+	}
+}
+
+/**
+ * @brief This callback method asks the user to provide the address
+ *        to where the next Scatter-Gather Element is located.
+ *
+ * Details regarding usage:
+ *   - Regarding the first SGE: the user should initialize an index,
+ *     or a pointer, prior to construction of the request that will
+ *     reference the very first scatter-gather element.  This is
+ *     important since this method is called for every scatter-gather
+ *     element, including the first element.
+ *   - Regarding the last SGE: the user should return NULL from this
+ *     method when this method is called and the SGL has exhausted
+ *     all elements.
+ *
+ * @param[in] scif_user_io_request This parameter points to the user's
+ *            IO request object.  It is a cookie that allows the user to
+ *            provide the necessary information for this callback.
+ * @param[in] current_sge_address This parameter specifies the address for
+ *            the current SGE (i.e. the one that has just processed).
+ * @param[out] next_sge An address specifying the location for the next scatter
+ *             gather element to be processed.
+ *
+ * @return None.
+ */
+void
+scif_cb_io_request_get_next_sge(void * scif_user_io_request,
+    void * current_sge_address, void ** next_sge)
+{
+	struct ISCI_IO_REQUEST *isci_request =
+	    (struct ISCI_IO_REQUEST *)scif_user_io_request;
+
+	if (isci_request->current_sge_index == isci_request->num_segments)
+		*next_sge = NULL;
+	else {
+		bus_dma_segment_t *sge =
+		    &isci_request->sge[isci_request->current_sge_index];
+
+		isci_request->current_sge_index++;
+		*next_sge = sge;
+	}
+}
+
+/**
+ * @brief This callback method asks the user to provide the contents of the
+ *        "address" field in the Scatter-Gather Element.
+ *
+ * @param[in] scif_user_io_request This parameter points to the user's
+ *            IO request object.  It is a cookie that allows the user to
+ *            provide the necessary information for this callback.
+ * @param[in] sge_address This parameter specifies the address for the
+ *            SGE from which to retrieve the address field.
+ *
+ * @return A physical address specifying the contents of the SGE's address
+ *         field.
+ */
+SCI_PHYSICAL_ADDRESS
+scif_cb_sge_get_address_field(void *scif_user_io_request, void *sge_address)
+{
+	bus_dma_segment_t *sge = (bus_dma_segment_t *)sge_address;
+
+	return ((SCI_PHYSICAL_ADDRESS)sge->ds_addr);
+}
+
+/**
+ * @brief This callback method asks the user to provide the contents of the
+ *        "length" field in the Scatter-Gather Element.
+ *
+ * @param[in] scif_user_io_request This parameter points to the user's
+ *            IO request object.  It is a cookie that allows the user to
+ *            provide the necessary information for this callback.
+ * @param[in] sge_address This parameter specifies the address for the
+ *            SGE from which to retrieve the address field.
+ *
+ * @return This method returns the length field specified inside the SGE
+ *         referenced by the sge_address parameter.
+ */
+uint32_t
+scif_cb_sge_get_length_field(void *scif_user_io_request, void *sge_address)
+{
+	bus_dma_segment_t *sge = (bus_dma_segment_t *)sge_address;
+
+	return ((uint32_t)sge->ds_len);
+}
+
+void
+isci_request_construct(struct ISCI_REQUEST *request,
+    SCI_CONTROLLER_HANDLE_T scif_controller_handle,
+    bus_dma_tag_t io_buffer_dma_tag, bus_addr_t physical_address)
+{
+
+	request->controller_handle = scif_controller_handle;
+	request->dma_tag = io_buffer_dma_tag;
+	request->physical_address = physical_address;
+	bus_dmamap_create(request->dma_tag, 0, &request->dma_map);
+	callout_init(&request->timer, CALLOUT_MPSAFE);
+}
+
+static void
+isci_io_request_construct(void *arg, bus_dma_segment_t *seg, int nseg,
+    int error)
+{
+	union ccb *ccb;
+	struct ISCI_IO_REQUEST *io_request = (struct ISCI_IO_REQUEST *)arg;
+	SCI_REMOTE_DEVICE_HANDLE_T *device = io_request->parent.remote_device_handle;
+	SCI_STATUS status;
+
+	io_request->num_segments = nseg;
+	io_request->sge = seg;
+	ccb = io_request->ccb;
+
+	/* XXX More cleanup is needed here */
+	if ((nseg == 0) || (error != 0)) {
+		ccb->ccb_h.status = CAM_REQ_INVALID;
+		xpt_done(ccb);
+		return;
+	}
+
+	io_request->status = scif_io_request_construct(
+	    io_request->parent.controller_handle,
+	    io_request->parent.remote_device_handle,
+	    SCI_CONTROLLER_INVALID_IO_TAG, (void *)io_request,
+	    (void *)((char*)io_request + sizeof(struct ISCI_IO_REQUEST)),
+	    &io_request->sci_object);
+
+	if (io_request->status != SCI_SUCCESS) {
+		isci_io_request_complete(io_request->parent.controller_handle,
+		    device, io_request, io_request->status);
+		return;
+	}
+
+	sci_object_set_association(io_request->sci_object, io_request);
+
+	bus_dmamap_sync(io_request->parent.dma_tag, io_request->parent.dma_map,
+	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+
+	status = (SCI_STATUS)scif_controller_start_io(
+	    io_request->parent.controller_handle, device,
+	    io_request->sci_object, SCI_CONTROLLER_INVALID_IO_TAG);
+
+	if (status != SCI_SUCCESS) {
+		isci_io_request_complete(io_request->parent.controller_handle,
+		    device, io_request, status);
+		return;
+	}
+
+	if (ccb->ccb_h.timeout != CAM_TIME_INFINITY)
+		callout_reset(&io_request->parent.timer, ccb->ccb_h.timeout,
+		    isci_io_request_timeout, io_request);
+}
+
+void
+isci_io_request_execute_scsi_io(union ccb *ccb,
+    struct ISCI_CONTROLLER *controller)
+{
+	struct ccb_scsiio *csio = &ccb->csio;
+	target_id_t target_id = ccb->ccb_h.target_id;
+	struct ISCI_REQUEST *request;
+	struct ISCI_IO_REQUEST *io_request;
+	struct ISCI_REMOTE_DEVICE *device =
+	    controller->remote_device[target_id];
+	int error;
+
+	if (device == NULL) {
+		ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
+		ccb->ccb_h.status &= ~CAM_STATUS_MASK;
+		ccb->ccb_h.status |= CAM_DEV_NOT_THERE;
+		xpt_done(ccb);
+		return;
+	}
+
+	if (sci_pool_empty(controller->request_pool)) {
+		ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
+		ccb->ccb_h.status &= ~CAM_STATUS_MASK;
+		ccb->ccb_h.status |= CAM_REQUEUE_REQ;
+		xpt_freeze_simq(controller->sim, 1);
+		controller->is_frozen = TRUE;
+		xpt_done(ccb);
+		return;
+	}
+
+	ASSERT(device->is_resetting == FALSE);
+
+	sci_pool_get(controller->request_pool, request);
+	io_request = (struct ISCI_IO_REQUEST *)request;
+
+	io_request->ccb = ccb;
+	io_request->current_sge_index = 0;
+	io_request->parent.remote_device_handle = device->sci_object;
+
+	if ((ccb->ccb_h.flags & CAM_SCATTER_VALID) != 0)
+		panic("Unexpected CAM_SCATTER_VALID flag!  flags = 0x%x\n",
+		    ccb->ccb_h.flags);
+
+	if ((ccb->ccb_h.flags & CAM_DATA_PHYS) != 0)
+		panic("Unexpected CAM_DATA_PHYS flag!  flags = 0x%x\n",
+		    ccb->ccb_h.flags);
+
+	error = bus_dmamap_load(io_request->parent.dma_tag,
+	    io_request->parent.dma_map, csio->data_ptr, csio->dxfer_len,
+	    isci_io_request_construct, io_request, 0x0);
+
+	/* A resource shortage from BUSDMA will be automatically
+	 * continued at a later point, pushing the CCB processing
+	 * forward, which will in turn unfreeze the simq.
+	 */
+	if (error == EINPROGRESS) {
+		xpt_freeze_simq(controller->sim, 1);
+		ccb->ccb_h.flags |= CAM_RELEASE_SIMQ;
+	}
+}
+
+void
+isci_io_request_timeout(void *arg)
+{
+	struct ISCI_IO_REQUEST *request = (struct ISCI_IO_REQUEST *)arg;
+	struct ISCI_REMOTE_DEVICE *remote_device = (struct ISCI_REMOTE_DEVICE *)
+		sci_object_get_association(request->parent.remote_device_handle);
+	struct ISCI_CONTROLLER *controller = remote_device->domain->controller;
+
+	mtx_lock(&controller->lock);
+	isci_remote_device_reset(remote_device, NULL);
+	mtx_unlock(&controller->lock);
+}
+
+#if __FreeBSD_version >= 900026
+/**
+ * @brief This callback method gets the size of and pointer to the buffer
+ *         (if any) containing the request buffer for an SMP request.
+ *
+ * @param[in]  core_request This parameter specifies the SCI core's request
+ *             object associated with the SMP request.
+ * @param[out] smp_request_buffer This parameter returns a pointer to the
+ *             payload portion of the SMP request - i.e. everything after
+ *             the SMP request header.
+ *
+ * @return Size of the request buffer in bytes.  This does *not* include
+ *          the size of the SMP request header.
+ */
+static uint32_t
+smp_io_request_cb_get_request_buffer(SCI_IO_REQUEST_HANDLE_T core_request,
+    uint8_t ** smp_request_buffer)
+{
+	struct ISCI_IO_REQUEST *isci_request = (struct ISCI_IO_REQUEST *)
+	    sci_object_get_association(sci_object_get_association(core_request));
+
+	*smp_request_buffer = isci_request->ccb->smpio.smp_request +
+	    sizeof(SMP_REQUEST_HEADER_T);
+
+	return (isci_request->ccb->smpio.smp_request_len -
+	    sizeof(SMP_REQUEST_HEADER_T));
+}
+
+/**
+ * @brief This callback method gets the SMP function for an SMP request.
+ *
+ * @param[in]  core_request This parameter specifies the SCI core's request
+ *             object associated with the SMP request.
+ *
+ * @return SMP function for the SMP request.
+ */
+static uint8_t
+smp_io_request_cb_get_function(SCI_IO_REQUEST_HANDLE_T core_request)
+{
+	struct ISCI_IO_REQUEST *isci_request = (struct ISCI_IO_REQUEST *)
+	    sci_object_get_association(sci_object_get_association(core_request));
+	SMP_REQUEST_HEADER_T *header =
+	    (SMP_REQUEST_HEADER_T *)isci_request->ccb->smpio.smp_request;
+
+	return (header->function);
+}
+
+/**
+ * @brief This callback method gets the SMP frame type for an SMP request.
+ *
+ * @param[in]  core_request This parameter specifies the SCI core's request
+ *             object associated with the SMP request.
+ *
+ * @return SMP frame type for the SMP request.
+ */
+static uint8_t
+smp_io_request_cb_get_frame_type(SCI_IO_REQUEST_HANDLE_T core_request)
+{
+	struct ISCI_IO_REQUEST *isci_request = (struct ISCI_IO_REQUEST *)
+	    sci_object_get_association(sci_object_get_association(core_request));
+	SMP_REQUEST_HEADER_T *header =
+	    (SMP_REQUEST_HEADER_T *)isci_request->ccb->smpio.smp_request;
+
+	return (header->smp_frame_type);
+}
+
+/**
+ * @brief This callback method gets the allocated response length for an SMP request.
+ *
+ * @param[in]  core_request This parameter specifies the SCI core's request
+ *             object associated with the SMP request.
+ *
+ * @return Allocated response length for the SMP request.
+ */
+static uint8_t
+smp_io_request_cb_get_allocated_response_length(
+    SCI_IO_REQUEST_HANDLE_T core_request)
+{
+	struct ISCI_IO_REQUEST *isci_request = (struct ISCI_IO_REQUEST *)
+	    sci_object_get_association(sci_object_get_association(core_request));
+	SMP_REQUEST_HEADER_T *header =
+	    (SMP_REQUEST_HEADER_T *)isci_request->ccb->smpio.smp_request;
+
+	return (header->allocated_response_length);
+}
+
+static SCI_STATUS
+isci_smp_request_construct(struct ISCI_IO_REQUEST *request)
+{
+	SCI_STATUS status;
+	SCIC_SMP_PASSTHRU_REQUEST_CALLBACKS_T callbacks;
+
+	status = scif_request_construct(request->parent.controller_handle,
+	    request->parent.remote_device_handle, SCI_CONTROLLER_INVALID_IO_TAG,
+	    (void *)request,
+	    (void *)((char*)request + sizeof(struct ISCI_IO_REQUEST)),
+	    &request->sci_object);
+
+	if (status == SCI_SUCCESS) {
+		callbacks.scic_cb_smp_passthru_get_request =
+		    &smp_io_request_cb_get_request_buffer;
+		callbacks.scic_cb_smp_passthru_get_function =
+		    &smp_io_request_cb_get_function;
+		callbacks.scic_cb_smp_passthru_get_frame_type =
+		    &smp_io_request_cb_get_frame_type;
+		callbacks.scic_cb_smp_passthru_get_allocated_response_length =
+		    &smp_io_request_cb_get_allocated_response_length;
+
+		/* create the smp passthrough part of the io request */
+		status = scic_io_request_construct_smp_pass_through(
+		    scif_io_request_get_scic_handle(request->sci_object),
+		    &callbacks);
+	}
+
+	return (status);
+}
+
+void
+isci_io_request_execute_smp_io(union ccb *ccb,
+    struct ISCI_CONTROLLER *controller)
+{
+	SCI_STATUS status;
+	target_id_t target_id = ccb->ccb_h.target_id;
+	struct ISCI_REQUEST *request;
+	struct ISCI_IO_REQUEST *io_request;
+	SCI_REMOTE_DEVICE_HANDLE_T smp_device_handle;
+	struct ISCI_REMOTE_DEVICE *end_device = controller->remote_device[target_id];
+
+	/* SMP commands are sent to an end device, because SMP devices are not
+	 *  exposed to the kernel.  It is our responsibility to use this method
+	 *  to get the SMP device that contains the specified end device.  If
+	 *  the device is direct-attached, the handle will come back NULL, and
+	 *  we'll just fail the SMP_IO with DEV_NOT_THERE.
+	 */
+	scif_remote_device_get_containing_device(end_device->sci_object,
+	    &smp_device_handle);
+
+	if (smp_device_handle == NULL) {
+		ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
+		ccb->ccb_h.status &= ~CAM_STATUS_MASK;
+		ccb->ccb_h.status |= CAM_DEV_NOT_THERE;
+		xpt_done(ccb);
+		return;
+	}
+
+	if (sci_pool_empty(controller->request_pool)) {
+		ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
+		ccb->ccb_h.status &= ~CAM_STATUS_MASK;
+		ccb->ccb_h.status |= CAM_REQUEUE_REQ;
+		xpt_freeze_simq(controller->sim, 1);
+		controller->is_frozen = TRUE;
+		xpt_done(ccb);
+		return;
+	}
+
+	ASSERT(device->is_resetting == FALSE);
+
+	sci_pool_get(controller->request_pool, request);
+	io_request = (struct ISCI_IO_REQUEST *)request;
+
+	io_request->ccb = ccb;
+	io_request->parent.remote_device_handle = smp_device_handle;
+
+	status = isci_smp_request_construct(io_request);
+
+	if (status != SCI_SUCCESS) {
+		isci_io_request_complete(controller->scif_controller_handle,
+		    smp_device_handle, io_request, status);
+		return;
+	}
+
+	sci_object_set_association(io_request->sci_object, io_request);
+
+	status = (SCI_STATUS) scif_controller_start_io(
+	    controller->scif_controller_handle, smp_device_handle,
+	    io_request->sci_object, SCI_CONTROLLER_INVALID_IO_TAG);
+
+	if (status != SCI_SUCCESS) {
+		isci_io_request_complete(controller->scif_controller_handle,
+		    smp_device_handle, io_request, status);
+		return;
+	}
+
+	if (ccb->ccb_h.timeout != CAM_TIME_INFINITY)
+		callout_reset(&io_request->parent.timer, ccb->ccb_h.timeout,
+		    isci_io_request_timeout, request);
+}
+#endif
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/isci_logger.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/isci_logger.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,351 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <dev/isci/isci.h>
+
+#include <dev/isci/scil/scif_user_callback.h>
+#include <dev/isci/scil/scic_user_callback.h>
+#include <dev/isci/scil/sci_logger.h>
+
+#include <machine/stdarg.h>
+#include <sys/time.h>
+
+#define ERROR_LEVEL	0
+#define WARNING_LEVEL	1
+#define TRACE_LEVEL	2
+#define INFO_LEVEL	3
+
+void
+isci_log_message(uint32_t verbosity, char *log_message_prefix,
+    char *log_message, ...)
+{
+	va_list argp;
+	char buffer[512];
+	struct timeval tv;
+
+	if (verbosity > g_isci_debug_level)
+		return;
+
+	va_start (argp, log_message);
+	vsnprintf(buffer, sizeof(buffer)-1, log_message, argp);
+	va_end(argp);
+	microtime(&tv);
+
+	printf("isci: %d:%06d %s %s", (int)tv.tv_sec, (int)tv.tv_usec,
+	    log_message_prefix, buffer);
+}
+
+
+#ifdef SCI_LOGGING
+#define SCI_ENABLE_LOGGING_ERROR	1
+#define SCI_ENABLE_LOGGING_WARNING	1
+#define SCI_ENABLE_LOGGING_INFO		1
+#define SCI_ENABLE_LOGGING_TRACE	1
+#define SCI_ENABLE_LOGGING_STATES	1
+
+#define ISCI_LOG_MESSAGE(			\
+	logger_object,				\
+	log_object_mask,			\
+	log_message,				\
+	verbosity,				\
+	log_message_prefix			\
+)						\
+{						\
+	va_list argp;				\
+	char buffer[512];			\
+						\
+	if (!sci_logger_is_enabled(logger_object, log_object_mask, verbosity)) \
+		return;				\
+						\
+	va_start (argp, log_message);		\
+	vsnprintf(buffer, sizeof(buffer)-1, log_message, argp); \
+	va_end(argp);				\
+						\
+	/* prepend the "object:verbosity_level:" */ \
+	isci_log_message(verbosity, log_message_prefix, buffer); \
+}
+#endif /* SCI_LOGGING */
+
+
+#ifdef SCI_ENABLE_LOGGING_ERROR
+/**
+ * @brief In this method the user is expected to log the supplied
+ *        error information.  The user must be capable of handling variable
+ *        length argument lists and should consider prepending the fact
+ *        that this is an error from the framework.
+ *
+ * @param[in]  logger_object This parameter specifies the logger object
+ *             associated with this message.
+ * @param[in]  log_object_mask This parameter specifies the log objects
+ *             for which this message is being generated.
+ * @param[in]  log_message This parameter specifies the message to be logged.
+ *
+ * @return none
+ */
+void scif_cb_logger_log_error(SCI_LOGGER_HANDLE_T logger_object,
+    uint32_t log_object_mask, char *log_message, ...)
+{
+
+	ISCI_LOG_MESSAGE(logger_object, log_object_mask, log_message,
+	    SCI_LOG_VERBOSITY_ERROR, "FRAMEWORK: ERROR: ");
+}
+#endif
+
+#ifdef SCI_ENABLE_LOGGING_WARNING
+/**
+ * @brief In this method the user is expected to log the supplied warning
+ *        information.  The user must be capable of handling variable
+ *        length argument lists and should consider prepending the fact
+ *        that this is a warning from the framework.
+ *
+ * @param[in]  logger_object This parameter specifies the logger object
+ *             associated with this message.
+ * @param[in]  log_object_mask This parameter specifies the log objects
+ *             for which this message is being generated.
+ * @param[in]  log_message This parameter specifies the message to be logged.
+ *
+ * @return none
+ */
+void
+scif_cb_logger_log_warning(SCI_LOGGER_HANDLE_T logger_object,
+    uint32_t log_object_mask, char *log_message, ...)
+{
+
+	ISCI_LOG_MESSAGE(logger_object, log_object_mask, log_message,
+	    SCI_LOG_VERBOSITY_WARNING, "FRAMEWORK: WARNING: ");
+}
+#endif
+
+#ifdef SCI_ENABLE_LOGGING_INFO
+/**
+ * @brief In this method the user is expected to log the supplied debug
+ *        information.  The user must be capable of handling variable
+ *        length argument lists and should consider prepending the fact
+ *        that this is a debug message from the framework.
+ *
+ * @param[in]  logger_object This parameter specifies the logger object
+ *             associated with this message.
+ * @param[in]  log_object_mask This parameter specifies the log objects
+ *             for which this message is being generated.
+ * @param[in]  log_message This parameter specifies the message to be logged.
+ *
+ * @return none
+ */
+void
+scif_cb_logger_log_info(SCI_LOGGER_HANDLE_T logger_object,
+    uint32_t log_object_mask, char *log_message, ...)
+{
+
+	ISCI_LOG_MESSAGE(logger_object, log_object_mask, log_message,
+	    SCI_LOG_VERBOSITY_INFO, "FRAMEWORK: INFO: ");
+}
+#endif
+
+#ifdef SCI_ENABLE_LOGGING_TRACE
+/**
+ * @brief In this method the user is expected to log the supplied function
+ *        trace information.  The user must be capable of handling variable
+ *        length argument lists and should consider prepending the fact
+ *        that this is a function trace (i.e. entry/exit) message from the
+ *        framework.
+ *
+ * @param[in]  logger_object This parameter specifies the logger object
+ *             associated with this message.
+ * @param[in]  log_object_mask This parameter specifies the log objects
+ *             for which this message is being generated.
+ * @param[in]  log_message This parameter specifies the message to be logged.
+ *
+ * @return none
+ */
+void
+scif_cb_logger_log_trace(SCI_LOGGER_HANDLE_T logger_object,
+    uint32_t log_object_mask, char *log_message, ...)
+{
+
+	ISCI_LOG_MESSAGE(logger_object, log_object_mask, log_message,
+	    SCI_LOG_VERBOSITY_TRACE, "FRAMEWORK: TRACE: ");
+}
+#endif
+
+#ifdef SCI_ENABLE_LOGGING_STATES
+/**
+ * @brief In this method the user is expected to log the supplied function
+ *        state transition information.  The user must be capable of handling
+ *        variable length argument lists and should consider prepending the
+ *        fact that this is a function trace (i.e. entry/exit) message from
+ *        the framework.
+ *
+ * @param[in]  logger_object This parameter specifies the logger object
+ *             associated with this message.
+ * @param[in]  log_object_mask This parameter specifies the log objects
+ *             for which this message is being generated.
+ * @param[in]  log_message This parameter specifies the message to be logged.
+ *
+ * @return none
+ */
+void
+scif_cb_logger_log_states(SCI_LOGGER_HANDLE_T logger_object,
+    uint32_t log_object_mask, char *log_message, ...)
+{
+
+	ISCI_LOG_MESSAGE(logger_object, log_object_mask, log_message,
+	    SCI_LOG_VERBOSITY_STATES, "FRAMEWORK: STATE TRANSITION: ");
+}
+#endif
+
+#ifdef SCI_ENABLE_LOGGING_ERROR
+/**
+ * @brief In this method the user is expected to log the supplied
+ *        error information.  The user must be capable of handling variable
+ *        length argument lists and should consider prepending the fact
+ *        that this is an error from the core.
+ *
+ * @param[in]  logger_object This parameter specifies the logger object
+ *             associated with this message.
+ * @param[in]  log_object_mask This parameter specifies the log objects
+ *             for which this message is being generated.
+ * @param[in]  log_message This parameter specifies the message to be logged.
+ *
+ * @return none
+ */
+void
+scic_cb_logger_log_error(SCI_LOGGER_HANDLE_T logger_object,
+    uint32_t log_object_mask, char *log_message, ...)
+{
+
+	ISCI_LOG_MESSAGE(logger_object, log_object_mask, log_message,
+	    SCI_LOG_VERBOSITY_ERROR, "CORE: ERROR: ");
+}
+#endif
+
+#ifdef SCI_ENABLE_LOGGING_WARNING
+/**
+ * @brief In this method the user is expected to log the supplied warning
+ *        information.  The user must be capable of handling variable
+ *        length argument lists and should consider prepending the fact
+ *        that this is a warning from the core.
+ *
+ * @param[in]  logger_object This parameter specifies the logger object
+ *             associated with this message.
+ * @param[in]  log_object_mask This parameter specifies the log objects
+ *             for which this message is being generated.
+ * @param[in]  log_message This parameter specifies the message to be logged.
+ *
+ * @return none
+ */
+void
+scic_cb_logger_log_warning(SCI_LOGGER_HANDLE_T logger_object,
+    uint32_t log_object_mask, char *log_message, ...)
+{
+
+	ISCI_LOG_MESSAGE(logger_object, log_object_mask, log_message,
+	    SCI_LOG_VERBOSITY_WARNING, "CORE: WARNING: ");
+}
+#endif
+
+#ifdef SCI_ENABLE_LOGGING_INFO
+/**
+ * @brief In this method the user is expected to log the supplied debug
+ *        information.  The user must be capable of handling variable
+ *        length argument lists and should consider prepending the fact
+ *        that this is a debug message from the core.
+ *
+ * @param[in]  logger_object This parameter specifies the logger object
+ *             associated with this message.
+ * @param[in]  log_object_mask This parameter specifies the log objects
+ *             for which this message is being generated.
+ * @param[in]  log_message This parameter specifies the message to be logged.
+ *
+ * @return none
+ */
+void
+scic_cb_logger_log_info(SCI_LOGGER_HANDLE_T logger_object,
+    uint32_t log_object_mask, char *log_message, ...)
+{
+
+	ISCI_LOG_MESSAGE(logger_object, log_object_mask, log_message,
+	    SCI_LOG_VERBOSITY_INFO, "CORE: INFO: ");
+}
+#endif
+
+#ifdef SCI_ENABLE_LOGGING_TRACE
+/**
+ * @brief In this method the user is expected to log the supplied function
+ *        trace information.  The user must be capable of handling variable
+ *        length argument lists and should consider prepending the fact
+ *        that this is a function trace (i.e. entry/exit) message from the
+ *        core.
+ *
+ * @param[in]  logger_object This parameter specifies the logger object
+ *             associated with this message.
+ * @param[in]  log_object_mask This parameter specifies the log objects
+ *             for which this message is being generated.
+ * @param[in]  log_message This parameter specifies the message to be logged.
+ *
+ * @return none
+ */
+void
+scic_cb_logger_log_trace(SCI_LOGGER_HANDLE_T logger_object,
+    uint32_t log_object_mask, char *log_message, ...)
+{
+
+	ISCI_LOG_MESSAGE(logger_object, log_object_mask, log_message,
+	    SCI_LOG_VERBOSITY_TRACE, "CORE: TRACE: ");
+}
+#endif
+
+#ifdef SCI_ENABLE_LOGGING_STATES
+/**
+ * @brief In this method the user is expected to log the supplied function
+ *        state transition information.  The user must be capable of handling
+ *        variable length argument lists and should consider prepending the
+ *        fact that this is a function trace (i.e. entry/exit) message from
+ *        the core.
+ *
+ * @param[in]  logger_object This parameter specifies the logger object
+ *             associated with this message.
+ * @param[in]  log_object_mask This parameter specifies the log objects
+ *             for which this message is being generated.
+ * @param[in]  log_message This parameter specifies the message to be logged.
+ *
+ * @return none
+ */
+void
+scic_cb_logger_log_states(SCI_LOGGER_HANDLE_T logger_object,
+    uint32_t log_object_mask, char *log_message, ...)
+{
+
+	ISCI_LOG_MESSAGE(logger_object, log_object_mask, log_message,
+	    SCI_LOG_VERBOSITY_STATES, "CORE: STATE TRANSITION: ");
+}
+#endif
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/isci_oem_parameters.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/isci_oem_parameters.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,176 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <dev/isci/isci.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <machine/pmap.h>
+#include <machine/vmparam.h>
+#include <machine/pc/bios.h>
+#include <dev/isci/scil/scu_bios_definitions.h>
+
+struct pcir_header
+{
+	uint32_t	signature;
+	uint16_t	vendor_id;
+	uint16_t	device_id;
+	uint16_t	reserved;
+	uint16_t	struct_length;
+	uint8_t		struct_revision;
+	uint8_t		cc_interface;
+	uint8_t		cc_subclass;
+	uint8_t		cc_baseclass;
+	uint16_t	image_length;
+	uint16_t	code_revision;
+	uint8_t		code_type;
+	uint8_t		indicator;
+	uint16_t	reserved1;
+};
+
+struct rom_header
+{
+	uint8_t		signature_byte[2];
+	uint8_t		rom_length;
+	uint8_t		jmp_code;
+	uint16_t	entry_address;
+	uint8_t		reserved[0x12];
+	uint16_t	pcir_pointer;
+	uint16_t	pnp_pointer;
+};
+
+struct oem_parameters_table
+{
+	uint8_t		signature[4];  /* "$OEM" */
+	struct revision
+	{
+		uint16_t	major:8;  /* bits [7:0] */
+		uint16_t	minor:8;  /* bits [8:15] */
+	} revision;
+
+	uint16_t	length;
+	uint8_t		checksum;
+	uint8_t		reserved1;
+	uint16_t	reserved2;
+	uint8_t		data[1];
+};
+
+void
+isci_get_oem_parameters(struct isci_softc *isci)
+{
+	uint32_t OROM_PHYSICAL_ADDRESS_START = 0xC0000;
+	uint32_t OROM_SEARCH_LENGTH = 0x30000;
+	uint16_t OROM_SIGNATURE = 0xAA55;
+	uint32_t OROM_SIZE = 512;
+	uint8_t *orom_start =
+	    (uint8_t *)BIOS_PADDRTOVADDR(OROM_PHYSICAL_ADDRESS_START);
+	uint32_t offset = 0;
+
+	while (offset < OROM_SEARCH_LENGTH) {
+
+		/* Look for the OROM signature at the beginning of every
+		 *  512-byte block in the OROM region
+		 */
+		if (*(uint16_t*)(orom_start + offset) == OROM_SIGNATURE) {
+			uint32_t *rom;
+			struct rom_header *rom_header;
+			struct pcir_header *pcir_header;
+			uint16_t vendor_id = isci->pci_common_header.vendor_id;
+			uint16_t device_id = isci->pci_common_header.device_id;
+
+			rom = (uint32_t *)(orom_start + offset);
+			rom_header = (struct rom_header *)rom;
+			pcir_header = (struct pcir_header *)
+			    ((uint8_t*)rom + rom_header->pcir_pointer);
+
+			/* OROM signature was found.  Now check if the PCI
+			 *  device and vendor IDs match.
+			 */
+			if (pcir_header->vendor_id == vendor_id &&
+			    pcir_header->device_id == device_id)
+			{
+				/* OROM for this PCI device was found.  Search
+				 *  this 512-byte block for the $OEM string,
+				 *  which will mark the beginning of the OEM
+				 *  parameter block.
+				 */
+				uint8_t oem_sig[4] = {'$', 'O', 'E', 'M'};
+				int dword_index;
+
+				for (dword_index = 0;
+				    dword_index < OROM_SIZE/sizeof(uint32_t);
+				    dword_index++)
+					if (rom[dword_index] == *(uint32_t *)oem_sig) {
+						/* $OEM signature string was found.  Now copy the OEM parameter block
+						 *  into the struct ISCI_CONTROLLER objects.  After the controllers are
+						 *  constructed, we will pass this OEM parameter data to the SCI core
+						 *  controller.
+						 */
+						struct oem_parameters_table *oem =
+							(struct oem_parameters_table *)&rom[dword_index];
+						SCI_BIOS_OEM_PARAM_BLOCK_T *oem_data =
+							(SCI_BIOS_OEM_PARAM_BLOCK_T *)oem->data;
+						int index;
+
+						isci->oem_parameters_found = TRUE;
+						isci_log_message(1, "ISCI", "oem_data->header.num_elements = %d\n",
+						    oem_data->header.num_elements);
+
+						for (index = 0; index < oem_data->header.num_elements; index++)
+						{
+							memcpy(&isci->controllers[index].oem_parameters.sds1,
+							       &oem_data->controller_element[index],
+							       sizeof(SCIC_SDS_OEM_PARAMETERS_T));
+
+							isci_log_message(1, "ISCI", "OEM Parameter Data for controller %d\n",
+							    index);
+
+							for (int i = 0; i < sizeof(SCIC_SDS_OEM_PARAMETERS_T); i++) {
+								uint8_t val = ((uint8_t *)&oem_data->controller_element[index])[i];
+								isci_log_message(1, "ISCI", "%02x ", val);
+							}
+							isci_log_message(1, "ISCI", "\n");
+							isci->controllers[index].oem_parameters_version = oem_data->header.version;
+						}
+					}
+
+				/* No need to continue searching for another
+				 *  OROM that matches this PCI device, so return
+				 *  immediately.
+				 */
+				return;
+			}
+		}
+
+		offset += OROM_SIZE;
+	}
+}
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/isci_remote_device.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/isci_remote_device.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,298 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <dev/isci/isci.h>
+
+#include <cam/cam_periph.h>
+#include <cam/cam_xpt_periph.h>
+
+#include <dev/isci/scil/scif_task_request.h>
+#include <dev/isci/scil/scif_controller.h>
+#include <dev/isci/scil/scif_domain.h>
+#include <dev/isci/scil/scif_user_callback.h>
+
+#include <dev/isci/scil/scic_port.h>
+#include <dev/isci/scil/scic_phy.h>
+
+/**
+ * @brief This callback method informs the framework user that the remote
+ *        device is ready and capable of processing IO requests.
+ *
+ * @param[in]  controller This parameter specifies the controller object
+ *             with which this callback is associated.
+ * @param[in]  domain This parameter specifies the domain object with
+ *             which this callback is associated.
+ * @param[in]  remote_device This parameter specifies the device object with
+ *             which this callback is associated.
+ *
+ * @return none
+ */
+void
+scif_cb_remote_device_ready(SCI_CONTROLLER_HANDLE_T controller,
+    SCI_DOMAIN_HANDLE_T domain, SCI_REMOTE_DEVICE_HANDLE_T remote_device)
+{
+	struct ISCI_REMOTE_DEVICE *isci_remote_device =
+	    sci_object_get_association(remote_device);
+	struct ISCI_CONTROLLER *isci_controller =
+	    sci_object_get_association(controller);
+	uint32_t device_index = isci_remote_device->index;
+
+	if (isci_controller->remote_device[device_index] == NULL) {
+		/* This new device is now ready, so put it in the controller's
+		 *  remote device list so it is visible to CAM.
+		 */
+		isci_controller->remote_device[device_index] =
+		    isci_remote_device;
+
+		if (isci_controller->sim != NULL) {
+			/* The sim object is not NULL, meaning we have attached
+			 *  the controller to CAM already.  In that case, create
+			 *  a CCB to instruct CAM to rescan this device.
+			 * If the sim object is NULL, this device will get
+			 *  scanned as part of the initial scan when the
+			 *  controller is attached to CAM.
+			 */
+			union ccb *ccb = xpt_alloc_ccb_nowait();
+
+			xpt_create_path(&ccb->ccb_h.path, xpt_periph,
+			    cam_sim_path(isci_controller->sim),
+			    isci_remote_device->index, CAM_LUN_WILDCARD);
+
+			xpt_rescan(ccb);
+		}
+	}
+
+	isci_remote_device_release_device_queue(isci_remote_device);
+}
+
+/**
+ * @brief This callback method informs the framework user that the remote
+ *              device is not ready.  Thus, it is incapable of processing IO
+ *              requests.
+ *
+ * @param[in]  controller This parameter specifies the controller object
+ *             with which this callback is associated.
+ * @param[in]  domain This parameter specifies the domain object with
+ *             which this callback is associated.
+ * @param[in]  remote_device This parameter specifies the device object with
+ *             which this callback is associated.
+ *
+ * @return none
+ */
+void
+scif_cb_remote_device_not_ready(SCI_CONTROLLER_HANDLE_T controller,
+    SCI_DOMAIN_HANDLE_T domain, SCI_REMOTE_DEVICE_HANDLE_T remote_device)
+{
+
+}
+
+/**
+ * @brief This callback method informs the framework user that the remote
+ *        device failed.  This typically occurs shortly after the device
+ *        has been discovered, during the configuration phase for the device.
+ *
+ * @param[in]  controller This parameter specifies the controller object
+ *             with which this callback is associated.
+ * @param[in]  domain This parameter specifies the domain object with
+ *             which this callback is associated.
+ * @param[in]  remote_device This parameter specifies the device object with
+ *             which this callback is associated.
+ * @param[in]  status This parameter specifies the specific failure condition
+ *             associated with this device failure.
+ *
+ * @return none
+ */
+void
+scif_cb_remote_device_failed(SCI_CONTROLLER_HANDLE_T controller,
+    SCI_DOMAIN_HANDLE_T domain, SCI_REMOTE_DEVICE_HANDLE_T remote_device,
+    SCI_STATUS status)
+{
+
+}
+
+void
+isci_remote_device_reset(struct ISCI_REMOTE_DEVICE *remote_device,
+    union ccb *ccb)
+{
+	struct ISCI_CONTROLLER *controller = remote_device->domain->controller;
+	struct ISCI_REQUEST *request;
+	struct ISCI_TASK_REQUEST *task_request;
+	SCI_STATUS status;
+
+	if (remote_device->is_resetting == TRUE) {
+		/* device is already being reset, so return immediately */
+		return;
+	}
+
+	if (sci_pool_empty(controller->request_pool)) {
+		/* No requests are available in our request pool.  If this reset is tied
+		 *  to a CCB, ask CAM to requeue it.  Otherwise, we need to put it on our
+		 *  pending device reset list, so that the reset will occur when a request
+		 *  frees up.
+		 */
+		if (ccb == NULL)
+			sci_fast_list_insert_tail(
+			    &controller->pending_device_reset_list,
+			    &remote_device->pending_device_reset_element);
+		else {
+			ccb->ccb_h.status &= ~CAM_STATUS_MASK;
+			ccb->ccb_h.status |= CAM_REQUEUE_REQ;
+			xpt_done(ccb);
+		}
+		return;
+	}
+
+	isci_log_message(0, "ISCI",
+	    "Sending reset to device on controller %d domain %d CAM index %d\n",
+	    controller->index, remote_device->domain->index,
+	    remote_device->index
+	);
+
+	sci_pool_get(controller->request_pool, request);
+	task_request = (struct ISCI_TASK_REQUEST *)request;
+
+	task_request->parent.remote_device_handle = remote_device->sci_object;
+	task_request->ccb = ccb;
+
+	remote_device->is_resetting = TRUE;
+
+	status = (SCI_STATUS) scif_task_request_construct(
+	    controller->scif_controller_handle, remote_device->sci_object,
+	    SCI_CONTROLLER_INVALID_IO_TAG, (void *)task_request,
+	    (void *)((char*)task_request + sizeof(struct ISCI_TASK_REQUEST)),
+	    &task_request->sci_object);
+
+	if (status != SCI_SUCCESS) {
+		isci_task_request_complete(controller->scif_controller_handle,
+		    remote_device->sci_object, task_request->sci_object,
+		    status);
+		return;
+	}
+
+	status = (SCI_STATUS)scif_controller_start_task(
+	    controller->scif_controller_handle, remote_device->sci_object,
+	    task_request->sci_object, SCI_CONTROLLER_INVALID_IO_TAG);
+
+	if (status != SCI_SUCCESS) {
+		isci_task_request_complete(
+		    controller->scif_controller_handle,
+		    remote_device->sci_object, task_request->sci_object,
+		    status);
+		return;
+	}
+}
+
+uint32_t
+isci_remote_device_get_bitrate(struct ISCI_REMOTE_DEVICE *remote_device)
+{
+	struct ISCI_DOMAIN *domain = remote_device->domain;
+	struct ISCI_CONTROLLER *controller = domain->controller;
+	SCI_PORT_HANDLE_T port_handle;
+	SCIC_PORT_PROPERTIES_T port_properties;
+	uint8_t phy_index;
+	SCI_PHY_HANDLE_T phy_handle;
+	SCIC_PHY_PROPERTIES_T phy_properties;
+
+	/* get a handle to the port associated with this remote device's
+	 *  domain
+	 */
+	port_handle = scif_domain_get_scic_port_handle(domain->sci_object);
+	scic_port_get_properties(port_handle, &port_properties);
+
+	/* get the lowest numbered phy in the port */
+	phy_index = 0;
+	while ((port_properties.phy_mask != 0) &&
+	    !(port_properties.phy_mask & 0x1)) {
+
+		phy_index++;
+		port_properties.phy_mask >>= 1;
+	}
+
+	/* get the properties for the lowest numbered phy */
+	scic_controller_get_phy_handle(
+	    scif_controller_get_scic_handle(controller->scif_controller_handle),
+	    phy_index, &phy_handle);
+	scic_phy_get_properties(phy_handle, &phy_properties);
+
+	switch (phy_properties.negotiated_link_rate) {
+	case SCI_SAS_150_GB:
+		return (150000);
+	case SCI_SAS_300_GB:
+		return (300000);
+	case SCI_SAS_600_GB:
+		return (600000);
+	default:
+		return (0);
+	}
+}
+
+void
+isci_remote_device_freeze_lun_queue(struct ISCI_REMOTE_DEVICE *remote_device,
+    lun_id_t lun)
+{
+	if (!(remote_device->frozen_lun_mask & (1 << lun))) {
+		struct cam_path *path;
+
+		xpt_create_path(&path, xpt_periph,
+		    cam_sim_path(remote_device->domain->controller->sim),
+		    remote_device->index, lun);
+		xpt_freeze_devq(path, 1);
+		xpt_free_path(path);
+		remote_device->frozen_lun_mask |= (1 << lun);
+	}
+}
+
+void
+isci_remote_device_release_lun_queue(struct ISCI_REMOTE_DEVICE *remote_device,
+    lun_id_t lun)
+{
+	if (remote_device->frozen_lun_mask & (1 << lun)) {
+		struct cam_path *path;
+
+		xpt_create_path(&path, xpt_periph,
+		    cam_sim_path(remote_device->domain->controller->sim),
+		    remote_device->index, lun);
+		xpt_release_devq(path, 1, TRUE);
+		xpt_free_path(path);
+		remote_device->frozen_lun_mask &= ~(1 << lun);
+	}
+}
+
+void
+isci_remote_device_release_device_queue(
+    struct ISCI_REMOTE_DEVICE *remote_device)
+{
+	lun_id_t lun;
+	for (lun = 0; lun < ISCI_MAX_LUN; lun++)
+		isci_remote_device_release_lun_queue(remote_device, lun);
+}
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/isci_sysctl.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/isci_sysctl.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,229 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <dev/isci/isci.h>
+
+#include <sys/sysctl.h>
+
+#include <dev/isci/scil/scif_controller.h>
+#include <dev/isci/scil/scic_phy.h>
+
+static int
+isci_sysctl_coalesce_timeout(SYSCTL_HANDLER_ARGS)
+{
+	struct isci_softc *isci = (struct isci_softc *)arg1;
+	int error = sysctl_handle_int(oidp, &isci->coalesce_timeout, 0, req);
+	int i;
+
+	if (error)
+		return (error);
+
+	for (i = 0; i < isci->controller_count; i++)
+		scif_controller_set_interrupt_coalescence(
+		    isci->controllers[i].scif_controller_handle,
+		    isci->coalesce_number, isci->coalesce_timeout);
+
+	return (0);
+}
+
+static int
+isci_sysctl_coalesce_number(SYSCTL_HANDLER_ARGS)
+{
+	struct isci_softc *isci = (struct isci_softc *)arg1;
+	int error = sysctl_handle_int(oidp, &isci->coalesce_number, 0, req);
+	int i;
+
+	if (error)
+		return (error);
+
+	for (i = 0; i < isci->controller_count; i++)
+		scif_controller_set_interrupt_coalescence(
+		    isci->controllers[i].scif_controller_handle,
+		    isci->coalesce_number, isci->coalesce_timeout);
+
+	return (0);
+}
+
+static void
+isci_sysctl_reset_remote_devices(struct ISCI_CONTROLLER *controller,
+    uint32_t remote_devices_to_be_reset)
+{
+	uint32_t i = 0;
+
+	while (remote_devices_to_be_reset != 0) {
+		if (remote_devices_to_be_reset & 0x1) {
+			struct ISCI_REMOTE_DEVICE *remote_device =
+				controller->remote_device[i];
+
+			if (remote_device != NULL) {
+				mtx_lock(&controller->lock);
+				isci_remote_device_reset(remote_device, NULL);
+				mtx_unlock(&controller->lock);
+			}
+		}
+		remote_devices_to_be_reset >>= 1;
+		i++;
+	}
+}
+
+static int
+isci_sysctl_reset_remote_device_on_controller0(SYSCTL_HANDLER_ARGS)
+{
+	struct isci_softc *isci = (struct isci_softc *)arg1;
+	uint32_t remote_devices_to_be_reset = 0;
+	struct ISCI_CONTROLLER *controller = &isci->controllers[0];
+	int error = sysctl_handle_int(oidp, &remote_devices_to_be_reset, 0, req);
+
+	if (error || remote_devices_to_be_reset == 0)
+		return (error);
+
+	isci_sysctl_reset_remote_devices(controller, remote_devices_to_be_reset);
+
+	return (0);
+}
+
+static int
+isci_sysctl_reset_remote_device_on_controller1(SYSCTL_HANDLER_ARGS)
+{
+	struct isci_softc *isci = (struct isci_softc *)arg1;
+	uint32_t remote_devices_to_be_reset = 0;
+	struct ISCI_CONTROLLER *controller = &isci->controllers[1];
+	int error =
+	    sysctl_handle_int(oidp, &remote_devices_to_be_reset, 0, req);
+
+	if (error || remote_devices_to_be_reset == 0)
+		return (error);
+
+	isci_sysctl_reset_remote_devices(controller,
+	    remote_devices_to_be_reset);
+
+	return (0);
+}
+
+static void
+isci_sysctl_stop(struct ISCI_CONTROLLER *controller, uint32_t phy_to_be_stopped)
+{
+	SCI_PHY_HANDLE_T phy_handle = NULL;
+
+	scic_controller_get_phy_handle(
+	    scif_controller_get_scic_handle(controller->scif_controller_handle),
+	    phy_to_be_stopped, &phy_handle);
+
+	scic_phy_stop(phy_handle);
+}
+
+static int
+isci_sysctl_stop_phy(SYSCTL_HANDLER_ARGS)
+{
+	struct isci_softc *isci = (struct isci_softc *)arg1;
+	uint32_t phy_to_be_stopped = 0xff;
+	uint32_t controller_index, phy_index;
+	int error = sysctl_handle_int(oidp, &phy_to_be_stopped, 0, req);
+
+	controller_index = phy_to_be_stopped / SCI_MAX_PHYS;
+	phy_index = phy_to_be_stopped % SCI_MAX_PHYS;
+
+	if(error || controller_index >= isci->controller_count)
+		return (error);
+
+	isci_sysctl_stop(&isci->controllers[controller_index], phy_index);
+
+	return (0);
+}
+
+static void
+isci_sysctl_start(struct ISCI_CONTROLLER *controller,
+    uint32_t phy_to_be_started)
+{
+	SCI_PHY_HANDLE_T phy_handle = NULL;
+
+	scic_controller_get_phy_handle(
+	    scif_controller_get_scic_handle(controller->scif_controller_handle),
+	    phy_to_be_started, &phy_handle);
+
+	scic_phy_start(phy_handle);
+}
+
+static int
+isci_sysctl_start_phy(SYSCTL_HANDLER_ARGS)
+{
+	struct isci_softc *isci = (struct isci_softc *)arg1;
+	uint32_t phy_to_be_started = 0xff;
+	uint32_t controller_index, phy_index;
+	int error = sysctl_handle_int(oidp, &phy_to_be_started, 0, req);
+
+	controller_index = phy_to_be_started / SCI_MAX_PHYS;
+	phy_index = phy_to_be_started % SCI_MAX_PHYS;
+
+	if(error || controller_index >= isci->controller_count)
+		return error;
+
+	isci_sysctl_start(&isci->controllers[controller_index], phy_index);
+
+	return 0;
+}
+
+void isci_sysctl_initialize(struct isci_softc *isci)
+{
+	struct sysctl_ctx_list *sysctl_ctx = device_get_sysctl_ctx(isci->device);
+	struct sysctl_oid *sysctl_tree = device_get_sysctl_tree(isci->device);
+
+	SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO,
+	    "coalesce_timeout", CTLTYPE_UINT | CTLFLAG_RW, isci, 0,
+	    isci_sysctl_coalesce_timeout, "IU",
+	    "Interrupt coalescing timeout (in microseconds)");
+
+	SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO,
+	    "coalesce_number", CTLTYPE_UINT | CTLFLAG_RW, isci, 0,
+	    isci_sysctl_coalesce_number, "IU",
+	    "Interrupt coalescing number");
+
+	SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO,
+	    "reset_remote_device_on_controller0", CTLTYPE_UINT| CTLFLAG_RW,
+	    isci, 0, isci_sysctl_reset_remote_device_on_controller0, "IU",
+	    "Reset remote device on controller 0");
+
+	SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO,
+	    "reset_remote_device_on_controller1", CTLTYPE_UINT| CTLFLAG_RW,
+	    isci, 0, isci_sysctl_reset_remote_device_on_controller1, "IU",
+	    "Reset remote device on controller 1");
+
+	SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO,
+	    "stop_phy", CTLTYPE_UINT| CTLFLAG_RW, isci, 0, isci_sysctl_stop_phy,
+	    "IU", "Stop PHY on a controller");
+
+	SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO,
+	    "start_phy", CTLTYPE_UINT| CTLFLAG_RW, isci, 0,
+	    isci_sysctl_start_phy, "IU", "Start PHY on a controller");
+}
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/isci_task_request.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/isci_task_request.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,258 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <dev/isci/isci.h>
+
+#include <dev/isci/scil/scif_controller.h>
+#include <dev/isci/scil/scif_user_callback.h>
+
+/**
+ * @brief This user callback will inform the user that a task management
+ *        request completed.
+ *
+ * @param[in]  controller This parameter specifies the controller on
+ *             which the task management request is completing.
+ * @param[in]  remote_device This parameter specifies the remote device on
+ *             which this task management request is completing.
+ * @param[in]  task_request This parameter specifies the task management
+ *             request that has completed.
+ * @param[in]  completion_status This parameter specifies the results of
+ *             the IO request operation.  SCI_TASK_SUCCESS indicates
+ *             successful completion.
+ *
+ * @return none
+ */
+void
+scif_cb_task_request_complete(SCI_CONTROLLER_HANDLE_T controller,
+    SCI_REMOTE_DEVICE_HANDLE_T remote_device,
+    SCI_TASK_REQUEST_HANDLE_T task_request, SCI_TASK_STATUS completion_status)
+{
+
+	scif_controller_complete_task(controller, remote_device, task_request);
+	isci_task_request_complete(controller, remote_device, task_request,
+	    completion_status);
+}
+
+/**
+ * @brief This method returns the Logical Unit to be utilized for this
+ *        task management request.
+ *
+ * @note The contents of the value returned from this callback are defined
+ *       by the protocol standard (e.g. T10 SAS specification).  Please
+ *       refer to the transport task information unit description
+ *       in the associated standard.
+ *
+ * @param[in] scif_user_task_request This parameter points to the user's
+ *            task request object.  It is a cookie that allows the user to
+ *            provide the necessary information for this callback.
+ *
+ * @return This method returns the LUN associated with this request.
+ * @todo This should be U64?
+ */
+uint32_t
+scif_cb_task_request_get_lun(void * scif_user_task_request)
+{
+
+	/* Currently we are only doing hard resets, not LUN resets.  So
+	 *  always returning 0 is OK here, since LUN doesn't matter for
+	 *  a hard device reset.
+	 */
+	return (0);
+}
+
+/**
+ * @brief This method returns the task management function to be utilized
+ *        for this task request.
+ *
+ * @note The contents of the value returned from this callback are defined
+ *       by the protocol standard (e.g. T10 SAS specification).  Please
+ *       refer to the transport task information unit description
+ *       in the associated standard.
+ *
+ * @param[in] scif_user_task_request This parameter points to the user's
+ *            task request object.  It is a cookie that allows the user to
+ *            provide the necessary information for this callback.
+ *
+ * @return This method returns an unsigned byte representing the task
+ *         management function to be performed.
+ */
+uint8_t scif_cb_task_request_get_function(void * scif_user_task_request)
+{
+	/* SCIL supports many types of task management functions, but this
+	 *  driver only uses HARD_RESET.
+	 */
+	return (SCI_SAS_HARD_RESET);
+}
+
+/**
+ * @brief This method returns the task management IO tag to be managed.
+ *        Depending upon the task management function the value returned
+ *        from this method may be ignored.
+ *
+ * @param[in] scif_user_task_request This parameter points to the user's
+ *            task request object.  It is a cookie that allows the user to
+ *            provide the necessary information for this callback.
+ *
+ * @return This method returns an unsigned 16-bit word depicting the IO
+ *         tag to be managed.
+ */
+uint16_t
+scif_cb_task_request_get_io_tag_to_manage(void * scif_user_task_request)
+{
+
+	return (0);
+}
+
+/**
+ * @brief This callback method asks the user to provide the virtual
+ *        address of the response data buffer for the supplied IO request.
+ *
+ * @param[in] scif_user_task_request This parameter points to the user's
+ *            task request object.  It is a cookie that allows the user to
+ *            provide the necessary information for this callback.
+ *
+ * @return This method returns the virtual address for the response data buffer
+ *         associated with this IO request.
+ */
+void *
+scif_cb_task_request_get_response_data_address(void * scif_user_task_request)
+{
+	struct ISCI_TASK_REQUEST *task_request =
+	    (struct ISCI_TASK_REQUEST *)scif_user_task_request;
+
+	return (&task_request->sense_data);
+}
+
+/**
+ * @brief This callback method asks the user to provide the length of the
+ *        response data buffer for the supplied IO request.
+ *
+ * @param[in] scif_user_task_request This parameter points to the user's
+ *            task request object.  It is a cookie that allows the user to
+ *            provide the necessary information for this callback.
+ *
+ * @return This method returns the length of the response buffer data
+ *         associated with this IO request.
+ */
+uint32_t
+scif_cb_task_request_get_response_data_length(void * scif_user_task_request)
+{
+
+	return (sizeof(struct scsi_sense_data));
+}
+
+void
+isci_task_request_complete(SCI_CONTROLLER_HANDLE_T scif_controller,
+    SCI_REMOTE_DEVICE_HANDLE_T remote_device,
+    SCI_TASK_REQUEST_HANDLE_T task_request, SCI_TASK_STATUS completion_status)
+{
+	struct ISCI_TASK_REQUEST *isci_task_request =
+		(struct ISCI_TASK_REQUEST *)sci_object_get_association(task_request);
+	struct ISCI_CONTROLLER *isci_controller =
+		(struct ISCI_CONTROLLER *)sci_object_get_association(scif_controller);
+	struct ISCI_REMOTE_DEVICE *isci_remote_device =
+		(struct ISCI_REMOTE_DEVICE *)sci_object_get_association(remote_device);
+	struct ISCI_REMOTE_DEVICE *pending_remote_device;
+	BOOL retry_task = FALSE;
+	union ccb *ccb = isci_task_request->ccb;
+
+	isci_remote_device->is_resetting = FALSE;
+
+	switch (completion_status) {
+	case SCI_TASK_SUCCESS:
+	case SCI_TASK_FAILURE_RESPONSE_VALID:
+		break;
+
+	case SCI_TASK_FAILURE_INVALID_STATE:
+	case SCI_TASK_FAILURE_INSUFFICIENT_RESOURCES:
+	case SCI_FAILURE_TIMEOUT:
+		retry_task = TRUE;
+		isci_log_message(0, "ISCI",
+		    "unhandled task completion code 0x%x\n", completion_status);
+		break;
+
+	case SCI_TASK_FAILURE:
+	case SCI_TASK_FAILURE_UNSUPPORTED_PROTOCOL:
+	case SCI_TASK_FAILURE_INVALID_TAG:
+	case SCI_TASK_FAILURE_CONTROLLER_SPECIFIC_ERR:
+	case SCI_TASK_FAILURE_TERMINATED:
+	case SCI_TASK_FAILURE_INVALID_PARAMETER_VALUE:
+		isci_log_message(0, "ISCI",
+		    "unhandled task completion code 0x%x\n", completion_status);
+		break;
+
+	default:
+		isci_log_message(0, "ISCI",
+		    "unhandled task completion code 0x%x\n", completion_status);
+		break;
+	}
+
+	if (isci_controller->is_frozen == TRUE) {
+		isci_controller->is_frozen = FALSE;
+		xpt_release_simq(isci_controller->sim, TRUE);
+	}
+
+	sci_pool_put(isci_controller->request_pool,
+	    (struct ISCI_REQUEST *)isci_task_request);
+
+	/* Make sure we release the device queue, since it may have been frozen
+	 *  if someone tried to start an I/O while the task was in progress.
+	 */
+	isci_remote_device_release_device_queue(isci_remote_device);
+
+	if (retry_task == TRUE)
+		isci_remote_device_reset(isci_remote_device, ccb);
+	else {
+		pending_remote_device = sci_fast_list_remove_head(
+		    &isci_controller->pending_device_reset_list);
+
+		if (pending_remote_device != NULL) {
+			/* Any resets that were triggered from an XPT_RESET_DEV
+			 *  CCB are never put in the pending list if the request
+			 *  pool is empty - they are given back to CAM to be
+			 *  requeued.  So we will alawys pass NULL here,
+			 *  denoting that there is no CCB associated with the
+			 *  device reset.
+			 */
+			isci_remote_device_reset(pending_remote_device, NULL);
+		} else if (ccb != NULL) {
+			/* There was a CCB associated with this reset, so mark
+			 *  it complete and return it to CAM.
+			 */
+			ccb->ccb_h.status &= ~CAM_STATUS_MASK;
+			ccb->ccb_h.status |= CAM_REQ_CMP;
+			xpt_done(ccb);
+		}
+	}
+}
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/isci_timer.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/isci_timer.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,166 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <dev/isci/isci.h>
+
+#include <dev/isci/scil/scif_user_callback.h>
+
+static void
+isci_timer_timeout(void *arg)
+{
+	struct ISCI_TIMER *timer = (struct ISCI_TIMER *)arg;
+
+	isci_log_message(3, "TIMER", "timeout %p\n", timer);
+
+	/* callout_stop() will *not* keep the timer from running if it is
+	 *  pending.  callout_drain() cannot be called from interrupt context,
+	 *  because it may cause thread to sleep which is not allowed in
+	 *  interrupt context.  So instead, check the is_started flag to see if
+	 *  the timer routine should actually be run or not.
+	 */
+	if (timer->is_started == TRUE)
+		timer->callback(timer->cookie);
+}
+
+/**
+ * @brief This callback method asks the user to start the supplied timer.
+ *
+ * @warning All timers in the system started by the SCI Framework are one
+ *          shot timers.  Therefore, the SCI user should make sure that it
+ *          removes the timer from it's list when a timer actually fires.
+ *          Additionally, SCI Framework user's should be able to handle
+ *          calls from the SCI Framework to stop a timer that may already
+ *          be stopped.
+ *
+ * @param[in]  controller This parameter specifies the controller with
+ *             which this timer is to associated.
+ * @param[in]  timer This parameter specifies the timer to be started.
+ * @param[in]  milliseconds This parameter specifies the number of
+ *             milliseconds for which to stall.  The operating system driver
+ *             is allowed to round this value up where necessary.
+ *
+ * @return none
+ */
+void
+scif_cb_timer_start(SCI_CONTROLLER_HANDLE_T controller, void *timer,
+    uint32_t milliseconds)
+{
+	struct ISCI_TIMER *isci_timer = (struct ISCI_TIMER *)timer;
+
+	isci_timer->is_started = TRUE;
+	isci_log_message(3, "TIMER", "start %p %d\n", timer, milliseconds);
+	callout_reset(&isci_timer->callout, (milliseconds * hz)/1000,
+	    isci_timer_timeout, timer);
+}
+
+/**
+ * @brief This callback method asks the user to stop the supplied timer.
+ *
+ * @param[in]  controller This parameter specifies the controller with
+ *             which this timer is to associated.
+ * @param[in]  timer This parameter specifies the timer to be stopped.
+ *
+ * @return none
+ */
+void
+scif_cb_timer_stop(SCI_CONTROLLER_HANDLE_T controller, void *timer)
+{
+	struct ISCI_TIMER *isci_timer = (struct ISCI_TIMER *)timer;
+
+	isci_log_message(3, "TIMER", "stop %p\n", timer);
+	isci_timer->is_started = FALSE;
+	callout_stop(&isci_timer->callout);
+}
+
+/**
+ * @brief This callback method asks the user to create a timer and provide
+ *        a handle for this timer for use in further timer interactions.
+ *
+ * @warning The "timer_callback" method should be executed in a mutually
+ *          exlusive manner from the controller completion handler
+ *          handler (refer to scic_controller_get_handler_methods()).
+ *
+ * @param[in]  timer_callback This parameter specifies the callback method
+ *             to be invoked whenever the timer expires.
+ * @param[in]  controller This parameter specifies the controller with
+ *             which this timer is to be associated.
+ * @param[in]  cookie This parameter specifies a piece of information that
+ *             the user must retain.  This cookie is to be supplied by the
+ *             user anytime a timeout occurs for the created timer.
+ *
+ * @return This method returns a handle to a timer object created by the
+ *         user.  The handle will be utilized for all further interactions
+ *         relating to this timer.
+ */
+void *
+scif_cb_timer_create(SCI_CONTROLLER_HANDLE_T scif_controller,
+    SCI_TIMER_CALLBACK_T timer_callback, void *cookie)
+{
+	struct ISCI_CONTROLLER *isci_controller = (struct ISCI_CONTROLLER *)
+	    sci_object_get_association(scif_controller);
+	struct ISCI_TIMER *timer;
+
+	sci_pool_get(isci_controller->timer_pool, timer);
+
+	callout_init_mtx(&timer->callout, &isci_controller->lock, FALSE);
+
+	timer->callback = timer_callback;
+	timer->cookie = cookie;
+	timer->is_started = FALSE;
+
+	isci_log_message(3, "TIMER", "create %p %p %p\n", timer, timer_callback, cookie);
+
+	return (timer);
+}
+
+/**
+ * @brief This callback method asks the user to destory the supplied timer.
+ *
+ * @param[in]  controller This parameter specifies the controller with
+ *             which this timer is to associated.
+ * @param[in]  timer This parameter specifies the timer to be destroyed.
+ *
+ * @return none
+ */
+void
+scif_cb_timer_destroy(SCI_CONTROLLER_HANDLE_T scif_controller,
+    void *timer_handle)
+{
+	struct ISCI_CONTROLLER *isci_controller = (struct ISCI_CONTROLLER *)
+	    sci_object_get_association(scif_controller);
+
+	scif_cb_timer_stop(scif_controller, timer_handle);
+	sci_pool_put(isci_controller->timer_pool, (struct ISCI_TIMER *)timer_handle);
+
+	isci_log_message(3, "TIMER", "destroy %p\n", timer_handle);
+}
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/sci_environment.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/sci_environment.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,1 @@
+/* empty file for now. compiler needs it */
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/intel_ata.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/intel_ata.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,654 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+/**
+ * @file
+ * @brief This file defines all of the ATA related constants, enumerations,
+ *        and types.  Please note that this file does not necessarily contain
+ *        an exhaustive list of all constants, commands, sub-commands, etc.
+ */
+
+#ifndef _ATA_H_
+#define _ATA_H_
+
+#include <dev/isci/types.h>
+
+/**
+ * @name ATA_COMMAND_CODES
+ *
+ * These constants depict the various ATA command codes defined
+ * in the ATA/ATAPI specification.
+ */
+/*@{*/
+#define ATA_IDENTIFY_DEVICE            0xEC
+#define ATA_CHECK_POWER_MODE           0xE5
+#define ATA_STANDBY                    0xE2
+#define ATA_STANDBY_IMMED              0xE0
+#define ATA_IDLE_IMMED                 0xE1
+#define ATA_IDLE                       0xE3
+#define ATA_FLUSH_CACHE                0xE7
+#define ATA_FLUSH_CACHE_EXT            0xEA
+#define ATA_READ_DMA_EXT               0x25
+#define ATA_READ_DMA                   0xC8
+#define ATA_READ_SECTORS_EXT           0x24
+#define ATA_READ_SECTORS               0x20
+#define ATA_WRITE_DMA_EXT              0x35
+#define ATA_WRITE_DMA                  0xCA
+#define ATA_WRITE_SECTORS_EXT          0x34
+#define ATA_WRITE_SECTORS              0x30
+#define ATA_WRITE_UNCORRECTABLE        0x45
+#define ATA_READ_VERIFY_SECTORS        0x40
+#define ATA_READ_VERIFY_SECTORS_EXT    0x42
+#define ATA_READ_BUFFER                0xE4
+#define ATA_WRITE_BUFFER               0xE8
+#define ATA_EXECUTE_DEVICE_DIAG        0x90
+#define ATA_SET_FEATURES               0xEF
+#define ATA_SMART                      0xB0
+#define ATA_PACKET_IDENTIFY            0xA1
+#define ATA_PACKET                     0xA0
+#define ATA_READ_FPDMA                 0x60
+#define ATA_WRITE_FPDMA                0x61
+#define ATA_READ_LOG_EXT               0x2F
+#define ATA_NOP                        0x00
+#define ATA_DEVICE_RESET               0x08
+#define ATA_MEDIA_EJECT                0xED
+#define ATA_SECURITY_UNLOCK            0xF2
+#define ATA_SECURITY_FREEZE_LOCK       0xF5
+#define ATA_DATA_SET_MANAGEMENT        0x06
+#define ATA_DOWNLOAD_MICROCODE         0x92
+#define ATA_WRITE_STREAM_DMA_EXT       0x3A
+#define ATA_READ_LOG_DMA_EXT           0x47
+#define ATA_READ_STREAM_DMA_EXT        0x2A
+#define ATA_WRITE_DMA_FUA              0x3D
+#define ATA_WRITE_LOG_DMA_EXT          0x57
+#define ATA_READ_DMA_QUEUED            0xC7
+#define ATA_READ_DMA_QUEUED_EXT        0x26
+#define ATA_WRITE_DMA_QUEUED           0xCC
+#define ATA_WRITE_DMA_QUEUED_EXT       0x36
+#define ATA_WRITE_DMA_QUEUED_FUA_EXT   0x3E
+#define ATA_READ_MULTIPLE              0xC4
+#define ATA_READ_MULTIPLE_EXT          0x29
+#define ATA_WRITE_MULTIPLE             0xC5
+#define ATA_WRITE_MULTIPLE_EXT         0x39
+#define ATA_WRITE_MULTIPLE_FUA_EXT     0xCE
+
+
+/*@}*/
+
+/**
+ * @name ATA_SMART_SUB_COMMAND_CODES
+ *
+ * These constants define the ATA SMART command sub-codes that can be
+ * executed.
+ */
+/*@{*/
+#define ATA_SMART_SUB_CMD_ENABLE        0xD8
+#define ATA_SMART_SUB_CMD_DISABLE       0xD9
+#define ATA_SMART_SUB_CMD_RETURN_STATUS 0xDA
+#define ATA_SMART_SUB_CMD_READ_LOG      0xD5
+/*@}*/
+
+/**
+ * @name ATA_SET_FEATURES_SUB_COMMAND_CODES
+ *
+ * These constants define the ATA SET FEATURES command sub-codes that can
+ * be executed.
+ */
+/*@{*/
+#define ATA_SET_FEATURES_SUB_CMD_ENABLE_CACHE       0x02
+#define ATA_SET_FEATURES_SUB_CMD_DISABLE_CACHE      0x82
+#define ATA_SET_FEATURES_SUB_CMD_DISABLE_READ_AHEAD 0x55
+#define ATA_SET_FEATURES_SUB_CMD_ENABLE_READ_AHEAD  0xAA
+#define ATA_SET_FEATURES_SUB_CMD_SET_TRANSFER_MODE  0x3
+/*@}*/
+
+/**
+ * @name ATA_READ_LOG_EXT_PAGE_CODES
+ *
+ * This is a list of log page codes available for use.
+ */
+/*@{*/
+#define ATA_LOG_PAGE_NCQ_ERROR                  0x10
+#define ATA_LOG_PAGE_SMART_SELF_TEST            0x06
+#define ATA_LOG_PAGE_EXTENDED_SMART_SELF_TEST   0x07
+/*@}*/
+
+/**
+ * @name ATA_LOG_PAGE_NCQ_ERROR_CONSTANTS
+ *
+ * These constants define standard values for use when requesting the NCQ
+ * error log page.
+ */
+/*@{*/
+#define ATA_LOG_PAGE_NCQ_ERROR_SECTOR        0
+#define ATA_LOG_PAGE_NCQ_ERROR_SECTOR_COUNT  1
+/*@}*/
+
+/**
+ * @name ATA_STATUS_REGISTER_BITS
+ *
+ * The following are status register bit definitions per ATA/ATAPI-7.
+ */
+/*@{*/
+#define ATA_STATUS_REG_BSY_BIT          0x80
+#define ATA_STATUS_REG_DEVICE_FAULT_BIT 0x20
+#define ATA_STATUS_REG_ERROR_BIT        0x01
+/*@}*/
+
+/**
+ * @name ATA_ERROR_REGISTER_BITS
+ *
+ * The following are error register bit definitions per ATA/ATAPI-7.
+ */
+/*@{*/
+#define ATA_ERROR_REG_NO_MEDIA_BIT              0x02
+#define ATA_ERROR_REG_ABORT_BIT                 0x04
+#define ATA_ERROR_REG_MEDIA_CHANGE_REQUEST_BIT  0x08
+#define ATA_ERROR_REG_ID_NOT_FOUND_BIT          0x10
+#define ATA_ERROR_REG_MEDIA_CHANGE_BIT          0x20
+#define ATA_ERROR_REG_UNCORRECTABLE_BIT         0x40
+#define ATA_ERROR_REG_WRITE_PROTECTED_BIT       0x40
+#define ATA_ERROR_REG_ICRC_BIT                  0x80
+/*@}*/
+
+/**
+ * @name ATA_CONTROL_REGISTER_BITS
+ *
+ * The following are control register bit definitions per ATA/ATAPI-7
+ */
+/*@{*/
+#define ATA_CONTROL_REG_INTERRUPT_ENABLE_BIT 0x02
+#define ATA_CONTROL_REG_SOFT_RESET_BIT       0x04
+#define ATA_CONTROL_REG_HIGH_ORDER_BYTE_BIT  0x80
+/*@}*/
+
+/**
+ * @name ATA_DEVICE_HEAD_REGISTER_BITS
+ *
+ * The following are device/head register bit definitions per ATA/ATAPI-7.
+ */
+/*@{*/
+#define ATA_DEV_HEAD_REG_LBA_MODE_ENABLE  0x40
+#define ATA_DEV_HEAD_REG_FUA_ENABLE       0x80
+/*@}*/
+
+/**
+ * @name ATA_IDENTIFY_DEVICE_FIELD_LENGTHS
+ *
+ * The following constants define the number of bytes contained in various
+ * fields found in the IDENTIFY DEVICE data structure.
+ */
+/*@{*/
+#define ATA_IDENTIFY_SERIAL_NUMBER_LEN        20
+#define ATA_IDENTIFY_MODEL_NUMBER_LEN         40
+#define ATA_IDENTIFY_FW_REVISION_LEN          8
+#define ATA_IDENTIFY_48_LBA_LEN               8
+#define ATA_IDENTIFY_MEDIA_SERIAL_NUMBER_LEN  30
+#define ATA_IDENTIFY_WWN_LEN                  8
+/*@}*/
+
+/**
+ * @name ATA_IDENTIFY_DEVICE_FIELD_MASKS
+ *
+ * The following constants define bit masks utilized to determine if a
+ * feature is supported/enabled or if a bit is simply set inside of the
+ * IDENTIFY DEVICE data structre.
+ */
+/*@{*/
+#define ATA_IDENTIFY_REMOVABLE_MEDIA_ENABLE              0x0080
+#define ATA_IDENTIFY_CAPABILITIES1_NORMAL_DMA_ENABLE     0x0100
+#define ATA_IDENTIFY_CAPABILITIES1_STANDBY_ENABLE        0x2000
+#define ATA_IDENTIFY_COMMAND_SET_SUPPORTED0_SMART_ENABLE 0x0001
+#define ATA_IDENTIFY_COMMAND_SET_SUPPORTED1_48BIT_ENABLE 0x0400
+#define ATA_IDENTIFY_COMMAND_SET_WWN_SUPPORT_ENABLE      0x0100
+#define ATA_IDENTIFY_COMMAND_SET_ENABLED0_SMART_ENABLE   0x0001
+#define ATA_IDENTIFY_SATA_CAPABILITIES_NCQ_ENABLE        0x0100
+#define ATA_IDENTIFY_NCQ_QUEUE_DEPTH_ENABLE              0x001F
+#define ATA_IDENTIFY_SECTOR_LARGER_THEN_512_ENABLE       0x0100
+#define ATA_IDENTIFY_LOGICAL_SECTOR_PER_PHYSICAL_SECTOR_MASK   0x000F
+#define ATA_IDENTIFY_LOGICAL_SECTOR_PER_PHYSICAL_SECTOR_ENABLE 0x2000
+#define ATA_IDENTIFY_WRITE_UNCORRECTABLE_SUPPORT         0x0004
+#define ATA_IDENTIFY_COMMAND_SET_SMART_SELF_TEST_SUPPORTED     0x0002
+#define ATA_IDENTIFY_COMMAND_SET_DSM_TRIM_SUPPORTED            0x0001
+#define ATA_IDENTIFY_COMMAND_ADDL_SUPPORTED_DETERMINISTIC_READ 0x4000
+#define ATA_IDENTIFY_COMMAND_ADDL_SUPPORTED_READ_ZERO          0x0020
+/*@}*/
+
+/**
+ * @name ATAPI_IDENTIFY_DEVICE_FIELD_MASKS
+ *
+ * These constants define the various bit definitions for the
+ * fields in the PACKET IDENTIFY DEVICE data structure.
+ */
+/*@{*/
+#define ATAPI_IDENTIFY_16BYTE_CMD_PCKT_ENABLE       0x01
+/*@}*/
+
+/**
+ * @name ATA_PACKET_FEATURE_BITS
+ *
+ * These constants define the various bit definitions for the
+ * ATA PACKET feature register.
+ */
+/*@{*/
+#define ATA_PACKET_FEATURE_DMA     0x01
+#define ATA_PACKET_FEATURE_OVL     0x02
+#define ATA_PACKET_FEATURE_DMADIR  0x04
+/*@}*/
+
+/**
+ * @name ATA_Device_Power_Mode_Values
+ *
+ * These constants define the power mode values returned by
+ * ATA_Check_Power_Mode
+ */
+/*@{*/
+#define ATA_STANDBY_POWER_MODE    0x00
+#define ATA_IDLE_POWER_MODE       0x80
+#define ATA_ACTIVE_POWER_MODE     0xFF
+/*@}*/
+
+/**
+ * @name ATA_WRITE_UNCORRECTIABLE feature field values
+ *
+ * These constants define the Write Uncorrectable feature values
+ * used with the SATI translation.
+ */
+/*@{*/
+#define ATA_WRITE_UNCORRECTABLE_PSUEDO    0x55
+#define ATA_WRITE_UNCORRECTABLE_FLAGGED   0xAA
+/*@}*/
+
+
+
+/**
+ * @name ATA_SECURITY_STATUS field values
+ *
+ * These constants define the mask of the securityStatus field and the various bits within it
+ */
+/*@{*/
+#define ATA_SECURITY_STATUS_SUPPORTED      0x0001
+#define ATA_SECURITY_STATUS_ENABLED        0x0002
+#define ATA_SECURITY_STATUS_LOCKED         0x0004
+#define ATA_SECURITY_STATUS_FROZEN         0x0008
+#define ATA_SECURITY_STATUS_EXPIRED        0x0010
+#define ATA_SECURITY_STATUS_ERASESUPPORTED 0x0020
+#define ATA_SECURITY_STATUS_RESERVED       0xFEC0
+#define ATA_SECURITY_STATUS_SECURITYLEVEL  0x0100
+/*@}*/
+
+/**
+ * @struct ATA_IDENTIFY_DEVICE
+ *
+ * @brief This structure depicts the ATA IDENTIFY DEVICE data format.
+ */
+typedef struct ATA_IDENTIFY_DEVICE_DATA
+{
+   U16   general_config_bits;                             // word  00
+   U16   obsolete0;                                       // word  01 (num cylinders)
+   U16   vendor_specific_config_bits;                     // word  02
+   U16   obsolete1;                                       // word  03 (num heads)
+   U16   retired1[2];                                     // words 04-05
+   U16   obsolete2;                                       // word  06 (sectors / track)
+   U16   reserved_for_compact_flash1[2];                  // words 07-08
+   U16   retired0;                                        // word  09
+   U8    serial_number[ATA_IDENTIFY_SERIAL_NUMBER_LEN];   // word 10-19
+   U16   retired2[2];                                     // words 20-21
+   U16   obsolete4;                                       // word  22
+   U8    firmware_revision[ATA_IDENTIFY_FW_REVISION_LEN]; // words 23-26
+   U8    model_number[ATA_IDENTIFY_MODEL_NUMBER_LEN];     // words 27-46
+   U16   max_sectors_per_multiple;                        // word  47
+   U16   reserved0;                                       // word  48
+   U16   capabilities1;                                   // word  49
+   U16   capabilities2;                                   // word  50
+   U16   obsolete5[2];                                    // words 51-52
+   U16   validity_bits;                                   // word  53
+   U16   obsolete6[5];                                    // words 54-58 Used to be:
+                                                          // current cylinders,
+                                                          // current heads,
+                                                          // current sectors/Track,
+                                                          // current capacity
+   U16   current_max_sectors_per_multiple;                // word  59
+   U8    total_num_sectors[4];                            // words 60-61
+   U16   obsolete7;                                       // word  62
+   U16   multi_word_dma_mode;                             // word  63
+   U16   pio_modes_supported;                             // word  64
+   U16   min_multiword_dma_transfer_cycle;                // word  65
+   U16   rec_min_multiword_dma_transfer_cycle;            // word  66
+   U16   min_pio_transfer_no_flow_ctrl;                   // word  67
+   U16   min_pio_transfer_with_flow_ctrl;                 // word  68
+   U16   additional_supported;                            // word  69
+   U16   reserved1;                                       // word  70
+   U16   reserved2[4];                                    // words 71-74
+   U16   queue_depth;                                     // word  75
+   U16   serial_ata_capabilities;                         // word  76
+   U16   serial_ata_reserved;                             // word  77
+   U16   serial_ata_features_supported;                   // word  78
+   U16   serial_ata_features_enabled;                     // word  79
+   U16   major_version_number;                            // word  80
+   U16   minor_version_number;                            // word  81
+   U16   command_set_supported0;                          // word  82
+   U16   command_set_supported1;                          // word  83
+   U16   command_set_supported_extention;                 // word  84
+   U16   command_set_enabled0;                            // word  85
+   U16   command_set_enabled1;                            // word  86
+   U16   command_set_default;                             // word  87
+   U16   ultra_dma_mode;                                  // word  88
+   U16   security_erase_completion_time;                  // word  89
+   U16   enhanced_security_erase_time;                    // word  90
+   U16   current_power_mgmt_value;                        // word  91
+   U16   master_password_revision;                        // word  92
+   U16   hardware_reset_result;                           // word  93
+   U16   current_acoustic_management_value;               // word  94
+   U16   stream_min_request_size;                         // word  95
+   U16   stream_transfer_time;                            // word  96
+   U16   stream_access_latency;                           // word  97
+   U16   stream_performance_granularity[2];               // words 98-99
+   U8    max_48bit_lba[ATA_IDENTIFY_48_LBA_LEN];          // words 100-103
+   U16   streaming_transfer_time;                         // word  104
+   U16   max_lba_range_entry_blocks;                      // word  105
+   U16   physical_logical_sector_info;                    // word  106
+   U16   acoustic_test_interseek_delay;                   // word  107
+   U8    world_wide_name[ATA_IDENTIFY_WWN_LEN];           // words 108-111
+   U8    reserved_for_wwn_extention[ATA_IDENTIFY_WWN_LEN];// words 112-115
+   U16   reserved4;                                       // word  116
+   U8    words_per_logical_sector[4];                     // words 117-118
+   U16   command_set_supported2;                          // word  119
+   U16   reserved5[7];                                    // words 120-126
+   U16   removable_media_status;                          // word  127
+   U16   security_status;                                 // word  128
+   U16   vendor_specific1[31];                            // words 129-159
+   U16   cfa_power_mode1;                                 // word  160
+   U16   reserved_for_compact_flash2[7];                  // words 161-167
+   U16   device_nominal_form_factor;                      // word  168
+   U16   data_set_management;                             // word  169
+   U16   reserved_for_compact_flash3[6];                  // words 170-175
+   U16   current_media_serial_number[ATA_IDENTIFY_MEDIA_SERIAL_NUMBER_LEN];//words 176-205
+   U16   reserved6[3];                                    // words 206-208
+   U16   logical_sector_alignment;                        // words 209
+   U16   reserved7[7];                                    // words 210-216
+   U16   nominal_media_rotation_rate;                     // word  217
+   U16   reserved8[16];                                   // words 218-233
+   U16   min_num_blocks_per_microcode;                    // word  234
+   U16   max_num_blocks_per_microcode;                    // word  235
+   U16   reserved9[19];                                   // words 236-254
+   U16   integrity_word;                                  // word  255
+
+} ATA_IDENTIFY_DEVICE_DATA_T;
+
+#define ATA_IDENTIFY_DEVICE_GET_OFFSET(field_name) \
+   ((POINTER_UINT)&(((ATA_IDENTIFY_DEVICE_DATA_T*)0)->field_name))
+#define ATA_IDENTIFY_DEVICE_WCE_ENABLE  0x20
+#define ATA_IDENTIFY_DEVICE_RA_ENABLE   0x40
+
+/**
+ * @struct ATAPI_IDENTIFY_PACKET_DATA
+ *
+ * @brief The following structure depicts the ATA-ATAPI 7 version of the
+ *        IDENTIFY PACKET DEVICE data structure.
+ */
+typedef struct ATAPI_IDENTIFY_PACKET_DEVICE
+{
+   U16   generalConfigBits;                      // word  00
+   U16   reserved0;                              // word  01 (num cylinders)
+   U16   uniqueConfigBits;                       // word  02
+   U16   reserved1[7];                           // words 03 - 09
+   U8    serialNumber[ATA_IDENTIFY_SERIAL_NUMBER_LEN];  // word 10-19
+   U16   reserved2[3];                           // words 20-22
+   U8    firmwareRevision[ATA_IDENTIFY_FW_REVISION_LEN];// words 23-26
+   U8    modelNumber[ATA_IDENTIFY_MODEL_NUMBER_LEN];    // words 27-46
+   U16   reserved4[2];                           // words 47-48
+   U16   capabilities1;                          // word  49
+   U16   capabilities2;                          // word  50
+   U16   obsolete0[2];                           // words 51-52
+   U16   validityBits;                           // word  53
+   U16   reserved[8];                            // words 54-61
+
+   U16   DMADIRBitRequired;                      // word  62, page2
+   U16   multiWordDmaMode;                       // word  63
+   U16   pioModesSupported;                      // word  64
+   U16   minMultiwordDmaTransferCycle;           // word  65
+   U16   recMinMultiwordDmaTransferCycle;        // word  66
+   U16   minPioTransferNoFlowCtrl;               // word  67
+   U16   minPioTransferWithFlowCtrl;             // word  68
+   U16   reserved6[2];                           // words 69-70
+   U16   nsFromPACKETReceiptToBusRelease;        // word  71
+   U16   nsFromSERVICEReceiptToBSYreset;         // wore  72
+   U16   reserved7[2];                           // words 73-74
+   U16   queueDepth;                             // word  75
+   U16   serialAtaCapabilities;                  // word  76
+   U16   serialAtaReserved;                      // word  77
+   U16   serialAtaFeaturesSupported;             // word  78
+   U16   serialAtaFeaturesEnabled;               // word  79
+
+   U16   majorVersionNumber;                     // word  80, page3
+   U16   minorVersionNumber;                     // word  81
+   U16   commandSetSupported0;                   // word  82
+   U16   commandSetSupported1;                   // word  83
+
+   U16   commandSetSupportedExtention;           // word  84, page4
+   U16   commandSetEnabled0;                     // word  85
+   U16   commandSetEnabled1;                     // word  86
+   U16   commandSetDefault;                      // word  87
+
+   U16   ultraDmaMode;                           // word  88, page5
+   U16   reserved8[4];                           // words 89 - 92
+
+   U16   hardwareResetResult;                    // word  93, page6
+   U16   currentAcousticManagementValue;         // word  94
+   U16   reserved9[30];                          // words 95-124
+   U16   ATAPIByteCount0Behavior;                // word  125
+   U16   obsolete1;                              // word  126
+   U16   removableMediaStatus;                   // word  127,
+
+   U16   securityStatus;                         // word  128, page7
+   U16   vendorSpecific1[31];                    // words 129-159
+   U16   reservedForCompactFlash[16];            // words 160-175
+   U16   reserved10[79];                         // words 176-254
+   U16   integrityWord;                          // word  255
+} ATAPI_IDENTIFY_PACKET_DEVICE_T;
+
+/**
+* @struct ATA_EXTENDED_SMART_SELF_TEST_LOG
+*
+* @brief The following structure depicts the ATA-8 version of the
+*        Extended SMART self test log page descriptor entry.
+*/
+typedef union ATA_DESCRIPTOR_ENTRY
+{
+      struct DESCRIPTOR_ENTRY
+      {
+         U8 lba_field;
+         U8 status_byte;
+         U8 time_stamp_low;
+         U8 time_stamp_high;
+         U8 checkpoint_byte;
+         U8 failing_lba_low;
+         U8 failing_lba_mid;
+         U8 failing_lba_high;
+         U8 failing_lba_low_ext;
+         U8 failing_lba_mid_ext;
+         U8 failing_lba_high_ext;
+
+         U8 vendor_specific1;
+         U8 vendor_specific2;
+         U8 vendor_specific3;
+         U8 vendor_specific4;
+         U8 vendor_specific5;
+         U8 vendor_specific6;
+         U8 vendor_specific7;
+         U8 vendor_specific8;
+         U8 vendor_specific9;
+         U8 vendor_specific10;
+         U8 vendor_specific11;
+         U8 vendor_specific12;
+         U8 vendor_specific13;
+         U8 vendor_specific14;
+         U8 vendor_specific15;
+      } DESCRIPTOR_ENTRY;
+
+      U8 descriptor_entry[26];
+
+} ATA_DESCRIPTOR_ENTRY_T;
+
+/**
+* @struct ATA_EXTENDED_SMART_SELF_TEST_LOG
+*
+* @brief The following structure depicts the ATA-8 version of the
+*        SMART self test log page descriptor entry.
+*/
+typedef union ATA_SMART_DESCRIPTOR_ENTRY
+{
+      struct SMART_DESCRIPTOR_ENTRY
+      {
+         U8 lba_field;
+         U8 status_byte;
+         U8 time_stamp_low;
+         U8 time_stamp_high;
+         U8 checkpoint_byte;
+         U8 failing_lba_low;
+         U8 failing_lba_mid;
+         U8 failing_lba_high;
+         U8 failing_lba_low_ext;
+
+         U8 vendor_specific1;
+         U8 vendor_specific2;
+         U8 vendor_specific3;
+         U8 vendor_specific4;
+         U8 vendor_specific5;
+         U8 vendor_specific6;
+         U8 vendor_specific7;
+         U8 vendor_specific8;
+         U8 vendor_specific9;
+         U8 vendor_specific10;
+         U8 vendor_specific11;
+         U8 vendor_specific12;
+         U8 vendor_specific13;
+         U8 vendor_specific14;
+         U8 vendor_specific15;
+      } SMART_DESCRIPTOR_ENTRY;
+
+      U8 smart_descriptor_entry[24];
+
+} ATA_SMART_DESCRIPTOR_ENTRY_T;
+
+/**
+* @struct ATA_EXTENDED_SMART_SELF_TEST_LOG
+*
+* @brief The following structure depicts the ATA-8 version of the
+*        Extended SMART self test log page.
+*/
+typedef struct ATA_EXTENDED_SMART_SELF_TEST_LOG
+{
+   U8    self_test_log_data_structure_revision_number;   //byte 0
+   U8    reserved0;                                      //byte 1
+   U8    self_test_descriptor_index[2];                  //byte 2-3
+
+   ATA_DESCRIPTOR_ENTRY_T descriptor_entrys[19];         //bytes 4-497
+
+   U8    vendor_specific[2];                             //byte 498-499
+   U8    reserved1[11];                                  //byte 500-510
+   U8    data_structure_checksum;                        //byte 511
+
+} ATA_EXTENDED_SMART_SELF_TEST_LOG_T;
+
+/**
+* @struct ATA_EXTENDED_SMART_SELF_TEST_LOG
+*
+* @brief The following structure depicts the ATA-8 version of the
+*        SMART self test log page.
+*/
+typedef struct ATA_SMART_SELF_TEST_LOG
+{
+   U8    self_test_log_data_structure_revision_number[2];   //bytes 0-1
+
+   ATA_SMART_DESCRIPTOR_ENTRY_T descriptor_entrys[21];      //bytes 2-505
+
+   U8    vendor_specific[2];                                //byte 506-507
+   U8    self_test_index;                                   //byte 508
+   U8    reserved1[2];                                      //byte 509-510
+   U8    data_structure_checksum;                           //byte 511
+
+} ATA_SMART_SELF_TEST_LOG_T;
+
+/**
+* @struct ATA_NCQ_COMMAND_ERROR_LOG
+*
+* @brief The following structure depicts the ATA-8 version of the
+*        NCQ command error log page.
+*/
+typedef struct ATA_NCQ_COMMAND_ERROR_LOG
+{
+   U8    ncq_tag   : 5;
+   U8    reserved1 : 2;
+   U8    nq        : 1;
+   U8    reserved2;
+   U8    status;
+   U8    error;
+   U8    lba_7_0;
+   U8    lba_15_8;
+   U8    lba_23_16;
+   U8    device;
+   U8    lba_31_24;
+   U8    lba_39_32;
+   U8    lba_47_40;
+   U8    reserved3;
+   U8    count_7_0;
+   U8    count_15_8;
+   U8    reserved4[242];
+   U8    vendor_specific[255];
+   U8    checksum;
+} ATA_NCQ_COMMAND_ERROR_LOG_T;
+
+#endif // _ATA_H_
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/intel_pci.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/intel_pci.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,90 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _INTEL_PCI_H_
+#define _INTEL_PCI_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the definitions relating to structures,
+ *        constants, etc. defined by the PCI specification.
+ */
+
+#include <dev/isci/types.h>
+
+typedef struct sci_pci_common_header
+{
+   // Offset 0x00
+   U16 vendor_id;
+   U16 device_id;
+
+   // Offset 0x04
+   U16 command;
+   U16 status;
+
+   // Offset 0x08
+   U8  revision;
+   U8  program_interface;
+   U8  sub_class;
+   U8  base_class;
+
+   // Offset 0x0C
+   U8  cache_line_size;
+   U8  master_latency_timer;
+   U8  header_type;
+   U8  built_in_self_test;
+
+} SCI_PCI_COMMON_HEADER_T;
+
+#endif // _INTEL_PCI_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/intel_sas.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/intel_sas.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,977 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _INTEL_SAS_H_
+#define _INTEL_SAS_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the definitions relating to structures,
+ *        constants, etc. defined by the SAS specification.
+ */
+
+#include <dev/isci/types.h>
+#include <dev/isci/scil/intel_sata.h>
+#include <dev/isci/scil/intel_scsi.h>
+
+/**
+ * @struct SCI_SAS_ADDRESS
+ * @brief  This structure depicts how a SAS address is represented by SCI.
+ */
+typedef struct SCI_SAS_ADDRESS
+{
+   /**
+    * This member contains the higher 32-bits of the SAS address.
+    */
+   U32 high;
+
+   /**
+    * This member contains the lower 32-bits of the SAS address.
+    */
+   U32 low;
+
+} SCI_SAS_ADDRESS_T;
+
+/**
+ * @struct SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS
+ * @brief  This structure depicts the contents of bytes 2 and 3 in the
+ *         SAS IDENTIFY ADDRESS FRAME (IAF).
+ *         @note For specific information on each of these
+ *               individual fields please reference the SAS specification
+ *               Link layer section on address frames.
+ */
+typedef struct SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS
+{
+   union
+   {
+      struct
+      {
+         U16  restricted1        : 1;
+         U16  smp_initiator      : 1;
+         U16  stp_initiator      : 1;
+         U16  ssp_initiator      : 1;
+         U16  reserved3          : 4;
+         U16  restricted2        : 1;
+         U16  smp_target         : 1;
+         U16  stp_target         : 1;
+         U16  ssp_target         : 1;
+         U16  reserved4          : 4;
+      } bits;
+
+      U16 all;
+   } u;
+
+} SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T;
+
+/**
+ * @struct SCI_SAS_IDENTIFY_ADDRESS_FRAME
+ * @brief  This structure depicts the contents of the SAS IDENTIFY ADDRESS
+ *         FRAME (IAF).
+ *         @note For specific information on each of these
+ *               individual fields please reference the SAS specification
+ *               Link layer section on address frames.
+ */
+typedef struct SCI_SAS_IDENTIFY_ADDRESS_FRAME
+{
+   U16  address_frame_type : 4;
+   U16  device_type        : 3;
+   U16  reserved1          : 1;
+   U16  reason             : 4;
+   U16  reserved2          : 4;
+
+   SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T protocols;
+
+   SCI_SAS_ADDRESS_T  device_name;
+   SCI_SAS_ADDRESS_T  sas_address;
+
+   U32  phy_identifier      : 8;
+   U32  break_reply_capable : 1;
+   U32  requested_in_zpsds  : 1;
+   U32  in_zpsds_persistent : 1;
+   U32  reserved5           : 21;
+
+   U32  reserved6[4];
+
+} SCI_SAS_IDENTIFY_ADDRESS_FRAME_T;
+
+/**
+ * @struct SAS_CAPABILITIES
+ * @brief  This structure depicts the various SAS capabilities supported
+ *         by the directly attached target device.  For specific information
+ *         on each of these individual fields please reference the SAS
+ *         specification Phy layer section on speed negotiation windows.
+ */
+typedef struct SAS_CAPABILITIES
+{
+   union
+   {
+#if defined (SCIC_SDS_4_ENABLED)
+      struct
+      {
+         /**
+          * The SAS specification indicates the start bit shall always be set to
+          * 1.  This implementation will have the start bit set to 0 if the
+          * PHY CAPABILITIES were either not received or speed negotiation failed.
+          */
+         U32  start                       : 1;
+         U32  tx_ssc_type                 : 1;
+         U32  reserved1                   : 2;
+         U32  requested_logical_link_rate : 4;
+
+         U32  gen1_without_ssc_supported  : 1;
+         U32  gen1_with_ssc_supported     : 1;
+         U32  gen2_without_ssc_supported  : 1;
+         U32  gen2_with_ssc_supported     : 1;
+         U32  gen3_without_ssc_supported  : 1;
+         U32  gen3_with_ssc_supported     : 1;
+         U32  reserved2                   : 17;
+         U32  parity                      : 1;
+      } bits;
+#endif // (SCIC_SDS_4_ENABLED)
+
+      U32 all;
+   } u;
+
+} SAS_CAPABILITIES_T;
+
+/**
+ * @enum  _SCI_SAS_LINK_RATE
+ * @brief This enumeration depicts the SAS specification defined link speeds.
+ */
+typedef enum _SCI_SAS_LINK_RATE
+{
+   SCI_SAS_NO_LINK_RATE = 0,
+   SCI_SATA_SPINUP_HOLD = 0x3,
+   SCI_SAS_150_GB = 0x8,
+   SCI_SAS_300_GB = 0x9,
+   SCI_SAS_600_GB = 0xA
+} SCI_SAS_LINK_RATE;
+
+/**
+ * @enum  _SCI_SAS_TASK_ATTRIBUTE
+ * @brief This enumeration depicts the SAM/SAS specification defined task
+ *        attribute values for a command information unit.
+ */
+typedef enum _SCI_SAS_TASK_ATTRIBUTE
+{
+   SCI_SAS_SIMPLE_ATTRIBUTE = 0,
+   SCI_SAS_HEAD_OF_QUEUE_ATTRIBUTE = 1,
+   SCI_SAS_ORDERED_ATTRIBUTE = 2,
+   SCI_SAS_ACA_ATTRIBUTE = 4,
+} SCI_SAS_TASK_ATTRIBUTE;
+
+/**
+ * @enum  _SCI_SAS_TASK_MGMT_FUNCTION
+ * @brief This enumeration depicts the SAM/SAS specification defined task
+ *        management functions.
+ *        @note This HARD_RESET function listed here is not actually defined
+ *              as a task management function in the industry standard.
+ */
+typedef enum _SCI_SAS_TASK_MGMT_FUNCTION
+{
+   SCI_SAS_ABORT_TASK = SCSI_TASK_REQUEST_ABORT_TASK,
+   SCI_SAS_ABORT_TASK_SET = SCSI_TASK_REQUEST_ABORT_TASK_SET,
+   SCI_SAS_CLEAR_TASK_SET = SCSI_TASK_REQUEST_CLEAR_TASK_SET,
+   SCI_SAS_LOGICAL_UNIT_RESET = SCSI_TASK_REQUEST_LOGICAL_UNIT_RESET,
+   SCI_SAS_I_T_NEXUS_RESET = SCSI_TASK_REQUEST_I_T_NEXUS_RESET,
+   SCI_SAS_CLEAR_ACA = SCSI_TASK_REQUEST_CLEAR_ACA,
+   SCI_SAS_QUERY_TASK = SCSI_TASK_REQUEST_QUERY_TASK,
+   SCI_SAS_QUERY_TASK_SET = SCSI_TASK_REQUEST_QUERY_TASK_SET,
+   SCI_SAS_QUERY_ASYNCHRONOUS_EVENT = SCSI_TASK_REQUEST_QUERY_UNIT_ATTENTION,
+   SCI_SAS_HARD_RESET = 0xFF
+} SCI_SAS_TASK_MGMT_FUNCTION_T;
+
+
+/**
+ * @enum  _SCI_SAS_FRAME_TYPE
+ * @brief This enumeration depicts the SAS specification defined SSP frame
+ *        types.
+ */
+typedef enum _SCI_SAS_FRAME_TYPE
+{
+   SCI_SAS_DATA_FRAME = 0x01,
+   SCI_SAS_XFER_RDY_FRAME = 0x05,
+   SCI_SAS_COMMAND_FRAME = 0x06,
+   SCI_SAS_RESPONSE_FRAME = 0x07,
+   SCI_SAS_TASK_FRAME = 0x16
+} SCI_SAS_FRAME_TYPE_T;
+
+
+/**
+ * @struct SCI_SSP_COMMAND_IU
+ * @brief This structure depicts the contents of the SSP COMMAND
+ *        INFORMATION UNIT. For specific information on each of these
+ *        individual fields please reference the SAS specification SSP
+ *        transport layer section.
+ */
+typedef struct SCI_SSP_COMMAND_IU
+{
+
+   U32 lun[2];
+
+   U32 additional_cdb_length  : 6;
+   U32 reserved0              : 2;
+   U32 reserved1              : 8;
+   U32 enable_first_burst     : 1;
+   U32 task_priority          : 4;
+   U32 task_attribute         : 3;
+   U32 reserved2              : 8;
+
+   U32 cdb[4];
+
+} SCI_SSP_COMMAND_IU_T;
+
+/**
+ * @struct SCI_SSP_TASK_IU
+ * @brief This structure depicts the contents of the SSP TASK INFORMATION
+ *        UNIT. For specific information on each of these individual fields
+ *        please reference the SAS specification SSP transport layer
+ *        section.
+ */
+typedef struct SCI_SSP_TASK_IU
+{
+   U32 lun_upper;
+   U32 lun_lower;
+
+   U32 reserved0     : 8;
+   U32 task_function : 8;
+   U32 reserved1     : 8;
+   U32 reserved2     : 8;
+
+   U32 reserved3     : 16;
+   U32 task_tag      : 16;
+
+   U32 reserved4[3];
+
+} SCI_SSP_TASK_IU_T;
+
+#define SSP_RESPONSE_IU_MAX_DATA 64
+
+#define SCI_SSP_RESPONSE_IU_DATA_PRESENT_MASK   (0x03)
+
+/**
+ * @struct SCI_SSP_RESPONSE_IU
+ * @brief This structure depicts the contents of the SSP RESPONSE
+ *        INFORMATION UNIT. For specific information on each of these
+ *        individual fields please reference the SAS specification SSP
+ *        transport layer section.
+ */
+typedef struct SCI_SSP_RESPONSE_IU
+{
+   U8  reserved0[8];
+
+   U8  retry_delay_timer[2];
+   U8  data_present;
+   U8  status;
+
+   U8  reserved1[4];
+   U8  sense_data_length[4];
+   U8  response_data_length[4];
+
+   U32 data[SSP_RESPONSE_IU_MAX_DATA];
+
+} SCI_SSP_RESPONSE_IU_T;
+
+/**
+ * @enum  _SCI_SAS_DATA_PRESENT_TYPE
+ * @brief This enumeration depicts the SAS specification defined SSP data present
+ *        types in SCI_SSP_RESPONSE_IU.
+ */
+typedef enum _SCI_SSP_RESPONSE_IU_DATA_PRESENT_TYPE
+{
+   SCI_SSP_RESPONSE_IU_NO_DATA = 0x00,
+   SCI_SSP_RESPONSE_IU_RESPONSE_DATA = 0x01,
+   SCI_SSP_RESPONSE_IU_SENSE_DATA = 0x02
+} SCI_SSP_RESPONSE_IU_DATA_PRESENT_TYPE_T;
+
+/**
+ * @struct SCI_SSP_FRAME_HEADER
+ *
+ * @brief This structure depicts the contents of an SSP frame header.  For
+ *        specific information on the individual fields please reference
+ *        the SAS specification transport layer SSP frame format.
+ */
+typedef struct SCI_SSP_FRAME_HEADER
+{
+   // Word 0
+   U32 hashed_destination_address  :24;
+   U32 frame_type                  : 8;
+
+   // Word 1
+   U32 hashed_source_address       :24;
+   U32 reserved1_0                 : 8;
+
+   // Word 2
+   U32 reserved2_2                 : 6;
+   U32 fill_bytes                  : 2;
+   U32 reserved2_1                 : 3;
+   U32 tlr_control                 : 2;
+   U32 retry_data_frames           : 1;
+   U32 retransmit                  : 1;
+   U32 changing_data_pointer       : 1;
+   U32 reserved2_0                 :16;
+
+   // Word 3
+   U32 uiResv4;
+
+   // Word 4
+   U16 target_port_transfer_tag;
+   U16 tag;
+
+   // Word 5
+   U32 data_offset;
+
+} SCI_SSP_FRAME_HEADER_T;
+
+/**
+ * @struct SMP_REQUEST_HEADER
+ * @brief  This structure defines the contents of an SMP Request header.
+ *         @note For specific information on each of these
+ *               individual fields please reference the SAS specification.
+ */
+typedef struct SMP_REQUEST_HEADER
+{
+   U8 smp_frame_type;                // byte 0
+   U8 function;                      // byte 1
+   U8 allocated_response_length;     // byte 2
+   U8 request_length;                // byte 3
+} SMP_REQUEST_HEADER_T;
+
+/**
+ * @struct SMP_RESPONSE_HEADER
+ * @brief  This structure depicts the contents of the SAS SMP DISCOVER
+ *         RESPONSE frame.  For specific information on each of these
+ *         individual fields please reference the SAS specification Link
+ *         layer section on address frames.
+ */
+typedef struct SMP_RESPONSE_HEADER
+{
+   U8 smp_frame_type;      // byte 0
+   U8 function;            // byte 1
+   U8 function_result;     // byte 2
+   U8 response_length;     // byte 3
+} SMP_RESPONSE_HEADER_T;
+
+/**
+ * @struct SMP_REQUEST_GENERAL
+ * @brief  This structure defines the contents of an SMP Request that
+ *         is comprised of the SMP_REQUEST_HEADER and a CRC.
+ *         @note For specific information on each of these
+ *               individual fields please reference the SAS specification.
+ */
+typedef struct SMP_REQUEST_GENERAL
+{
+  U32 crc;            // bytes 4-7
+
+} SMP_REQUEST_GENERAL_T;
+
+/**
+ * @struct SMP_REQUEST_PHY_IDENTIFIER
+ * @brief  This structure defines the contents of an SMP Request that
+ *         is comprised of the SMP_REQUEST_HEADER and a phy identifier.
+ *         Examples: SMP_REQUEST_DISCOVER, SMP_REQUEST_REPORT_PHY_SATA.
+ *         @note For specific information on each of these
+ *               individual fields please reference the SAS specification.
+ */
+typedef struct SMP_REQUEST_PHY_IDENTIFIER
+{
+  U32 reserved_byte4_7;      // bytes 4-7
+
+  U32 ignore_zone_group:1;    // byte 8
+  U32 reserved_byte8:7;
+
+  U32 phy_identifier:8;       // byte 9
+  U32 reserved_byte10:8;      // byte 10
+  U32 reserved_byte11:8;      // byte 11
+
+} SMP_REQUEST_PHY_IDENTIFIER_T;
+
+/**
+ * @struct SMP_REQUEST_CONFIGURE_ROUTE_INFORMATION
+ * @brief  This structure defines the contents of an SMP Configure Route
+ *         Information request.
+ *         @note For specific information on each of these
+ *               individual fields please reference the SAS specification.
+ */
+typedef struct SMP_REQUEST_CONFIGURE_ROUTE_INFORMATION
+{
+  U32 expected_expander_change_count:16;    // bytes 4-5
+  U32 expander_route_index_high:8;
+  U32 expander_route_index:8;              // bytes 6-7
+
+  U32 reserved_byte8:8;           // bytes 8
+  U32 phy_identifier:8;           // bytes 9
+  U32 reserved_byte_10_11:16;     // bytes 10-11
+
+  U32 reserved_byte_12_bit_0_6:7;
+  U32 disable_route_entry:1;    // byte 12
+  U32 reserved_byte_13_15:24;   // bytes 13-15
+
+  U32 routed_sas_address[2];    // bytes 16-23
+  U8 reserved_byte_24_39[16];    // bytes 24-39
+
+} SMP_REQUEST_CONFIGURE_ROUTE_INFORMATION_T;
+
+/**
+ * @struct SMP_REQUEST_PHY_CONTROL
+ * @brief  This structure defines the contents of an SMP Phy Controler
+ *         request.
+ *         @note For specific information on each of these
+ *               individual fields please reference the SAS specification.
+ */
+typedef struct SMP_REQUEST_PHY_CONTROL
+{
+  U16 expected_expander_change_count;   // byte 4-5
+
+  U16 reserved_byte_6_7;   // byte 6-7
+  U8 reserved_byte_8;      // byte 8
+
+  U8 phy_identifier;       // byte 9
+  U8 phy_operation;        // byte 10
+
+  U8 update_partial_pathway_timeout_value:1;
+  U8 reserved_byte_11_bit_1_7:7;   // byte 11
+
+  U8 reserved_byte_12_23[12];      // byte 12-23
+
+  U8 attached_device_name[8];      // byte 24-31
+
+  U8 reserved_byte_32_bit_3_0:4;   // byte 32
+  U8 programmed_minimum_physical_link_rate:4;
+
+  U8 reserved_byte_33_bit_3_0:4;   // byte 33
+  U8 programmed_maximum_physical_link_rate:4;
+
+  U16 reserved_byte_34_35;      // byte 34-35
+
+  U8 partial_pathway_timeout_value:4;
+  U8 reserved_byte_36_bit_4_7:4;  // byte 36
+
+  U16 reserved_byte_37_38;  // byte 37-38
+  U8 reserved_byte_39;      // byte 39
+
+} SMP_REQUEST_PHY_CONTROL_T;
+
+/**
+ * @struct SMP_REQUEST_VENDOR_SPECIFIC
+ * @brief  This structure depicts the vendor specific space for SMP request.
+ */
+ #define SMP_REQUEST_VENDOR_SPECIFIC_MAX_LENGTH 1016
+typedef struct SMP_REQUEST_VENDOR_SPECIFIC
+{
+   U8 request_bytes[SMP_REQUEST_VENDOR_SPECIFIC_MAX_LENGTH];
+}SMP_REQUEST_VENDOR_SPECIFIC_T;
+
+/**
+ * @struct SMP_REQUEST
+ * @brief  This structure simply unionizes the existing request
+ *         structures into a common request type.
+ */
+typedef struct _SMP_REQUEST
+{
+  SMP_REQUEST_HEADER_T header;
+
+  union
+  {            // bytes 4-N
+    SMP_REQUEST_GENERAL_T                       report_general;
+    SMP_REQUEST_PHY_IDENTIFIER_T                discover;
+    SMP_REQUEST_GENERAL_T                       report_manufacturer_information;
+    SMP_REQUEST_PHY_IDENTIFIER_T                report_phy_sata;
+    SMP_REQUEST_PHY_CONTROL_T                   phy_control;
+    SMP_REQUEST_PHY_IDENTIFIER_T                report_phy_error_log;
+    SMP_REQUEST_PHY_IDENTIFIER_T                report_route_information;
+    SMP_REQUEST_CONFIGURE_ROUTE_INFORMATION_T   configure_route_information;
+    SMP_REQUEST_VENDOR_SPECIFIC_T               vendor_specific_request;
+  } request;
+
+} SMP_REQUEST_T;
+
+
+/**
+ * @struct SMP_RESPONSE_REPORT_GENERAL
+ * @brief  This structure depicts the SMP Report General for
+ *         expander devices.  It adheres to the SAS-2.1 specification.
+ *         @note For specific information on each of these
+ *               individual fields please reference the SAS specification
+ *               Application layer section on SMP.
+ */
+typedef struct SMP_RESPONSE_REPORT_GENERAL
+{
+  U16 expander_change_count;  //byte 4-5
+  U16 expander_route_indexes; //byte 6-7
+
+  U32 reserved_byte8:7;        //byte 8 bit 0-6
+  U32 long_response:1;         //byte 8 bit 7
+
+  U32 number_of_phys:8;        //byte 9
+
+  U32 configurable_route_table:1; //byte 10
+  U32 configuring:1;
+  U32 configures_others:1;
+  U32 open_reject_retry_supported:1;
+  U32 stp_continue_awt:1;
+  U32 self_configuring:1;
+  U32 zone_configuring:1;
+  U32 table_to_table_supported:1;
+
+  U32 reserved_byte11:8;       //byte 11
+
+  U32 enclosure_logical_identifier_high; //byte 12-15
+  U32 enclosure_logical_identifier_low;  //byte 16-19
+
+  U32 reserved_byte20_23;
+  U32 reserved_byte24_27;
+
+} SMP_RESPONSE_REPORT_GENERAL_T;
+
+typedef struct SMP_RESPONSE_REPORT_GENERAL_LONG
+{
+   SMP_RESPONSE_REPORT_GENERAL_T sas1_1;
+
+   struct
+   {
+      U16 reserved1;
+      U16 stp_bus_inactivity_time_limit;
+      U16 stp_max_connect_time_limit;
+      U16 stp_smp_i_t_nexus_loss_time;
+
+      U32 zoning_enabled                         : 1;
+      U32 zoning_supported                       : 1;
+      U32 physicaL_presence_asserted             : 1;
+      U32 zone_locked                            : 1;
+      U32 reserved2                              : 1;
+      U32 num_zone_groups                        : 3;
+      U32 saving_zoning_enabled_supported        : 3;
+      U32 saving_zone_perms_table_supported      : 1;
+      U32 saving_zone_phy_info_supported         : 1;
+      U32 saving_zone_manager_password_supported : 1;
+      U32 saving                                 : 1;
+      U32 reserved3                              : 1;
+      U32 max_number_routed_sas_addresses        : 16;
+
+      SCI_SAS_ADDRESS_T active_zone_manager_sas_address;
+
+      U16 zone_lock_inactivity_time_limit;
+      U16 reserved4;
+
+      U8 reserved5;
+      U8 first_enclosure_connector_element_index;
+      U8 number_of_enclosure_connector_element_indices;
+      U8 reserved6;
+
+      U32 reserved7                            : 7;
+      U32 reduced_functionality                : 1;
+      U32 time_to_reduce_functionality         : 8;
+      U32 initial_time_to_reduce_functionality : 8;
+      U8  max_reduced_functionality_time;
+
+      U16 last_self_config_status_descriptor_index;
+      U16 max_number_of_stored_self_config_status_descriptors;
+
+      U16 last_phy_event_list_descriptor_index;
+      U16 max_number_of_stored_phy_event_list_descriptors;
+   } sas2;
+
+} SMP_RESPONSE_REPORT_GENERAL_LONG_T;
+
+/**
+ * @struct SMP_RESPONSE_REPORT_MANUFACTURER_INFORMATION
+ * @brief  This structure depicts the SMP report manufacturer
+ *         information for expander devices.  It adheres to the
+ *         SAS-2.1 specification.
+ *         @note For specific information on each of these
+ *               individual fields please reference the SAS specification
+ *               Application layer section on SMP.
+ */
+typedef struct SMP_RESPONSE_REPORT_MANUFACTURER_INFORMATION
+{
+  U32 expander_change_count : 16;    // bytes 4-5
+  U32 reserved1             : 16;
+
+  U32 sas1_1_format         : 1;
+  U32 reserved2             : 31;
+
+  U8  vendor_id[8];
+  U8  product_id[16];
+  U8  product_revision_level[4];
+  U8  component_vendor_id[8];
+  U8  component_id[2];
+  U8  component_revision_level;
+  U8  reserved3;
+  U8  vendor_specific[8];
+
+} SMP_RESPONSE_REPORT_MANUFACTURER_INFORMATION_T;
+
+#define SMP_RESPONSE_DISCOVER_FORMAT_1_1_SIZE 52
+#define SMP_RESPONSE_DISCOVER_FORMAT_2_SIZE   116
+
+/**
+ * @struct SMP_DISCOVER_RESPONSE_PROTOCOLS
+ * @brief  This structure depicts the discover response where the
+ *         supported protocols by the remote phy are specified.
+ *         @note For specific information on each of these
+ *               individual fields please reference the SAS specification
+ *               Link layer section on address frames.
+ */
+typedef struct SMP_DISCOVER_RESPONSE_PROTOCOLS
+{
+   union
+   {
+      struct
+      {
+         U16  attached_sata_host           : 1;
+         U16  attached_smp_initiator       : 1;
+         U16  attached_stp_initiator       : 1;
+         U16  attached_ssp_initiator       : 1;
+         U16  reserved3                    : 4;
+         U16  attached_sata_device         : 1;
+         U16  attached_smp_target          : 1;
+         U16  attached_stp_target          : 1;
+         U16  attached_ssp_target          : 1;
+         U16  reserved4                    : 3;
+         U16  attached_sata_port_selector  : 1;
+      } bits;
+
+      U16 all;
+   } u;
+
+} SMP_DISCOVER_RESPONSE_PROTOCOLS_T;
+
+/**
+ * @struct SMP_RESPONSE_DISCOVER_FORMAT
+ * @brief  This structure defines the SMP phy discover response format.
+ *         It handles both SAS1.1 and SAS 2 definitions.  The unions
+ *         indicate locations where the SAS specification versions
+ *         differ from one another.
+ */
+typedef struct SMP_RESPONSE_DISCOVER
+{
+
+   union
+   {
+      struct
+      {
+         U8 reserved[2];
+      } sas1_1;
+
+      struct
+      {
+         U16  expander_change_count;
+      } sas2;
+
+   } u1;
+
+   U8   reserved1[3];
+   U8   phy_identifier;
+   U8   reserved2[2];
+
+   union
+   {
+      struct
+      {
+         U16  reserved1                     : 4;
+         U16  attached_device_type          : 3;
+         U16  reserved2                     : 1;
+         U16  negotiated_physical_link_rate : 4;
+         U16  reserved3                     : 4;
+      } sas1_1;
+
+      struct
+      {
+         U16  attached_reason              : 4;
+         U16  attached_device_type         : 3;
+         U16  reserved2                    : 1;
+         U16  negotiated_logical_link_rate : 4;
+         U16  reserved3                    : 4;
+      } sas2;
+
+   } u2;
+
+   SMP_DISCOVER_RESPONSE_PROTOCOLS_T protocols;
+   SCI_SAS_ADDRESS_T  sas_address;
+   SCI_SAS_ADDRESS_T  attached_sas_address;
+
+   U8   attached_phy_identifier;
+
+   union
+   {
+      struct
+      {
+         U8   reserved;
+      } sas1_1;
+
+      struct
+      {
+         U8   attached_break_reply_capable     : 1;
+         U8   attached_requested_inside_zpsds  : 1;
+         U8   attached_inside_zpsds_persistent : 1;
+         U8   reserved1                        : 5;
+      } sas2;
+
+   } u3;
+
+   U8   reserved_for_identify[6];
+
+   U32  hardware_min_physical_link_rate   : 4;
+   U32  programmed_min_physical_link_rate : 4;
+   U32  hardware_max_physical_link_rate   : 4;
+   U32  programmed_max_physical_link_rate : 4;
+   U32  phy_change_count                  : 8;
+   U32  partial_pathway_timeout_value     : 4;
+   U32  reserved5                         : 3;
+   U32  virtual_phy                       : 1;
+
+   U32  routing_attribute                 : 4;
+   U32  reserved6                         : 4;
+   U32  connector_type                    : 7;
+   U32  reserved7                         : 1;
+   U32  connector_element_index           : 8;
+   U32  connector_physical_link           : 8;
+
+   U16  reserved8;
+   U16  vendor_specific;
+
+   union
+   {
+      struct
+      {
+         /**
+          * In the SAS 1.1 specification this structure ends after 52 bytes.
+          * As a result, the contents of this field should never have a
+          * real value.  It is undefined.
+          */
+         U8 undefined[SMP_RESPONSE_DISCOVER_FORMAT_2_SIZE
+                      - SMP_RESPONSE_DISCOVER_FORMAT_1_1_SIZE];
+      } sas1_1;
+
+      struct
+      {
+         SCI_SAS_ADDRESS_T attached_device_name;
+
+         U32  zoning_enabled                             : 1;
+         U32  inside_zpsds                               : 1;
+         U32  zone_group_persistent                      : 1;
+         U32  reserved1                                  : 1;
+         U32  requested_inside_zpsds                     : 1;
+         U32  inside_zpsds_persistent                    : 1;
+         U32  requested_inside_zpsds_changed_by_expander : 1;
+         U32  reserved2                                  : 1;
+         U32  reserved_for_zoning_fields                 : 16;
+         U32  zone_group                                 : 8;
+
+         U8   self_configuration_status;
+         U8   self_configuration_levels_completed;
+         U16  reserved_for_self_config_fields;
+
+         SCI_SAS_ADDRESS_T self_configuration_sas_address;
+
+         U32  programmed_phy_capabilities;
+         U32  current_phy_capabilities;
+         U32  attached_phy_capabilities;
+
+         U32  reserved3;
+
+         U32  reserved4                     : 16;
+         U32  negotiated_physical_link_rate : 4;
+         U32  reason                        : 4;
+         U32  hardware_muxing_supported     : 1;
+         U32  negotiated_ssc                : 1;
+         U32  reserved5                     : 6;
+
+         U32  default_zoning_enabled          : 1;
+         U32  reserved6                       : 1;
+         U32  default_zone_group_persistent   : 1;
+         U32  reserved7                       : 1;
+         U32  default_requested_inside_zpsds  : 1;
+         U32  default_inside_zpsds_persistent : 1;
+         U32  reserved8                       : 2;
+         U32  reserved9                       : 16;
+         U32  default_zone_group              : 8;
+
+         U32  saved_zoning_enabled          : 1;
+         U32  reserved10                    : 1;
+         U32  saved_zone_group_persistent   : 1;
+         U32  reserved11                    : 1;
+         U32  saved_requested_inside_zpsds  : 1;
+         U32  saved_inside_zpsds_persistent : 1;
+         U32  reserved12                    : 18;
+         U32  saved_zone_group              : 8;
+
+         U32  reserved14                     : 2;
+         U32  shadow_zone_group_persistent   : 1;
+         U32  reserved15                     : 1;
+         U32  shadow_requested_inside_zpsds  : 1;
+         U32  shadow_inside_zpsds_persistent : 1;
+         U32  reserved16                     : 18;
+         U32  shadow_zone_group              : 8;
+
+         U8   device_slot_number;
+         U8   device_slot_group_number;
+         U8   device_slot_group_output_connector[6];
+      } sas2;
+
+   } u4;
+
+} SMP_RESPONSE_DISCOVER_T;
+
+/**
+ * @struct SMP_RESPONSE_REPORT_PHY_SATA
+ * @brief  This structure depicts the contents of the SAS SMP REPORT
+ *         PHY SATA frame.  For specific information on each of these
+ *         individual fields please reference the SAS specification Link
+ *         layer section on address frames.
+ */
+typedef struct SMP_RESPONSE_REPORT_PHY_SATA
+{
+  U32 ignored_byte_4_7;       // bytes 4-7
+
+  U32  affiliations_valid:1;
+  U32  affiliations_supported:1;
+  U32  reserved_byte11:6;     // byte 11
+  U32  ignored_byte10:8;      // byte 10
+  U32  phy_identifier:8;      // byte  9
+  U32  reserved_byte_8:8;     // byte  8
+
+  U32  reserved_12_15;
+  U32  stp_sas_address[2];
+  U8   device_to_host_fis[20];
+  U32  reserved_44_47;
+  U32  affiliated_stp_initiator_sas_address[2];
+
+} SMP_RESPONSE_REPORT_PHY_SATA_T;
+
+typedef struct SMP_RESPONSE_VENDOR_SPECIFIC
+{
+   U8 response_bytes[SMP_REQUEST_VENDOR_SPECIFIC_MAX_LENGTH];
+}SMP_RESPONSE_VENDOR_SPECIFIC_T;
+
+typedef union SMP_RESPONSE_BODY
+{
+   SMP_RESPONSE_REPORT_GENERAL_T report_general;
+   SMP_RESPONSE_REPORT_MANUFACTURER_INFORMATION_T report_manufacturer_information;
+   SMP_RESPONSE_DISCOVER_T discover;
+   SMP_RESPONSE_REPORT_PHY_SATA_T report_phy_sata;
+   SMP_RESPONSE_VENDOR_SPECIFIC_T vendor_specific_response;
+} SMP_RESPONSE_BODY_T;
+
+/**
+ * @struct SMP_RESPONSE
+ * @brief  This structure simply unionizes the existing response
+ *         structures into a common response type.
+ */
+typedef struct _SMP_RESPONSE
+{
+   SMP_RESPONSE_HEADER_T header;
+
+   SMP_RESPONSE_BODY_T   response;
+
+} SMP_RESPONSE_T;
+
+// SMP Request Functions
+#define SMP_FUNCTION_REPORT_GENERAL                   0x00
+#define SMP_FUNCTION_REPORT_MANUFACTURER_INFORMATION  0x01
+#define SMP_FUNCTION_DISCOVER                         0x10
+#define SMP_FUNCTION_REPORT_PHY_ERROR_LOG             0x11
+#define SMP_FUNCTION_REPORT_PHY_SATA                  0x12
+#define SMP_FUNCTION_REPORT_ROUTE_INFORMATION         0X13
+#define SMP_FUNCTION_CONFIGURE_ROUTE_INFORMATION      0X90
+#define SMP_FUNCTION_PHY_CONTROL                      0x91
+#define SMP_FUNCTION_PHY_TEST                         0x92
+
+#define SMP_FRAME_TYPE_REQUEST          0x40
+#define SMP_FRAME_TYPE_RESPONSE         0x41
+
+#define PHY_OPERATION_NOP               0x00
+#define PHY_OPERATION_LINK_RESET        0x01
+#define PHY_OPERATION_HARD_RESET        0x02
+#define PHY_OPERATION_DISABLE           0x03
+#define PHY_OPERATION_CLEAR_ERROR_LOG   0x05
+#define PHY_OPERATION_CLEAR_AFFILIATION 0x06
+
+#define NPLR_PHY_ENABLED_UNK_LINK_RATE 0x00
+#define NPLR_PHY_DISABLED     0x01
+#define NPLR_PHY_ENABLED_SPD_NEG_FAILED   0x02
+#define NPLR_PHY_ENABLED_SATA_HOLD  0x03
+#define NPLR_PHY_ENABLED_1_5G    0x08
+#define NPLR_PHY_ENABLED_3_0G    0x09
+
+// SMP Function Result values.
+#define SMP_RESULT_FUNCTION_ACCEPTED              0x00
+#define SMP_RESULT_UNKNOWN_FUNCTION               0x01
+#define SMP_RESULT_FUNCTION_FAILED                0x02
+#define SMP_RESULT_INVALID_REQUEST_FRAME_LEN      0x03
+#define SMP_RESULT_INAVALID_EXPANDER_CHANGE_COUNT 0x04
+#define SMP_RESULT_BUSY                           0x05
+#define SMP_RESULT_INCOMPLETE_DESCRIPTOR_LIST     0x06
+#define SMP_RESULT_PHY_DOES_NOT_EXIST             0x10
+#define SMP_RESULT_INDEX_DOES_NOT_EXIST           0x11
+#define SMP_RESULT_PHY_DOES_NOT_SUPPORT_SATA      0x12
+#define SMP_RESULT_UNKNOWN_PHY_OPERATION          0x13
+#define SMP_RESULT_UNKNOWN_PHY_TEST_FUNCTION      0x14
+#define SMP_RESULT_PHY_TEST_IN_PROGRESS           0x15
+#define SMP_RESULT_PHY_VACANT                     0x16
+
+/* Attached Device Types */
+#define SMP_NO_DEVICE_ATTACHED      0
+#define SMP_END_DEVICE_ONLY         1
+#define SMP_EDGE_EXPANDER_DEVICE    2
+#define SMP_FANOUT_EXPANDER_DEVICE  3
+
+/* Expander phy routine attribute */
+#define DIRECT_ROUTING_ATTRIBUTE        0
+#define SUBTRACTIVE_ROUTING_ATTRIBUTE   1
+#define TABLE_ROUTING_ATTRIBUTE         2
+
+#endif // _INTEL_SAS_H_
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/intel_sat.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/intel_sat.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,94 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SAT_H_
+#define _SAT_H_
+
+/**
+ * @file
+ * @brief This file contains constants and constructs defined in the SCSI
+ *        to ATA Translation (SAT) T10 standard.  For more information please
+ *        refer to www.t10.org.
+ */
+
+/**
+ * @name SAT_PROTOCOLS
+ *
+ * These constants indicate the various protocol values that can be supported
+ * in a SAT translator.
+ */
+/*@{*/
+#define SAT_PROTOCOL_ATA_HARD_RESET       0
+#define SAT_PROTOCOL_SOFT_RESET           1
+#define SAT_PROTOCOL_NON_DATA             3
+#define SAT_PROTOCOL_PIO_DATA_IN          4
+#define SAT_PROTOCOL_PIO_DATA_OUT         5
+#define SAT_PROTOCOL_DMA                  6
+#define SAT_PROTOCOL_DMA_QUEUED           7
+#define SAT_PROTOCOL_DEVICE_DIAGNOSTIC    8
+#define SAT_PROTOCOL_DEVICE_RESET         9
+#define SAT_PROTOCOL_UDMA_DATA_IN         10
+#define SAT_PROTOCOL_UDMA_DATA_OUT        11
+#define SAT_PROTOCOL_FPDMA                12
+#define SAT_PROTOCOL_RETURN_RESPONSE_INFO 15
+
+#define SAT_PROTOCOL_PACKET               0x10
+#define SAT_PROTOCOL_PACKET_NON_DATA      (SAT_PROTOCOL_PACKET | 0x0)
+#define SAT_PROTOCOL_PACKET_DMA_DATA_IN   (SAT_PROTOCOL_PACKET | 0x1)
+#define SAT_PROTOCOL_PACKET_DMA_DATA_OUT  (SAT_PROTOCOL_PACKET | 0x2)
+#define SAT_PROTOCOL_PACKET_PIO_DATA_IN   (SAT_PROTOCOL_PACKET | 0x3)
+#define SAT_PROTOCOL_PACKET_PIO_DATA_OUT  (SAT_PROTOCOL_PACKET | 0x4)
+/*@}*/
+
+#endif // _SAT_H_
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/intel_sata.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/intel_sata.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,284 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATA_H_
+#define _SATA_H_
+
+#include <dev/isci/types.h>
+
+/**
+ * @file
+ *
+ * @brief This file defines all of the SATA releated constants, enumerations,
+ *        and types. Please note that this file does not necessarily contain
+ *        an exhaustive list of all contants and commands.
+ */
+
+/**
+ * @name SATA FIS Types
+ *
+ * These constants depict the various SATA FIS types devined in the serial ATA
+ * specification.
+ */
+/*@{*/
+#define SATA_FIS_TYPE_REGH2D          0x27
+#define SATA_FIS_TYPE_REGD2H          0x34
+#define SATA_FIS_TYPE_SETDEVBITS      0xA1
+#define SATA_FIS_TYPE_DMA_ACTIVATE    0x39
+#define SATA_FIS_TYPE_DMA_SETUP       0x41
+#define SATA_FIS_TYPE_BIST_ACTIVATE   0x58
+#define SATA_FIS_TYPE_PIO_SETUP       0x5F
+#define SATA_FIS_TYPE_DATA            0x46
+/*@}*/
+
+#define SATA_REGISTER_FIS_SIZE 0x20
+
+/**
+ * @struct  SATA_FIS_HEADER
+ *
+ * @brief This is the common definition for a SATA FIS Header word.  A
+ *        different header word is defined for any FIS type that does not use
+ *        the standard header.
+ */
+typedef struct SATA_FIS_HEADER
+{
+   U32 fis_type         :8;   // word 0
+   U32 pm_port          :4;
+   U32 reserved         :1;
+   U32 direction_flag   :1;   // direction
+   U32 interrupt_flag   :1;
+   U32 command_flag     :1;   // command, auto_activate, or notification
+   U32 status           :8;
+   U32 error            :8;
+} SATA_FIS_HEADER_T;
+
+
+/**
+ * @struct SATA_FIS_REG_H2D
+ *
+ * @brief This is the definition for a SATA Host to Device Register FIS.
+ */
+typedef struct SATA_FIS_REG_H2D
+{
+   U32 fis_type         :8;     // word 0
+   U32 pm_port          :4;
+   U32 reserved0        :3;
+   U32 command_flag     :1;
+   U32 command          :8;
+   U32 features         :8;
+   U32 lba_low          :8;     // word 1
+   U32 lba_mid          :8;
+   U32 lba_high         :8;
+   U32 device           :8;
+   U32 lba_low_exp      :8;     // word 2
+   U32 lba_mid_exp      :8;
+   U32 lba_high_exp     :8;
+   U32 features_exp     :8;
+   U32 sector_count     :8;     // word 3
+   U32 sector_count_exp :8;
+   U32 reserved1        :8;
+   U32 control          :8;
+   U32 reserved2;               // word 4
+} SATA_FIS_REG_H2D_T;
+
+/**
+ * @struct SATA_FIS_REG_D2H
+ *
+ * @brief SATA Device To Host FIS
+ */
+typedef struct SATA_FIS_REG_D2H
+{
+   U32 fis_type   :8;         // word 0
+   U32 pm_port    :4;
+   U32 reserved0  :2;
+   U32 irq        :1;
+   U32 reserved1  :1;
+   U32 status     :8;
+   U32 error      :8;
+   U8 lba_low;               // word 1
+   U8 lba_mid;
+   U8 lba_high;
+   U8 device;
+   U8 lba_low_exp;           // word 2
+   U8 lba_mid_exp;
+   U8 lba_high_exp;
+   U8 reserved;
+   U8 sector_count;          // word 3
+   U8 sector_count_exp;
+   U16 reserved2;
+   U32 reserved3;
+} SATA_FIS_REG_D2H_T;
+
+/**
+ *  Status field bit definitions
+ */
+#define SATA_FIS_STATUS_DEVBITS_MASK  (0x77)
+
+/**
+ * @struct SATA_FIS_SET_DEV_BITS
+ *
+ * @brief SATA Set Device Bits FIS
+ */
+typedef struct SATA_FIS_SET_DEV_BITS
+{
+   U32 fis_type      :8;   // word 0
+   U32 pm_port       :4;
+   U32 reserved0     :2;
+   U32 irq           :1;
+   U32 notification  :1;
+   U32 status_low    :4;
+   U32 status_high   :4;
+   U32 error         :8;
+   U32 s_active;           // word 1
+} SATA_FIS_SET_DEV_BITS_T;
+
+/**
+ * @struct SATA_FIS_DMA_ACTIVATE
+ *
+ * @brief SATA DMA Activate FIS
+ */
+typedef struct SATA_FIS_DMA_ACTIVATE
+{
+   U32 fis_type      :8;   // word 0
+   U32 pm_port       :4;
+   U32 reserved0     :24;
+} SATA_FIS_DMA_ACTIVATE_T;
+
+/**
+ * The lower 5 bits in the DMA Buffer ID Low field of the DMA Setup
+ * are used to communicate the command tag.
+ */
+#define SATA_DMA_SETUP_TAG_ENABLE      0x1F
+
+#define SATA_DMA_SETUP_AUTO_ACT_ENABLE 0x80
+
+/**
+ * @struct SATA_FIS_DMA_SETUP
+ *
+ * @brief SATA DMA Setup FIS
+ */
+typedef struct SATA_FIS_DMA_SETUP
+{
+   U32 fis_type            :8;   // word 0
+   U32 pm_port             :4;
+   U32 reserved_00         :1;
+   U32 direction           :1;
+   U32 irq                 :1;
+   U32 auto_activate       :1;
+   U32 reserved_01         :16;
+   U32 dma_buffer_id_low;        // word 1
+   U32 dma_buffer_id_high;       // word 2
+   U32 reserved0;                // word 3
+   U32 dma_buffer_offset;        // word 4
+   U32 dma_transfer_count;       // word 5
+   U32 reserved1;                // word 6
+} SATA_FIS_DMA_SETUP_T;
+
+/**
+ *  @struct SATA_FIS_BIST_ACTIVATE
+ *
+ *  @brief SATA BIST Activate FIS
+ */
+typedef struct SATA_FIS_BIST_ACTIVATE
+{
+   U32 fis_type               :8;   // word 0
+   U32 reserved0              :8;
+   U32 pattern_definition     :8;
+   U32 reserved1              :8;
+   U32 data1;                       // word 1
+   U32 data2;                       // word 1
+} SATA_FIS_BIST_ACTIVATE_T;
+
+/*
+ *  SATA PIO Setup FIS
+ */
+typedef struct SATA_FIS_PIO_SETUP
+{
+   U32 fis_type         :8;   // word 0
+   U32 pm_port          :4;
+   U32 reserved_00      :1;
+   U32 direction        :1;
+   U32 irq              :1;
+   U32 reserved_01      :1;
+   U32 status           :8;
+   U32 error            :8;
+   U32 lba_low          :8;   // word 1
+   U32 lba_mid          :8;
+   U32 lba_high         :8;
+   U32 device           :8;
+   U32 lba_low_exp      :8;   // word 2
+   U32 lba_mid_exp      :8;
+   U32 lba_high_exp     :8;
+   U32 reserved         :8;
+   U32 sector_count     :8;   // word 3
+   U32 sector_count_exp :8;
+   U32 reserved1        :8;
+   U32 ending_status    :8;
+   U32 transfter_count  :16;  // word 4
+   U32 reserved3        :16;
+} SATA_FIS_PIO_SETUP_T;
+
+/**
+ * @struct SATA_FIS_DATA
+ *
+ * @brief SATA Data FIS
+ */
+typedef struct SATA_FIS_DATA
+{
+   U32 fis_type      :8;   // word 0
+   U32 pm_port       :4;
+   U32 reserved0     :24;
+   U8  data[4];            // word 1
+} SATA_FIS_DATA_T;
+
+#endif // _SATA_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/intel_scsi.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/intel_scsi.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,540 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+/**
+ * @file
+ * @brief This file defines all of the SCSI related constants, enumerations,
+ *        and types.  Please note that this file does not necessarily contain
+ *        an exhaustive list of all constants, commands, sub-commands, etc.
+ */
+
+#ifndef _SCSI_H__
+#define _SCSI_H__
+
+
+//******************************************************************************
+//* C O N S T A N T S   A N D   M A C R O S
+//******************************************************************************
+
+/**
+ * @enum _SCSI_TASK_MGMT_REQUEST_CODES
+ *
+ * @brief This enumberation contains the constants to be used for SCSI task
+ *        management request codes.  SAM does not specify any particular
+ *        values for these codes so constants used here are the same as
+ *        those specified in SAS.
+ */
+typedef enum _SCSI_TASK_MGMT_REQUEST_CODES
+{
+   SCSI_TASK_REQUEST_ABORT_TASK           = 0x01,
+   SCSI_TASK_REQUEST_ABORT_TASK_SET       = 0x02,
+   SCSI_TASK_REQUEST_CLEAR_TASK_SET       = 0x04,
+   SCSI_TASK_REQUEST_LOGICAL_UNIT_RESET   = 0x08,
+   SCSI_TASK_REQUEST_I_T_NEXUS_RESET      = 0x10,
+   SCSI_TASK_REQUEST_CLEAR_ACA            = 0x40,
+   SCSI_TASK_REQUEST_QUERY_TASK           = 0x80,
+   SCSI_TASK_REQUEST_QUERY_TASK_SET       = 0x81,
+   SCSI_TASK_REQUEST_QUERY_UNIT_ATTENTION = 0x82,
+
+} SCSI_TASK_MGMT_REQUEST_CODES;
+
+/**
+ * @enum _SCSI_TASK_MGMT_RESPONSE_CODES
+ *
+ * @brief This enumeration contains all of the SCSI task management response
+ *        codes.
+ */
+typedef enum _SCSI_TASK_MGMT_RESPONSE_CODES
+{
+   SCSI_TASK_MGMT_FUNC_COMPLETE      = 0,
+   SCSI_INVALID_FRAME                = 2,
+   SCSI_TASK_MGMT_FUNC_NOT_SUPPORTED = 4,
+   SCSI_TASK_MGMT_FUNC_FAILED        = 5,
+   SCSI_TASK_MGMT_FUNC_SUCCEEDED     = 8,
+   SCSI_INVALID_LUN                  = 9
+} SCSI_TASK_MGMT_RESPONSE_CODES;
+
+/**
+ * @enum _SCSI_SENSE_RESPONSE_CODE
+ *
+ * @brief this enumeration depicts the types of sense data responses as
+ *      per SPC-3.
+ */
+typedef enum _SCSI_SENSE_RESPONSE_CODE
+{
+   SCSI_FIXED_CURRENT_RESPONSE_CODE       = 0x70,
+   SCSI_FIXED_DEFERRED_RESPONSE_CODE      = 0x71,
+   SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE  = 0x72,
+   SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE = 0x73
+
+} SCSI_SENSE_RESPONSE_CODE;
+
+/**
+ * @enum _SCSI_SENSE_DATA_DESCRIPTOR_TYPE
+ *
+ * @brief this enumeration depicts the types of sense data descriptor as
+ *      per SPC-4.
+ */
+typedef enum _SCSI_SENSE_DATA_DESCRIPTOR_TYPE
+{
+    SCSI_INFORMATION_DESCRIPTOR_TYPE                = 0x00,
+    SCSI_CMD_SPECIFIC_DESCRIPTOR_TYPE            = 0x01,
+    SCSI_KEY_SPECIFIC_DESCRIPTOR_TYPE                = 0x02,
+    SCSI_FIELD_REPLACEABLE_UNIT_DESCRIPTOR_TYPE        = 0x03,
+    SCSI_STREAM_CMD_DESCRIPTOR_TYPE                     = 0x04,
+    SCSI_BLOCK_DESCRIPTOR_TYPE                         = 0x05,
+    SCSI_OSD_OBJ_IDENTIFICATION_DESCRIPTOR_TYPE      = 0x06,
+    SCSI_OSC_RESPONSE_INTEGRITY_DESCRIPTOR_TYPE      = 0x07,
+    SCSI_OSD_ATTR_IDENTIFICATION_DESCRIPTOR_TYPE     = 0x08,
+    SCSI_ATA_STATUS_RETURN_DESCRIPTOR_TYPE            = 0x09,
+    SCSI_PROGRESS_INDICATION_DESCRIPTOR_TYPE        = 0x0a,
+    SCSI_USER_DATA_SEGEMNT_REF_DESCRIPTOR_TYPE        = 0x0b
+} SCSI_SENSE_DATA_DESCRIPTOR_TYPE;
+
+#define SCSI_CMD_SPECIFIC_DESCRIPTOR_ADDITIONAL_LENGTH    0x0a
+#define SCSI_CMD_SPECIFIC_DESCRIPTOR_LENGTH                0x0c
+#define SCSI_INFORMATION_DESCRIPTOR_ADDITIONAL_LENGTH    0x0a
+#define SCSI_INFORMATION_DESCRIPTOR_LENGTH                0x0c
+#define SCSI_BLOCK_DESCRIPTOR_ADDITIONAL_LENGTH            0x2
+#define SCSI_BLOCK_DESCRIPTOR_LENGTH                    0x4
+
+#define SCSI_SENSE_DATA_DESC_BIT    0x01
+
+// This constant represents the valid bit located in byte 0 of a FIXED
+// format sense data.
+#define SCSI_FIXED_SENSE_DATA_VALID_BIT   0x80
+
+#define SCSI_FIXED_SENSE_DATA_BASE_LENGTH 18
+
+// This value is used in the DATAPRES field of the SCSI Response IU.
+#define SCSI_RESPONSE_DATA_PRES_SENSE_DATA 0x02
+
+/**
+ * @name SCSI_SENSE_KEYS
+ *
+ * These constants delineate all of the SCSI protocol sense key constants
+ */
+/*@{*/
+#define SCSI_SENSE_NO_SENSE        0x00
+#define SCSI_SENSE_RECOVERED_ERROR 0x01
+#define SCSI_SENSE_NOT_READY       0x02
+#define SCSI_SENSE_MEDIUM_ERROR    0x03
+#define SCSI_SENSE_HARDWARE_ERROR  0x04
+#define SCSI_SENSE_ILLEGAL_REQUEST 0x05
+#define SCSI_SENSE_UNIT_ATTENTION  0x06
+#define SCSI_SENSE_DATA_PROTECT    0x07
+#define SCSI_SENSE_BLANK_CHECK     0x08
+#define SCSI_SENSE_VENDOR_SPECIFIC 0x09
+#define SCSI_SENSE_COPY_ABORTED    0x0A
+#define SCSI_SENSE_ABORTED_COMMAND 0x0B
+#define SCSI_SENSE_VOLUME_OVERFLOW 0x0D
+#define SCSI_SENSE_MISCOMPARE      0x0E
+/*@}*/
+
+/**
+ * @name SCSI_ADDITIONAL_SENSE_CODES
+ *
+ * These constants delineate all of the SCSI protocol additional sense
+ * code constants.
+ */
+/*@{*/
+#define SCSI_ASC_NO_ADDITIONAL_SENSE             0x00
+#define SCSI_ASC_INITIALIZING_COMMAND_REQUIRED   0x04
+#define SCSI_ASC_LUN_SELF_TEST_IN_PROGRESS       0x04
+#define SCSI_ASC_LUN_FORMAT_IN_PROGRESS          0x04
+#define SCSI_ASC_LUN_NOT_RESPOND_TO_SELECTION    0x05
+#define SCSI_ASC_UNRECOVERED_READ_ERROR          0x11
+#define SCSI_ASC_INVALID_COMMAND_OPERATION_CODE  0x20
+#define SCSI_ASC_LBA_OUT_OF_RANGE                0x21
+#define SCSI_ASC_INVALID_FIELD_IN_CDB            0x24
+#define SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED      0x25
+#define SCSI_ASC_INVALID_FIELD_IN_PARM_LIST      0x26
+#define SCSI_ASC_WRITE_PROTECTED                 0x27
+#define SCSI_ASC_NOT_READY_TO_READY_CHANGE       0x28
+#define SCSI_ASC_MEDIUM_FORMAT_CORRUPTED         0x31
+#define SCSI_ASC_ENCLOSURE_SERVICES_UNAVAILABLE  0x35
+#define SCSI_ASC_SAVING_PARMS_NOT_SUPPORTED      0x39
+#define SCSI_ASC_MEDIUM_NOT_PRESENT              0x3A
+#define SCSI_ASC_INTERNAL_TARGET_FAILURE         0x44
+#define SCSI_ASC_IU_CRC_ERROR_DETECTED           0x47
+#define SCSI_ASC_MEDIUM_REMOVAL_REQUEST          0x5A
+#define SCSI_ASC_COMMAND_SEQUENCE_ERROR          0x2C
+#define SCSI_ASC_MEDIA_LOAD_OR_EJECT_FAILED      0x53
+#define SCSI_ASC_HARDWARE_IMPENDING_FAILURE      0x5D
+#define SCSI_ASC_POWER_STATE_CHANGE              0x5E
+#define SCSI_DIAGNOSTIC_FAILURE_ON_COMPONENT     0x40
+#define SCSI_ASC_LOGICAL_UNIT_FAILED             0x4C
+#define SCSI_ASC_ATA_DEVICE_FEATURE_NOT_ENABLED  0x67
+#define SCSI_ASC_MICROCODE_HAS_CHANGED           0x3F
+/*@}*/
+
+/**
+ * @name SCSI_ADDITIONAL_SENSE_CODE_QUALIFIERS
+ *
+ * This enumeration contains all of the used SCSI protocol additional
+ * sense code qualifier constants.
+ */
+/*@{*/
+#define SCSI_ASCQ_NO_ADDITIONAL_SENSE                            0x00
+#define SCSI_ASCQ_INVALID_FIELD_IN_CDB                           0x00
+#define SCSI_ASCQ_INVALID_FIELD_IN_PARM_LIST                     0x00
+#define SCSI_ASCQ_LUN_NOT_RESPOND_TO_SELECTION                   0x00
+#define SCSI_ASCQ_INTERNAL_TARGET_FAILURE                        0x00
+#define SCSI_ASCQ_LBA_OUT_OF_RANGE                               0x00
+#define SCSI_ASCQ_MEDIUM_NOT_PRESENT                             0x00
+#define SCSI_ASCQ_NOT_READY_TO_READY_CHANGE                      0x00
+#define SCSI_ASCQ_WRITE_PROTECTED                                0x00
+#define SCSI_ASCQ_UNRECOVERED_READ_ERROR                         0x00
+#define SCSI_ASCQ_SAVING_PARMS_NOT_SUPPORTED                     0x00
+#define SCSI_ASCQ_INVALID_COMMAND_OPERATION_CODE                 0x00
+#define SCSI_ASCQ_MEDIUM_REMOVAL_REQUEST                         0x01
+#define SCSI_ASCQ_INITIALIZING_COMMAND_REQUIRED                  0x02
+#define SCSI_ASCQ_IU_CRC_ERROR_DETECTED                          0x03
+#define SCSI_ASCQ_LUN_FORMAT_IN_PROGRESS                         0x04
+#define SCSI_ASCQ_LUN_SELF_TEST_IN_PROGRESS                      0x09
+#define SCSI_ASCQ_GENERAL_HARD_DRIVE_FAILURE                     0x10
+#define SCSI_ASCQ_IDLE_CONDITION_ACTIVATE_BY_COMMAND             0x03
+#define SCSI_ASCQ_STANDBY_CONDITION_ACTIVATE_BY_COMMAND          0x04
+#define SCSI_ASCQ_POWER_STATE_CHANGE_TO_IDLE                     0x42
+#define SCSI_ASCQ_POWER_STATE_CHANGE_TO_STANDBY                  0x43
+#define SCSI_ASCQ_ATA_DEVICE_FEATURE_NOT_ENABLED                 0x0B
+#define SCSI_ASCQ_UNRECOVERED_READ_ERROR_AUTO_REALLOCATE_FAIL    0x04
+#define SCSI_ASCQ_ATA_PASS_THROUGH_INFORMATION_AVAILABLE         0x1D
+#define SCSI_ASCQ_MICROCODE_HAS_CHANGED                          0x01
+/*@}*/
+
+/**
+ * @name SCSI_STATUS_CODES
+ *
+ * These constants define all of the used SCSI status values.
+ */
+/*@{*/
+#define SCSI_STATUS_GOOD            0x00
+#define SCSI_STATUS_CHECK_CONDITION 0x02
+#define SCSI_STATUS_CONDITION_MET   0x04
+#define SCSI_STATUS_BUSY            0x08
+#define SCSI_STATUS_TASKFULL        0x28
+#define SCSI_STATUS_ACA             0x30
+#define SCSI_STATUS_ABORT           0x40
+/*@}*/
+
+/**
+ * @name SCSI_OPERATION_CODES
+ *
+ * These constants delineate all of the SCSI command/operation codes.
+ */
+/*@{*/
+#define SCSI_INQUIRY                0x12
+#define SCSI_READ_CAPACITY_10       0x25
+#define SCSI_SERVICE_ACTION_IN_16   0x9E
+#define SCSI_TEST_UNIT_READY        0x00
+#define SCSI_START_STOP_UNIT        0x1B
+#define SCSI_SYNCHRONIZE_CACHE_10   0x35
+#define SCSI_SYNCHRONIZE_CACHE_16   0x91
+#define SCSI_REQUEST_SENSE          0x03
+#define SCSI_REPORT_LUNS            0xA0
+#define SCSI_REASSIGN_BLOCKS        0x07
+#define SCSI_READ_6                 0x08
+#define SCSI_READ_10                0x28
+#define SCSI_READ_12                0xA8
+#define SCSI_READ_16                0x88
+#define SCSI_WRITE_6                0x0A
+#define SCSI_WRITE_10               0x2A
+#define SCSI_WRITE_12               0xAA
+#define SCSI_WRITE_16               0x8A
+#define SCSI_VERIFY_10              0x2F
+#define SCSI_VERIFY_12              0xAF
+#define SCSI_VERIFY_16              0x8F
+#define SCSI_SEEK_6                 0x01
+#define SCSI_SEEK_10                0x02
+#define SCSI_WRITE_VERIFY           0x2E
+#define SCSI_FORMAT_UNIT            0x04
+#define SCSI_READ_BUFFER            0x3C
+#define SCSI_WRITE_BUFFER           0x3B
+#define SCSI_SEND_DIAGNOSTIC        0x1D
+#define SCSI_RECEIVE_DIAGNOSTIC     0x1C
+#define SCSI_MODE_SENSE_6           0x1A
+#define SCSI_MODE_SENSE_10          0x5A
+#define SCSI_MODE_SELECT_6          0x15
+#define SCSI_MODE_SELECT_10         0x55
+#define SCSI_MAINTENANCE_IN         0xA3
+#define SCSI_LOG_SENSE              0x4D
+#define SCSI_LOG_SELECT             0x4C
+#define SCSI_RESERVE_6              0x16
+#define SCSI_RESERVE_10             0x56
+#define SCSI_RELEASE_6              0x17
+#define SCSI_RELEASE_10             0x57
+#define SCSI_ATA_PASSTHRU_12        0xA1
+#define SCSI_ATA_PASSTHRU_16        0x85
+#define SCSI_WRITE_LONG_10          0x3F
+#define SCSI_WRITE_LONG_16          0x9F
+#define SCSI_PERSISTENT_RESERVE_IN  0x5E
+#define SCSI_PERSISTENT_RESERVE_OUT 0x5F
+#define SCSI_SECURITY_PROTOCOL_IN   0xA2
+#define SCSI_SECURITY_PROTOCOL_OUT  0xB5
+#define SCSI_UNMAP                  0x42
+#define SCSI_WRITE_AND_VERIFY_10    0x2E
+#define SCSI_WRITE_AND_VERIFY_12    0xAE
+#define SCSI_WRITE_AND_VERIFY_16    0x8E
+/*@}*/
+
+/**
+ * @name SCSI_SERVICE_ACTION_IN_CODES
+ *
+ * Service action in operations.
+ */
+/*@{*/
+#define SCSI_SERVICE_ACTION_IN_CODES_READ_CAPACITY_16     0x10
+/*@}*/
+
+/**
+*
+* Service action mask.
+ */
+/*@{*/
+#define SCSI_SERVICE_ACTION_MASK 0x1f
+/*@}*/
+
+/**
+ * @name SCSI_MAINTENANCE_IN_SERVICE_ACTION_CODES
+ *
+ * MAINTENANCE IN service action codes.
+ */
+/*@{*/
+#define SCSI_REPORT_TASK_MGMT  0x0D
+#define SCSI_REPORT_OP_CODES   0x0C
+/*@}*/
+
+/**
+ * @name SCSI_MODE_PAGE_CONTROLS
+ *
+ * These constants delineate all of the used SCSI Mode Page control
+ * values.
+ */
+/*@{*/
+#define SCSI_MODE_SENSE_PC_CURRENT     0x0
+#define SCSI_MODE_SENSE_PC_CHANGEABLE  0x1
+#define SCSI_MODE_SENSE_PC_DEFAULT     0x2
+#define SCSI_MODE_SENSE_PC_SAVED       0x3
+/*@}*/
+
+#define SCSI_MODE_SENSE_PC_SHIFT           0x06
+#define SCSI_MODE_SENSE_PAGE_CODE_ENABLE   0x3F
+#define SCSI_MODE_SENSE_DBD_ENABLE         0x08
+#define SCSI_MODE_SENSE_LLBAA_ENABLE       0x10
+
+#define SCSI_MODE_PAGE_CONTROL_D_SENSE_DISABLE  0x0
+#define SCSI_MODE_PAGE_CONTROL_D_SENSE_ENABLE    0x1
+/**
+ * @name SCSI_MODE_PAGE_CODES
+ *
+ * These constants delineate all of the used SCSI Mode Page codes.
+ */
+/*@{*/
+#define SCSI_MODE_PAGE_READ_WRITE_ERROR           0x01
+#define SCSI_MODE_PAGE_DISCONNECT_RECONNECT       0x02
+#define SCSI_MODE_PAGE_CACHING                    0x08
+#define SCSI_MODE_PAGE_CONTROL                    0x0A
+#define SCSI_MODE_PAGE_PROTOCOL_SPECIFIC_PORT     0x19
+#define SCSI_MODE_PAGE_POWER_CONDITION            0x1A
+#define SCSI_MODE_PAGE_INFORMATIONAL_EXCP_CONTROL 0x1C
+#define SCSI_MODE_PAGE_ALL_PAGES                  0x3F
+/*@}*/
+
+#define SCSI_MODE_SENSE_ALL_SUB_PAGES_CODE         0xFF
+#define SCSI_MODE_SENSE_NO_SUB_PAGES_CODE          0x0
+#define SCSI_MODE_SENSE_PROTOCOL_PORT_NUM_SUBPAGES 0x1
+#define SCSI_MODE_PAGE_CACHE_PAGE_WCE_BIT          0x04
+#define SCSI_MODE_PAGE_CACHE_PAGE_DRA_BIT          0x20
+#define SCSI_MODE_PAGE_DEXCPT_ENABLE               0x08
+#define SCSI_MODE_SENSE_HEADER_FUA_ENABLE          0x10
+#define SCSI_MODE_PAGE_POWER_CONDITION_STANDBY     0x1
+#define SCSI_MODE_PAGE_POWER_CONDITION_IDLE        0x2
+
+#define SCSI_MODE_SENSE_6_HEADER_LENGTH              4
+#define SCSI_MODE_SENSE_10_HEADER_LENGTH             8
+#define SCSI_MODE_SENSE_STD_BLOCK_DESCRIPTOR_LENGTH  8
+#define SCSI_MODE_SENSE_LLBA_BLOCK_DESCRIPTOR_LENGTH 16
+
+#define SCSI_MODE_PAGE_INFORMATIONAL_EXCP_DXCPT_ENABLE 0x08
+#define SCSI_MODE_PAGE_19_SAS_ID         0x6
+#define SCSI_MODE_PAGE_19_SUB1_PAGE_NUM  0x1
+#define SCSI_MODE_PAGE_19_SUB1_PC        0x59
+
+#define SCSI_MODE_HEADER_MEDIUM_TYPE_SBC 0x00
+
+//Mode Select constrains related masks value
+#define SCSI_MODE_SELECT_PF_BIT                       0x1
+#define SCSI_MODE_SELECT_PF_MASK                      0x10
+#define SCSI_MODE_SELECT_MODE_PAGE_MRIE_BYTE          0x6
+#define SCSI_MODE_SELECT_MODE_PAGE_MRIE_MASK          0x0F
+#define SCSI_MODE_SELECT_MODE_PAGE_SPF_MASK           0x40
+#define SCSI_MODE_SELECT_MODE_PAGE_01_AWRE_MASK       0x80
+#define SCSI_MODE_SELECT_MODE_PAGE_01_ARRE_MASK       0x40
+#define SCSI_MODE_SELECT_MODE_PAGE_01_RC_ERBITS_MASK  0x1F
+#define SCSI_MODE_SELECT_MODE_PAGE_08_FSW_LBCSS_NVDIS 0xC1
+#define SCSI_MODE_SELECT_MODE_PAGE_1C_PERF_TEST       0x84
+#define SCSI_MODE_SELECT_MODE_PAGE_0A_TST_TMF_RLEC    0xF1
+#define SCSI_MODE_SELECT_MODE_PAGE_0A_MODIFIER        0xE0
+#define SCSI_MODE_SELECT_MODE_PAGE_0A_UA_SWP          0x38
+#define SCSI_MODE_SELECT_MODE_PAGE_0A_TAS_AUTO        0x47
+#define SCSI_MODE_SELECT_MODE_PAGE_D_SENSE            0x4
+
+#define SCSI_CONTROL_BYTE_NACA_BIT_ENABLE  0x04
+#define SCSI_MOVE_FUA_BIT_ENABLE           0x08
+#define SCSI_READ_CAPACITY_PMI_BIT_ENABLE  0x01
+#define SCSI_READ_CAPACITY_10_DATA_LENGTH  8
+#define SCSI_READ_CAPACITY_16_DATA_LENGTH  32
+
+// Inquiry constants
+#define SCSI_INQUIRY_EVPD_ENABLE          0x01
+#define SCSI_INQUIRY_PAGE_CODE_OFFSET     0x02
+#define SCSI_INQUIRY_SUPPORTED_PAGES_PAGE 0x00
+#define SCSI_INQUIRY_UNIT_SERIAL_NUM_PAGE 0x80
+#define SCSI_INQUIRY_DEVICE_ID_PAGE       0x83
+#define SCSI_INQUIRY_ATA_INFORMATION_PAGE 0x89
+#define SCSI_INQUIRY_BLOCK_DEVICE_PAGE    0xB1
+#define SCSI_INQUIRY_BLOCK_DEVICE_LENGTH  0x3C
+#define SCSI_INQUIRY_STANDARD_ALLOCATION_LENGTH 0x24 //36
+
+#define SCSI_REQUEST_SENSE_ALLOCATION_LENGTH   0xFC  //252
+
+/** Defines the log page codes that are use in gathing Smart data
+*/
+#define SCSI_LOG_PAGE_SUPPORTED_PAGES       0x00
+#define SCSI_LOG_PAGE_INFORMATION_EXCEPTION 0x2F
+#define SCSI_LOG_PAGE_SELF_TEST             0x10
+
+/**
+ * @name SCSI_INQUIRY_VPD
+ *
+ * The following are constants used with vital product data inquiry pages.
+ * Values are already shifted into the proper nibble location.
+ */
+/*@{*/
+#define SCSI_PIV_ENABLE                 0x80
+#define SCSI_LUN_ASSOCIATION            0x00
+#define SCSI_TARGET_PORT_ASSOCIATION    0x10
+
+#define SCSI_VEN_UNIQUE_IDENTIFIER_TYPE 0x00
+#define SCSI_NAA_IDENTIFIER_TYPE        0x03
+
+#define SCSI_T10_IDENTIFIER_TYPE        0x01
+#define SCSI_BINARY_CODE_SET            0x01
+#define SCSI_ASCII_CODE_SET             0x02
+#define SCSI_FC_PROTOCOL_IDENTIFIER     0x00
+#define SCSI_SAS_PROTOCOL_IDENTIFIER    0x60
+/*@}*/
+
+#define SCSI_VERIFY_BYTCHK_ENABLED      0x02
+
+#define SCSI_SYNCHRONIZE_CACHE_IMMED_ENABLED 0x02
+/**
+ * @name SCSI_START_STOP_UNIT_POWER_CONDITION_CODES
+ *
+ * The following are SCSI Start Stop Unit command Power Condition codes.
+ */
+/*@{*/
+#define SCSI_START_STOP_UNIT_POWER_CONDITION_START_VALID       0x0
+#define SCSI_START_STOP_UNIT_POWER_CONDITION_ACTIVE            0x1
+#define SCSI_START_STOP_UNIT_POWER_CONDITION_IDLE              0x2
+#define SCSI_START_STOP_UNIT_POWER_CONDITION_STANDBY           0x3
+#define SCSI_START_STOP_UNIT_POWER_CONDITION_LU_CONTROL        0x7
+#define SCSI_START_STOP_UNIT_POWER_CONDITION_FORCE_S_CONTROL   0xB
+/*@}*/
+
+#define SCSI_START_STOP_UNIT_IMMED_MASK            0x1
+#define SCSI_START_STOP_UNIT_IMMED_SHIFT           0
+
+#define SCSI_START_STOP_UNIT_START_BIT_MASK        0x1
+#define SCSI_START_STOP_UNIT_START_BIT_SHIFT       0
+
+#define SCSI_START_STOP_UNIT_LOEJ_BIT_MASK         0x2
+#define SCSI_START_STOP_UNIT_LOEJ_BIT_SHIFT        1
+
+#define SCSI_START_STOP_UNIT_NO_FLUSH_MASK         0x4
+#define SCSI_START_STOP_UNIT_NO_FLUSH_SHIFT        2
+
+#define SCSI_START_STOP_UNIT_POWER_CONDITION_MODIFIER_MASK   0xF
+#define SCSI_START_STOP_UNIT_POWER_CONDITION_MODIFIER_SHIFT  0
+
+#define SCSI_START_STOP_UNIT_POWER_CONDITION_MASK  0xF0
+#define SCSI_START_STOP_UNIT_POWER_CONDITION_SHIFT 4
+
+#define SCSI_LOG_SENSE_PC_FIELD_MASK      0xC0
+#define SCSI_LOG_SENSE_PC_FIELD_SHIFT     6
+
+#define SCSI_LOG_SENSE_PAGE_CODE_FIELD_MASK      0x3F
+#define SCSI_LOG_SENSE_PAGE_CODE_FIELD_SHIFT     0
+
+/**
+ * @name MRIE - Method of reporting informational exceptions codes
+ */
+/*@{*/
+#define NO_REPORTING_INFO_EXCEPTION_CONDITION      0x0
+#define ASYNCHRONOUS_EVENT_REPORTING               0x1
+#define ESTABLISH_UNIT_ATTENTION_CONDITION         0x2
+#define CONDITIONALLY_GENERATE_RECOVERED_ERROR     0x3
+#define UNCONDITIONALLY_GENERATE_RECOVERED_ERROR   0x4
+#define GENERATE_NO_SENSE                          0x5
+#define REPORT_INFO_EXCEPTION_CONDITION_ON_REQUEST 0x6
+/*@}*/
+
+#define SCSI_INFORMATION_EXCEPTION_DEXCPT_BIT      0x08
+
+//Reassign Blocks masks
+#define SCSI_REASSIGN_BLOCKS_LONGLBA_BIT           0x02
+#define SCSI_REASSIGN_BLOCKS_LONGLIST_BIT          0x01
+
+#endif // _SCSI_H_
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,1250 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains all of the method implementations that
+ *        can be utilized by a user to perform SCSI-to-ATA Translation.
+ *        SATI adheres to the www.t10.org SAT specification.
+ *
+ * For situations where compliance is not observed, the SATI will
+ * return an error indication (most likely INVALID FIELD IN CDB sense data).
+ */
+
+#include <dev/isci/scil/sati.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/sati_report_luns.h>
+#include <dev/isci/scil/sati_inquiry.h>
+#include <dev/isci/scil/sati_mode_sense_6.h>
+#include <dev/isci/scil/sati_mode_sense_10.h>
+#include <dev/isci/scil/sati_mode_select.h>
+#include <dev/isci/scil/sati_test_unit_ready.h>
+#include <dev/isci/scil/sati_read_capacity.h>
+#include <dev/isci/scil/sati_read.h>
+#include <dev/isci/scil/sati_write.h>
+#include <dev/isci/scil/sati_verify.h>
+#include <dev/isci/scil/sati_synchronize_cache.h>
+#include <dev/isci/scil/sati_lun_reset.h>
+#include <dev/isci/scil/sati_start_stop_unit.h>
+#include <dev/isci/scil/sati_request_sense.h>
+#include <dev/isci/scil/sati_write_long.h>
+#include <dev/isci/scil/sati_reassign_blocks.h>
+#include <dev/isci/scil/sati_log_sense.h>
+#include <dev/isci/scil/sati_abort_task_set.h>
+#include <dev/isci/scil/sati_unmap.h>
+#include <dev/isci/scil/sati_passthrough.h>
+#include <dev/isci/scil/sati_write_and_verify.h>
+#include <dev/isci/scil/sati_read_buffer.h>
+#include <dev/isci/scil/sati_write_buffer.h>
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_scsi.h>
+#include <dev/isci/scil/intel_sat.h>
+
+//******************************************************************************
+//* P R I V A T E   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method performs the translation of ATA error register values
+ *        into SCSI sense data.
+ *        For more information on the parameter passed to this method please
+ *        reference the sati_translate_response() method.
+ *
+ * @param[in] error This parameter specifies the contents of the ATA error
+ *            register to be translated.
+ *
+ * @return none
+ */
+void sati_translate_error(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   U8                           error
+)
+{
+   if (error & ATA_ERROR_REG_NO_MEDIA_BIT)
+   {
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_NOT_READY,
+         SCSI_ASC_MEDIUM_NOT_PRESENT,
+         SCSI_ASCQ_MEDIUM_NOT_PRESENT
+      );
+   }
+   else if (error & ATA_ERROR_REG_MEDIA_CHANGE_BIT)
+   {
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_UNIT_ATTENTION,
+         SCSI_ASC_NOT_READY_TO_READY_CHANGE,
+         SCSI_ASCQ_NOT_READY_TO_READY_CHANGE
+      );
+   }
+   else if (error & ATA_ERROR_REG_MEDIA_CHANGE_REQUEST_BIT)
+   {
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_UNIT_ATTENTION,
+         SCSI_ASC_MEDIUM_REMOVAL_REQUEST,
+         SCSI_ASCQ_MEDIUM_REMOVAL_REQUEST
+      );
+   }
+   else if (error & ATA_ERROR_REG_ID_NOT_FOUND_BIT)
+   {
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_ILLEGAL_REQUEST,
+         SCSI_ASC_LBA_OUT_OF_RANGE,
+         SCSI_ASCQ_LBA_OUT_OF_RANGE
+      );
+   }
+   else if (error & ATA_ERROR_REG_UNCORRECTABLE_BIT)
+   {
+      //Mark the Sequence state as a read error so more sense data
+      //can be returned later
+      sequence->state = SATI_SEQUENCE_STATE_READ_ERROR;
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_MEDIUM_ERROR,
+         SCSI_ASC_UNRECOVERED_READ_ERROR,
+         SCSI_ASCQ_UNRECOVERED_READ_ERROR
+      );
+   }
+   else if (  (sequence->data_direction == SATI_DATA_DIRECTION_OUT)
+           && (error & ATA_ERROR_REG_WRITE_PROTECTED_BIT) )
+   {
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_DATA_PROTECT,
+         SCSI_ASC_WRITE_PROTECTED,
+         SCSI_ASCQ_WRITE_PROTECTED
+      );
+   }
+   else if (error & ATA_ERROR_REG_ICRC_BIT)
+   {
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_ABORTED_COMMAND,
+         SCSI_ASC_IU_CRC_ERROR_DETECTED,
+         SCSI_ASCQ_IU_CRC_ERROR_DETECTED
+      );
+   }
+   else // (error & ATA_ERROR_REG_ABORT_BIT)
+   {
+      // The ABORT bit has the lowest precedence of all errors.
+      // As a result, it is at the bottom of the conditional
+      // statement.
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_ABORTED_COMMAND,
+         SCSI_ASC_NO_ADDITIONAL_SENSE,
+         SCSI_ASCQ_NO_ADDITIONAL_SENSE
+      );
+   }
+}
+
+/**
+ * @brief This method translates the supplied ATA payload data into the
+ *        corresponding SCSI data.  This is necessary for SCSI commands
+ *        that have well-defined payload data associated with them (e.g.
+ *        READ CAPACITY).
+ *
+ * @param[in]  sequence This parameter specifies the sequence
+ *             data associated with the translation.
+ * @param[in]  ata_io This parameter specifies the ATA payload
+ *             buffer location and size to be translated.
+ * @param[out] scsi_output_data This parameter specifies the SCSI payload
+ *             memory area into which the translator is to write.
+ *
+ * @return none
+ */
+static
+void sati_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+)
+{
+   // Update the device capabilities in the odd/crazy event something changed.
+   sati_device_update_capabilities(
+      sequence->device, (ATA_IDENTIFY_DEVICE_DATA_T*) ata_input_data
+   );
+
+   // Look at the first byte to determine the SCSI command to translate.
+   switch (sequence->type)
+   {
+#if !defined(DISABLE_SATI_INQUIRY)
+      case SATI_SEQUENCE_INQUIRY_STANDARD:
+         sati_inquiry_standard_translate_data(
+            sequence, ata_input_data, scsi_io
+         );
+      break;
+
+      case SATI_SEQUENCE_INQUIRY_SERIAL_NUMBER:
+         sati_inquiry_serial_number_translate_data(
+            sequence, ata_input_data, scsi_io
+         );
+      break;
+
+      case SATI_SEQUENCE_INQUIRY_DEVICE_ID:
+         sati_inquiry_device_id_translate_data(
+            sequence, ata_input_data, scsi_io
+         );
+      break;
+
+      case SATI_SEQUENCE_INQUIRY_BLOCK_DEVICE:
+         sati_inquiry_block_device_translate_data(
+            sequence, ata_input_data, scsi_io
+         );
+      break;
+
+      case SATI_SEQUENCE_INQUIRY_ATA_INFORMATION:
+         sati_inquiry_ata_information_translate_data(
+            sequence, ata_input_data, scsi_io
+         );
+      break;
+
+#endif // !defined(DISABLE_SATI_INQUIRY)
+
+#if !defined(DISABLE_SATI_READ_CAPACITY)
+      case SATI_SEQUENCE_READ_CAPACITY_10:
+         sati_read_capacity_10_translate_data(sequence, ata_input_data, scsi_io);
+      break;
+
+      case SATI_SEQUENCE_READ_CAPACITY_16:
+         sati_read_capacity_16_translate_data(sequence, ata_input_data, scsi_io);
+      break;
+#endif // !defined(DISABLE_SATI_READ_CAPACITY)
+
+#if !defined(DISABLE_SATI_MODE_SENSE)
+      case SATI_SEQUENCE_MODE_SENSE_6_CACHING:
+         sati_mode_sense_6_caching_translate_data(
+            sequence, ata_input_data, scsi_io
+         );
+      break;
+
+      case SATI_SEQUENCE_MODE_SENSE_6_INFORMATIONAL_EXCP_CONTROL:
+         sati_mode_sense_6_informational_excp_control_translate_data(
+            sequence, ata_input_data, scsi_io
+         );
+      break;
+
+      case SATI_SEQUENCE_MODE_SENSE_6_READ_WRITE_ERROR:
+         sati_mode_sense_6_read_write_error_translate_data(
+            sequence, ata_input_data, scsi_io
+         );
+      break;
+
+      case SATI_SEQUENCE_MODE_SENSE_6_DISCONNECT_RECONNECT:
+         sati_mode_sense_6_disconnect_reconnect_translate_data(
+            sequence, ata_input_data, scsi_io
+         );
+      break;
+
+      case SATI_SEQUENCE_MODE_SENSE_6_CONTROL:
+         sati_mode_sense_6_control_translate_data(
+            sequence, ata_input_data, scsi_io
+         );
+      break;
+
+      case SATI_SEQUENCE_MODE_SENSE_6_ALL_PAGES:
+         sati_mode_sense_6_all_pages_translate_data(
+            sequence, ata_input_data, scsi_io
+         );
+      break;
+
+      case SATI_SEQUENCE_MODE_SENSE_6_POWER_CONDITION:
+         sati_mode_sense_6_power_condition_translate_data(
+            sequence, ata_input_data, scsi_io
+         );
+      break;
+
+      case SATI_SEQUENCE_MODE_SENSE_10_POWER_CONDITION:
+         sati_mode_sense_10_power_condition_translate_data(
+            sequence, ata_input_data, scsi_io
+         );
+      break;
+
+      case SATI_SEQUENCE_MODE_SENSE_10_CACHING:
+         sati_mode_sense_10_caching_translate_data(
+            sequence, ata_input_data, scsi_io
+         );
+      break;
+
+      case SATI_SEQUENCE_MODE_SENSE_10_INFORMATIONAL_EXCP_CONTROL:
+         sati_mode_sense_10_informational_excp_control_translate_data(
+            sequence, ata_input_data, scsi_io
+         );
+      break;
+
+      case SATI_SEQUENCE_MODE_SENSE_10_READ_WRITE_ERROR:
+         sati_mode_sense_10_read_write_error_translate_data(
+            sequence, ata_input_data, scsi_io
+         );
+      break;
+
+      case SATI_SEQUENCE_MODE_SENSE_10_DISCONNECT_RECONNECT:
+         sati_mode_sense_10_disconnect_reconnect_translate_data(
+            sequence, ata_input_data, scsi_io
+         );
+      break;
+
+      case SATI_SEQUENCE_MODE_SENSE_10_CONTROL:
+         sati_mode_sense_10_control_translate_data(
+            sequence, ata_input_data, scsi_io
+         );
+      break;
+
+      case SATI_SEQUENCE_MODE_SENSE_10_ALL_PAGES:
+         sati_mode_sense_10_all_pages_translate_data(
+            sequence, ata_input_data, scsi_io
+         );
+      break;
+#endif // !defined(DISABLE_SATI_MODE_SENSE)
+
+      default:
+      break;
+   }
+}
+
+//******************************************************************************
+//* P U B L I C   M E T H O D S
+//******************************************************************************
+
+SATI_STATUS sati_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   SATI_DEVICE_T              * sati_device,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   SATI_STATUS   status = SATI_FAILURE;
+   U8          * cdb = sati_cb_get_cdb_address(scsi_io);
+
+   //No sense response has been set for the translation sequence yet
+   sequence->is_sense_response_set          = FALSE;
+   // Default to no translation response required
+   sequence->is_translate_response_required = FALSE;
+   // Assign sati_device to sequence
+   sequence->device  = sati_device;
+
+   /**
+    * Fail any I/O request with LUN != 0
+    */
+   if (sati_cb_get_lun(scsi_io) != 0)
+   {
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_ILLEGAL_REQUEST,
+         SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED,
+         0
+      );
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+
+   /**
+    * SAT dictates:
+    * - the NACA bit in the control byte (last byte) must be 0
+    */
+   if ( (sati_get_cdb_byte(cdb, sati_cb_get_cdb_length(scsi_io) - 1)
+         & SCSI_CONTROL_BYTE_NACA_BIT_ENABLE))
+   {
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_ILLEGAL_REQUEST,
+         SCSI_ASC_INVALID_FIELD_IN_CDB,
+         SCSI_ASCQ_INVALID_FIELD_IN_CDB
+      );
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+
+   /**
+    * Per SAT "Error and sense reporting" section.  All subsequent IOs after
+    * a device fault should receive INTERNAL TARGET FAILURE sense data.
+    */
+   if (sati_device->state == SATI_DEVICE_STATE_DEVICE_FAULT_OCCURRED)
+   {
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_HARDWARE_ERROR,
+         SCSI_ASC_INTERNAL_TARGET_FAILURE,
+         SCSI_ASCQ_INTERNAL_TARGET_FAILURE
+      );
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+
+   if(sequence->state == SATI_SEQUENCE_STATE_INITIAL)
+   {
+      sequence->command_specific_data.scratch = 0;
+      sequence->number_data_bytes_set = 0;
+   }
+
+
+#ifdef SATI_TRANSPORT_SUPPORTS_SATA
+   {
+      U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+      sati_set_sata_command_flag(register_fis);
+      sati_set_sata_fis_type(register_fis, SATA_FIS_TYPE_REGH2D);
+   }
+#endif // SATI_TRANSPORT_SUPPORTS_SATA
+
+   // Look at the first byte to determine the SCSI command to translate.
+   switch (sati_get_cdb_byte(cdb, 0))
+   {
+#if !defined(DISABLE_SATI_REPORT_LUNS)
+      case SCSI_REPORT_LUNS:
+         status = sati_report_luns_translate_command(
+                     sequence, scsi_io, ata_io
+                  );
+      break;
+#endif // !defined(DISABLE_SATI_REPORT_LUNS)
+
+#if !defined(DISABLE_SATI_INQUIRY)
+      case SCSI_INQUIRY:
+         status = sati_inquiry_translate_command(
+                     sequence, scsi_io, ata_io
+                  );
+      break;
+#endif // !defined(DISABLE_SATI_INQUIRY)
+
+#if !defined(DISABLE_SATI_MODE_SENSE)
+      case SCSI_MODE_SENSE_6:
+         status = sati_mode_sense_6_translate_command(
+                     sequence, scsi_io, ata_io
+                  );
+      break;
+
+      case SCSI_MODE_SENSE_10:
+         status = sati_mode_sense_10_translate_command(
+                     sequence, scsi_io, ata_io
+                  );
+      break;
+#endif // !defined(DISABLE_SATI_MODE_SENSE)
+
+#if !defined(DISABLE_SATI_MODE_SELECT)
+      case SCSI_MODE_SELECT_6:
+         status = sati_mode_select_6_translate_command(
+                     sequence, scsi_io, ata_io
+                  );
+      break;
+
+      case SCSI_MODE_SELECT_10:
+         status = sati_mode_select_10_translate_command(
+                     sequence, scsi_io, ata_io
+                  );
+      break;
+#endif // !defined(DISABLE_SATI_MODE_SELECT)
+
+#if !defined(DISABLE_SATI_TEST_UNIT_READY)
+      case SCSI_TEST_UNIT_READY:
+         status = sati_test_unit_ready_translate_command(
+                     sequence, scsi_io, ata_io
+                  );
+      break;
+#endif // !defined(DISABLE_SATI_TEST_UNIT_READY)
+
+#if !defined(DISABLE_SATI_READ_CAPACITY)
+      case SCSI_READ_CAPACITY_10:
+         status = sati_read_capacity_10_translate_command(
+                     sequence, scsi_io, ata_io
+                  );
+      break;
+
+      case SCSI_SERVICE_ACTION_IN_16:
+         if ( (sati_get_cdb_byte(cdb, 1) & SCSI_SERVICE_ACTION_MASK)
+              == SCSI_SERVICE_ACTION_IN_CODES_READ_CAPACITY_16)
+            status = sati_read_capacity_16_translate_command(
+                        sequence, scsi_io, ata_io
+                     );
+         else
+            status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+      break;
+#endif // !defined(DISABLE_SATI_READ_CAPACITY)
+
+#if !defined(DISABLE_SATI_REQUEST_SENSE)
+      case SCSI_REQUEST_SENSE:
+         status = sati_request_sense_translate_command(
+                     sequence, scsi_io, ata_io
+                  );
+      break;
+#endif // !defined(DISABLE_SATI_REQUEST_SENSE)
+
+      case SCSI_READ_6:
+         status = sati_read_6_translate_command(sequence, scsi_io, ata_io);
+      break;
+
+      case SCSI_READ_10:
+         status = sati_read_10_translate_command(sequence, scsi_io, ata_io);
+      break;
+
+      case SCSI_READ_12:
+         status = sati_read_12_translate_command(sequence, scsi_io, ata_io);
+      break;
+
+      case SCSI_READ_16:
+         status = sati_read_16_translate_command(sequence, scsi_io, ata_io);
+      break;
+
+      case SCSI_WRITE_6:
+         status = sati_write_6_translate_command(sequence, scsi_io, ata_io);
+      break;
+
+      case SCSI_WRITE_10:
+         status = sati_write_10_translate_command(sequence, scsi_io, ata_io);
+      break;
+
+      case SCSI_WRITE_12:
+         status = sati_write_12_translate_command(sequence, scsi_io, ata_io);
+      break;
+
+      case SCSI_WRITE_16:
+         status = sati_write_16_translate_command(sequence, scsi_io, ata_io);
+      break;
+
+#if !defined(DISABLE_SATI_VERIFY)
+      case SCSI_VERIFY_10:
+         status = sati_verify_10_translate_command(sequence, scsi_io, ata_io);
+      break;
+
+      case SCSI_VERIFY_12:
+         status = sati_verify_12_translate_command(sequence, scsi_io, ata_io);
+      break;
+
+      case SCSI_VERIFY_16:
+         status = sati_verify_16_translate_command(sequence, scsi_io, ata_io);
+      break;
+#endif // !defined(DISABLE_SATI_VERIFY)
+
+#if    !defined(DISABLE_SATI_WRITE_AND_VERIFY)  \
+   && !defined(DISABLE_SATI_VERIFY)        \
+   && !defined(DISABLE_SATI_WRITE)
+
+      case SCSI_WRITE_AND_VERIFY_10:
+         status = sati_write_and_verify_10_translate_command(sequence, scsi_io, ata_io);
+      break;
+
+      case SCSI_WRITE_AND_VERIFY_12:
+         status = sati_write_and_verify_12_translate_command(sequence, scsi_io, ata_io);
+      break;
+
+      case SCSI_WRITE_AND_VERIFY_16:
+         status = sati_write_and_verify_16_translate_command(sequence, scsi_io, ata_io);
+      break;
+#endif //    !defined(DISABLE_SATI_WRITE_AND_VERIFY)
+      // && !defined(DISABLE_SATI_VERIFY)
+      // && !defined(DISABLE_SATI_WRITE)
+
+#if !defined(DISABLE_SATI_REASSIGN_BLOCKS)
+      case SCSI_REASSIGN_BLOCKS:
+         status = sati_reassign_blocks_translate_command(sequence, scsi_io, ata_io);
+      break;
+#endif // !defined(DISABLE_SATI_REASSIGN_BLOCKS)
+
+#if !defined(DISABLE_SATI_SYNCHRONIZE_CACHE)
+      case SCSI_SYNCHRONIZE_CACHE_10:
+      case SCSI_SYNCHRONIZE_CACHE_16:
+         status = sati_synchronize_cache_translate_command(sequence, scsi_io, ata_io);
+      break;
+#endif // !defined(DISABLE_SATI_SYNCHRONIZE_CACHE)
+
+#if !defined(DISABLE_SATI_START_STOP_UNIT)
+      case SCSI_START_STOP_UNIT:
+         status = sati_start_stop_unit_translate_command(
+                     sequence, scsi_io, ata_io
+                  );
+      break;
+#endif // !defined(DISABLE_SATI_START_STOP_UNIT)
+
+#if !defined(DISABLE_SATI_WRITE_LONG)
+      case SCSI_WRITE_LONG_10:
+      case SCSI_WRITE_LONG_16:
+         status = sati_write_long_translate_command(sequence, scsi_io, ata_io);
+      break;
+#endif // !defined(DISABLE_SATI_WRITE_LONG)
+
+#if !defined(DISABLE_SATI_LOG_SENSE)
+      case SCSI_LOG_SENSE:
+         status = sati_log_sense_translate_command(sequence, scsi_io, ata_io);
+      break;
+#endif // !defined(DISABLE_SATI_LOG_SENSE)
+
+      case SCSI_PERSISTENT_RESERVE_IN:
+      case SCSI_PERSISTENT_RESERVE_OUT:
+         //These commands are not supported by SATI
+         sati_scsi_sense_data_construct(
+            sequence,
+            scsi_io,
+            SCSI_STATUS_CHECK_CONDITION,
+            SCSI_SENSE_ILLEGAL_REQUEST,
+            SCSI_ASC_INVALID_COMMAND_OPERATION_CODE,
+            SCSI_ASCQ_INVALID_COMMAND_OPERATION_CODE
+         );
+         //returning status now to keep sense data set above
+         return SATI_FAILURE_CHECK_RESPONSE_DATA;
+      break;
+
+#if !defined(DISABLE_SATI_UNMAP)
+      case SCSI_UNMAP:
+         status = sati_unmap_translate_command(sequence, scsi_io, ata_io);
+      break;
+#endif // !defined(DISABLE_SATI_UNMAP)
+
+#if !defined(DISABLE_SATI_ATA_PASSTHROUGH)
+      case SCSI_ATA_PASSTHRU_12:
+          status = sati_passthrough_12_translate_command(sequence, scsi_io, ata_io);
+      break;
+
+      case SCSI_ATA_PASSTHRU_16:
+          status = sati_passthrough_16_translate_command(sequence, scsi_io, ata_io);
+      break;
+
+#endif // !define(DISABLE_SATI_ATA_PASSTHRU)
+
+#if !defined(DISABLE_SATI_READ_BUFFER)
+      case SCSI_READ_BUFFER:
+         status = sati_read_buffer_translate_command(sequence, scsi_io, ata_io);
+      break;
+#endif //!defined(DISABLE_SATI_READ_BUFFER)
+
+#if !defined(DISABLE_SATI_WRITE_BUFFER)
+      case SCSI_WRITE_BUFFER:
+         status = sati_write_buffer_translate_command(sequence, scsi_io, ata_io);
+      break;
+#endif //!defined(DISABLE_SATI_WRITE_BUFFER)
+      default:
+         status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+      break;
+   }
+
+   if( (status == SATI_FAILURE_CHECK_RESPONSE_DATA) &&
+       !(sequence->is_sense_response_set) )
+   {
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_ILLEGAL_REQUEST,
+         SCSI_ASC_INVALID_FIELD_IN_CDB,
+         SCSI_ASCQ_INVALID_FIELD_IN_CDB
+      );
+   }
+   return status;
+}
+
+// -----------------------------------------------------------------------------
+
+#if !defined(DISABLE_SATI_TASK_MANAGEMENT)
+SATI_STATUS sati_translate_task_management(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   SATI_DEVICE_T              * sati_device,
+   void                       * scsi_task,
+   void                       * ata_io
+)
+{
+   SATI_STATUS status=SATI_FAILURE;
+   U8 task_function = sati_cb_get_task_function(scsi_task);
+
+   sequence->device = sati_device;
+
+   switch (task_function)
+   {
+      /**
+       * @todo We need to update the ABORT_TASK and ABORT_TASK_SET to be
+       *       SAT compliant.
+       */
+      case SCSI_TASK_REQUEST_ABORT_TASK:
+      case SCSI_TASK_REQUEST_LOGICAL_UNIT_RESET:
+         status = sati_lun_reset_translate_command(sequence, scsi_task, ata_io);
+      break;
+
+      case SCSI_TASK_REQUEST_ABORT_TASK_SET:
+#if !defined(DISABLE_SATI_ABORT_TASK_SET)
+         status = sati_abort_task_set_translate_command(sequence, scsi_task, ata_io);
+#else
+         status = SATI_FAILURE;
+#endif
+         break;
+      default:
+         status = SATI_FAILURE;
+      break;
+   }
+
+   return status;
+}
+#endif // !defined(DISABLE_SATI_TASK_MANAGEMENT)
+
+// -----------------------------------------------------------------------------
+#if      !defined(DISABLE_SATI_INQUIRY)            \
+      || !defined(DISABLE_SATI_READY_CAPACITY)     \
+      || !defined(DISABLE_SATI_MODE_SENSE)         \
+      || !defined(DISABLE_SATI_MODE_SELECT)        \
+      || !defined(DISABLE_SATI_REASSIGN_BLOCKS)    \
+      || !defined(DISABLE_SATI_START_STOP_UNIT)    \
+      || !defined(DISABLE_SATI_REQUEST_SENSE)      \
+      || !defined(DISABLE_SATI_WRITE_LONG)         \
+      || !defined(DISABLE_SATI_LOG_SENSE)          \
+      || !defined(DISABLE_SATI_UNMAP)
+
+static
+SATI_STATUS sati_check_data_io(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence
+)
+{
+   if(sequence->state == SATI_SEQUENCE_STATE_INCOMPLETE)
+   {
+      return SATI_SEQUENCE_INCOMPLETE;
+   }
+   else if(sequence->number_data_bytes_set < sequence->allocation_length)
+   {
+      return SATI_COMPLETE_IO_DONE_EARLY;
+   }
+   else
+   {
+      return SATI_COMPLETE;
+   }
+}
+#endif   //    !defined(DISABLE_SATI_INQUIRY)
+         // || !defined(DISABLE_SATI_READY_CAPACITY)
+         // || !defined(DISABLE_SATI_MODE_SENSE)
+         // || !defined(DISABLE_SATI_MODE_SELECT)
+         // || !defined(DISABLE_SATI_REASSIGN_BLOCKS)
+         // || !defined(DISABLE_SATI_START_STOP_UNIT)
+         // || !defined(DISABLE_SATI_REQUEST_SENSE)
+         // || !defined(DISABLE_SATI_WRITE_LONG)
+         // || !defined(DISABLE_SATI_LOG_SENSE)
+         // || !defined(DISABLE_SATI_UNMAP)
+// -----------------------------------------------------------------------------
+SATI_STATUS sati_translate_command_response(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   SATI_STATUS   status       = SATI_COMPLETE;
+   U8          * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
+   U8            ata_status;
+
+   /**
+    * If the device fault bit is set in the status register, then
+    * set the sense data and return.
+    */
+   ata_status = (U8) sati_get_ata_status(register_fis);
+   if (ata_status & ATA_STATUS_REG_DEVICE_FAULT_BIT)
+   {
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_HARDWARE_ERROR,
+         SCSI_ASC_INTERNAL_TARGET_FAILURE,
+         SCSI_ASCQ_INTERNAL_TARGET_FAILURE
+      );
+
+      sequence->device->state = SATI_DEVICE_STATE_DEVICE_FAULT_OCCURRED;
+
+      // Make sure that the terminate sequence is called to allow
+      // translation logic to perform any cleanup before the IO is completed.
+      sati_sequence_terminate(sequence,
+                              scsi_io,
+                              ata_io);
+
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+
+   // Look at the sequence type to determine the response translation method
+   // to invoke.
+   switch (sequence->type)
+   {
+#if !defined(DISABLE_SATI_TEST_UNIT_READY)
+      case SATI_SEQUENCE_TEST_UNIT_READY:
+         status = sati_test_unit_ready_translate_response(
+                     sequence, scsi_io, ata_io
+                  );
+      break;
+#endif // !defined(DISABLE_SATI_TEST_UNIT_READY)
+
+#if    !defined(DISABLE_SATI_INQUIRY)        \
+    || !defined(DISABLE_SATI_READY_CAPACITY) \
+    || !defined(DISABLE_SATI_MODE_SENSE)
+
+      case SATI_SEQUENCE_INQUIRY_EXECUTE_DEVICE_DIAG:
+
+         if (ata_status & ATA_STATUS_REG_ERROR_BIT)
+         {
+            U8  error = (U8) sati_get_ata_error(register_fis);
+            status    = SATI_FAILURE_CHECK_RESPONSE_DATA;
+            sati_translate_error(sequence, scsi_io, error);
+         }
+         else
+         {
+            sati_inquiry_ata_information_finish_translation(
+               sequence,
+               scsi_io,
+               ata_io
+            );
+            status = sati_check_data_io(sequence);
+         }
+      break;
+
+      case SATI_SEQUENCE_INQUIRY_STANDARD:
+      case SATI_SEQUENCE_INQUIRY_SUPPORTED_PAGES:
+      case SATI_SEQUENCE_INQUIRY_SERIAL_NUMBER:
+      case SATI_SEQUENCE_INQUIRY_BLOCK_DEVICE:
+      case SATI_SEQUENCE_INQUIRY_ATA_INFORMATION:
+      case SATI_SEQUENCE_INQUIRY_DEVICE_ID:
+      case SATI_SEQUENCE_READ_CAPACITY_10:
+      case SATI_SEQUENCE_READ_CAPACITY_16:
+      case SATI_SEQUENCE_MODE_SENSE_6_CACHING:
+      case SATI_SEQUENCE_MODE_SENSE_6_INFORMATIONAL_EXCP_CONTROL:
+      case SATI_SEQUENCE_MODE_SENSE_6_READ_WRITE_ERROR:
+      case SATI_SEQUENCE_MODE_SENSE_6_DISCONNECT_RECONNECT:
+      case SATI_SEQUENCE_MODE_SENSE_6_CONTROL:
+      case SATI_SEQUENCE_MODE_SENSE_6_POWER_CONDITION:
+      case SATI_SEQUENCE_MODE_SENSE_6_ALL_PAGES:
+      case SATI_SEQUENCE_MODE_SENSE_10_CACHING:
+      case SATI_SEQUENCE_MODE_SENSE_10_INFORMATIONAL_EXCP_CONTROL:
+      case SATI_SEQUENCE_MODE_SENSE_10_READ_WRITE_ERROR:
+      case SATI_SEQUENCE_MODE_SENSE_10_CONTROL:
+      case SATI_SEQUENCE_MODE_SENSE_10_POWER_CONDITION:
+      case SATI_SEQUENCE_MODE_SENSE_10_DISCONNECT_RECONNECT:
+      case SATI_SEQUENCE_MODE_SENSE_10_ALL_PAGES:
+         // Did an error occur during the IO request?
+         if (ata_status & ATA_STATUS_REG_ERROR_BIT)
+         {
+            U8  error = (U8) sati_get_ata_error(register_fis);
+            status    = SATI_FAILURE_CHECK_RESPONSE_DATA;
+            sati_translate_error(sequence, scsi_io, error);
+         }
+         else
+         {
+            void * ata_data = sati_cb_get_ata_data_address(ata_io);
+
+            if(ata_data == NULL)
+            {
+               status = SATI_FAILURE;
+            }
+            else
+            {
+               sati_translate_data(sequence, ata_data, scsi_io);
+               status = sati_check_data_io(sequence);
+            }
+         }
+      break;
+#endif //    !defined(DISABLE_SATI_INQUIRY)
+       // && !defined(DISABLE_SATI_READY_CAPACITY)
+       // && !defined(DISABLE_SATI_MODE_SENSE)
+
+#if !defined(DISABLE_SATI_MODE_SELECT)
+      case SATI_SEQUENCE_MODE_SELECT_MODE_PAGE_CACHING:
+
+         status = sati_mode_select_translate_response(
+            sequence, scsi_io, ata_io
+               );
+         if(status == SATI_COMPLETE)
+         {
+            status = sati_check_data_io(sequence);
+         }
+         break;
+
+      case SATI_SEQUENCE_MODE_SELECT_MODE_POWER_CONDITION:
+      case SATI_SEQUENCE_MODE_SELECT_MODE_INFORMATION_EXCEPT_CONTROL:
+         // Did an error occur during the IO request?
+         if (ata_status & ATA_STATUS_REG_ERROR_BIT)
+         {
+            U8  error = (U8) sati_get_ata_error(register_fis);
+            status    = SATI_FAILURE_CHECK_RESPONSE_DATA;
+            sati_translate_error(sequence, scsi_io, error);
+         }
+         else
+         {
+            status = sati_check_data_io(sequence);
+         }
+      break;
+#endif // !defined(DISABLE_SATI_MODE_SELECT)
+
+#if !defined(DISABLE_SATI_WRITE_AND_VERIFY)
+      case SATI_SEQUENCE_WRITE_AND_VERIFY:
+
+         if (ata_status & ATA_STATUS_REG_ERROR_BIT)
+         {
+            U8  error = (U8) sati_get_ata_error(register_fis);
+            sati_translate_error(sequence, scsi_io, error);
+
+            return SATI_FAILURE_CHECK_RESPONSE_DATA;
+         }
+         else
+         {
+            status = sati_write_and_verify_translate_response(
+                        sequence,
+                        scsi_io,
+                        ata_io
+                     );
+         }
+      break;
+#endif // !defined(DISABLE_SATI_WRITE_AND_VERIFY)
+
+      case SATI_SEQUENCE_READ_6:
+      case SATI_SEQUENCE_READ_10:
+      case SATI_SEQUENCE_READ_12:
+      case SATI_SEQUENCE_READ_16:
+      case SATI_SEQUENCE_WRITE_6:
+      case SATI_SEQUENCE_WRITE_10:
+      case SATI_SEQUENCE_WRITE_12:
+      case SATI_SEQUENCE_WRITE_16:
+      case SATI_SEQUENCE_VERIFY_10:
+      case SATI_SEQUENCE_VERIFY_12:
+      case SATI_SEQUENCE_VERIFY_16:
+      case SATI_SEQUENCE_SYNCHRONIZE_CACHE:
+         if (ata_status & ATA_STATUS_REG_ERROR_BIT)
+         {
+            U8  error = (U8) sati_get_ata_error(register_fis);
+            status    = SATI_FAILURE_CHECK_RESPONSE_DATA;
+            sati_translate_error(sequence, scsi_io, error);
+
+            if(sequence->state == SATI_SEQUENCE_STATE_READ_ERROR )
+            {
+               sati_scsi_read_error_sense_construct(
+                  sequence,
+                  scsi_io,
+                  ata_io,
+                  SCSI_STATUS_CHECK_CONDITION,
+                  SCSI_SENSE_MEDIUM_ERROR,
+                  SCSI_ASC_UNRECOVERED_READ_ERROR,
+                  SCSI_ASCQ_UNRECOVERED_READ_ERROR
+               );
+               sequence->state = SATI_SEQUENCE_STATE_FINAL;
+            }
+         }
+         else
+         {
+            // We haven't satisified the transfer count from the original
+            // SCSI CDB.  As a result, we need to re-issue the command
+            // with updated logical block address and transfer count.
+            if (sequence->command_specific_data.scratch)
+            {
+               /** @todo update the contents of the CDB directly?  Should be
+                *  done during previous command translation?
+                */
+               status = SATI_SEQUENCE_INCOMPLETE;
+            }
+         }
+      break;
+
+#if !defined(DISABLE_SATI_READ_BUFFER)
+      case SATI_SEQUENCE_READ_BUFFER:
+         status = sati_read_buffer_translate_response(
+                     sequence, scsi_io, ata_io
+                  );
+
+         if(status == SATI_COMPLETE)
+         {
+            status = sati_check_data_io(sequence);
+         }
+      break;
+#endif //!defined(DISABLE_SATI_READ_BUFFER)
+
+#if !defined(DISABLE_SATI_WRITE_BUFFER)
+      case SATI_SEQUENCE_WRITE_BUFFER:
+      case SATI_SEQUENCE_WRITE_BUFFER_MICROCODE:
+         status = sati_write_buffer_translate_response(
+                     sequence, scsi_io, ata_io
+                  );
+      break;
+#endif //!defined(DISABLE_SATI_WRITE_BUFFER)
+
+#if !defined(DISABLE_SATI_REASSIGN_BLOCKS)
+      case SATI_SEQUENCE_REASSIGN_BLOCKS:
+         status = sati_reassign_blocks_translate_response(
+                     sequence, scsi_io, ata_io
+                  );
+         if(status == SATI_COMPLETE)
+         {
+            status = sati_check_data_io(sequence);
+         }
+      break;
+#endif // !defined(DISABLE_SATI_REASSIGN_BLOCKS)
+
+#if !defined(DISABLE_SATI_START_STOP_UNIT)
+      case SATI_SEQUENCE_START_STOP_UNIT:
+         status = sati_start_stop_unit_translate_response(
+                     sequence, scsi_io, ata_io
+                  );
+         if(status == SATI_COMPLETE)
+         {
+            status = sati_check_data_io(sequence);
+         }
+      break;
+#endif // !defined(DISABLE_SATI_START_STOP_UNIT)
+
+#if !defined(DISABLE_SATI_REQUEST_SENSE)
+      case SATI_SEQUENCE_REQUEST_SENSE_SMART_RETURN_STATUS:
+      case SATI_SEQUENCE_REQUEST_SENSE_CHECK_POWER_MODE:
+         status = sati_request_sense_translate_response(
+                     sequence, scsi_io, ata_io
+                  );
+         if(status == SATI_COMPLETE)
+         {
+            status = sati_check_data_io(sequence);
+         }
+      break;
+#endif // !defined(DISABLE_SATI_REQUEST_SENSE)
+
+#if !defined(DISABLE_SATI_WRITE_LONG)
+      case SATI_SEQUENCE_WRITE_LONG:
+         status = sati_write_long_translate_response(
+                     sequence, scsi_io, ata_io
+                  );
+         if(status == SATI_COMPLETE)
+         {
+            status = sati_check_data_io(sequence);
+         }
+      break;
+#endif // !defined(DISABLE_SATI_WRITE_LONG)
+
+#if !defined(DISABLE_SATI_LOG_SENSE)
+      case SATI_SEQUENCE_LOG_SENSE_SUPPORTED_LOG_PAGE:
+      case SATI_SEQUENCE_LOG_SENSE_SELF_TEST_LOG_PAGE:
+      case SATI_SEQUENCE_LOG_SENSE_EXTENDED_SELF_TEST_LOG_PAGE:
+      case SATI_SEQUENCE_LOG_SENSE_INFO_EXCEPTION_LOG_PAGE:
+         status = sati_log_sense_translate_response(
+                     sequence, scsi_io, ata_io
+                  );
+         if(status == SATI_COMPLETE)
+         {
+            status = sati_check_data_io(sequence);
+         }
+      break;
+#endif // !defined(DISABLE_SATI_LOG_SENSE)
+
+#if !defined(DISABLE_SATI_UNMAP)
+      case SATI_SEQUENCE_UNMAP:
+         status = sati_unmap_translate_response(
+                     sequence, scsi_io, ata_io
+                  );
+         if(status == SATI_COMPLETE)
+         {
+            status = sati_check_data_io(sequence);
+         }
+      break;
+#endif // !defined(DISABLE_SATI_UNMAP)
+
+#if !defined(DISABLE_SATI_ATA_PASSTHROUGH)
+      case SATI_SEQUENCE_ATA_PASSTHROUGH_12:
+      case SATI_SEQUENCE_ATA_PASSTHROUGH_16:
+         status = sati_passthrough_translate_response(
+                     sequence, scsi_io, ata_io
+                  );
+      break;
+#endif // !defined(DISABLE_SATI_ATA_PASSTHROUGH)
+
+      default:
+         status = SATI_FAILURE_INVALID_SEQUENCE_TYPE;
+      break;
+   }
+
+   return status;
+}
+
+// -----------------------------------------------------------------------------
+
+#if !defined(DISABLE_SATI_TASK_MANAGEMENT)
+SATI_STATUS sati_translate_task_response(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   SATI_STATUS   status       = SATI_FAILURE_CHECK_RESPONSE_DATA;
+   U8          * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
+   U8            ata_status;
+
+   /**
+    * If the device fault bit is set in the status register, then
+    * set the sense data and return.
+    */
+   ata_status = (U8) sati_get_ata_status(register_fis);
+   if (ata_status & ATA_STATUS_REG_DEVICE_FAULT_BIT)
+   {
+      sati_scsi_response_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_TASK_MGMT_FUNC_FAILED
+      );
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+
+   // Look at the sequence type to determine the response translation method
+   // to invoke.
+   switch (sequence->type)
+   {
+      case SATI_SEQUENCE_LUN_RESET:
+         if (ata_status & ATA_STATUS_REG_ERROR_BIT)
+         {
+            sati_scsi_response_data_construct(
+               sequence, scsi_io, SCSI_TASK_MGMT_FUNC_FAILED);
+         }
+         else
+         {
+            sati_scsi_response_data_construct(
+               sequence, scsi_io, SCSI_TASK_MGMT_FUNC_COMPLETE);
+         }
+
+         status = SATI_COMPLETE;
+      break;
+
+#if !defined(DISABLE_SATI_ABORT_TASK_SET)
+      case SATI_SEQUENCE_ABORT_TASK_SET:
+         if (ata_status & ATA_STATUS_REG_ERROR_BIT)
+         {
+            sati_scsi_response_data_construct(
+               sequence, scsi_io, SCSI_TASK_MGMT_FUNC_FAILED);
+         }
+         else
+         {
+            void * ata_data = sati_cb_get_ata_data_address(ata_io);
+
+            if(ata_data == NULL)
+            {
+               status = SATI_FAILURE;
+            }
+            else
+            {
+               status = sati_abort_task_set_translate_data(
+                           sequence,
+                           ata_data,
+                           scsi_io
+                        );
+            }
+         }
+      break;
+#endif // !defined(DISABLE_SATI_ABORT_TASK_SET)
+
+      default:
+         status = SATI_FAILURE_INVALID_SEQUENCE_TYPE;
+      break;
+   }
+
+   return status;
+}
+#endif // !defined(DISABLE_SATI_TASK_MANAGEMENT)
+
+#if !defined(ENABLE_MINIMUM_MEMORY_MODE)
+U32 sati_get_sat_compliance_version(
+   void
+)
+{
+   return 2;  // Compliant with SAT-2.
+}
+
+U32 sati_get_sat_compliance_version_revision(
+   void
+)
+{
+   return 7;  // Compliant with SAT-2 revision 7.
+}
+
+#endif // !defined(ENABLE_MINIMUM_MEMORY_MODE)
+
+U16 sati_get_number_data_bytes_set(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence
+)
+{
+   return sequence->number_data_bytes_set;
+}
+
+void sati_sequence_construct(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence
+)
+{
+   sequence->state = SATI_SEQUENCE_STATE_INITIAL;
+}
+
+void sati_sequence_terminate(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   // Decode the sequence type to determine how to handle the termination
+   // of the the translation method.
+   switch (sequence->type)
+   {
+   case SATI_SEQUENCE_UNMAP:
+      sati_unmap_terminate(sequence,scsi_io,ata_io);
+   break;
+   }
+}
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,271 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_H_
+#define _SATI_H_
+
+/**
+ * @file
+ * @brief This file contains all of the interface methods, macros, structures
+ *        that can be utilized by a user to perform SCSI-to-ATA Translation.
+ *        SATI adheres to the www.t10.org SAT specification.
+ *
+ * For specific compliance information please refer to:
+ * - sati_get_sat_compliance_version() and
+ * - sati_get_sat_compliance_version_revision()
+ *
+ * For situations where compliance is not observed, the SATI will
+ * return an error indication (most likely INVALID FIELD IN CDB sense).
+ */
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+/**
+ * @brief This method will be called by the core to indicate the start of a
+ *        new translation sequence.  Set up the initial sequence state.
+ *
+ * @return None
+ */
+void sati_sequence_construct(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence
+);
+
+/**
+ * @brief This method will be called by the core to request the current translation
+ *        sequence be terminated.
+ *
+ * @param[in]  sequence This parameter specifies the sequence
+ *             data associated with the translation.
+ * @param[in,out] scsi_io This parameter specifies the user's SCSI IO request
+ *                object.  SATI expects that the user can access the SCSI CDB,
+ *                response, and data from this pointer.  For example, if there
+ *                is a failure in translation resulting in sense data, then
+ *                SATI will call sati_cb_set_status() and pass the scsi_io
+ *                pointer as a parameter.
+ * @param[out] ata_io This parameter specifies the location of the
+ *             ATA register FIS into which the translator can write the
+ *             resultant ATA command if translation is successful.  This
+ *             parameter is passed back to the user through the
+ *             SATI_SATA_CALLBACKS when it is necessary to write fields
+ *             in the ata_io.
+ *
+ * @return None
+ */
+void sati_sequence_terminate(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+/**
+ * @brief This method translates the supplied SCSI command into a
+ *        corresponding ATA command.
+ *
+ * @param[in]  sequence This parameter specifies the sequence
+ *             data associated with the translation.
+ * @param[in]  sati_device This parameter specifies the remote device
+ *             for which the translated request is destined.
+ * @param[in,out] scsi_io This parameter specifies the user's SCSI IO request
+ *                object.  SATI expects that the user can access the SCSI CDB,
+ *                response, and data from this pointer.  For example, if there
+ *                is a failure in translation resulting in sense data, then
+ *                SATI will call sati_cb_set_status() and pass the scsi_io
+ *                pointer as a parameter.
+ * @param[out] ata_io This parameter specifies the location of the
+ *             ATA register FIS into which the translator can write the
+ *             resultant ATA command if translation is successful.  This
+ *             parameter is passed back to the user through the
+ *             SATI_SATA_CALLBACKS when it is necessary to write fields
+ *             in the ata_io.
+ *
+ * @return Indicate if the translation was successful.
+ * @retval SATI_SUCCESS
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA
+ */
+SATI_STATUS sati_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   SATI_DEVICE_T              * sati_device,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+/**
+ * @brief This method translates the supplied SCSI task management request
+ *        into a corresponding ATA command/control FIS.
+ *
+ * @param[in]  sequence This parameter specifies the sequence
+ *             data associated with the translation.
+ * @param[in]  sati_device This parameter specifies the remote device
+ *             for which the translated request is destined.
+ * @param[in,out] scsi_io This parameter specifies the user's SCSI IO request
+ *                object.  SATI expects that the user can access the SCSI CDB,
+ *                response, and data from this pointer.  For example, if there
+ *                is a failure in translation resulting in sense data, then
+ *                SATI will call sati_cb_set_status() and pass the scsi_io
+ *                pointer as a parameter.
+ * @param[out] ata_io This parameter specifies the location of the
+ *             ATA register FIS into which the translator can write the
+ *             resultant ATA command if translation is successful.  This
+ *             parameter is passed back to the user through the
+ *             SATI_SATA_CALLBACKS when it is necessary to write fields
+ *             in the ata_io.
+ *
+ * @return Indicate if the translation was successful.
+ * @retval SATI_SUCCESS
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA
+ */
+SATI_STATUS sati_translate_task_management(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   SATI_DEVICE_T              * sati_device,
+   void                       * scsi_task,
+   void                       * ata_io
+);
+
+/**
+ * @brief This method translates the supplied ATA response into the
+ *        corresponding SCSI command response.
+ *
+ * @param[in]  sequence This parameter specifies the sequence
+ *             data associated with the translation.
+ * @param[out] scsi_io This parameter specifies the user's SCSI IO request
+ *             object.  SATI expects that the user can access the SCSI CDB,
+ *             response, and data from this pointer.  For example, if there
+ *             is a failure in translation resulting in sense data, then
+ *             SATI will call sati_cb_set_status() and pass the scsi_io
+ *             pointer as a parameter.
+ * @param[out] ata_io This parameter specifies the location of the
+ *             ATA IO request (e.g. register FIS, PIO Setup etc.) from which
+ *             the translator can read the received ATA status and error
+ *             fields.
+ *
+ * @return Indicate if the translation was successful.
+ * @retval SATI_SUCCESS
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA
+ */
+SATI_STATUS sati_translate_command_response(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+/**
+ * @brief This method translates the supplied ATA response into the
+ *        corresponding SCSI task response.
+ *
+ * @param[in]  sequence This parameter specifies the sequence
+ *             data associated with the translation.
+ * @param[out] scsi_io This parameter specifies the user's SCSI IO request
+ *             object.  SATI expects that the user can access the SCSI CDB,
+ *             response, and data from this pointer.  For example, if there
+ *             is a failure in translation resulting in sense data, then
+ *             SATI will call sati_cb_set_status() and pass the scsi_io
+ *             pointer as a parameter.
+ * @param[out] ata_io This parameter specifies the location of the
+ *             ATA IO request (e.g. register FIS, PIO Setup etc.) from which
+ *             the translator can read the received ATA status and error
+ *             fields.
+ *
+ * @return Indicate if the translation was successful.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA
+ */
+SATI_STATUS sati_translate_task_response(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+/**
+ * @brief This method simply returns the SAT major compliance version number
+ *        for which the implementation is compliant.
+ *
+ * @return Return the specification identifier with which this translator
+ *         is compliant.
+ */
+U32 sati_get_sat_compliance_version(
+   void
+);
+
+/**
+ * @brief This method simply returns the SAT version revision identifier
+ *        for which the implementation is compliant.
+ *
+ * @return Return the specification revision identifier with which this
+ *         translator is compliant.
+ */
+U32 sati_get_sat_compliance_version_revision(
+   void
+);
+
+/**
+* @brief This method returns the number of data bytes written
+*        by the translation sequence.
+*
+* @param[in] sequence This parameter specifies the sequence data
+*            associated with the translation.
+*
+* @return Return the U16 number_data_bytes_set in the
+*         SATI_TRANSLATOR_SEQUENCE.
+*/
+U16 sati_get_number_data_bytes_set(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence
+);
+
+void sati_translate_error(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   U8                           error
+);
+
+#endif // _SATI_H_
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_abort_task_set.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_abort_task_set.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,177 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ *
+ * @brief This file contains the method implementations required to
+ *        translate the SCSI abort task set command.
+ */
+
+#if !defined(DISABLE_SATI_TASK_MANAGEMENT)
+
+#include <dev/isci/scil/sati_abort_task_set.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/sati.h>
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_scsi.h>
+#include <dev/isci/scil/intel_sat.h>
+
+//******************************************************************************
+//* P U B L I C   M E T H O D S
+//******************************************************************************
+
+#if !defined(DISABLE_SATI_ABORT_TASK_SET)
+
+/**
+ * @brief This method will translate the abort task set SCSI task request into an
+ *        ATA READ LOG EXT command. For more information on the parameters
+ *        passed to this method, please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the command translation was
+ *         successful.
+ */
+SATI_STATUS sati_abort_task_set_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   U8 * register_fis;
+
+   //ATA Read Log Ext with log address set to 0x10
+   sati_ata_read_log_ext_construct(
+      ata_io,
+      sequence,
+      ATA_LOG_PAGE_NCQ_ERROR,
+      sizeof(ATA_NCQ_COMMAND_ERROR_LOG_T)
+   );
+
+   register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+   sati_set_sata_command_flag(register_fis);
+
+   sequence->type                = SATI_SEQUENCE_ABORT_TASK_SET;
+   sequence->state               = SATI_SEQUENCE_STATE_AWAIT_RESPONSE;
+
+   return SATI_SUCCESS;
+}
+
+SATI_STATUS sati_abort_task_set_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_task
+)
+{
+   ATA_NCQ_COMMAND_ERROR_LOG_T * log =
+      (ATA_NCQ_COMMAND_ERROR_LOG_T *)ata_input_data;
+   U8 tag_index;
+
+   sequence->state = SATI_SEQUENCE_STATE_TRANSLATE_DATA;
+
+   for (tag_index = 0; tag_index < 32; tag_index++)
+   {
+      void     * matching_command;
+      SCI_STATUS completion_status;
+      sati_cb_device_get_request_by_ncq_tag(
+         scsi_task,
+         tag_index,
+         matching_command
+      );
+
+      if (matching_command != NULL)
+      {
+         if (
+              (log->ncq_tag == tag_index) &&
+              (log->nq == 0) // nq==1 means a non-queued command
+                             //  caused this failure
+            )
+         {
+            sati_translate_error(sequence, matching_command, log->error);
+            completion_status = SCI_FAILURE_IO_RESPONSE_VALID;
+
+            if(sequence->state == SATI_SEQUENCE_STATE_READ_ERROR)
+            {
+               //Uncorrectable read error, return additional sense data
+               sati_scsi_read_ncq_error_sense_construct(
+                  sequence,
+                  matching_command,
+                  ata_input_data,
+                  SCSI_STATUS_CHECK_CONDITION,
+                  SCSI_SENSE_MEDIUM_ERROR,
+                  SCSI_ASC_UNRECOVERED_READ_ERROR,
+                  SCSI_ASCQ_UNRECOVERED_READ_ERROR
+               );
+            }
+         }
+         else
+         {
+            completion_status = SCI_FAILURE_IO_TERMINATED;
+         }
+
+         sati_cb_io_request_complete(matching_command, completion_status);
+      }
+   }
+
+   sequence->state = SATI_SEQUENCE_STATE_FINAL;
+
+   return SATI_COMPLETE;
+}
+
+#endif // !defined(DISABLE_SATI_ABORT_TASK_SET)
+
+#endif // !defined(DISABLE_SATI_TASK_MANAGEMENT)
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_abort_task_set.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_abort_task_set.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,83 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_ABORT_TASK_SET_H_
+#define _SATI_ABORT_TASK_SET_H_
+
+/**
+ * @file
+ * @brief This file contains the method interfaces required to translate the
+ *        SCSI abort task set task request as well as translate response
+ *        for the task request.
+ */
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+#if !defined(DISABLE_SATI_ABORT_TASK_SET)
+
+SATI_STATUS sati_abort_task_set_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_task,
+   void                       * ata_io
+);
+
+SATI_STATUS sati_abort_task_set_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_task
+);
+
+#endif // !defined(DISABLE_SATI_ABORT_TASK_SET)
+
+#endif // _SATI_ABORT_TASK_SET_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_atapi.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_atapi.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,257 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains all of the method implementations that
+ *        can be utilized by a user to perform SCSI-to-ATA Translation.
+ *        SATI adheres to the www.t10.org SAT specification.
+ *
+ * For situations where compliance is not observed, the SATI will
+ * return an error indication (most likely INVALID FIELD IN CDB sense data).
+ */
+
+#include <dev/isci/scil/sati.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/sati_atapi.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_scsi.h>
+#include <dev/isci/scil/intel_sat.h>
+#include <dev/isci/scil/sati_report_luns.h>
+
+
+//******************************************************************************
+//* P U B L I C   M E T H O D S
+//******************************************************************************
+
+SATI_STATUS sati_atapi_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   SATI_DEVICE_T              * sati_device,
+   void                       * scsi_io,
+   void                       * atapi_io
+)
+{
+   SATI_STATUS   status;
+   U8          * cdb = sati_cb_get_cdb_address(scsi_io);
+
+   SATA_FIS_REG_H2D_T * register_fis =
+      (SATA_FIS_REG_H2D_T *)sati_cb_get_h2d_register_fis_address(atapi_io);
+
+   U8 io_direction = SATI_DATA_DIRECTION_IN;
+
+   //No sense response has been set for the translation sequence yet
+   sequence->is_sense_response_set = FALSE;
+   // Default to no translation response required
+   sequence->is_translate_response_required = FALSE;
+
+   sequence->number_data_bytes_set = 0;
+   sequence->device  = sati_device;
+   sequence->command_specific_data.scratch = 0;
+
+   sati_cb_get_data_direction(scsi_io, &io_direction);
+
+   //set sat protocol.
+   if (io_direction == SATI_DATA_DIRECTION_NONE)
+      sequence->protocol = SAT_PROTOCOL_PACKET_NON_DATA;
+   else if (io_direction == SATI_DATA_DIRECTION_IN)
+      sequence->protocol = SAT_PROTOCOL_PACKET_DMA_DATA_IN;
+   else if (io_direction == SATI_DATA_DIRECTION_OUT)
+      sequence->protocol = SAT_PROTOCOL_PACKET_DMA_DATA_OUT;
+
+   // We don't send Report Luns command out.
+   if  (sati_get_cdb_byte(cdb, 0) == SCSI_REPORT_LUNS)
+   {
+      status = sati_report_luns_translate_command(
+                  sequence, scsi_io, atapi_io
+               );
+   }
+   else if (sati_cb_get_lun(scsi_io) != 0)
+   {
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_ILLEGAL_REQUEST,
+         SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED,
+         0
+      );
+      status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+   else
+   {
+      if (sequence->state == SATI_SEQUENCE_STATE_INCOMPLETE)
+      {  //Request Sense command is required.
+         U8 request_sense_cdb[SATI_ATAPI_REQUEST_SENSE_CDB_LENGTH] =
+            {0x3, 0x0, 0x0, 0x0, 0x12, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
+
+         //set the sequence->protocol to DATA_IN anyway;
+         sequence->protocol = SAT_PROTOCOL_PACKET_DMA_DATA_IN;
+
+         //set the cdb for Request Sense using command_specific_data field.
+         memcpy(sequence->command_specific_data.sati_atapi_data.request_sense_cdb,
+                request_sense_cdb,
+                SATI_ATAPI_REQUEST_SENSE_CDB_LENGTH
+               );
+      }
+
+      //build Packet Fis for any other command translation.
+      register_fis->command = ATA_PACKET;
+      register_fis->features |= ATA_PACKET_FEATURE_DMA;
+
+      register_fis->fis_type = SATA_FIS_TYPE_REGH2D;
+      register_fis->command_flag = 1;
+
+      status = SATI_SUCCESS;
+   }
+
+   return status;
+}
+
+
+SATI_STATUS sati_atapi_translate_command_response(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * atapi_io
+)
+{
+   SATI_STATUS   status       = SATI_COMPLETE;
+   U8          * register_fis = sati_cb_get_d2h_register_fis_address(atapi_io);
+   U8            ata_status;
+
+   /**
+    * If the device fault bit is set in the status register, then
+    * set the sense data and return.
+    */
+   ata_status = (U8) sati_get_ata_status(register_fis);
+   if (ata_status & ATA_STATUS_REG_DEVICE_FAULT_BIT)
+   {
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_HARDWARE_ERROR,
+         SCSI_ASC_INTERNAL_TARGET_FAILURE,
+         SCSI_ASCQ_INTERNAL_TARGET_FAILURE
+      );
+
+      sequence->device->state = SATI_DEVICE_STATE_DEVICE_FAULT_OCCURRED;
+
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+   else if (ata_status & ATA_STATUS_REG_ERROR_BIT)
+   {
+       //reset the register_fis.
+       memset(register_fis, 0, sizeof(SATA_FIS_REG_D2H_T));
+
+       //Internal Request Sense command is needed.
+       sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
+       return SATI_SEQUENCE_INCOMPLETE;
+   }
+
+   return status;
+}
+
+void sati_atapi_translate_request_sense_response(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * atapi_io
+)
+{
+   //sense data is already in place.
+   SCI_SSP_RESPONSE_IU_T * rsp_iu = (SCI_SSP_RESPONSE_IU_T*)
+                                 sati_cb_get_response_iu_address(scsi_io);
+
+   sati_scsi_common_response_iu_construct(
+      rsp_iu,
+      SCSI_STATUS_CHECK_CONDITION,
+      sati_scsi_get_sense_data_length(sequence, scsi_io),
+      SCSI_RESPONSE_DATA_PRES_SENSE_DATA
+   );
+
+   sequence->is_sense_response_set = TRUE;
+
+   sequence->state = SATI_SEQUENCE_STATE_FINAL;
+}
+
+
+U32 sati_atapi_translate_number_of_bytes_transferred(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * atapi_io
+)
+{
+   U8* cdb = sati_cb_get_cdb_address(scsi_io);
+   U8 response_data;
+   U32 data_length = 0;
+
+   switch(cdb[0])
+   {
+      case SCSI_MODE_SENSE_10:
+         sati_cb_get_data_byte(scsi_io, 1, &response_data);
+         data_length = response_data+2;
+         break;
+
+      case 0x51: //READ DISC INFORMATION
+         sati_cb_get_data_byte(scsi_io, 1, &response_data);
+         data_length = response_data+2;
+         break;
+
+      default:
+         break;
+   }
+
+   return data_length;
+}
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_atapi.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_atapi.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,177 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_ATAPI_H_
+#define _SATI_ATAPI_H_
+
+/**
+ * @file
+ * @brief This file contains all of the interface methods, macros, structures
+ *        that can be utilized by a user to perform SCSI-to-ATA PACKET IO
+ *        Translation.
+ */
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+/**
+ * @brief This method translates the supplied SCSI command into a
+ *        corresponding ATA packet protocol command.
+ *
+ * @param[in]  sequence This parameter specifies the sequence
+ *             data associated with the translation.
+ * @param[in]  sati_device This parameter specifies the remote device
+ *             for which the translated request is destined.
+ * @param[in,out] scsi_io This parameter specifies the user's SCSI IO request
+ *                object.  SATI expects that the user can access the SCSI CDB,
+ *                response, and data from this pointer.  For example, if there
+ *                is a failure in translation resulting in sense data, then
+ *                SATI will call sati_cb_set_status() and pass the scsi_io
+ *                pointer as a parameter.
+ * @param[out] atapi_io This parameter specifies the location of the
+ *             ATA Packet FIS into which the translator can write the resultant
+ *             ATA command if translation is successful.  This parameter is
+ *             passed back to the user through the SATI_SATA_CALLBACKS when it
+ *             is necessary to write fields in the ata_io.
+ *
+ * @return Indicate if the translation was successful.
+ * @retval SATI_SUCCESS
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA
+ */
+SATI_STATUS sati_atapi_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   SATI_DEVICE_T              * sati_device,
+   void                       * scsi_io,
+   void                       * atapi_io
+);
+
+
+/**
+ * @brief This method translates the supplied ATA packet IO response into the
+ *        corresponding SCSI command response.
+ *
+ * @param[out]  sequence This parameter specifies the sequence
+ *             data associated with the translation and will be updated
+ *             according to the command response.
+ * @param[out] scsi_io This parameter specifies the user's SCSI IO request
+ *             object.  SATI expects that the user can access the SCSI CDB,
+ *             response, and data from this pointer.  For example, if there
+ *             is a failure in translation resulting in sense data, then
+ *             SATI will call sati_cb_set_status() and pass the scsi_io
+ *             pointer as a parameter.
+ * @param[in] atapi_io This parameter specifies the location of the
+ *             ATAPI IO request (e.g. register FIS, PIO Setup etc.) from which
+ *             the translator can read the received ATA status and error
+ *             fields.
+ *
+ * @return Indicate if the translation was successful.
+ * @retval SATI_SUCCESS
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA
+ */
+SATI_STATUS sati_atapi_translate_command_response(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * atapi_io
+);
+
+
+/**
+ * @brief This method translates the internal Request Sense command response
+ *        and set the sense data for the previous failed SCSI command.
+ *
+ * @param[out] sequence This parameter specifies the sequence
+ *             data associated with the translation and to be updated to
+ *             final state.
+ * @param[out] scsi_io This parameter specifies the user's SCSI IO request
+ *             object.  SATI expects that the user can access the SCSI CDB,
+ *             response, and data from this pointer.  For example, if there
+ *             is a failure in translation resulting in sense data, then
+ *             SATI will call sati_cb_set_status() and pass the scsi_io
+ *             pointer as a parameter.
+ * @param[in] atapi_io This parameter specifies the location of the
+ *             ATAPI IO request (e.g. register FIS, PIO Setup etc.) from which
+ *             the translator can read the received ATA status and error
+ *             fields.
+ *
+ * @return None.
+ */
+void sati_atapi_translate_request_sense_response(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * atapi_io
+);
+
+
+/**
+ * @brief This method retrieve ATA packet IO actual transferred data length.
+ *
+ * @param[in]  sequence This parameter specifies the sequence
+ *             data associated with the translation.
+ * @param[out] scsi_io This parameter specifies the user's SCSI IO request
+ *             object.  SATI expects that the user can access the SCSI CDB,
+ *             response, and data from this pointer.  For example, if there
+ *             is a failure in translation resulting in sense data, then
+ *             SATI will call sati_cb_set_status() and pass the scsi_io
+ *             pointer as a parameter.
+ * @param[out] atapi_io This parameter specifies the location of the
+ *             ATAPI IO request (e.g. register FIS, PIO Setup etc.) from which
+ *             the translator can read the received ATA status and error
+ *             fields.
+ *
+ * @return Actual data transfer length.
+ */
+U32 sati_atapi_translate_number_of_bytes_transferred(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * atapi_io
+);
+#endif
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_callbacks.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_callbacks.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,481 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_CALLBACKS_H_
+#define _SATI_CALLBACKS_H_
+
+/**
+ * @file
+ * @brief This file contains the default callback bindings for SATI.  These
+ *        must be overridden by the SATI user to ensure successful operation.
+ */
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/intel_sas.h>
+
+#ifdef SATI_DEFAULT_DECLARATION
+
+/**
+ * @brief This callback method asks the user to provide the address for
+ *        the command descriptor block (CDB) associated with this IO request.
+ *
+ * @param[in] scsi_io This parameter points to the user's IO request object
+ *            It is a cookie that allows the user to provide the necessary
+ *            information for this callback.
+ *
+ * @return This method returns the virtual address of the CDB.
+ */
+void * sati_cb_get_cdb_address(
+   void * scsi_io
+);
+
+/**
+ * @brief This callback method asks the user to provide the length of
+ *        the command descriptor block (CDB) associated with this IO request.
+ *
+ * @param[in] scsi_io This parameter points to the user's IO request object.
+ *            It is a cookie that allows the user to provide the necessary
+ *            information for this callback.
+ *
+ * @return This method returns the length of the CDB.
+ */
+U32 sati_cb_get_cdb_length(
+   void * scsi_io
+);
+
+/**
+ * @brief This callback method asks the user to provide the data transfer
+ *        direction of this IO request.
+ *
+ * @param[in] scsi_io This parameter points to the user's IO request object.
+ *            It is a cookie that allows the user to provide the necessary
+ *            information for this callback.
+ * @param[in] io_direction to return
+ * @return This method returns the length of the CDB.
+ */
+void sati_cb_get_data_direction(
+   void * scsi_io,
+   U8 * io_direction
+);
+
+/**
+ * @brief This callback method sets a value into the data buffer associated
+ *        with the supplied user SCSI IO request at the supplied byte offset.
+ *
+ * @note SATI does not manage the user scatter-gather-list.  As a result,
+ *       the user must ensure that data is written according to the SGL.
+ *
+ * @param[in]  scsi_io This parameter specifies the user's SCSI IO request
+ *             for which to set the data buffer byte.
+ * @param[in]  byte_offset This parameter specifies the offset into the
+ *             data buffer at which to set the value.
+ * @param[in]  value This parameter specifies the new value to be set into
+ *             the data buffer.
+ *
+ * @return none
+ */
+void sati_cb_set_data_byte(
+   void * scsi_io,
+   U32    byte_offset,
+   U8     value
+);
+
+/**
+ * @brief This callback method gets a value from the data buffer associated
+ *        with the supplied user SCSI IO request at the supplied byte offset.
+ *
+ * @note SATI does not manage the user scatter-gather-list.  As a result,
+ *       the user must ensure that data is written according to the SGL.
+ *
+ * @param[in]  scsi_io This parameter specifies the user's SCSI IO request
+ *             for which to get the data buffer byte.
+ * @param[in]  byte_offset This parameter specifies the offset into the
+ *             data buffer at which to get the value.
+ * @param[in]  value This parameter specifies the new value to be get into
+ *             the data buffer.
+ *
+ * @return none
+ */
+void sati_cb_get_data_byte(
+   void * scsi_io,
+   U32    byte_offset,
+   U8   * value
+);
+
+/**
+ * @brief This callback method gets the the task type for the SCSI task
+ *        request.
+ *
+ * @param[in] scsi_task This parameter specifies the user's SCSI Task request.
+ *            It is a cookie that allows the user to provide the necessary
+ *            information for this callback.
+ *
+ * @return This method returns one of the enumeration values for
+ *         SCSI_TASK_MGMT_REQUEST_CODES
+ */
+U8 sati_cb_get_task_function(
+   void * scsi_task
+);
+
+#ifdef SATI_TRANSPORT_SUPPORTS_SAS
+/**
+ * @brief This callback method retrieves the address of the user's SSP
+ *        response IU buffer.
+ *
+ * @param[in]  scsi_io This parameter specifies the user's SCSI IO request
+ *             for which to retreive the location of the response buffer to
+ *             be written.
+ *
+ * @return This method returns the address of the response data buffer.
+ */
+void * sati_cb_get_response_iu_address(
+   void * scsi_io
+);
+
+#else // SATI_TRANSPORT_SUPPORTS_SAS
+
+/**
+ * @brief This callback method retrieves the address of the user's sense data
+ *        buffer.
+ *
+ * @param[in]  scsi_io This parameter specifies the user's SCSI IO request
+ *             for which to retreive the location of the sense buffer to
+ *             be written.
+ *
+ * @return This method returns the address of the sense data buffer.
+ */
+U8* sati_cb_get_sense_data_address(
+   void * scsi_io
+);
+
+/**
+ * @brief This callback method retrieves the length of the user's sense data
+ *        buffer.
+ *
+ * @param[in]  scsi_io This parameter specifies the user's SCSI IO request
+ *             for which to retreive the location of the sense buffer to
+ *             be written.
+ *
+ * @return This method returns the length of the sense data buffer.
+ */
+U32 sati_cb_get_sense_data_length(
+   void * scsi_io
+);
+
+/**
+ * @brief This callback method sets the SCSI status to be associated with
+ *        the supplied user's SCSI IO request.
+ *
+ * @param[in]  scsi_io This parameter specifies the user's SCSI IO request
+ *             for which to set the SCSI status.
+ * @param[in]  status This parameter specifies the SCSI status to be
+ *             associated with the supplied user's SCSI IO request.
+ *
+ * @return none
+ */
+void sati_cb_set_scsi_status(
+   void * scsi_io,
+   U8     status
+);
+
+#endif // SATI_TRANSPORT_SUPPORTS_SAS
+
+/**
+ * @brief This method retrieves the ATA task file (register FIS) relating to
+ *        the host to device command values.
+ *
+ * @param[in] ata_io This parameter specifies the user's ATA IO request
+ *            from which to retrieve the h2d register FIS address.
+ *
+ * @return This method returns the address for the host to device register
+ *         FIS.
+ */
+U8 * sati_cb_get_h2d_register_fis_address(
+   void * ata_io
+);
+
+/**
+ * @brief This method retrieves the ATA task file (register FIS) relating to
+ *        the device to host reponse values.
+ *
+ * @param[in] ata_io This parameter specifies the user's ATA IO request
+ *            from which to retrieve the d2h register FIS address.
+ *
+ * @return This method returns the address for the device to host register
+ *         FIS.
+ */
+U8 * sati_cb_get_d2h_register_fis_address(
+   void * ata_io
+);
+
+/**
+ * @brief This method retrieves the address where the ATA data received
+ *        from the device is stored.
+ *
+ * @param[in] ata_io This parameter specifies the user's ATA IO request
+ *            from which to retrieve the received data address.
+ *
+ * @return This method returns the address for the data received from
+ *         the remote device.
+ */
+void * sati_cb_get_ata_data_address(
+   void * ata_io
+);
+
+/**
+ * @brief This method allocates a DMA buffer
+ *        that can be utilized for small (<=4K) DMA sequences.
+ *        This is utilized to translate SCSI UNMAP requests.
+ *
+ * @param[in]  scsi_io This parameter specifies the user's SCSI IO request
+ *             for which to set the SCSI status.
+ * @param[in] length in bytes of the buffer to be allocated
+ * @param[in] virtual address of the allocated DMA buffer.
+ * @param[in] low 32 bits of the physical DMA address.
+ * @param[in] high 32 bits of the physical DMA address.
+ *
+ * @return This method returns the virtual and physical address
+ *         of the allocated DMA buffer.
+ */
+void sati_cb_allocate_dma_buffer(
+   void *  scsi_io,
+   U32     length,
+   void ** virt_address,
+   U32  *  phys_address_low,
+   U32  *  phys_address_high
+);
+
+/**
+ * @brief This method frees a previously allocated DMA buffer
+ *
+ * @param[in]  scsi_io This parameter specifies the user's SCSI IO request
+ *             for which to set the SCSI status.
+ * @param[in] address - write buffer address being freed
+ *
+ * @return This method returns the address for the data received from
+ *         the remote device.
+ */
+void sati_cb_free_dma_buffer(
+   void * scsi_io,
+   void * virt_address
+);
+
+/**
+ * @brief This method retrieves a pointer to the next scatter gather
+ *        list element.
+ *
+ * @param[in] scsi_io This parameter specifies the user's SCSI IO request
+ *            from which to retrieve the scatter gather list.
+ * @param[in] ata_io This parameter specifies the user's ATA IO request
+ *            from which to retrieve the scatter gather list.
+ * @param[in] current_sge This parameter specifies the current SG element
+ *            being pointed to.  If retrieving the first element,
+ *            then this value should be NULL.
+ * @param[in] next_sge This parameter is the returned SGL element
+ *            based on current_sge.
+ *
+ * @return This method returns a pointer to the scatter gather element.
+ */
+void sati_cb_sgl_next_sge(
+   void * scsi_io,
+   void * ata_io,
+   void * current_sge,
+   void ** next_sge
+);
+
+/**
+ * @brief This method will set the next scatter-gather elements address
+ *        low field.
+ *
+ * @param[in] current_sge This parameter specifies the current SG element
+ *            being pointed to.
+ * @param[in] address_low This parameter specifies the lower 32-bits
+ *            of address to be programmed into the SG element.
+ * @param[in] address_high This parameter specifies the upper 32-bits
+ *            of address to be programmed into the SG element.
+ * @param[in] length This parameter specifies the number of bytes
+ *            to be programmed into the SG element.
+ *
+ * @return none
+ */
+void sati_cb_sge_write(
+   void * current_sge,
+   U32    phys_address_low,
+   U32    phys_address_high,
+   U32    byte_length
+);
+
+/**
+ * @brief This method will check to see if the translation requires
+ *        a translation response callback.  Some translations need to be alerted on all
+ *        failures so sequence cleanup can be completed for halting the translation.
+ *
+ * @param[in] the current SCIC request under going translation.
+ *
+ * @return TRUE A response callback will be required to complete this translation sequence.
+ */
+BOOL sati_cb_do_translate_response(
+   void * request
+);
+
+/**
+ * @brief This method retrieves the SAS address for the device associated
+ *        with the supplied SCSI IO request.  This method assumes that the
+ *        associated device is contained in a SAS Domain.
+ *
+ * @param[in]  scsi_io This parameter specifies the user's SCSI IO request
+ *             for which to retreive the SAS address of the device.
+ * @param[out] sas_address This parameter specifies the SAS address memory
+ *             to be contain the retrieved value.
+ *
+ * @return none
+ */
+void sati_cb_device_get_sas_address(
+   void              * scsi_io,
+   SCI_SAS_ADDRESS_T * sas_address
+);
+
+/**
+ * @brief In this method the user is expected to log the supplied
+ *        error information.  The user must be capable of handling variable
+ *        length argument lists and should consider prepending the fact
+ *        that this is an error from the core.
+ *
+ * @param[in]  logger_object This parameter specifies the logger object
+ *             associated with this message.
+ * @param[in]  log_object_mask This parameter specifies the log objects
+ *             for which this message is being generated.
+ * @param[in]  log_message This parameter specifies the message to be logged.
+ *
+ * @return none
+ */
+void sati_cb_logger_log_error(
+   void                * logger_object,
+   U32                   log_object_mask,
+   char                * log_message,
+   ...
+);
+
+/**
+ * @brief In this method the user is expected to log the supplied warning
+ *        information.  The user must be capable of handling variable
+ *        length argument lists and should consider prepending the fact
+ *        that this is a warning from the core.
+ *
+ * @param[in]  logger_object This parameter specifies the logger object
+ *             associated with this message.
+ * @param[in]  log_object_mask This parameter specifies the log objects
+ *             for which this message is being generated.
+ * @param[in]  log_message This parameter specifies the message to be logged.
+ *
+ * @return none
+ */
+void sati_cb_logger_log_warning(
+   void                * logger_object,
+   U32                   log_object_mask,
+   char                * log_message,
+   ...
+);
+
+/**
+ * @brief In this method the user is expected to log the supplied debug
+ *        information.  The user must be capable of handling variable
+ *        length argument lists and should consider prepending the fact
+ *        that this is a debug message from the core.
+ *
+ * @param[in]  logger_object This parameter specifies the logger object
+ *             associated with this message.
+ * @param[in]  log_object_mask This parameter specifies the log objects
+ *             for which this message is being generated.
+ * @param[in]  log_message This parameter specifies the message to be logged.
+ *
+ * @return none
+ */
+void sati_cb_logger_log_info(
+   void                * logger_object,
+   U32                   log_object_mask,
+   char                * log_message,
+   ...
+);
+
+/**
+ * @brief In this method the user is expected to log the supplied function
+ *        trace information.  The user must be capable of handling variable
+ *        length argument lists and should consider prepending the fact
+ *        that this is a function trace (i.e. entry/exit) message from the
+ *        core.
+ *
+ * @param[in]  logger_object This parameter specifies the logger object
+ *             associated with this message.
+ * @param[in]  log_object_mask This parameter specifies the log objects
+ *             for which this message is being generated.
+ * @param[in]  log_message This parameter specifies the message to be logged.
+ *
+ * @return none
+ */
+void sati_cb_logger_log_trace(
+   void                * logger_object,
+   U32                   log_object_mask,
+   char                * log_message,
+   ...
+);
+
+#include <dev/isci/scil/sati_callbacks_implementation.h>
+
+#else // SATI_DEFAULT_DECLARATION
+
+#include <dev/isci/scil/scif_sas_sati_binding.h>
+#endif // SATI_DEFAULT_DECLARATION
+
+#endif // _SATI_CALLBACKS_H_
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_design.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_design.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,169 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_DESIGN_H_
+#define _SATI_DESIGN_H_
+
+/**
+ at page sati_design_page SATI High Level Design
+
+<b>Authors:</b>
+- Nathan Marushak
+
+ at section scif_sas_scope_and_audience Scope and Audience
+
+This document provides design information relating to the SCSI to ATA
+Translation Implementation (SATI).  Driver developers are the primary
+audience for this document.  The reader is expected to have an understanding
+of SCSI (Simple Computer Storage Interface), ATA (Advanced Technology
+Attachment), and SAT (SCSI-to-ATA Translation).
+
+Please refer to www.t10.org for specifications relating to SCSI and SAT.
+Please refer to www.t13.org for specifications relating to ATA.
+
+ at section overview Overview
+
+SATI provides environment agnostic functionality for translating SCSI
+commands, data, and responses into ATA commands, data, and responses.  As
+a result, in some instances the user must fill out callbacks to set data.
+This ensures that user isn't forced to have to copy the data an additional
+time due to memory access restrictions.
+
+SATI complies with the t10 SAT specification where possible.  In cases where
+there are variances the design and implementation will make note.
+Additionally, for parameters, pages, functionality, or commands for which
+SATI is unable to translate, SATI will return sense data indicating
+INVALID FIELD IN CDB.
+
+SATI has two primary entry points from which the user can enter:
+- sati_translate_command()
+- sati_translate_response() (this method performs data translation).
+
+Additionally, SATI provides a means through which the user can query to
+determine the t10 specification revision with which SATI is compliant.  For
+more information please refer to:
+- sati_get_sat_compliance_version()
+- sati_get_sat_compliance_version_revision()
+
+ at section sati_definitions Definitions
+
+- scsi_io: The SCSI IO is considered to be the user's SCSI IO request object
+(e.g. the windows driver IO request object and SRB).  It is passed back to
+the user via callback methods to retrieve required SCSI information (e.g. CDB,
+response IU address, etc.).  The SCSI IO is just a cookie and can represent
+any value the caller desires, but the user must be able to utilize this value
+when it is passed back through callback methods during translation.
+- ata_io: The ATA IO is considered to be the user's ATA IO request object.  If
+you are utilizing the SCI Framework, then the SCI Framework is the ATA IO.
+The ATA IO is just a cookie and can represent any value the caller desires,
+but the user must be able to utilize this value when it is passed back
+through callback methods during translation.
+
+ at section sati_use_cases Use Cases
+
+The SCSI Primary Command (SPC) set is comprised of commands that are valid
+for all device types defined in SCSI.  Some of these commands have
+sub-commands or parameter data defined in another specification (e.g. SBC, SAT).
+These separate sub-commands or parameter data are captured in the SPC use
+case diagram for simplicity.
+
+ at note
+- For simplicify the association between the actor and the use cases
+has not been drawn, but is assumed.
+- The use cases in green indicate the use case has been implemented in
+  source.
+
+ at image html Use_Case_Diagram__SATI__SATI_-_SPC.jpg "SCSI Primary Command Translation Use Cases"
+
+The SCSI Block Command (SBC) set is comprised of commands that are valid for
+block devices (e.g. disks).
+
+ at image html Use_Case_Diagram__SATI__SATI_-_SBC.jpg "SCSI Block Command Translation Use Cases"
+
+The SCSI-to-ATA Translation (SAT) specification defines a few of it's own
+commands, parameter data, and log pages.  This use case diagram, however, only
+captures the SAT specific commands being translated.
+
+ at image html Use_Case_Diagram__SATI__SATI_-_SAT_Specific.jpg "SCSI-to-ATA Translation Specific Use Cases"
+
+ at section sati_class_hierarchy Class Hierarchy
+
+ at image html Class_Diagram__SATI__Class_Diagram.jpg "SATI Class Diagram"
+
+ at section sati_sequences Sequence Diagrams
+
+ at note These sequence diagrams are currently a little out of date.  An
+      update is required.
+
+This sequence diagram simply depicts the high-level translation sequence to
+be followed for command translations.
+
+ at image html Sequence_Diagram__General_Cmd_Translation_Sequence__General_Cmd_Translation_Sequence.jpg "General Command Translation Sequence"
+
+This sequence diagram simply depicts the high-level translation sequence to
+be followed for reponse translations.
+
+ at image html Sequence_Diagram__General_Rsp_Translation_Sequence__General_Rsp_Translation_Sequence.jpg "General Response Translation Sequence"
+
+This sequence diagram simply depicts the high-level translation sequence to
+be followed for data translations.  Some SCSI commands such as READ CAPACITY,
+INQUIRY, etc. have payload data associated with them.  As a result, it is
+necessary for the ATA payload data to be translated to meet the expected SCSI
+output.
+
+ at image html Sequence_Diagram__General_Data_Translation_Sequence__General_Data_Translation_Sequence.jpg "General Data Translation Sequence"
+
+*/
+
+#endif // _SATI_DESIGN_H_
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_device.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_device.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,245 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains all of the defintions for the SATI remote
+ *        device object.  Some translations require information to be
+ *        remembered on a per device basis.  This information is stored
+ *        in the object defined in this file.
+ */
+
+#include <dev/isci/scil/sati_device.h>
+#include <dev/isci/scil/sci_util.h>  // Move this file.
+#include <dev/isci/scil/sati_unmap.h>
+#include <dev/isci/scil/intel_scsi.h>
+
+/**
+ * @brief This method simply initializes the data members in the device
+ *        object to their appropriate values.
+ *
+ * @param[in] device This parameter specifies the device for which to
+ *            initialize the data members.
+ * @param[in] is_ncq_enabled This parameter specifies if NCQ is to be
+ *            utilized for this particular SATI device.
+ * @param[in] max_ncq_depth This parameter specifies the maximum desired
+ *            NCQ depth.  Once this value is set it can never be increased.
+ * @param[in] ignore_fua This parameter specifies FUA is to be ignored and not
+ *            sent to the end device. Some OS (Windows) has quirky behaviors with FUA
+ *            and recommend driver developers ignore the bit.
+ *
+ * @return none
+ */
+void sati_device_construct(
+   SATI_DEVICE_T * device,
+   BOOL            is_ncq_enabled,
+   U8              max_ncq_depth,
+   BOOL            ignore_fua
+)
+{
+   device->state                   = SATI_DEVICE_STATE_OPERATIONAL;
+   device->capabilities            = 0;
+   device->descriptor_sense_enable = SCSI_MODE_PAGE_CONTROL_D_SENSE_DISABLE;
+
+   // The user requested that NCQ be utilized if it is supported by
+   // the device.
+   if (is_ncq_enabled == TRUE)
+      device->capabilities |= SATI_DEVICE_CAP_NCQ_REQUESTED_ENABLE;
+
+   device->ncq_depth      = max_ncq_depth;
+
+   // The user requested that FUA is ignored (windows performance issue)
+   if (ignore_fua == TRUE)
+      device->capabilities |= SATI_DEVICE_CAP_IGNORE_FUA;
+
+}
+
+/**
+ * @brief This method will update the SATI_DEVICE capabilities based on
+ *        the supplied ATA_IDENTIFY_DEVICE_DATA.
+ *
+ * @param[in] device This parameter specifies the device for which to update
+ *            the supported capabilities.
+ * @param[in] identify This parameter specifies the ata identify device
+ *            information from which to extract the capabilities of the
+ *            device.
+ *
+ * @return none
+ */
+void sati_device_update_capabilities(
+   SATI_DEVICE_T              * device,
+   ATA_IDENTIFY_DEVICE_DATA_T * identify
+)
+{
+   U16 capabilities = 0;
+
+   if (identify->capabilities1 & ATA_IDENTIFY_CAPABILITIES1_NORMAL_DMA_ENABLE)
+      capabilities |= SATI_DEVICE_CAP_UDMA_ENABLE;
+
+   if (identify->command_set_supported1
+       & ATA_IDENTIFY_COMMAND_SET_SUPPORTED1_48BIT_ENABLE)
+   {
+      capabilities |= SATI_DEVICE_CAP_48BIT_ENABLE;
+   }
+
+   if (identify->command_set_supported0
+       & ATA_IDENTIFY_COMMAND_SET_SUPPORTED0_SMART_ENABLE)
+   {
+      capabilities |= SATI_DEVICE_CAP_SMART_SUPPORT;
+   }
+
+   if (identify->command_set_enabled0
+       & ATA_IDENTIFY_COMMAND_SET_SUPPORTED0_SMART_ENABLE)
+   {
+       capabilities |= SATI_DEVICE_CAP_SMART_ENABLE;
+   }
+
+   // Save the NCQ related capabilities information.
+   if (identify->serial_ata_capabilities
+       & ATA_IDENTIFY_SATA_CAPABILITIES_NCQ_ENABLE)
+   {
+      if (device->capabilities & SATI_DEVICE_CAP_NCQ_REQUESTED_ENABLE)
+      {
+         capabilities      |= SATI_DEVICE_CAP_NCQ_REQUESTED_ENABLE;
+         capabilities      |= SATI_DEVICE_CAP_NCQ_SUPPORTED_ENABLE;
+         capabilities      |= SATI_DEVICE_CAP_DMA_FUA_ENABLE;
+         device->ncq_depth  = MIN(
+                                 device->ncq_depth,
+                                 (U8) (identify->queue_depth
+                                 & ATA_IDENTIFY_NCQ_QUEUE_DEPTH_ENABLE) + 1
+                              );
+      }
+   }
+
+   // if the user requested that FUA is ignored; transfer it so we don't lose on update.
+   if (device->capabilities & SATI_DEVICE_CAP_IGNORE_FUA)
+	   capabilities |= SATI_DEVICE_CAP_IGNORE_FUA;
+
+   if (identify->general_config_bits & ATA_IDENTIFY_REMOVABLE_MEDIA_ENABLE)
+      capabilities |= SATI_DEVICE_CAP_REMOVABLE_MEDIA;
+
+   if(identify->command_set_supported2 & ATA_IDENTIFY_WRITE_UNCORRECTABLE_SUPPORT )
+   {
+      capabilities |= SATI_DEVICE_CAP_WRITE_UNCORRECTABLE_ENABLE;
+   }
+
+   if(identify->physical_logical_sector_info &
+      ATA_IDENTIFY_LOGICAL_SECTOR_PER_PHYSICAL_SECTOR_ENABLE)
+   {
+      capabilities |= SATI_DEVICE_CAP_MULTIPLE_SECTORS_PER_PHYSCIAL_SECTOR;
+   }
+
+   if(identify->command_set_supported_extention &
+      ATA_IDENTIFY_COMMAND_SET_SMART_SELF_TEST_SUPPORTED)
+   {
+      capabilities |= SATI_DEVICE_CAP_SMART_SELF_TEST_SUPPORT;
+   }
+
+   if (identify->nominal_media_rotation_rate == 1)
+   {
+       capabilities |= SATI_DEVICE_CAP_SSD;
+   }
+
+   // Save off the logical block size reported by the drive
+   // See if Word 106 is valid and reports a logical sector size
+   if ((identify->physical_logical_sector_info & 0x5000) == 0x5000)
+   {
+       device->logical_block_size = (identify->words_per_logical_sector[3] << 24) |
+                                    (identify->words_per_logical_sector[2] << 16) |
+                                    (identify->words_per_logical_sector[1] << 8) |
+                                    (identify->words_per_logical_sector[0]);
+   }
+   else
+   {
+       device->logical_block_size = 512;
+   }
+
+   // Determine DSM TRIM capabilities
+   // Defend against SSDs which report TRIM support, but set
+   //  max_lba_range_entry_blocks to zero, by disabling TRIM for
+   //  those SSDs.
+   if (
+     (identify->data_set_management & ATA_IDENTIFY_COMMAND_SET_DSM_TRIM_SUPPORTED)
+     && (identify->max_lba_range_entry_blocks > 0)
+      )
+   {
+      capabilities |= SATI_DEVICE_CAP_DSM_TRIM_SUPPORT;
+      device->max_lba_range_entry_blocks = identify->max_lba_range_entry_blocks;
+   }
+
+   if (identify->additional_supported
+       & ATA_IDENTIFY_COMMAND_ADDL_SUPPORTED_DETERMINISTIC_READ)
+   {
+      capabilities |= SATI_DEVICE_CAP_DETERMINISTIC_READ_AFTER_TRIM;
+   }
+
+   if (identify->additional_supported
+       & ATA_IDENTIFY_COMMAND_ADDL_SUPPORTED_READ_ZERO)
+   {
+      capabilities |= SATI_DEVICE_CAP_READ_ZERO_AFTER_TRIM;
+   }
+
+   if (identify->capabilities1
+       & ATA_IDENTIFY_CAPABILITIES1_STANDBY_ENABLE)
+   {
+       capabilities |= SATI_DEVICE_CAP_STANDBY_ENABLE;
+   }
+
+   device->min_blocks_per_microcode_command = identify->min_num_blocks_per_microcode;
+   device->max_blocks_per_microcode_command = identify->max_num_blocks_per_microcode;
+
+   device->capabilities = capabilities;
+}
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_device.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_device.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,203 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_DEVICE_H_
+#define _SATI_DEVICE_H_
+
+/**
+ * @file
+ * @brief This file contains all of the defintions for the SATI remote
+ *        device object.  Some translations require information to be
+ *        remembered on a per device basis.  This information is stored
+ *        in the object defined in this file.
+ */
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/intel_ata.h>
+
+/**
+ * @enum _SATI_DEVICE_STATE
+ *
+ * @brief This enumeration depicts the various states possible for the a
+ *        translation remote device object.
+ */
+typedef enum _SATI_DEVICE_STATE
+{
+   SATI_DEVICE_STATE_OPERATIONAL,
+   SATI_DEVICE_STATE_STOPPED,
+   SATI_DEVICE_STATE_STANDBY,
+   SATI_DEVICE_STATE_IDLE,
+   SATI_DEVICE_STATE_DEVICE_FAULT_OCCURRED,
+   SATI_DEVICE_STATE_FORMAT_UNIT_IN_PROGRESS,
+   SATI_DEVICE_STATE_SELF_TEST_IN_PROGRESS,
+   SATI_DEVICE_STATE_SEQUENCE_INCOMPLETE,
+   SATI_DEVICE_STATE_UNIT_ATTENTION_CONDITION
+
+} SATI_DEVICE_STATE;
+
+/**
+ * @name SATI_DEVICE_CAPABILITIES
+ *
+ * These constants define the various capabilities that a remote device may
+ * support for which there is an impact on translation.
+ */
+/*@{*/
+#define SATI_DEVICE_CAP_UDMA_ENABLE          0x00000001
+#define SATI_DEVICE_CAP_NCQ_REQUESTED_ENABLE 0x00000002
+#define SATI_DEVICE_CAP_NCQ_SUPPORTED_ENABLE 0x00000004
+#define SATI_DEVICE_CAP_48BIT_ENABLE         0x00000008
+#define SATI_DEVICE_CAP_DMA_FUA_ENABLE       0x00000010
+#define SATI_DEVICE_CAP_SMART_SUPPORT        0x00000020
+#define SATI_DEVICE_CAP_REMOVABLE_MEDIA      0x00000040
+#define SATI_DEVICE_CAP_SMART_ENABLE         0x00000080
+#define SATI_DEVICE_CAP_WRITE_UNCORRECTABLE_ENABLE           0x00000100
+#define SATI_DEVICE_CAP_MULTIPLE_SECTORS_PER_PHYSCIAL_SECTOR 0x00000200
+#define SATI_DEVICE_CAP_SMART_SELF_TEST_SUPPORT              0x00000400
+#define SATI_DEVICE_CAP_SSD                                  0x00000800
+#define SATI_DEVICE_CAP_DSM_TRIM_SUPPORT                     0x00001000
+#define SATI_DEVICE_CAP_DETERMINISTIC_READ_AFTER_TRIM        0x00002000
+#define SATI_DEVICE_CAP_READ_ZERO_AFTER_TRIM                 0x00004000
+#define SATI_DEVICE_CAP_STANDBY_ENABLE                       0x00008000
+#define SATI_DEVICE_CAP_IGNORE_FUA                           0x00010000
+
+
+/*@}*/
+
+/**
+ * @struct SATI_DEVICE
+ *
+ * @brief The SATI_DEVICE structure define the state of the remote device
+ *        with respect to translation.
+ */
+typedef struct SATI_DEVICE
+{
+   /**
+    * This field simply dictates the state of the SATI device.
+    */
+   SATI_DEVICE_STATE state;
+
+   /**
+    * This field indicates features supported by the remote device that
+    * impact translation execution.
+    */
+   U16 capabilities;
+
+   /**
+    * This field indicates the depth of the native command queue supported
+    * by the device.
+    */
+   U8 ncq_depth;
+
+   /**
+    * This field stores the additional sense code for a unit attention
+    * condition.
+    */
+   U8 unit_attention_asc;
+
+   /**
+    * This field indicates the additional sense code qualifier for a unit
+    * attention condition.
+    */
+   U8 unit_attention_ascq;
+
+   /**
+    * This field indicates the ATA standby timer value set throught the
+    * ATA IDLE and ATA Standby commands
+    */
+   U8 ata_standby_timer;
+
+   /**
+    * This field indicates the maximum number of data set management
+    * descriptor entries the device supports in blocks.
+    */
+   U16 max_lba_range_entry_blocks;
+
+   /**
+    * The field is the reported logical block size for the device
+    */
+   U32 logical_block_size;
+
+   /**
+    * This field is the maximum number of blocks per Download Microcode command
+    * for this device.
+    */
+   U16 max_blocks_per_microcode_command;
+
+   /**
+   * This field is the minimum number of blocks per Download Microcode command
+   * for this device.
+   */
+   U16 min_blocks_per_microcode_command;
+
+   /**
+    * This field indicates the type of constructed sense data if enabled descriptor
+    * sense data will be constructed
+    */
+   U8 descriptor_sense_enable;
+
+} SATI_DEVICE_T;
+
+void sati_device_construct(
+   SATI_DEVICE_T * device,
+   BOOL            is_ncq_enabled,
+   U8              max_ncq_depth,
+   BOOL            ignore_fua
+);
+
+void sati_device_update_capabilities(
+   SATI_DEVICE_T              * device,
+   ATA_IDENTIFY_DEVICE_DATA_T * identify
+);
+
+#endif // _SATI_TRANSLATOR_SEQUENCE_H_
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_inquiry.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_inquiry.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,799 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ *
+ * @brief This file contains the method implementations required to
+ *        translate the SCSI inquiry command.
+ *        The following (VPD) pages are currently supported:
+ *        - Standard
+ *        - Supported Pages
+ *        - Unit Serial Number
+ *        - Device Identification
+ */
+
+#if !defined(DISABLE_SATI_INQUIRY)
+
+#include <dev/isci/scil/sati_inquiry.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_scsi.h>
+
+//******************************************************************************
+//* P R I V A T E   M E T H O D S
+//******************************************************************************
+/**
+* @brief This method builds the SCSI data associated with the SATI product
+*        revision that is commonly used on the Standard inquiry response and
+*        the ATA information page.
+*
+* @param[in]  sequence This parameter specifies the translator sequence
+*             object to be utilized during data translation.
+* @param[in]  ata_input_data This parameter specifies ata data received from
+*             the remote device.
+* @param[out] scsi_io This parameter specifies the user IO request for
+*             which to construct the standard inquiry data.
+*
+* @return none
+*/
+static
+void sati_inquiry_construct_product_revision(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+)
+{
+   ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
+      ata_input_data;
+
+   // Fill in the product revision level field.
+   // Per SAT, copy portions of the firmware revision that is not filled
+   // with spaces.  Some devices left-align their firmware rev ID, while
+   // others right-align.
+   if (  (identify->firmware_revision[4] == 0x20)
+       && (identify->firmware_revision[5] == 0x20)
+       && (identify->firmware_revision[6] == 0x20)
+       && (identify->firmware_revision[7] == 0x20) )
+   {
+      sati_ata_identify_device_copy_data(
+         sequence,
+         scsi_io,
+         32,
+         ata_input_data,
+         ATA_IDENTIFY_DEVICE_GET_OFFSET(firmware_revision),
+         4,
+         TRUE
+       );
+   }
+   else
+   {
+      // Since the last 4 bytes of the firmware revision are not spaces,
+      // utilize these bytes as the firmware revision in the inquiry data.
+      sati_ata_identify_device_copy_data(
+         sequence,
+         scsi_io,
+         32,
+         ata_input_data,
+         ATA_IDENTIFY_DEVICE_GET_OFFSET(firmware_revision)+4,
+         4,
+         TRUE
+      );
+   }
+}
+
+
+//******************************************************************************
+//* P U B L I C   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method builds the SCSI data associated with a SCSI standard
+ *        inquiry request.
+ *
+ * @param[in]  sequence This parameter specifies the translator sequence
+ *             object to be utilized during data translation.
+ * @param[in]  ata_input_data This parameter specifies ata data received from
+ *             the remote device.
+ * @param[out] scsi_io This parameter specifies the user IO request for
+ *             which to construct the standard inquiry data.
+ *
+ * @return none
+ */
+void sati_inquiry_standard_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+)
+{
+   ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
+                                           ata_input_data;
+   U32  index;
+
+   // Device type is disk, attached to this lun.
+   sati_set_data_byte(sequence, scsi_io, 0, 0x00);
+
+   // If the device indicates it's a removable media device, then set the
+   // RMB bit
+   if (identify->general_config_bits & ATA_IDENTIFY_REMOVABLE_MEDIA_ENABLE)
+      sati_set_data_byte(sequence, scsi_io, 1, 0x80);
+   else
+      sati_set_data_byte(sequence, scsi_io, 1, 0x00);
+
+   sati_set_data_byte(sequence, scsi_io, 2, 0x05); // Indicate SPC-3 support
+   sati_set_data_byte(sequence, scsi_io, 3, 0x02); // Response Format SPC-3
+
+   sati_set_data_byte(sequence, scsi_io, 4, 62); // 62 Additional Data Bytes.
+                                                 // n-4 per the spec, we end at
+                                                 // byte 66, so 66-4.
+   sati_set_data_byte(sequence, scsi_io, 5, 0x00);
+   sati_set_data_byte(sequence, scsi_io, 6, 0x00);
+   sati_set_data_byte(sequence, scsi_io, 7, 0x02); // Enable Cmd Queueing
+
+   // The Vender identification field is set to "ATA     "
+   sati_set_data_byte(sequence, scsi_io, 8, 0x41);
+   sati_set_data_byte(sequence, scsi_io, 9, 0x54);
+   sati_set_data_byte(sequence, scsi_io, 10, 0x41);
+   sati_set_data_byte(sequence, scsi_io, 11, 0x20);
+   sati_set_data_byte(sequence, scsi_io, 12, 0x20);
+   sati_set_data_byte(sequence, scsi_io, 13, 0x20);
+   sati_set_data_byte(sequence, scsi_io, 14, 0x20);
+   sati_set_data_byte(sequence, scsi_io, 15, 0x20);
+
+   // Fill in the product ID field.
+   sati_ata_identify_device_copy_data(
+      sequence,
+      scsi_io,
+      16,
+      ata_input_data,
+      ATA_IDENTIFY_DEVICE_GET_OFFSET(model_number),
+      16,
+      TRUE
+   );
+
+   sati_inquiry_construct_product_revision(
+      sequence,
+      ata_input_data,
+      scsi_io
+   );
+
+   // Set the remaining fields up to the version descriptors to 0.
+   for (index = 36; index < 58; index++)
+      sati_set_data_byte(sequence, scsi_io, index, 0);
+
+   // Add version descriptors for the various protocols in play.
+
+   // SAM-4
+   sati_set_data_byte(sequence, scsi_io, 58, 0);
+   sati_set_data_byte(sequence, scsi_io, 59, 0x80);
+
+   // SAS-2
+   sati_set_data_byte(sequence, scsi_io, 60, 0x0C);
+   sati_set_data_byte(sequence, scsi_io, 61, 0x20);
+
+   // SPC-4
+   sati_set_data_byte(sequence, scsi_io, 62, 0x04);
+   sati_set_data_byte(sequence, scsi_io, 63, 0x60);
+
+   // SBC-3
+   sati_set_data_byte(sequence, scsi_io, 64, 0x04);
+   sati_set_data_byte(sequence, scsi_io, 65, 0xC0);
+
+   // ATA/ATAPI-8 ACS
+   sati_set_data_byte(sequence, scsi_io, 66, 0x16);
+   sati_set_data_byte(sequence, scsi_io, 67, 0x23);
+}
+
+/**
+ * @brief This method builds the SCSI data associated with an SCSI inquiry
+ *        for the supported VPD pages page.
+ *
+ * @param[in]  sequence This parameter specifies the translator sequence
+ *             object to be utilized during data translation.
+ * @param[out] scsi_io This parameter specifies the user IO request for
+ *             which to construct the supported VPD page information.
+ *
+ * @return none
+ */
+static
+void sati_inquiry_supported_pages_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io
+)
+{
+   // Formulate the SCSI output data for the caller.
+   sati_set_data_byte(sequence, scsi_io, 0, 0); // Qualifier and Device Type
+   sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_SUPPORTED_PAGES_PAGE);
+   sati_set_data_byte(sequence, scsi_io, 2, 0); // Reserved.
+   sati_set_data_byte(sequence, scsi_io, 3, 4); // # VPD pages supported
+   sati_set_data_byte(sequence, scsi_io, 4, SCSI_INQUIRY_SUPPORTED_PAGES_PAGE);
+   sati_set_data_byte(sequence, scsi_io, 5, SCSI_INQUIRY_UNIT_SERIAL_NUM_PAGE);
+   sati_set_data_byte(sequence, scsi_io, 6, SCSI_INQUIRY_DEVICE_ID_PAGE);
+   sati_set_data_byte(sequence, scsi_io, 7, SCSI_INQUIRY_ATA_INFORMATION_PAGE);
+   sati_set_data_byte(sequence, scsi_io, 8, SCSI_INQUIRY_BLOCK_DEVICE_PAGE);
+   sati_set_data_byte(sequence, scsi_io, 9, 0); // End of the list
+}
+
+/**
+ * @brief This method builds the SCSI data associated with a request for
+ *        the unit serial number vital product data (VPD) page.
+ *
+ * @param[in]  sequence This parameter specifies the translator sequence
+ *             object to be utilized during data translation.
+ * @param[in]  ata_input_data This parameter specifies ata data received from
+ *             the remote device.
+ * @param[out] scsi_io This parameter specifies the user IO request for
+ *             which to construct the unit serial number data.
+ *
+ * @return none
+ */
+void sati_inquiry_serial_number_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+)
+{
+   // Peripheral qualifier (0x0, currently connected)
+   // Peripheral device type (0x0 direct-access block device)
+   sati_set_data_byte(sequence, scsi_io, 0, 0x00);
+
+   sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_UNIT_SERIAL_NUM_PAGE);
+   sati_set_data_byte(sequence, scsi_io, 2, 0x00);  // Reserved
+   sati_set_data_byte(sequence, scsi_io, 3, ATA_IDENTIFY_SERIAL_NUMBER_LEN);
+
+   sati_ata_identify_device_copy_data(
+      sequence,
+      scsi_io,
+      4,
+      ata_input_data,
+      ATA_IDENTIFY_DEVICE_GET_OFFSET(serial_number),
+      ATA_IDENTIFY_SERIAL_NUMBER_LEN,
+      TRUE
+   );
+}
+
+/**
+* @brief This method builds the SCSI data associated with a request for
+*        the Block Device Characteristics vital product data (VPD) page.
+*
+* @param[in]  sequence This parameter specifies the translator sequence
+*             object to be utilized during data translation.
+* @param[in]  ata_input_data This parameter specifies ata data received from
+*             the remote device.
+* @param[out] scsi_io This parameter specifies the user IO request for
+*             which to construct the unit serial number data.
+*
+* @return none
+*/
+void sati_inquiry_block_device_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+)
+{
+   ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
+      ata_input_data;
+
+   U32 offset;
+
+   // Peripheral qualifier (0x0, currently connected)
+   // Peripheral device type (0x0 direct-access block device)
+   sati_set_data_byte(sequence, scsi_io, 0, 0x00);
+
+   sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_BLOCK_DEVICE_PAGE);
+
+   //PAGE LENGTH 0x003C
+   sati_set_data_byte(sequence, scsi_io, 2, 0x00);
+   sati_set_data_byte(sequence, scsi_io, 3, SCSI_INQUIRY_BLOCK_DEVICE_LENGTH);
+
+   sati_ata_identify_device_copy_data(
+      sequence,
+      scsi_io,
+      4,
+      ata_input_data,
+      ATA_IDENTIFY_DEVICE_GET_OFFSET(nominal_media_rotation_rate),
+      2,
+      FALSE
+    );
+
+    sati_set_data_byte(sequence, scsi_io, 6, 0x00);
+
+    sati_set_data_byte(
+       sequence,
+       scsi_io,
+       7,
+       (identify->device_nominal_form_factor & 0x0F) // only need bits 0-3
+    );
+
+    //bytes 8-63 are reserved
+    for(offset = 8; offset < 63; offset++)
+    {
+       sati_set_data_byte(sequence, scsi_io, offset, 0x00);
+    }
+}
+
+/**
+ * @brief This method builds the SCSI data associated with a request for
+ *        the device identification vital product data (VPD) page.
+ *
+ * @param[in]  sequence This parameter specifies the translator sequence
+ *             object to be utilized during data translation.
+ * @param[in]  ata_input_data This parameter specifies ata data received from
+ *             the remote device.
+ * @param[out] scsi_io This parameter specifies the user IO request for
+ *             which to construct the device ID page.
+ *
+ * @return none
+ */
+void sati_inquiry_device_id_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+)
+{
+   ATA_IDENTIFY_DEVICE_DATA_T * identify    = (ATA_IDENTIFY_DEVICE_DATA_T*)
+                                              ata_input_data;
+   U16                     byte_offset = 4;
+   U16                     page_length;
+
+   // Peripheral qualifier (0x0, currently connected)
+   // Peripheral device type (0x0 direct-access block device)
+   sati_set_data_byte(sequence, scsi_io, 0, 0x00);
+
+   sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_DEVICE_ID_PAGE);
+
+   /**
+    * If World Wide Names are supported by this target, then build an
+    * identification descriptor using the WWN.
+    */
+
+   if (identify->command_set_supported_extention
+       & ATA_IDENTIFY_COMMAND_SET_WWN_SUPPORT_ENABLE)
+   {
+
+      sati_set_data_byte(sequence,
+         scsi_io, 4, SCSI_FC_PROTOCOL_IDENTIFIER | SCSI_BINARY_CODE_SET
+      );
+
+
+      sati_set_data_byte(sequence,
+         scsi_io, 5, SCSI_LUN_ASSOCIATION | SCSI_NAA_IDENTIFIER_TYPE
+      );
+
+      sati_set_data_byte(sequence, scsi_io, 6, 0);
+      sati_set_data_byte(sequence, scsi_io, 7, 0x08); // WWN are 8 bytes long
+
+      // Copy data from the identify device world wide name field into the
+      // buffer.
+      sati_ata_identify_device_copy_data(
+         sequence,
+         scsi_io,
+         8,
+         ata_input_data,
+         ATA_IDENTIFY_DEVICE_GET_OFFSET(world_wide_name),
+         ATA_IDENTIFY_WWN_LEN,
+         FALSE
+      );
+
+      byte_offset = 16;
+   }
+
+   /**
+    * Build a identification descriptor using the model number & serial number.
+    */
+
+   sati_set_data_byte(sequence,
+      scsi_io, byte_offset, SCSI_FC_PROTOCOL_IDENTIFIER | SCSI_ASCII_CODE_SET
+   );
+   byte_offset++;
+   sati_set_data_byte(sequence,
+      scsi_io, byte_offset, SCSI_LUN_ASSOCIATION | SCSI_T10_IDENTIFIER_TYPE
+   );
+   byte_offset++;
+   sati_set_data_byte(sequence, scsi_io, byte_offset, 0);
+   byte_offset++;
+
+   // Identifier length (8 bytes for "ATA     " + 40 bytes from ATA IDENTIFY
+   // model number field + 20 bytes from ATA IDENTIFY serial number field.
+   sati_set_data_byte(
+      sequence,
+      scsi_io,
+      byte_offset,
+      8 + (ATA_IDENTIFY_SERIAL_NUMBER_LEN) + (ATA_IDENTIFY_MODEL_NUMBER_LEN)
+   );
+   byte_offset++;
+
+   // Per SAT, write "ATA     ".
+   sati_set_data_byte(sequence, scsi_io, byte_offset, 0x41);
+   byte_offset++;
+   sati_set_data_byte(sequence, scsi_io, byte_offset, 0x54);
+   byte_offset++;
+   sati_set_data_byte(sequence, scsi_io, byte_offset, 0x41);
+   byte_offset++;
+   sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20);
+   byte_offset++;
+   sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20);
+   byte_offset++;
+   sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20);
+   byte_offset++;
+   sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20);
+   byte_offset++;
+   sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20);
+   byte_offset++;
+
+   // Copy data from the identify device model number field into the
+   // buffer and update the byte_offset.
+   sati_ata_identify_device_copy_data(
+      sequence,
+      scsi_io,
+      byte_offset,
+      ata_input_data,
+      ATA_IDENTIFY_DEVICE_GET_OFFSET(model_number),
+      ATA_IDENTIFY_MODEL_NUMBER_LEN,
+      TRUE
+   );
+
+   byte_offset += ATA_IDENTIFY_MODEL_NUMBER_LEN;
+
+   // Copy data from the identify device serial number field into the
+   // buffer and update the byte_offset.
+   sati_ata_identify_device_copy_data(
+      sequence,
+      scsi_io,
+      byte_offset,
+      ata_input_data,
+      ATA_IDENTIFY_DEVICE_GET_OFFSET(serial_number),
+      ATA_IDENTIFY_SERIAL_NUMBER_LEN,
+      TRUE
+   );
+
+   byte_offset += ATA_IDENTIFY_SERIAL_NUMBER_LEN;
+
+   /**
+    * If the target is contained in a SAS Domain, then build a target port
+    * ID descriptor using the SAS address.
+    */
+
+#if     defined(SATI_TRANSPORT_SUPPORTS_SAS)       \
+     && defined(DISABLE_MSFT_SCSI_COMPLIANCE_SUPPORT)
+   {
+      SCI_SAS_ADDRESS_T sas_address;
+
+      sati_set_data_byte(
+         sequence,
+         scsi_io,
+         byte_offset,
+         SCSI_SAS_PROTOCOL_IDENTIFIER | SCSI_BINARY_CODE_SET
+      );
+      byte_offset++;
+
+      sati_set_data_byte(
+         sequence,
+         scsi_io,
+         byte_offset,
+         SCSI_PIV_ENABLE | SCSI_TARGET_PORT_ASSOCIATION |
+         SCSI_NAA_IDENTIFIER_TYPE
+      );
+
+      byte_offset++;
+      sati_set_data_byte(sequence, scsi_io, byte_offset, 0);
+      byte_offset++;
+      sati_set_data_byte(sequence, scsi_io, byte_offset, 8); // SAS Addr=8 bytes
+      byte_offset++;
+
+      sati_cb_device_get_sas_address(scsi_io, &sas_address);
+
+      // Store the SAS address in the target port descriptor.
+      sati_set_data_dword(sequence, scsi_io, byte_offset, sas_address.high);
+      byte_offset += 4;
+      sati_set_data_dword(sequence, scsi_io, byte_offset, sas_address.low);
+      byte_offset += 4;
+   }
+#endif // SATI_TRANSPORT_SUPPORTS_SAS && DISABLE_MSFT_SCSI_COMPLIANCE_SUPPORT
+
+   /**
+    * Set the Page length field.  The page length is n-3, where n is the
+    * last offset in the page (considered page length - 4).
+    */
+
+   page_length = byte_offset - 4;
+   sati_set_data_byte(sequence, scsi_io, 2, (U8)((page_length & 0xFF00) >> 8));
+   sati_set_data_byte(sequence, scsi_io, 3, (U8)(page_length & 0x00FF));
+}
+
+/**
+* @brief This method builds the SCSI data associated with a request for
+*        the  ATA information vital product data (VPD) page.
+*
+* @param[in]  sequence This parameter specifies the translator sequence
+*             object to be utilized during data translation.
+* @param[in]  ata_input_data This parameter specifies ata data received from
+*             a identify device command processed by the remote device.
+* @param[out] scsi_io This parameter specifies the user IO request for
+*             which to construct the ATA information page.
+*
+* @return none
+*/
+SATI_STATUS sati_inquiry_ata_information_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+)
+{
+   sati_set_data_byte(sequence, scsi_io, 0, 0x00);
+   sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_ATA_INFORMATION_PAGE);
+   sati_set_data_byte(sequence, scsi_io, 2, 0x02);
+   sati_set_data_byte(sequence, scsi_io, 3, 0x38);
+
+   //Reserved SAT2r07
+   sati_set_data_byte(sequence, scsi_io, 4, 0x00);
+   sati_set_data_byte(sequence, scsi_io, 5, 0x00);
+   sati_set_data_byte(sequence, scsi_io, 6, 0x00);
+   sati_set_data_byte(sequence, scsi_io, 7, 0x00);
+
+   // The Vender identification field is set to "ATA     "
+   sati_set_data_byte(sequence, scsi_io, 8, 0x41);
+   sati_set_data_byte(sequence, scsi_io, 9, 0x54);
+   sati_set_data_byte(sequence, scsi_io, 10, 0x41);
+   sati_set_data_byte(sequence, scsi_io, 11, 0x20);
+   sati_set_data_byte(sequence, scsi_io, 12, 0x20);
+   sati_set_data_byte(sequence, scsi_io, 13, 0x20);
+   sati_set_data_byte(sequence, scsi_io, 14, 0x20);
+   sati_set_data_byte(sequence, scsi_io, 15, 0x20);
+
+   //SAT Product identification
+   sati_ata_identify_device_copy_data(
+      sequence,
+      scsi_io,
+      16,
+      ata_input_data,
+      ATA_IDENTIFY_DEVICE_GET_OFFSET(model_number),
+      16,
+      TRUE
+   );
+
+   //SAT Product Revision level bytes 32-35
+   sati_inquiry_construct_product_revision(
+      sequence,
+      ata_input_data,
+      scsi_io
+   );
+
+   //skipping ATA device signature for now
+
+   //Command code
+   sati_set_data_byte(sequence, scsi_io, 56, 0xEC);
+
+   //Reserved SAT2r07
+   sati_set_data_byte(sequence, scsi_io, 57, 0x00);
+   sati_set_data_byte(sequence, scsi_io, 58, 0x00);
+   sati_set_data_byte(sequence, scsi_io, 59, 0x00);
+
+   //copy all ATA identify device data
+   sati_ata_identify_device_copy_data(
+      sequence,
+      scsi_io,
+      60,
+      ata_input_data,
+      0,
+      sizeof(ATA_IDENTIFY_DEVICE_DATA_T),
+      FALSE
+   );
+
+   //Need to send ATA Execute Device Diagnostic command still
+   sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
+
+   return SATI_SEQUENCE_INCOMPLETE;
+}
+
+/**
+ * @brief This method will translate the inquiry SCSI command into
+ *        an ATA IDENTIFY DEVICE command.  It will handle several different
+ *        VPD pages and the standard inquiry page.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the command translation was
+ *         successful.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
+ *         the page isn't supported, or the page code
+ *         field is not zero when the EVPD bit is 0.
+ */
+SATI_STATUS sati_inquiry_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+   /**
+    * SPC dictates:
+    * - that the page code field must be 0, if VPD enable is 0.
+    */
+   if (  ((sati_get_cdb_byte(cdb, 1) & SCSI_INQUIRY_EVPD_ENABLE) == 0)
+      && (sati_get_cdb_byte(cdb, 2) != 0) )
+   {
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_ILLEGAL_REQUEST,
+         SCSI_ASC_INVALID_FIELD_IN_CDB,
+         SCSI_ASCQ_INVALID_FIELD_IN_CDB
+      );
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+
+   // Set the data length based on the allocation length field in the CDB.
+   sequence->allocation_length = (sati_get_cdb_byte(cdb, 3) << 8) |
+                                 (sati_get_cdb_byte(cdb, 4));
+
+   // Check to see if there was a request for the vital product data or just
+   // the standard inquiry.
+   if (sati_get_cdb_byte(cdb, 1) & SCSI_INQUIRY_EVPD_ENABLE)
+   {
+      // Parse the page code to determine which translator to invoke.
+      switch (sati_get_cdb_byte(cdb, 2))
+      {
+         case SCSI_INQUIRY_SUPPORTED_PAGES_PAGE:
+            sequence->type  = SATI_SEQUENCE_INQUIRY_SUPPORTED_PAGES;
+            sati_inquiry_supported_pages_translate_data(sequence, scsi_io);
+            return SATI_COMPLETE;
+         break;
+
+         case SCSI_INQUIRY_UNIT_SERIAL_NUM_PAGE:
+            sequence->type = SATI_SEQUENCE_INQUIRY_SERIAL_NUMBER;
+         break;
+
+         case SCSI_INQUIRY_DEVICE_ID_PAGE:
+            sequence->type = SATI_SEQUENCE_INQUIRY_DEVICE_ID;
+         break;
+
+         case SCSI_INQUIRY_ATA_INFORMATION_PAGE:
+
+            if(sequence->state == SATI_SEQUENCE_STATE_INCOMPLETE)
+            {
+               sati_ata_execute_device_diagnostic_construct(
+                  ata_io,
+                  sequence
+               );
+               sequence->type = SATI_SEQUENCE_INQUIRY_EXECUTE_DEVICE_DIAG;
+            }
+            else
+            {
+               sequence->type = SATI_SEQUENCE_INQUIRY_ATA_INFORMATION;
+            }
+         break;
+
+         case SCSI_INQUIRY_BLOCK_DEVICE_PAGE:
+            sequence->type = SATI_SEQUENCE_INQUIRY_BLOCK_DEVICE;
+         break;
+
+         default:
+            sati_scsi_sense_data_construct(
+               sequence,
+               scsi_io,
+               SCSI_STATUS_CHECK_CONDITION,
+               SCSI_SENSE_ILLEGAL_REQUEST,
+               SCSI_ASC_INVALID_FIELD_IN_CDB,
+               SCSI_ASCQ_INVALID_FIELD_IN_CDB
+            );
+            return SATI_FAILURE_CHECK_RESPONSE_DATA;
+         break;
+      }
+   }
+   else
+   {
+      sequence->type = SATI_SEQUENCE_INQUIRY_STANDARD;
+   }
+
+   sati_ata_identify_device_construct(ata_io, sequence);
+
+   return SATI_SUCCESS;
+}
+
+/**
+* @brief This method finishes the construction of the SCSI data associated
+         with a request for the  ATA information vital product data (VPD) page.
+         The ATA device signature is written into the data response from the
+         task fle registers after issuing a Execute Device Diagnostic command.
+*
+* @param[in]  sequence This parameter specifies the translator sequence
+*             object to be utilized during data translation.
+* @param[out] scsi_io This parameter specifies the user IO request for
+*             which to construct the ATA information page.
+* @param[in]  ata_io This parameter specifies the ATA payload
+*             buffer location and size to be translated.
+*
+* @return none
+*/
+void sati_inquiry_ata_information_finish_translation(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
+   U32 offset;
+
+   //SATA transport
+   sati_set_data_byte(sequence, scsi_io, 36, 0x34);
+   sati_set_data_byte(sequence, scsi_io, 37, 0x00);
+   sati_set_data_byte(sequence, scsi_io, 38, (U8) sati_get_ata_status(register_fis));
+   sati_set_data_byte(sequence, scsi_io, 39, (U8) sati_get_ata_error(register_fis));
+   sati_set_data_byte(sequence, scsi_io, 40, sati_get_ata_lba_low(register_fis));
+   sati_set_data_byte(sequence, scsi_io, 41, sati_get_ata_lba_mid(register_fis));
+   sati_set_data_byte(sequence, scsi_io, 42, sati_get_ata_lba_high(register_fis));
+   sati_set_data_byte(sequence, scsi_io, 43, sati_get_ata_device(register_fis));
+   sati_set_data_byte(sequence, scsi_io, 44, sati_get_ata_lba_low_ext(register_fis));
+   sati_set_data_byte(sequence, scsi_io, 45, sati_get_ata_lba_mid_ext(register_fis));
+   sati_set_data_byte(sequence, scsi_io, 46, sati_get_ata_lba_high_ext(register_fis));
+   sati_set_data_byte(sequence, scsi_io, 47, 0x00);
+   sati_set_data_byte(sequence, scsi_io, 48, sati_get_ata_sector_count(register_fis));
+   sati_set_data_byte(sequence, scsi_io, 49, sati_get_ata_sector_count_exp(register_fis));
+
+   for(offset = 50; offset < 56; offset++)
+   {
+      sati_set_data_byte(sequence, scsi_io, offset, 0x00);
+   }
+
+   sequence->state = SATI_SEQUENCE_STATE_FINAL;
+}
+
+#endif // !defined(DISABLE_SATI_INQUIRY)
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_inquiry.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_inquiry.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,114 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_INQUIRY_H_
+#define _SATI_INQUIRY_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains the method prototypes required to
+ *        translate the SCSI inquiry command.
+ *        The following (VPD) pages are currently supported:
+ *        - Standard
+ *        - Supported Pages
+ *        - Unit Serial Number
+ *        - Device Identification
+ */
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+void sati_inquiry_standard_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+);
+
+void sati_inquiry_serial_number_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+);
+
+void sati_inquiry_device_id_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+);
+
+void sati_inquiry_block_device_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+);
+
+SATI_STATUS sati_inquiry_ata_information_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+);
+
+SATI_STATUS sati_inquiry_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * translator_sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+void sati_inquiry_ata_information_finish_translation(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+#endif // _SATI_INQUIRY_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_log_sense.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_log_sense.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,807 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+* @file
+* @brief This file contains the method definitions to translate
+*        SCSI Log Sense command based of the SATv2 spec.
+*/
+
+#if !defined(DISABLE_SATI_LOG_SENSE)
+
+#include <dev/isci/scil/sati_log_sense.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_util.h>
+
+//******************************************************************************
+//* P R I V A T E   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method constructs the SATI supported log page. This is a log
+ *        containing the page codes of all the SATI supported log pages.
+ *
+ * @return n/a
+ *
+ */
+static
+void sati_supported_log_page_construct(
+   SATI_TRANSLATOR_SEQUENCE_T  * sequence,
+   void                        * scsi_io
+)
+{
+   U32 next_byte;
+   //set SPF = 0 and PAGE_CODE = 0
+   sati_set_data_byte(sequence, scsi_io, 0, 0x00);
+
+   //set SUBPAGE_CODE = 0
+   sati_set_data_byte(sequence, scsi_io, 1, 0x00);
+
+   //set the Page Length to (n-3) or 2 because only two log pages are supported
+   sati_set_data_byte(sequence, scsi_io, 2, 0x00);
+   sati_set_data_byte(sequence, scsi_io, 3, 0x02);
+
+   //specify the next byte to be set
+   next_byte = 4;
+
+   if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_SUPPORT)
+   {
+      sati_set_data_byte(
+         sequence,
+         scsi_io,
+         next_byte,
+         SCSI_LOG_PAGE_INFORMATION_EXCEPTION
+      );
+      next_byte = 5;
+   }
+
+   if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_SELF_TEST_SUPPORT)
+   {
+      sati_set_data_byte(
+         sequence,
+         scsi_io,
+         next_byte,
+         SCSI_LOG_PAGE_SELF_TEST
+      );
+   }
+}
+
+/**
+ * @brief This method sets bytes 4-19 of the self-test log parameter to zero.
+ *
+ * @return n/a
+ *
+ */
+static
+void sati_set_parameters_to_zero(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io
+)
+{
+      sati_set_data_byte(sequence, scsi_io, 8, 0x00);   //log_parameter byte 4
+      sati_set_data_byte(sequence, scsi_io, 9, 0x00);   //log_parameter byte 5
+      sati_set_data_byte(sequence, scsi_io, 10, 0x00);  //log_parameter byte 6
+      sati_set_data_byte(sequence, scsi_io, 11, 0x00);  //log_parameter byte 7
+      sati_set_data_byte(sequence, scsi_io, 12, 0x00);  //log_parameter byte 8
+      sati_set_data_byte(sequence, scsi_io, 13, 0x00);  //log_parameter byte 9
+      sati_set_data_byte(sequence, scsi_io, 14, 0x00);  //log_parameter byte 10
+      sati_set_data_byte(sequence, scsi_io, 15, 0x00);  //log_parameter byte 11
+      sati_set_data_byte(sequence, scsi_io, 16, 0x00);  //log_parameter byte 12
+      sati_set_data_byte(sequence, scsi_io, 17, 0x00);  //log_parameter byte 13
+      sati_set_data_byte(sequence, scsi_io, 18, 0x00);  //log_parameter byte 14
+      sati_set_data_byte(sequence, scsi_io, 19, 0x00);  //log_parameter byte 15
+      sati_set_data_byte(sequence, scsi_io, 20, 0x00);  //log_parameter byte 16
+      sati_set_data_byte(sequence, scsi_io, 21, 0x00);  //log_parameter byte 17
+      sati_set_data_byte(sequence, scsi_io, 22, 0x00);  //log_parameter byte 18
+      sati_set_data_byte(sequence, scsi_io, 23, 0x00);  //log_parameter byte 19
+}
+
+/**
+ * @brief This method translates the ATA Extended SMART self-test log into
+ *        SCSI Sense Key, Additional Sense Code, and Additional Sense code
+ *        qualifiers based on the self test status byte in the appropriate
+ *        descriptor entry.
+ *
+ * @return n/a
+ *
+ */
+static
+void sati_translate_sense_values(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   U8                           self_test_status_byte
+)
+{
+   //byte 17
+   sati_set_data_byte(
+      sequence,
+      scsi_io,
+      21,
+      SCSI_DIAGNOSTIC_FAILURE_ON_COMPONENT
+   );
+
+   switch(self_test_status_byte)
+   {
+      case 1:
+         //byte 16
+         sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_ABORTED_COMMAND);
+
+         //byte 18
+         sati_set_data_byte(sequence, scsi_io, 22, 0x81);
+         break;
+
+      case 2:
+         //byte 16
+         sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_ABORTED_COMMAND);
+
+         //byte 18
+         sati_set_data_byte(sequence, scsi_io, 22, 0x82);
+         break;
+
+      case 3:
+         //byte 16
+         sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_ABORTED_COMMAND);
+
+         //byte 18
+         sati_set_data_byte(sequence, scsi_io, 22, 0x83);
+         break;
+
+      case 4:
+         //byte 16
+         sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_HARDWARE_ERROR);
+
+         //byte 18
+         sati_set_data_byte(sequence, scsi_io, 22, 0x84);
+         break;
+
+      case 5:
+         //byte 16
+         sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_HARDWARE_ERROR);
+
+         //byte 18
+         sati_set_data_byte(sequence, scsi_io, 22, 0x85);
+         break;
+
+      case 6:
+         //byte 16
+         sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_HARDWARE_ERROR);
+
+         //byte 18
+         sati_set_data_byte(sequence, scsi_io, 22, 0x86);
+         break;
+
+      case 7:
+         //byte 16
+         sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_MEDIUM_ERROR);
+
+         //byte 18
+         sati_set_data_byte(sequence, scsi_io, 22, 0x87);
+         break;
+
+      case 8:
+         //byte 16
+         sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_HARDWARE_ERROR);
+
+         //byte 18
+         sati_set_data_byte(sequence, scsi_io, 22, 0x88);
+         break;
+
+      default:
+         //byte 16
+         sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_NO_SENSE);
+         //byte 17
+         sati_set_data_byte(sequence, scsi_io, 21, SCSI_ASC_NO_ADDITIONAL_SENSE);
+         //byte 18
+         sati_set_data_byte(sequence, scsi_io, 22, 0x00);
+         break;
+   }
+
+}
+
+/**
+ * @brief This method retrieves the correct self-test results by checking the
+ *        descriptor index in the extended SMART self-test log. The index is
+ *        used to determine the appropriate descriptor entry.
+ *
+ * @return n/a
+ *
+ */
+static
+void sati_get_self_test_results(
+   SATI_TRANSLATOR_SEQUENCE_T          * sequence,
+   void                                * scsi_io,
+   ATA_EXTENDED_SMART_SELF_TEST_LOG_T  * ata_log
+)
+{
+   U16 descriptor_index = *((U16 *)(&ata_log->self_test_descriptor_index[0]));
+
+   /*
+    * SATv2 wants data from descriptor N where N is equal to
+    * (descriptor_index - parameter_code) + 1. Since parameter
+    * code is always 0x0001 just checking descriptor_index.
+    */
+
+   if(descriptor_index <= 0)
+   {
+      sati_set_parameters_to_zero(sequence, scsi_io);
+   }
+   else
+   {
+      sati_set_data_byte(
+       sequence,
+       scsi_io,
+       8,
+       ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.status_byte
+      );
+
+      //Sef-test number unspecified per satv2
+      sati_set_data_byte(sequence, scsi_io, 9, 0x00);
+      sati_set_data_byte(
+       sequence,
+       scsi_io,
+       10,
+       ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.time_stamp_high
+      );
+
+      sati_set_data_byte(
+       sequence,
+       scsi_io,
+       11,
+       ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.time_stamp_low
+      );
+
+      //set to zero because it's a 48bit address
+      sati_set_data_byte(sequence, scsi_io, 12, 0x00);
+      sati_set_data_byte(sequence, scsi_io, 13, 0x00);
+
+      sati_set_data_byte(
+       sequence,
+       scsi_io,
+       14,
+       ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_high_ext
+      );
+
+      sati_set_data_byte(
+       sequence,
+       scsi_io,
+       15,
+       ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_mid_ext
+      );
+
+      sati_set_data_byte(
+       sequence,
+       scsi_io,
+       16,
+       ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_low_ext
+      );
+
+      sati_set_data_byte(
+       sequence,
+       scsi_io,
+       17,
+       ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_high
+      );
+
+      sati_set_data_byte(
+       sequence,
+       scsi_io,
+       18,
+       ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_mid
+      );
+
+      sati_set_data_byte(
+       sequence,
+       scsi_io,
+       19,
+       ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_low
+      );
+
+      sati_translate_sense_values(
+       sequence,
+       scsi_io,
+       ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.status_byte
+      );
+   }
+}
+
+/**
+* @brief This method will construct the first eight bytes of the SCSI self test
+*        log page for both cases when SATI sends a ATA read log ext and a smart
+*        read log command.
+*
+* @return n/a
+*
+*/
+static
+void sati_self_test_log_header_construct(
+   SATI_TRANSLATOR_SEQUENCE_T  * sequence,
+   void                        * scsi_io
+)
+{
+   //PAGE CODE for Self-Test Log Page
+   sati_set_data_byte(sequence, scsi_io, 0, 0x10);
+   sati_set_data_byte(sequence, scsi_io, 1, 0x00);
+
+   //PAGE LENGTH is 0x14 instead of 0x190, not returning 20/0x190 log perameters
+   sati_set_data_byte(sequence, scsi_io, 2, 0x00);
+   sati_set_data_byte(sequence, scsi_io, 3, 0x14);
+
+   /*
+    * Log PARAMETER 0x0001
+    * Only sending one log parameter per self-test request.
+    */
+   sati_set_data_byte(sequence, scsi_io, 4, 0x00);       //log_parameter byte 0
+   sati_set_data_byte(sequence, scsi_io, 5, 0x01);       //log_parameter byte 1
+
+   //Set to 0x03 per SATv2 spec
+   sati_set_data_byte(sequence, scsi_io, 6, 0x03);       //log_parameter byte 2
+
+   //Parameter Length set to 0x10 per SATv2 spec
+   sati_set_data_byte(sequence, scsi_io, 7, 0x10);       //log_parameter byte 3
+}
+
+/**
+ * @brief This method will construct the SCSI self test log page from
+ *        the Extended SMART self-test log response recieved from the
+ *        ATA device. The response is from a ATA_Read_Log_EXT command
+ *        issued by SATI.
+ *
+ * @return n/a
+ *
+ */
+static
+void sati_extended_self_test_log_page_construct(
+   SATI_TRANSLATOR_SEQUENCE_T  * sequence,
+   void                        * scsi_io,
+   void                        * ata_data
+)
+{
+   ATA_EXTENDED_SMART_SELF_TEST_LOG_T * ata_log =
+                  (ATA_EXTENDED_SMART_SELF_TEST_LOG_T*) ata_data;
+
+   sati_self_test_log_header_construct(sequence, scsi_io);
+
+   //bytes 4-19
+   if( (ata_log->self_test_descriptor_index[0] == 0) &&
+       (ata_log->self_test_descriptor_index[1] == 0))
+   {
+      sati_set_parameters_to_zero(sequence, scsi_io);
+   }
+   else
+   {
+      sati_get_self_test_results(sequence, scsi_io, ata_log);
+   }
+}
+
+/**
+* @brief This method will construct the SCSI self test log page from
+*        the SMART self-test log response recieved from the ATA device.
+*        The response is from a ATA_SMART_Read_Log command issued by SATI.
+*
+* @return n/a
+*
+*/
+static
+void sati_self_test_log_page_construct(
+   SATI_TRANSLATOR_SEQUENCE_T  * sequence,
+   void                        * scsi_io,
+   void                        * ata_data
+)
+{
+   ATA_SMART_SELF_TEST_LOG_T * ata_log =
+                        (ATA_SMART_SELF_TEST_LOG_T*) ata_data;
+
+   sati_self_test_log_header_construct(sequence, scsi_io);
+
+   //first descriptor entry(index == 0) is always used because scsi_parameter_code == 1
+   sati_set_data_byte(
+      sequence,
+      scsi_io,
+      8,
+      ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.status_byte
+   );
+
+   //Sef-test number unspecified per satv2
+   sati_set_data_byte(sequence, scsi_io, 9, 0x00);
+
+   sati_set_data_byte(
+      sequence,
+      scsi_io,
+      10,
+      ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.time_stamp_high
+   );
+
+   sati_set_data_byte(
+      sequence,
+      scsi_io,
+      11,
+      ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.time_stamp_low
+   );
+
+   //set to zero because it's a 28bit address
+   sati_set_data_byte(sequence, scsi_io, 12, 0x00);
+   sati_set_data_byte(sequence, scsi_io, 13, 0x00);
+   sati_set_data_byte(sequence, scsi_io, 14, 0x00);
+   sati_set_data_byte(sequence, scsi_io, 15, 0x00);
+
+   sati_set_data_byte(
+      sequence,
+      scsi_io,
+      16,
+      ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.failing_lba_low_ext
+   );
+
+   sati_set_data_byte(
+      sequence,
+      scsi_io,
+      17,
+      ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.failing_lba_high
+   );
+
+   sati_set_data_byte(
+      sequence,
+      scsi_io,
+      18,
+      ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.failing_lba_mid
+   );
+
+   sati_set_data_byte(
+      sequence,
+      scsi_io,
+      19,
+      ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.failing_lba_low
+   );
+
+   sati_translate_sense_values(
+      sequence,
+      scsi_io,
+      ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.status_byte
+   );
+}
+
+/**
+* @brief This method will construct the SCSI information exception log page from
+*        the ATA SMART response recieved from the ATA device. The response is
+*         from a ATA SMART return status command issued by SATI.
+*
+* @return n/a
+*
+*/
+static
+void sati_information_exception_log_page_contruct(
+   SATI_TRANSLATOR_SEQUENCE_T  * sequence,
+   void                        * scsi_io,
+   void                        * ata_io
+)
+{
+   U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
+   U32 mid_register = sati_get_ata_lba_mid(register_fis);
+   U32 high_register = sati_get_ata_lba_high(register_fis);
+
+   //Information Exception Page code
+   sati_set_data_byte(
+      sequence,
+      scsi_io,
+      0,
+      SCSI_LOG_PAGE_INFORMATION_EXCEPTION
+   );
+
+   //Sub-page code
+   sati_set_data_byte(sequence, scsi_io, 1, 0x00);
+
+   //Page length of log parameters
+   sati_set_data_byte(sequence, scsi_io, 2, 0x00);
+   sati_set_data_byte(sequence, scsi_io, 3, 0x08);
+
+   //parameter code
+   sati_set_data_byte(sequence, scsi_io, 4, 0x00);
+   sati_set_data_byte(sequence, scsi_io, 5, 0x00);
+
+   //Format and Linking
+   sati_set_data_byte(sequence, scsi_io, 6, 0x03);
+   //Parameter Length
+   sati_set_data_byte(sequence, scsi_io, 7, 0x04);
+
+   if(mid_register == ATA_MID_REGISTER_THRESHOLD_EXCEEDED
+      && high_register == ATA_HIGH_REGISTER_THRESHOLD_EXCEEDED)
+   {
+      sati_set_data_byte(
+         sequence,
+         scsi_io,
+         8,
+         SCSI_ASC_HARDWARE_IMPENDING_FAILURE
+      );
+
+      sati_set_data_byte(
+         sequence,
+         scsi_io,
+         9,
+         SCSI_ASCQ_GENERAL_HARD_DRIVE_FAILURE
+      );
+   }
+   else
+   {
+      sati_set_data_byte(sequence, scsi_io, 8, SCSI_ASC_NO_ADDITIONAL_SENSE);
+      sati_set_data_byte(sequence, scsi_io, 9, SCSI_ASCQ_NO_ADDITIONAL_SENSE);
+   }
+   //setting most recent temperature reading to 0xFF(not supported) for now.
+   sati_set_data_byte(sequence, scsi_io, 10, 0xFF);
+}
+
+//******************************************************************************
+//* P U B L I C   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method will translate the SCSI Log Sense command into ATA commands
+ *        specified by SATv2. ATA commands Read Log EXT and SMART Read Log will
+ *        be issued by this translation.
+ *
+ * @return SATI_STATUS Indicates if the command translation succeeded.
+ *
+ */
+SATI_STATUS sati_log_sense_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+   SATI_STATUS status = SATI_FAILURE;
+
+   if(SATI_LOG_SENSE_GET_PC_FIELD(cdb) == 1 &&
+      (sati_get_cdb_byte(cdb, 3) == 0))
+   {
+      sequence->allocation_length = (sati_get_cdb_byte(cdb, 7) << 8) |
+                                    (sati_get_cdb_byte(cdb, 8));
+
+      switch(SATI_LOG_SENSE_GET_PAGE_CODE(cdb))
+      {
+         //Return Supported Log Pages log page
+         case SCSI_LOG_PAGE_SUPPORTED_PAGES :
+            sati_supported_log_page_construct(sequence, scsi_io);
+            sequence->type = SATI_SEQUENCE_LOG_SENSE_SUPPORTED_LOG_PAGE;
+            status = SATI_COMPLETE;
+            break;
+
+         //Return Self-Test Results log page
+         case SCSI_LOG_PAGE_SELF_TEST :
+
+            if((sequence->device->capabilities &
+               SATI_DEVICE_CAP_SMART_SELF_TEST_SUPPORT) == 0)
+            {
+               sati_scsi_sense_data_construct(
+                  sequence,
+                  scsi_io,
+                  SCSI_STATUS_CHECK_CONDITION,
+                  SCSI_SENSE_ILLEGAL_REQUEST,
+                  SCSI_ASC_INVALID_FIELD_IN_CDB,
+                  SCSI_ASCQ_INVALID_FIELD_IN_CDB
+               );
+               status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+            }
+            else
+            {
+               //check if 48-bit Address feature set is supported
+               if((sequence->device->capabilities &
+                  SATI_DEVICE_CAP_48BIT_ENABLE))
+               {
+                  //ATA Read Log Ext with log address set to 0x07
+                  sati_ata_read_log_ext_construct(
+                                     ata_io,
+                                     sequence,
+                                     ATA_LOG_PAGE_EXTENDED_SMART_SELF_TEST,
+                                     sizeof(ATA_EXTENDED_SMART_SELF_TEST_LOG_T)
+                  );
+                  sequence->type =
+                            SATI_SEQUENCE_LOG_SENSE_EXTENDED_SELF_TEST_LOG_PAGE;
+                  status = SATI_SUCCESS;
+               }
+               else
+               {
+                  //ATA Smart Read Log with log address set to 0x06
+                  sati_ata_smart_read_log_construct(
+                                       ata_io,
+                                       sequence,
+                                       ATA_LOG_PAGE_SMART_SELF_TEST,
+                                       sizeof(ATA_SMART_SELF_TEST_LOG_T)
+                  );
+                  sequence->type = SATI_SEQUENCE_LOG_SENSE_SELF_TEST_LOG_PAGE;
+                  status = SATI_SUCCESS;
+               }
+            }
+            break;
+
+         //Return Informational Exceptions log page
+         case SCSI_LOG_PAGE_INFORMATION_EXCEPTION :
+            if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_SUPPORT)
+            {
+               if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_ENABLE)
+               {
+                  sati_ata_smart_return_status_construct(
+                                       ata_io,
+                                       sequence,
+                                       ATA_SMART_SUB_CMD_RETURN_STATUS
+                  );
+                  sequence->type =
+                                SATI_SEQUENCE_LOG_SENSE_INFO_EXCEPTION_LOG_PAGE;
+                  status = SATI_SUCCESS;
+               }
+               else
+               {
+                  sati_scsi_sense_data_construct(
+                     sequence,
+                     scsi_io,
+                     SCSI_STATUS_CHECK_CONDITION,
+                     SCSI_SENSE_ABORTED_COMMAND,
+                     SCSI_ASC_ATA_DEVICE_FEATURE_NOT_ENABLED,
+                     SCSI_ASCQ_ATA_DEVICE_FEATURE_NOT_ENABLED
+                  );
+
+                  status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+               }
+            }
+            else
+            {
+               sati_scsi_sense_data_construct(
+                  sequence,
+                  scsi_io,
+                  SCSI_STATUS_CHECK_CONDITION,
+                  SCSI_SENSE_ILLEGAL_REQUEST,
+                  SCSI_ASC_INVALID_FIELD_IN_CDB,
+                  SCSI_ASCQ_INVALID_FIELD_IN_CDB
+               );
+
+               status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+            }
+            break;
+         default :
+            //UNSPECIFIED SATv2r9
+            sati_scsi_sense_data_construct(
+               sequence,
+               scsi_io,
+               SCSI_STATUS_CHECK_CONDITION,
+               SCSI_SENSE_ILLEGAL_REQUEST,
+               SCSI_ASC_NO_ADDITIONAL_SENSE ,
+               SCSI_ASCQ_NO_ADDITIONAL_SENSE
+            );
+            status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+            break;
+      }
+   }
+   return status;
+}
+
+/**
+ * @brief This method will translate the response to the SATI Log Sense
+ *        translation. ATA command responses will be translated into the
+ *        correct SCSI log pages to be returned by SATI.
+ *
+ * @return SATI_STATUS Indicates if the response translation succeeded.
+ *
+ */
+SATI_STATUS sati_log_sense_translate_response(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
+   SATI_STATUS status = SATI_FAILURE;
+
+   if(sati_get_ata_status(register_fis) & ATA_STATUS_REG_ERROR_BIT)
+   {
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_ABORTED_COMMAND,
+         SCSI_ASC_NO_ADDITIONAL_SENSE ,
+         SCSI_ASCQ_NO_ADDITIONAL_SENSE
+      );
+      status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+   else
+   {
+
+      void * ata_data = sati_cb_get_ata_data_address(ata_io);
+
+      if(ata_data == NULL)
+      {
+         return SATI_FAILURE;
+      }
+
+      switch(sequence->type)
+      {
+         case SATI_SEQUENCE_LOG_SENSE_EXTENDED_SELF_TEST_LOG_PAGE:
+            sati_extended_self_test_log_page_construct(
+                                 sequence, scsi_io, ata_data
+            );
+
+            status = SATI_COMPLETE;
+            break;
+
+         case SATI_SEQUENCE_LOG_SENSE_SELF_TEST_LOG_PAGE:
+            sati_self_test_log_page_construct(sequence, scsi_io, ata_data);
+            status = SATI_COMPLETE;
+            break;
+
+         case SATI_SEQUENCE_LOG_SENSE_INFO_EXCEPTION_LOG_PAGE:
+            //This function needs a d->h register fis, not ata data
+            sati_information_exception_log_page_contruct(
+                                 sequence, scsi_io, ata_io
+            );
+
+            status = SATI_COMPLETE;
+            break;
+
+         default:
+            sati_scsi_sense_data_construct(
+               sequence,
+               scsi_io,
+               SCSI_STATUS_CHECK_CONDITION,
+               SCSI_SENSE_ABORTED_COMMAND,
+               SCSI_ASC_NO_ADDITIONAL_SENSE ,
+               SCSI_ASCQ_NO_ADDITIONAL_SENSE
+            );
+            status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+            break;
+      }
+   }
+   return status;
+}
+
+#endif // !defined(DISABLE_SATI_LOG_SENSE)
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_log_sense.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_log_sense.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,87 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+/**
+ * @file
+ * @brief This file contains the method declarations to translate
+ *        SCSI Log Sense command based of the SATv2 spec.
+ */
+
+#ifndef _SATI_LOG_SENSE_H_
+#define _SATI_LOG_SENSE_H_
+
+#include <dev/isci/scil/intel_scsi.h>
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+#define SATI_LOG_SENSE_GET_PC_FIELD(cdb) \
+   (( sati_get_cdb_byte((cdb), 2) & SCSI_LOG_SENSE_PC_FIELD_MASK ) \
+   >> SCSI_LOG_SENSE_PC_FIELD_SHIFT )
+
+#define SATI_LOG_SENSE_GET_PAGE_CODE(cdb) \
+   (( sati_get_cdb_byte((cdb), 2) & SCSI_LOG_SENSE_PAGE_CODE_FIELD_MASK ) \
+   >> SCSI_LOG_SENSE_PAGE_CODE_FIELD_SHIFT )
+
+SATI_STATUS sati_log_sense_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+SATI_STATUS sati_log_sense_translate_response(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+#endif // _SATI_LOG_SENSE_H_
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_lun_reset.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_lun_reset.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,122 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ *
+ * @brief This file contains the method implementations required to
+ *        translate the SCSI lun reset command.
+ */
+
+#if !defined(DISABLE_SATI_TASK_MANAGEMENT)
+
+#include <dev/isci/scil/sati_lun_reset.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_scsi.h>
+#include <dev/isci/scil/intel_sat.h>
+
+//******************************************************************************
+//* P U B L I C   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method will translate the lun reset SCSI task request into an
+ *        ATA SOFT RESET command. For more information on the parameters
+ *        passed to this method, please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the command translation was
+ *         successful.
+ *
+ * @note It is up to the user of the sata translator to set the command bit
+ *       and clear the control softreset bit and send the second register fis.
+ */
+SATI_STATUS sati_lun_reset_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   U8* register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+   sati_set_ata_command(register_fis, ATA_NOP);
+   sati_set_ata_control(register_fis, ATA_CONTROL_REG_SOFT_RESET_BIT);
+
+   //set all other fields to zero.
+   sati_clear_sata_command_flag(register_fis);
+   sati_set_ata_features(register_fis, 0);
+   sati_set_ata_features_exp(register_fis, 0);
+   sati_set_ata_sector_count(register_fis, 0);
+   sati_set_ata_sector_count_exp(register_fis, 0);
+   sati_set_ata_lba_low(register_fis, 0);
+   sati_set_ata_lba_mid(register_fis, 0);
+   sati_set_ata_lba_high(register_fis, 0);
+   sati_set_ata_lba_low_exp(register_fis, 0);
+   sati_set_ata_lba_mid_exp(register_fis, 0);
+   sati_set_ata_lba_high_exp(register_fis, 0);
+   sati_set_ata_device_head(register_fis, 0);
+
+   sequence->type                = SATI_SEQUENCE_LUN_RESET;
+   sequence->data_direction      = SATI_DATA_DIRECTION_NONE;
+   sequence->protocol            = SAT_PROTOCOL_SOFT_RESET;
+   sequence->ata_transfer_length = 0;
+
+   return SATI_SUCCESS;
+}
+
+#endif // !defined(DISABLE_SATI_TASK_MANAGEMENT)
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_lun_reset.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_lun_reset.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,79 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_LUN_RESET_H_
+#define _SATI_LUN_RESET_H_
+
+/**
+ * @file
+ * @brief This file contains the method interfaces required to translate the
+ *        SCSI logical unit reset task request as well as translate response
+ *        for the task request.
+ */
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+SATI_STATUS sati_lun_reset_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_task,
+   void                       * ata_io
+);
+
+void sati_lun_reset_translate_resposne(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_task
+);
+
+#endif // _SATI_LUN_RESET_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_mode_pages.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_mode_pages.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,372 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains the mode page constants and data for the mode
+ *        pages supported by this translation implementation.
+ */
+
+// DO NOT MOVE THIS INCLUDE STATEMENT! This include must occur before
+// the below check for ENABLE_SATI_MODE_PAGES.
+#include <dev/isci/scil/sati_types.h>
+
+#if defined(ENABLE_SATI_MODE_PAGES)
+
+#include <dev/isci/scil/sati_mode_pages.h>
+#include <dev/isci/scil/intel_scsi.h>
+
+//******************************************************************************
+//* C O N S T A N T S
+//******************************************************************************
+
+#define SCSI_MODE_PAGE19_SAS_ID         0x6
+#define SCSI_MODE_PAGE19_SUB1_PAGE_NUM  0x1
+#define SCSI_MODE_PAGE19_SUB1_PC        0x59
+
+//******************************************************************************
+//* M O D E   P A G E S
+//******************************************************************************
+
+U8 sat_default_mode_page_01[] =
+{
+   SCSI_MODE_PAGE_READ_WRITE_ERROR, // Byte 0 - Page Code, SPF(0), PS(0)
+   SCSI_MODE_PAGE_01_LENGTH-2,      // Byte 1 - Page Length
+   0x80, // Byte 2 - AWRE, ARRE, TB, RC, EER, PER, DTE, DCR
+   0x00, // Byte 3 - Read Retry Count
+
+   0x00, // Byte 4 - Obsolete
+   0x00, // Byte 5 - Obsolete
+   0x00, // Byte 6 - Obsolete
+   0x00, // Byte 7 - Restricted for MMC-4
+
+   0x00, // Byte 8 - Write Retry Count
+   0x00, // Byte 9 - Reserved
+   0x00, // Byte 10 - Recovery Time Limit
+   0x00, // Byte 11
+};
+
+U8 sat_changeable_mode_page_01[] =
+{
+   SCSI_MODE_PAGE_READ_WRITE_ERROR,
+   SCSI_MODE_PAGE_01_LENGTH-2,
+   0x00,
+   0x00,
+
+   0x00,
+   0x00,
+   0x00,
+   0x00,
+
+   0x00,
+   0x00,
+   0x00,
+   0x00,
+};
+
+U8 sat_default_mode_page_02[] =
+{
+   SCSI_MODE_PAGE_DISCONNECT_RECONNECT, // Byte 0 - Page Code, SPF(0), PS(0)
+   SCSI_MODE_PAGE_02_LENGTH-2,          // Byte 1 - Page Length
+   0x00, // Byte 2 - Buffer Full Ratio
+   0x00, // Byte 3 - Buffer Empty Ratio
+
+   0x00, // Byte 4 - Bus Inactivity Limit
+   0x00, // Byte 5
+   0x00, // Byte 6 - Disconnect Time Limit
+   0x00, // Byte 7
+
+   0x00, // Byte 8 - Connect Time Limit
+   0x00, // Byte 9
+   0x00, // Byte 10 - Maximum Burst Size
+   0x00, // Byte 11
+
+   0x00, // Byte 12 - EMDP, FAIR_ARB, DIMM, DTDC
+   0x00, // Byte 13
+   0x00, // Byte 14 - First Burst Size
+   0x00, // Byte 15
+};
+
+U8 sat_changeable_mode_page_02[] =
+{
+   SCSI_MODE_PAGE_DISCONNECT_RECONNECT,
+   SCSI_MODE_PAGE_02_LENGTH-2,
+   0x00,
+   0x00,
+
+   0x00,
+   0x00,
+   0x00,
+   0x00,
+
+   0x00,
+   0x00,
+   0x00,
+   0x00,
+
+   0x00,
+   0x00,
+   0x00,
+   0x00,
+};
+
+U8 sat_default_mode_page_08[] =
+{
+   SCSI_MODE_PAGE_CACHING,     // Byte 0 - Page Code, SPF(0), PS(0)
+   SCSI_MODE_PAGE_08_LENGTH-2, // Byte 1 - Page Length
+   0x00, // Byte 2 - IC, ABPF, CAP, DISC, SIZE, WCE(1), MF, RCD
+   0x00, // Byte 3 - Demand Read Retention Priority, Write Retention Priority
+
+   0x00, // Byte 4 - Disable Pre-Fetch Transfer Length
+   0x00, // Byte 5
+   0x00, // Byte 6 - Minimum Pre-Fetch
+   0x00, // Byte 7
+
+   0x00, // Byte 8 - Maximum Pre-Fetch
+   0x00, // Byte 9
+   0x00, // Byte 10 - Maximum Pre-Fetch Ceiling
+   0x00, // Byte 11
+
+   0x00, // Byte 12 - FSW, LBCSS, DRA(0), Vendor Specific, NV_DIS
+   0x00, // Byte 13 - Number of Cache Segments
+   0x00, // Byte 14 - Cache Segment Size
+   0x00, // Byte 15
+
+   0x00, // Byte 16 - Reserved
+   0x00, // Byte 17 - Non-Cache Segment Size
+   0x00, // Byte 18
+   0x00, // PAD
+};
+
+U8 sat_changeable_mode_page_08[] =
+{
+   SCSI_MODE_PAGE_CACHING,
+   SCSI_MODE_PAGE_08_LENGTH-2,
+   SCSI_MODE_PAGE_CACHE_PAGE_WCE_BIT,
+   0x00,
+
+   0x00,
+   0x00,
+   0x00,
+   0x00,
+
+   0x00,
+   0x00,
+   0x00,
+   0x00,
+
+   SCSI_MODE_PAGE_CACHE_PAGE_DRA_BIT,
+   0x00,
+   0x00,
+   0x00,
+
+   0x00,
+   0x00,
+   0x00,
+   0x00, // PAD
+};
+
+U8 sat_default_mode_page_0A[] =
+{
+   SCSI_MODE_PAGE_CONTROL,     // Byte 0 - Page Code, SPF(0), PS(0)
+   SCSI_MODE_PAGE_0A_LENGTH-2, // Byte 1 - Page Length
+   0x00, // Byte 2 - TST(0), TMF_ONLY(0), D_SENSE(0), GLTSD(0), RLEC(0)
+   0x10, // Byte 3 - Queue Algorithm(0), QErr(0)
+
+   0x00, // Byte 4 - TAS(0), RAC(0), UA_(0), SWP(0)
+   0x00, // Byte 5 - ATO(0), AUTOLOAD(0)
+   0x00, // Byte 6
+   0x00, // Byte 7
+
+   0xFF, // Byte 8 - Unlimited Busy timeout
+   0xFF, // Byte 9
+   0x00, // Byte 10 - do not support self time compl time xlation
+   0x00, // Byte 11
+};
+
+U8 sat_changeable_mode_page_0A[] =
+{
+   SCSI_MODE_PAGE_CONTROL,
+   SCSI_MODE_PAGE_0A_LENGTH-2,
+   0x00,
+   0x00,
+
+   0x00,
+   0x00,
+   0x00,
+   0x00,
+
+   0x00,
+   0x00,
+   0x00,
+   0x00,
+};
+
+U8 sat_default_mode_page_19[] =
+{
+   SCSI_MODE_PAGE_PROTOCOL_SPECIFIC_PORT, // Byte 0 - PS, SPF, Page Code
+   SCSI_MODE_PAGE_19_LENGTH-2,  // Byte 1 - Page Length
+   SCSI_MODE_PAGE19_SAS_ID,     // Byte 2 - Rsvd, READY_LED,  ProtoID
+   0x00, // PAD
+
+   0xFF, // Byte 4 - IT NLT MSB, 0xFF retry forever
+   0xFF, // Byte 5 - IT NLT LSB, 0xFF retry forever
+   0x00, // Byte 6 - IRT MSB, 0x0 disable init resp timer
+   0x00, // Byte 7 - IRT LSB, 0x0 disable init resp timer
+};
+
+U8 sat_changeable_mode_page_19[] =
+{
+   SCSI_MODE_PAGE_PROTOCOL_SPECIFIC_PORT,
+   SCSI_MODE_PAGE_19_LENGTH-2,
+   0x00,
+   0x00,
+
+   0x00,
+   0x00,
+   0x00,
+   0x00,
+};
+
+U8 sat_default_mode_page_1C[] =
+{
+   SCSI_MODE_PAGE_INFORMATIONAL_EXCP_CONTROL, // Byte 0 - Page Code,
+                                              // SPF(0), PS(0)
+   SCSI_MODE_PAGE_1C_LENGTH-2,   // Byte 1 - Page Length
+   SCSI_MODE_PAGE_DEXCPT_ENABLE, // Byte 2 - Perf, EBF, EWasc,
+                                 // DExcpt(1), Test, LogErr
+   0x06, // Byte 3 -- MRIE (6 == values only available upon request)
+
+   0x00, // Byte 4 -- Interval Timer
+   0x00, // Byte 5
+   0x00, // Byte 6
+   0x00, // Byte 7
+
+   0x00, // Byte 8 -- Report Count
+   0x00, // Byte 9
+   0x00, // Byte 10
+   0x00, // Byte 11
+};
+
+U8 sat_changeable_mode_page_1C[] =
+{
+   SCSI_MODE_PAGE_INFORMATIONAL_EXCP_CONTROL,
+   SCSI_MODE_PAGE_1C_LENGTH-2,
+   SCSI_MODE_PAGE_DEXCPT_ENABLE,
+   0x00,
+
+   0x00,
+   0x00,
+   0x00,
+   0x00,
+
+   0x00,
+   0x00,
+   0x00,
+   0x00,
+};
+
+U8 sat_supported_mode_pages[] =
+{
+   SCSI_MODE_PAGE_READ_WRITE_ERROR,
+   SCSI_MODE_PAGE_DISCONNECT_RECONNECT,
+   SCSI_MODE_PAGE_CACHING,
+   SCSI_MODE_PAGE_CONTROL,
+   SCSI_MODE_PAGE_INFORMATIONAL_EXCP_CONTROL
+};
+
+U8 *sat_changeable_mode_pages[] =
+{
+   sat_changeable_mode_page_01,
+   sat_changeable_mode_page_02,
+   sat_changeable_mode_page_08,
+   sat_changeable_mode_page_0A,
+   sat_changeable_mode_page_1C
+};
+
+U8 *sat_default_mode_pages[] =
+{
+   sat_default_mode_page_01,
+   sat_default_mode_page_02,
+   sat_default_mode_page_08,
+   sat_default_mode_page_0A,
+   sat_default_mode_page_1C
+};
+
+U16 sat_mode_page_sizes[] =
+{
+   sizeof(sat_default_mode_page_01),
+   sizeof(sat_default_mode_page_02),
+   sizeof(sat_default_mode_page_08),
+   sizeof(sat_default_mode_page_0A),
+   sizeof(sat_default_mode_page_1C)
+};
+
+U16 sati_mode_page_get_page_index(
+   U8  page_code
+)
+{
+   U16 index;
+   for (index = 0; index < SAT_SUPPORTED_MODE_PAGES_LENGTH; index++)
+   {
+      if (sat_supported_mode_pages[index] == page_code)
+         return index;
+   }
+
+   return SATI_MODE_PAGE_UNSUPPORTED_INDEX;
+}
+
+#endif // defined(ENABLE_SATI_MODE_PAGES)
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_mode_pages.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_mode_pages.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,144 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+/**
+ * @file
+ * @brief This file contains the mode page constants and members that are
+ *        supported by this translation implementation.
+ */
+
+#include <dev/isci/scil/sati_types.h>
+
+// These values represent the mode page (not including header and block
+// descriptor).  The page length fields in the mode sense data are equivalent
+// to the constant values below less 2.  The minus 2 is due to not including
+// the page code byte (byte 0) and the page length byte (byte 1).
+#define SCSI_MODE_PAGE_01_LENGTH   0x0C
+#define SCSI_MODE_PAGE_02_LENGTH   0x10
+#define SCSI_MODE_PAGE_08_LENGTH   0x14
+#define SCSI_MODE_PAGE_0A_LENGTH   0x0C
+#define SCSI_MODE_PAGE_19_LENGTH   0x8
+#define SCSI_MODE_PAGE_1A_LENGTH   0x0C
+#define SCSI_MODE_PAGE_1C_LENGTH   0x0C
+#define SCSI_MODE_PAGE_3F_LENGTH   SCSI_MODE_PAGE_08_LENGTH    \
+                                   + SCSI_MODE_PAGE_1C_LENGTH  \
+
+#define SATI_MODE_PAGE_UNSUPPORTED_INDEX 0xFFFF
+
+#define SAT_SUPPORTED_MODE_PAGES_LENGTH sizeof(sat_supported_mode_pages)/sizeof(U8)
+
+typedef enum _RETURN_PAGE{
+   CHANGEABLE_PAGE,
+   DEFAULT_PAGE
+}RETURN_PAGE;
+
+
+/**
+ * @struct SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_6
+ *
+ * @brief This structure contains mode parameter header fields for 6 byte
+ *        mode select command.
+ */
+typedef  struct SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_6
+{
+   U8 mode_data_length;
+   U8 medium_type; //Should be 0
+   U8 device_specific_parameter;
+   U8 block_descriptor_length;
+
+}SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_6_T;
+
+/**
+ * @struct MODE_PARAMETER_HEADER_10
+ *
+ * @brief This structure contains mode parameter header fields for 10 byte
+ *        mode select command.
+ */
+typedef struct SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_10
+{
+   U8 mode_data_length[2];
+   U8 medium_type; //Should be 0
+   U8 device_specific_parameter;
+   U8 long_lba;
+   U8 reserve;
+   U8 block_descriptor_length[2];
+
+}SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_10_T;
+
+/**
+ * @struct MODE_PARAMETER_BLOCK_DESCRIPTOR
+ *
+ * @brief This structure contains mode parameter block descriptor fields.
+ */
+typedef struct SCSI_MODE_SELECT_MODE_PARAMETER_BLOCK_DESCRIPTOR
+{
+   U8 density_code;
+   U8 number_of_blocks[3];
+   U8 reserved;
+   U8 block_length[3];
+
+}SCSI_MODE_SELECT_MODE_PARAMETER_BLOCK_DESCRIPTOR_T;
+
+U16 sati_mode_page_get_page_index(
+   U8  page_code
+);
+
+U8 * sati_mode_page_get_mode_page(
+   U8 page_code,
+   RETURN_PAGE page
+);
+
+extern U8 * sat_changeable_mode_pages[];
+extern U8 * sat_default_mode_pages[];
+extern U16  sat_mode_page_sizes[];
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_mode_select.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_mode_select.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,1115 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ *        translate the SCSI mode select (6 and 10-byte) commands with 5
+ *        supported mode parameter pages (0x01, 0x02, 0x08, 0x0A, 0x1C).
+ */
+
+#if !defined(DISABLE_SATI_MODE_SELECT)
+
+#include <dev/isci/scil/sati_mode_select.h>
+#include <dev/isci/scil/sati_mode_pages.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sci_object.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+#include <dev/isci/scil/sati_util.h>
+
+//******************************************************************************
+//* P R I V A T E   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method will get medium type parameter field per CDB size.
+ *
+ * @param[in] scsi_io This parameter specifies the user's SCSI IO object
+ *            for which to calculate the mode page header.
+ * @param[in] cdb_size This parameter specifies the number of bytes
+ *            associated with the CDB for which to calculate the header.
+ *
+ * @return This method returns the medium type for the mode page header.
+ */
+static
+U8 sati_mode_select_get_medium_type(
+   U8 * mode_parameters,
+   U32  cdb_size
+)
+{
+   U8  medium_type =0xFF;
+   SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_6_T * mode_parameters_6;
+   SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_10_T * mode_parameters_10;
+
+   if(cdb_size == 6)
+   {
+      mode_parameters_6 = (SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_6_T *) mode_parameters;
+      medium_type = mode_parameters_6->medium_type;
+   }
+   else if(cdb_size == 10)
+   {
+      mode_parameters_10 = (SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_10_T *) mode_parameters;
+      medium_type = mode_parameters_10->medium_type;
+   }
+
+   return medium_type;
+}
+
+/**
+ * @brief This method will retrieve Block Descriptor Length.
+ *
+ * @param[in] mode_parameters This parameter contains the address to the mode parameters.
+ * @param[in] cdb_size This parameter specifies the number of bytes
+ *            associated with the CDB for which to process the block descriptor.
+ *
+ * @return This method returns the size, in bytes, for the mode parameter block descriptor.
+ */
+static
+U32 sati_mode_select_get_mode_block_descriptor_length(
+   U8 * mode_parameters,
+   U32  cdb_size
+)
+{
+   U32 mode_block_descriptor_length = 0;
+   SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_6_T * mode_parameters_6;
+   SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_10_T * mode_parameters_10;
+
+   if(cdb_size == 6)
+   {
+      mode_parameters_6 = (SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_6_T *) mode_parameters;
+      mode_block_descriptor_length = mode_parameters_6->block_descriptor_length;
+   }
+   else if(cdb_size == 10)
+   {
+      mode_parameters_10 = (SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_10_T *) mode_parameters;
+      //Long LBA bit is the bit0 of the byte
+      //Spec says another way to get the block descriptor length to multiply the block number
+      //   with block length (8 or 16), but we can get it directly.
+      mode_block_descriptor_length =(((U16)mode_parameters_10->block_descriptor_length[0]) << 8) +
+         mode_parameters_10->block_descriptor_length[1];
+
+   }
+
+   return mode_block_descriptor_length;
+
+}
+
+/**
+ * @brief This method will find the starting byte location for a page.
+ *
+ * @param[in] block_descriptor_length This parameter passes in the length of
+ *            block descriptor.
+ * @param[in] cdb_size This parameter specifies the number of bytes
+ *            associated with the CDB for which to calculate the header.
+ *
+ * @return This method returns the offset, for the mode page.
+ */
+static
+U32 sati_mode_select_get_mode_page_offset(
+    U32 block_descriptor_length,
+    U32 cdb_size
+    )
+{
+   U32 mode_page_offset;
+
+   if(cdb_size == 6)
+   {
+      mode_page_offset =  sizeof(SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_6_T) +  block_descriptor_length;
+   }
+   else if(cdb_size == 10)
+   {
+      mode_page_offset =  sizeof(SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_10_T) +  block_descriptor_length;
+   }
+   else
+   {
+      mode_page_offset = 0;
+   }
+
+   return mode_page_offset;
+}
+
+/**
+ * @brief This method will set the initial Mode Select processing state.
+ */
+static
+void  sati_mode_select_initialize_mode_sel_processing_state(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io,
+   U32 data_transfer_length,
+   U32 mode_page_offset
+   )
+{
+   sequence->command_specific_data.process_state.ata_command_sent_for_cmp = 0;
+   sequence->command_specific_data.process_state.mode_page_offset=mode_page_offset;
+   sequence->command_specific_data.process_state.mode_pages_size = data_transfer_length  -  mode_page_offset;
+   sequence->command_specific_data.process_state.size_of_data_processed = 0;
+   sequence->command_specific_data.process_state.current_mode_page_processed = FALSE;
+}
+
+/**
+ * @brief This method will get mode page size.
+ *
+ * @param[in] page_code This parameter contains page code for the current mode page.
+ *
+ * @return This method returns the size of current mode page.
+ */
+static
+U32 sati_mode_select_get_mode_page_size(
+   U8 page_code
+)
+{
+   U32 page_size=0;
+
+   switch (page_code)
+   {
+   case SCSI_MODE_PAGE_READ_WRITE_ERROR:
+      page_size=SCSI_MODE_PAGE_01_LENGTH;
+      break;
+
+   case SCSI_MODE_PAGE_DISCONNECT_RECONNECT:
+      page_size=SCSI_MODE_PAGE_02_LENGTH;
+      break;
+
+   case SCSI_MODE_PAGE_CACHING:
+      page_size=SCSI_MODE_PAGE_08_LENGTH;
+      break;
+
+   case SCSI_MODE_PAGE_CONTROL:
+      page_size=SCSI_MODE_PAGE_0A_LENGTH;
+      break;
+
+   case SCSI_MODE_PAGE_INFORMATIONAL_EXCP_CONTROL:
+      page_size=SCSI_MODE_PAGE_1C_LENGTH;
+      break;
+
+   case SCSI_MODE_PAGE_POWER_CONDITION:
+      page_size=SCSI_MODE_PAGE_1A_LENGTH;
+      break;
+   default:
+      page_size=0;
+      break;
+   }
+
+   return page_size;
+}
+
+/**
+ * @brief This method will check the validity of parameter data of Read Write Error Recovery
+ *            page and further processing the page data if necessary.
+ *
+ * @param[in] page_size This parameter specifies page size of current mode page.
+ *
+ * @return Indicate if the translation was successful.
+ * @retval SATI_SUCCESS
+ * @retval SATI_COMPLETE
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA
+ */
+static
+SATI_STATUS sati_mode_select_process_mode_page_read_write_error_recovery(
+   SATI_TRANSLATOR_SEQUENCE_T* sequence,
+   void     *  scsi_io,
+   U32   page_size
+   )
+{
+   SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+
+   U8 current_mode_page[SCSI_MODE_PAGE_01_LENGTH]={0,0,0,0,0,0,0,0,0,0,0,0};
+   U32 mode_page_offset;
+
+   mode_page_offset = sequence->command_specific_data.process_state.mode_page_offset;
+
+   //Check all the defined bits for this page
+   //SPF(0b); Page length 0x0A;AWRE 1; ARRE 0; Error recovery bits 0; RC 0;
+   //Recovery time limit last two bytes 0
+
+   sati_get_data_byte(sequence, scsi_io, mode_page_offset,   &current_mode_page[0]);
+   sati_get_data_byte(sequence, scsi_io, mode_page_offset+1, &current_mode_page[1]);
+   sati_get_data_byte(sequence, scsi_io, mode_page_offset+2, &current_mode_page[2]);
+   sati_get_data_byte(sequence, scsi_io, mode_page_offset+10, &current_mode_page[10]);
+   sati_get_data_byte(sequence, scsi_io, mode_page_offset+11, &current_mode_page[11]);
+
+   if ( ((current_mode_page[0] & SCSI_MODE_SELECT_MODE_PAGE_SPF_MASK)!= 0) ||
+      (current_mode_page[1] != (SCSI_MODE_PAGE_01_LENGTH - 2)) ||
+      ((current_mode_page[2] & SCSI_MODE_SELECT_MODE_PAGE_01_AWRE_MASK) == 0) ||
+      ((current_mode_page[2] & SCSI_MODE_SELECT_MODE_PAGE_01_ARRE_MASK) != 0) ||
+      ((current_mode_page[2] & SCSI_MODE_SELECT_MODE_PAGE_01_RC_ERBITS_MASK) != 0) ||
+      (current_mode_page[10] != 0 ) ||
+      (current_mode_page[11] != 0 ) )
+   {
+      status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+      return status;
+   }
+
+   //no need to send any command
+   {
+      sequence->command_specific_data.process_state.size_of_data_processed += page_size;
+      sequence->command_specific_data.process_state.mode_page_offset += page_size;
+      sequence->command_specific_data.process_state.current_mode_page_processed = TRUE;
+   }
+
+   status = SATI_COMPLETE;
+
+   return status;
+}
+
+/**
+ * @brief This method will check the validity of parameter data of Disconnect Reconnect mode
+ *            page and further processing the page data if necessary.
+ *
+ * @param[in] page_size This parameter specifies page size of current mode page.
+ *
+ * @return Indicate if the translation was successful.
+ * @retval SATI_SUCCESS
+ * @retval SATI_COMPLETE
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA
+ */
+static
+SATI_STATUS sati_mode_select_process_mode_page_disconnect_reconnect(
+   SATI_MODE_SELECT_PROCESSING_STATE_T * mode_select_process_state,
+   U32 page_size
+   )
+{
+   SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+
+   // No need to check data for valid or invalid this page (undefined)
+   // No ata command to send
+   {
+      mode_select_process_state->size_of_data_processed += page_size;
+      mode_select_process_state->mode_page_offset += page_size;
+      mode_select_process_state->current_mode_page_processed = TRUE;
+   }
+
+   // No further interaction with remote devices
+   status = SATI_COMPLETE;
+
+   return status;
+}
+
+/**
+ * @brief This method will check the validity of parameter data of Caching mode
+ *            page and issue multiple ATA set feature commands to complete the translation.
+ *
+ * @param[in] page_size This parameter specifies page size of current mode page.
+ *
+ * @return Indicate if the translation was successful.
+ * @retval SATI_SUCCESS
+ * @retval SATI_COMPLETE
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA
+ */
+static
+SATI_STATUS sati_mode_select_process_mode_page_caching(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void * scsi_io,
+   void * ata_io,
+   U32 page_size
+   )
+{
+   SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+
+   //SCSI_MODE_PAGE_08_LENGTH 0x14= 20
+   U8 current_mode_page[SCSI_MODE_PAGE_08_LENGTH] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+   U32 mode_page_offset;
+   U32 index;
+
+   mode_page_offset = sequence->command_specific_data.process_state.mode_page_offset;
+   sequence->type = SATI_SEQUENCE_MODE_SELECT_MODE_PAGE_CACHING;
+
+   for(index = 0; index < SCSI_MODE_PAGE_08_LENGTH; index++)
+   {
+      sati_get_data_byte(sequence, scsi_io, mode_page_offset+index, &current_mode_page[index]);
+   }
+
+   //Check for data validity
+   //SPF(0b); Page length 0x12;Byte2 to Byte15 all 0 with exception DRA and WCE changeable
+
+   if (((current_mode_page[0] & SCSI_MODE_SELECT_MODE_PAGE_SPF_MASK)!= 0) ||
+      (current_mode_page[1] != (SCSI_MODE_PAGE_08_LENGTH-2)) ||
+      ((current_mode_page[2] | SCSI_MODE_PAGE_CACHE_PAGE_WCE_BIT)!=SCSI_MODE_PAGE_CACHE_PAGE_WCE_BIT) ||
+      (current_mode_page[3] != 0 ) ||
+      (current_mode_page[4] != 0 ) ||
+      (current_mode_page[5] != 0 ) ||
+      (current_mode_page[6] != 0 ) ||
+      (current_mode_page[7] != 0 ) ||
+      (current_mode_page[8] != 0 ) ||
+      (current_mode_page[9] != 0 ) ||
+      (current_mode_page[10] != 0 ) ||
+      (current_mode_page[11] != 0 ) ||
+      ((current_mode_page[12] & SCSI_MODE_SELECT_MODE_PAGE_08_FSW_LBCSS_NVDIS) != 0) ||
+      (current_mode_page[13] != 0 ) ||
+      (current_mode_page[14] != 0 ) ||
+      (current_mode_page[15] != 0 ))
+   {
+      //parameter data passed in containing data that doesn't meet the SAT-2 requirement
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+
+   if(sequence->command_specific_data.process_state.ata_command_sent_for_cmp == 0)
+   {
+      //byte2 bit2 WCE==0 disable write cache WCE==1 enable write cache
+      //SCSI_MODE_PAGE_CACHE_PAGE_WCE_BIT ==0x4,
+
+      if ( (current_mode_page[2] & SCSI_MODE_PAGE_CACHE_PAGE_WCE_BIT) == 0)
+         sati_ata_set_features_construct(ata_io, sequence, ATA_SET_FEATURES_SUB_CMD_DISABLE_CACHE);
+      else
+         sati_ata_set_features_construct(ata_io, sequence, ATA_SET_FEATURES_SUB_CMD_ENABLE_CACHE);
+
+   }
+   else if(sequence->command_specific_data.process_state.ata_command_sent_for_cmp == 1)
+   {
+      // DRA bit is set to 0, enable Read look ahead AAh;
+      // DRA bit is set to 1, disable with set feature command 55h
+      // SCSI_MODE_PAGE_CACHE_PAGE_DRA_BIT== 0x20
+
+      if ( (current_mode_page[12] & SCSI_MODE_PAGE_CACHE_PAGE_DRA_BIT) == 0)
+         sati_ata_set_features_construct(ata_io, sequence,ATA_SET_FEATURES_SUB_CMD_ENABLE_READ_AHEAD);
+      else
+         sati_ata_set_features_construct(ata_io, sequence,ATA_SET_FEATURES_SUB_CMD_DISABLE_READ_AHEAD);
+
+      sequence->command_specific_data.process_state.size_of_data_processed += page_size;
+      sequence->command_specific_data.process_state.mode_page_offset += page_size;
+      sequence->command_specific_data.process_state.current_mode_page_processed = TRUE;
+
+
+   }
+   // No more ata commands to send
+
+   sequence->command_specific_data.process_state.ata_command_sent_for_cmp++;
+
+   status = SATI_SUCCESS;
+
+   return status;
+}
+
+/**
+ * @brief This method will check the validity of parameter data of Control mode
+ *            page and further processing the page data if necessary.
+ *
+ * @param[in] mode_select_process_state This parameter points to the processing state fields
+ *            of current mode page.
+ * @param[in] page_size This parameter specifies page size of current mode page.
+ *
+ * @return Indicate if the translation was successful.
+ * @retval SATI_SUCCESS
+ * @retval SATI_COMPLETE
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA
+ */
+static
+SATI_STATUS sati_mode_select_process_mode_page_control(
+         SATI_TRANSLATOR_SEQUENCE_T* sequence,
+         void     *  scsi_io,
+         void     *  ata_io,
+         U32 page_size
+      )
+{
+   SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+
+   //SCSI_MODE_PAGE_0A_LENGTH 12
+   U8 current_mode_page[SCSI_MODE_PAGE_0A_LENGTH]={0,0,0,0,0,0,0,0,0,0};
+   U32 mode_page_offset;
+   U32 index;
+
+   mode_page_offset = sequence->command_specific_data.process_state.mode_page_offset;
+
+   for(index = 0; index < SCSI_MODE_PAGE_0A_LENGTH; index++)
+   {
+      sati_get_data_byte(sequence, scsi_io, mode_page_offset+index, &current_mode_page[index]);
+   }
+
+   //bit 1 and 2 of byte3 Qerr full task management model etc. then both bits 0
+   //byte 8 and 9 busy time out period variable if not ffff setable?
+   //check for page data validity
+   //Byte2: 0000???0b  Byte3: Queued Algorithm Modifier should be set to 1 QErr?
+   //Byte4: ??000???   Byte5: ?0???000
+
+   if (((current_mode_page[0] & SCSI_MODE_SELECT_MODE_PAGE_SPF_MASK)!= 0) ||
+      (current_mode_page[1] != (SCSI_MODE_PAGE_0A_LENGTH - 2)) ||
+      ((current_mode_page[2] & SCSI_MODE_SELECT_MODE_PAGE_0A_TST_TMF_RLEC) != 0) ||
+      ((current_mode_page[3] & SCSI_MODE_SELECT_MODE_PAGE_0A_MODIFIER) != 0) ||
+      ((current_mode_page[4] & SCSI_MODE_SELECT_MODE_PAGE_0A_UA_SWP ) != 0) ||
+      ((current_mode_page[5] & SCSI_MODE_SELECT_MODE_PAGE_0A_TAS_AUTO ) != 0 ) )
+   {
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+
+   if ((current_mode_page[2] & SCSI_MODE_SELECT_MODE_PAGE_D_SENSE) != 0)
+       sequence->device->descriptor_sense_enable = SCSI_MODE_PAGE_CONTROL_D_SENSE_ENABLE;
+   else
+       sequence->device->descriptor_sense_enable = SCSI_MODE_PAGE_CONTROL_D_SENSE_DISABLE;
+
+   // no ata command need to be comfirmed
+   {
+      sequence->command_specific_data.process_state.size_of_data_processed += page_size;
+      sequence->command_specific_data.process_state.mode_page_offset += page_size;
+      sequence->command_specific_data.process_state.current_mode_page_processed = TRUE;
+   }
+
+   status = SATI_COMPLETE;
+
+   return status;
+}
+
+/**
+ * @brief This method will check the validity of parameter data of Information Exception Control
+ *            mode page and further processing the page data if necessary.
+ *
+ * @param[in] page_size This parameter specifies page size of current mode page.
+ *
+ * @return Indicate if the translation was successful.
+ * @retval SATI_SUCCESS
+ * @retval SATI_COMPLETE
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA
+ */
+static
+SATI_STATUS sati_mode_select_process_mode_page_informational_exception_control(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void     *  scsi_io,
+   void     *  ata_io,
+   U32 page_size
+   )
+{
+   SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+
+   //SCSI_MODE_PAGE_1C_LENGTH 12
+   U8 current_mode_page[SCSI_MODE_PAGE_1C_LENGTH]={0,0,0,0,0,0,0,0,0,0,0,0};
+   U32 mode_page_offset;
+   U32 index;
+
+   mode_page_offset = sequence->command_specific_data.process_state.mode_page_offset;
+   sequence->type = SATI_SEQUENCE_MODE_SELECT_MODE_INFORMATION_EXCEPT_CONTROL;
+
+   for(index = 0; index < 4; index++)
+   {
+      sati_get_data_byte(sequence, scsi_io, mode_page_offset+index, &current_mode_page[index]);
+   }
+
+   //Check for data validity
+   //SPF(0b); Page length 0x0A; Byte2 0????0?? Byte3: ????1100
+   //SCSI_MODE_SELECT_MODE_PAGE_MRIE_BYTE same as REPORT_INFO_EXCEPTION_CONDITION_ON_REQUEST 0x6
+   //SCSI_MODE_PAGE_DEXCPT_ENABLE
+
+   if (((current_mode_page[0] & SCSI_MODE_SELECT_MODE_PAGE_SPF_MASK)!= 0) ||
+      (current_mode_page[1] != (SCSI_MODE_PAGE_1C_LENGTH - 2)) ||
+      ((current_mode_page[2] & SCSI_MODE_SELECT_MODE_PAGE_1C_PERF_TEST)!= 0 ) ||
+      ((current_mode_page[3] & SCSI_MODE_SELECT_MODE_PAGE_MRIE_MASK) !=
+      SCSI_MODE_SELECT_MODE_PAGE_MRIE_BYTE ))
+   {
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+
+   // DEXCPT bit is set to 0, enable SMART reporting D8h;
+   // DEXCPT bit is set to 1, disable SMART reporting D9h
+   // SCSI_MODE_PAGE_DEXCPT_ENABLE== 0x08
+
+   if ( (current_mode_page[2] & SCSI_MODE_PAGE_DEXCPT_ENABLE) == 0)
+      sati_ata_smart_return_status_construct(ata_io, sequence, ATA_SMART_SUB_CMD_ENABLE);
+   else
+      sati_ata_smart_return_status_construct(ata_io, sequence, ATA_SMART_SUB_CMD_DISABLE);
+
+   sequence->command_specific_data.process_state.size_of_data_processed += page_size;
+   sequence->command_specific_data.process_state.mode_page_offset += page_size;
+   sequence->command_specific_data.process_state.current_mode_page_processed = TRUE;
+   // No more ata commands to send
+
+   status = SATI_SUCCESS;
+
+   return status;
+}
+
+/**
+ * @brief This method will check the validity of parameter data of Power Condition mode
+ *            page and issue multiple ATA set feature commands to complete the translation.
+ *
+ * @param[in] mode_select_process_state This parameter points to the processing state fields
+ *            of current mode page.
+ * @param[in] page_size This parameter specifies page size of current mode page.
+ *
+ * @return Indicate if the translation was successful.
+ * @retval SATI_SUCCESS
+ * @retval SATI_COMPLETE
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA
+ */
+static
+SATI_STATUS sati_mode_select_process_mode_page_power_condition(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void * scsi_io,
+   void * ata_io,
+   U32 page_size
+   )
+{
+   SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+
+   //SCSI_MODE_PAGE_1A_LENGTH 10
+   U8 current_mode_page[SCSI_MODE_PAGE_1A_LENGTH] = {0,0,0,0,0,0,0,0,0,0};
+   U32 mode_page_offset;
+   U32 index;
+
+   U32 timer = 0;
+   U16 count = 0;
+
+   mode_page_offset = sequence->command_specific_data.process_state.mode_page_offset;
+
+   sequence->type = SATI_SEQUENCE_MODE_SELECT_MODE_POWER_CONDITION;
+
+   for(index = 0; index < SCSI_MODE_PAGE_1A_LENGTH; index++)
+   {
+      sati_get_data_byte(sequence, scsi_io, mode_page_offset+index, &current_mode_page[index]);
+   }
+
+   //Check for data validity
+   //SPF(0b); Page length 0x0A;
+
+   if (((current_mode_page[0] & SCSI_MODE_SELECT_MODE_PAGE_SPF_MASK)!= 0) ||
+      (current_mode_page[1] != (SCSI_MODE_PAGE_1A_LENGTH - 2) ) ||
+      ((current_mode_page[3] & SCSI_MODE_PAGE_POWER_CONDITION_IDLE)!= 0)
+      )
+   {
+      //parameter data passed in containing data that doesn't meet the SAT-2 requirement
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+
+   // STANDBY bit is set to 0, do nothing since the standby timer can't be set;
+   // STANDBY bit is set to 1, translate the standby timer
+   // SCSI_MODE_PAGE_POWER_CONDITION_STANDBY== 0x01
+   if (current_mode_page[3] & SCSI_MODE_PAGE_POWER_CONDITION_STANDBY)
+   {
+      timer = (current_mode_page[8]<<24) + (current_mode_page[9]<<16) + (current_mode_page[10]<<8) + current_mode_page[11];
+
+      //If the ATA IDENTIFY DEVICE data word 49, bit 13 is set to one,
+      if (sequence->device->capabilities & SATI_DEVICE_CAP_STANDBY_ENABLE)
+      {
+         if (timer == 0)
+         {
+            //TPV=0 send ATA STANDBY_IMMEDIATE
+            sati_ata_standby_immediate_construct(ata_io, sequence);
+            sequence->command_specific_data.translated_command = ATA_STANDBY_IMMED;
+         }
+         else if ((timer > 0) && (timer <= 12000))
+         {
+            //1 to 12 000 INT((z - 1) / 50) + 1
+            count = (U16)((timer -1) / 50) + 1;
+            sati_ata_standby_construct(ata_io, sequence, count);
+         }
+         else if ((timer > 12000) && (timer <= 12600))
+         {
+            //12 001 to 12 600 FCh
+            sati_ata_standby_construct(ata_io, sequence, 0xFC);
+         }
+         else if ((timer > 12600) && (timer <= 12750))
+         {
+            //12 601 to 12 750 FFh
+            sati_ata_standby_construct(ata_io, sequence, 0xFF);
+         }
+         else if ((timer > 12750) && (timer < 18000))
+         {
+            //12 751 to 17 999 F1h
+            sati_ata_standby_construct(ata_io, sequence, 0xF1);
+         }
+         else if ((timer >= 18000) && (timer <= 198000))
+         {
+            //18 000 to 198 000 INT(z / 18 000) + 240
+            count = (U16)(timer / 18000) + 240;
+            sati_ata_standby_construct(ata_io, sequence, count);
+         }
+         else
+         {
+            //All other values FDh
+            sati_ata_standby_construct(ata_io, sequence, 0xFD);
+         }
+         status = SATI_SUCCESS ;
+      }
+      else
+      {
+         status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+         //If the ATA IDENTIFY DEVICE data word 49, bit 13 is set to 0
+      }
+   }
+   else
+   {
+      status = SATI_COMPLETE;
+   }
+
+   sequence->command_specific_data.process_state.size_of_data_processed += page_size;
+   sequence->command_specific_data.process_state.mode_page_offset += page_size;
+   sequence->command_specific_data.process_state.current_mode_page_processed = TRUE;
+
+   return status;
+}
+
+/**
+ * @brief This method will process the mode page.
+ *
+ *
+ * @return Indicate if the translation was successful.
+ * @retval SATI_SUCCESS
+ * @retval SATI_COMPLETE
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA
+ */
+static
+SATI_STATUS sati_mode_select_process_mode_page(
+   SATI_TRANSLATOR_SEQUENCE_T* sequence,
+   void                      * scsi_io,
+   void                      * ata_io
+)
+{
+   SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+
+   U8 page_code;
+   U32 page_size = 0; // in bytes
+   U32 size_of_data_to_be_processed;
+
+   U8 page_code_byte;
+   U32 mode_page_offset;
+
+   mode_page_offset = sequence->command_specific_data.process_state.mode_page_offset;
+
+   sati_get_data_byte(sequence, scsi_io, mode_page_offset, &page_code_byte);
+
+   // No more pages.
+   if(sequence->command_specific_data.process_state.mode_pages_size >
+      sequence->command_specific_data.process_state.size_of_data_processed)
+   {
+      //SCSI_MODE_SENSE_PAGE_CODE_ENABLE==0x3f same for Mode Select
+      page_code = page_code_byte & SCSI_MODE_SENSE_PAGE_CODE_ENABLE;
+      page_size = sati_mode_select_get_mode_page_size(page_code);
+      size_of_data_to_be_processed = sequence->command_specific_data.process_state.mode_pages_size
+         - sequence->command_specific_data.process_state.size_of_data_processed;
+
+      if( page_size == 0 )
+      {
+         status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+      }
+      else
+      {
+         // process mode page
+         switch(page_code)
+         {
+         case SCSI_MODE_PAGE_READ_WRITE_ERROR:
+            status = sati_mode_select_process_mode_page_read_write_error_recovery(
+                        sequence,
+                        scsi_io,
+                        page_size
+                     );
+            break;
+
+         case SCSI_MODE_PAGE_DISCONNECT_RECONNECT:
+            status = sati_mode_select_process_mode_page_disconnect_reconnect(
+                        &sequence->command_specific_data.process_state,
+                        page_size
+                     );
+            break;
+
+         case SCSI_MODE_PAGE_CACHING:
+            status = sati_mode_select_process_mode_page_caching(
+                        sequence,
+                        scsi_io,
+                        ata_io,
+                        page_size
+                     );
+            break;
+
+         case SCSI_MODE_PAGE_CONTROL:
+            status = sati_mode_select_process_mode_page_control(
+                        sequence,
+                        scsi_io,
+                        ata_io,
+                        page_size
+                     );
+            break;
+
+         case SCSI_MODE_PAGE_INFORMATIONAL_EXCP_CONTROL:
+            status = sati_mode_select_process_mode_page_informational_exception_control(
+                        sequence,
+                        scsi_io,
+                        ata_io,
+                        page_size
+                     );
+            break;
+
+         case SCSI_MODE_PAGE_POWER_CONDITION:
+            status = sati_mode_select_process_mode_page_power_condition(
+                        sequence,
+                        scsi_io,
+                        ata_io,
+                        page_size
+                     );
+
+            break;
+
+         default:
+            break;
+         }
+
+      }
+   }
+
+   return status;
+}
+
+//******************************************************************************
+//* P U B L I C   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method will translate the SCSI Mode Select 6 byte or 10 byte command
+ *        into corresponding ATA commands.  Depending upon the capabilities
+ *        supported by the target different ATA commands can be selected.
+ *        Additionally, in some cases more than a single ATA command may
+ *        be required.
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the command translation was
+ *         successful.
+ * @retval SCI_COMPLETE This is returned if the command translation was
+ *         successful and no ATA commands need to be set.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
+ *         sense data has been created as a result of something specified
+ *         in the parameter data fields.
+ */
+static
+SATI_STATUS sati_mode_select_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T   * sequence,
+   void                         * scsi_io,
+   void                         * ata_io,
+   U32                          cdb_size
+)
+{
+   SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+   U32 mode_page_offset;
+   U32 block_descriptor_length;
+   U32 index;
+   U16 data_transfer_length;
+   U8 current_mode_parameters[8]={0,0,0,0,0,0,0,0};
+   U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+   // cdb_size must be 6 or 10
+   if(FALSE == (cdb_size == 6 || cdb_size == 10))
+   {
+      return status;
+   }
+
+   if(sequence->state == SATI_SEQUENCE_STATE_INITIAL)
+   {
+      sequence->command_specific_data.process_state.ata_command_sent_for_cmp = 0;
+      sequence->state = SATI_SEQUENCE_STATE_TRANSLATE_DATA;
+   }
+
+   //First, initializes mode_sel_processing_state
+   if ( sequence->command_specific_data.process_state.ata_command_sent_for_cmp == 0 )
+   {
+      if (cdb_size == 6)
+      {
+         //CDB byte 4 is the parameter length
+         data_transfer_length = sati_get_cdb_byte(cdb, 4);
+      }
+      else
+      {
+         //CDB byte 7 and 8 for Mode Select 10
+         data_transfer_length = (sati_get_cdb_byte(cdb, 7) << 8) + sati_get_cdb_byte(cdb, 8);
+      }
+
+      sequence->allocation_length = data_transfer_length;
+
+      //Get 8 bytes for headers (4 bytes for Mode Select 6 and 8 bytes for Mode Select 10)
+      for( index = 0; index < 8; index++ )
+      {
+         sati_get_data_byte(sequence, scsi_io, index, &current_mode_parameters[index]);
+      }
+
+      //medium type should be 0
+      if ( sati_mode_select_get_medium_type(current_mode_parameters, cdb_size) != 0 )
+      {
+         sati_scsi_sense_data_construct(
+            sequence,
+            scsi_io,
+            SCSI_STATUS_CHECK_CONDITION,
+            SCSI_SENSE_ILLEGAL_REQUEST,
+            SCSI_ASC_INVALID_FIELD_IN_PARM_LIST,
+            SCSI_ASCQ_INVALID_FIELD_IN_PARM_LIST
+         );
+         return status;
+      }
+
+      block_descriptor_length = sati_mode_select_get_mode_block_descriptor_length(
+                                   current_mode_parameters,
+                                   cdb_size
+                                );
+
+      mode_page_offset = sati_mode_select_get_mode_page_offset(
+                            block_descriptor_length,
+                            cdb_size
+                         );
+
+      if(mode_page_offset > data_transfer_length)
+      {
+         sequence->state = SATI_SEQUENCE_STATE_FINAL;
+         status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+      }
+      else
+      {
+         sati_mode_select_initialize_mode_sel_processing_state(
+            sequence,
+            scsi_io,
+            ata_io,
+            data_transfer_length,
+            mode_page_offset
+         );
+
+      }
+    }
+
+   // move to next mode page
+   if(sequence->command_specific_data.process_state.current_mode_page_processed)
+   {
+      sequence->command_specific_data.process_state.ata_command_sent_for_cmp = 0;
+      sequence->command_specific_data.process_state.current_mode_page_processed = FALSE;
+   }
+
+   status = sati_mode_select_process_mode_page(sequence, scsi_io, ata_io);
+
+   if(sequence->command_specific_data.process_state.current_mode_page_processed != FALSE)
+   {
+      // Done this page
+      sequence->state = SATI_SEQUENCE_STATE_FINAL;
+   }
+   else
+   {
+      sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
+   }
+
+   if(status == SATI_FAILURE_CHECK_RESPONSE_DATA)
+   {
+      sequence->state = SATI_SEQUENCE_STATE_FINAL;
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_ILLEGAL_REQUEST,
+         SCSI_ASC_INVALID_FIELD_IN_PARM_LIST,
+         SCSI_ASCQ_INVALID_FIELD_IN_PARM_LIST
+      );
+   }
+
+   return status;
+}
+
+/**
+ * @brief This method will call Mode Select 6 Translation command
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the command translation was
+ *         successful.
+ * @retval SCI_COMPLETE This is returned if the command translation was
+ *         successful and no ATA commands need to be set.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
+ *         sense data has been created as a result of something specified
+ *         in the parameter data fields.
+ */
+SATI_STATUS sati_mode_select_6_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   SATI_STATUS status=SATI_FAILURE;
+   U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+   //PF bit needs to be 1 byte1 bit ???1????
+   if ((sati_get_cdb_byte(cdb, 1) & SCSI_MODE_SELECT_PF_MASK) == !SCSI_MODE_SELECT_PF_BIT)
+   {
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_ILLEGAL_REQUEST,
+         SCSI_ASC_INVALID_FIELD_IN_CDB,
+         SCSI_ASCQ_INVALID_FIELD_IN_CDB
+      );
+      status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+      return status;
+   }
+
+   status=sati_mode_select_translate_command(
+             sequence,
+             scsi_io,
+             ata_io,
+             6
+          );
+
+   if(status == SATI_FAILURE_CHECK_RESPONSE_DATA)
+   {
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_ILLEGAL_REQUEST,
+         SCSI_ASC_INVALID_FIELD_IN_PARM_LIST,
+         SCSI_ASCQ_INVALID_FIELD_IN_PARM_LIST
+      );
+   }
+   return status;
+
+}
+
+/**
+ * @brief This method will call Mode Select 10 translation command
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the command translation was
+ *         successful.
+ * @retval SCI_COMPLETE This is returned if the command translation was
+ *         successful and no ATA commands need to be set.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
+ *         sense data has been created as a result of something specified
+ *         in the parameter data fields.
+ */
+SATI_STATUS sati_mode_select_10_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   SATI_STATUS status=SATI_FAILURE;
+   U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+   //PF bit needs to be 1 byte1 bit ???1????
+   if ((sati_get_cdb_byte(cdb, 1) & SCSI_MODE_SELECT_PF_MASK) == !SCSI_MODE_SELECT_PF_BIT)
+   {
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_ILLEGAL_REQUEST,
+         SCSI_ASC_INVALID_FIELD_IN_CDB,
+         SCSI_ASCQ_INVALID_FIELD_IN_CDB
+      );
+      status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+      return status;
+   }
+
+   status=sati_mode_select_translate_command(
+             sequence,
+             scsi_io,
+             ata_io,
+             10
+          );
+
+   if(status == SATI_FAILURE_CHECK_RESPONSE_DATA)
+   {
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_ILLEGAL_REQUEST,
+         SCSI_ASC_INVALID_FIELD_IN_PARM_LIST,
+         SCSI_ASCQ_INVALID_FIELD_IN_PARM_LIST
+      );
+   }
+   return status;
+}
+
+/**
+* @brief This method will conduct error handling for the ATA Set Features command
+*        that is issued during a Mode Select translation for the Caching Mode
+*        page.
+*
+*
+* @return Indicate if the command translation succeeded.
+*
+* @retval SCI_COMPLETE This is returned if the command translation was
+*         successful and no additional ATA commands need to be set.
+* @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
+*         sense data has been created as a result of an error returned
+*/
+SATI_STATUS sati_mode_select_translate_response(
+SATI_TRANSLATOR_SEQUENCE_T * sequence,
+void                       * scsi_io,
+void                       * ata_io
+)
+{
+   U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
+   SATI_STATUS status = SATI_FAILURE;
+
+   if(sati_get_ata_status(register_fis) & ATA_STATUS_REG_ERROR_BIT)
+   {
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_ABORTED_COMMAND,
+         SCSI_ASC_NO_ADDITIONAL_SENSE,
+         SCSI_ASCQ_NO_ADDITIONAL_SENSE
+      );
+      status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+   else
+   {
+      if (sequence->state == SATI_SEQUENCE_STATE_INCOMPLETE)
+      {
+         status = SATI_SEQUENCE_INCOMPLETE;
+      }
+      else
+      {
+         status = SATI_COMPLETE;
+      }
+   }
+   return status;
+}
+
+#endif // !defined(DISABLE_SATI_MODE_SELECT)
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_mode_select.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_mode_select.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,84 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_MODE_SELECT_H_
+#define _SATI_MODE_SELECT_H_
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ *        translate the SCSI mode select (6 and 10-byte) commands.
+ */
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+SATI_STATUS sati_mode_select_6_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+SATI_STATUS sati_mode_select_10_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+SATI_STATUS sati_mode_select_translate_response(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+#endif // _SATI_MODE_SELECT_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_mode_sense.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_mode_sense.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,837 @@
+ /*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ *        translate the SCSI mode sense (6 and 10-byte) commands.
+ */
+
+#if !defined(DISABLE_SATI_MODE_SENSE)
+
+#include <dev/isci/scil/sati_mode_sense.h>
+#include <dev/isci/scil/sati_mode_pages.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/intel_scsi.h>
+#include <dev/isci/scil/intel_ata.h>
+
+//******************************************************************************
+//* P R I V A T E   M E T H O D S
+//******************************************************************************
+
+#define STANDBY_TIMER_DISABLED  0x00
+#define STANDBY_TIMER_ENABLED   0x01
+#define STANDBY_TIMER_SUPPORTED 0x2000
+
+
+
+/**
+ * @brief This method indicates if the supplied page control is supported
+ *        by this translation implementation.  Currently savable parameters
+ *        (i.e. non-volatile) are not supported.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @return This method returns an indication of whether the page control
+ *         specified in the SCSI CDB is supported.
+ * @retval SATI_SUCCESS This value is returned if the page control is
+ *         supported.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if the
+ *         page control is not supported.
+ */
+static
+SATI_STATUS sati_mode_sense_is_page_control_supported(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io
+)
+{
+   U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+   switch (sati_get_cdb_byte(cdb, 2) >> SCSI_MODE_SENSE_PC_SHIFT)
+   {
+      case SCSI_MODE_SENSE_PC_CURRENT:
+      case SCSI_MODE_SENSE_PC_DEFAULT:
+      case SCSI_MODE_SENSE_PC_CHANGEABLE:
+         return SATI_SUCCESS;
+      break;
+
+      default:
+      case SCSI_MODE_SENSE_PC_SAVED:
+         sati_scsi_sense_data_construct(
+            sequence,
+            scsi_io,
+            SCSI_STATUS_CHECK_CONDITION,
+            SCSI_SENSE_ILLEGAL_REQUEST,
+            SCSI_ASC_SAVING_PARMS_NOT_SUPPORTED,
+            SCSI_ASCQ_SAVING_PARMS_NOT_SUPPORTED
+         );
+         return SATI_FAILURE_CHECK_RESPONSE_DATA;
+      break;
+   }
+}
+
+/**
+ * @brief This method indicates if the page code field in the SCSI CDB
+ *        is supported by this translation.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @param[in] cdb_length This parameter specifies the length of the SCSI
+ *            CDB being translated (e.g. 6-byte, 10-byte, 12-byte, etc.)
+ *
+ * @return This method returns an indication as to whether the page code
+ *         in the CDB is supported.
+ * @retval SATI_SUCCESS This value is returned if the page code is
+ *         supported.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if the
+ *         page code is not supported.
+ */
+static
+SATI_STATUS sati_mode_sense_is_page_code_supported(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   U8                           cdb_length
+)
+{
+   U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+   switch (sati_get_cdb_byte(cdb, 2) & SCSI_MODE_SENSE_PAGE_CODE_ENABLE)
+   {
+      case SCSI_MODE_PAGE_CACHING:
+         if (sati_get_cdb_byte(cdb, 0) == SCSI_MODE_SENSE_6)
+            sequence->type = SATI_SEQUENCE_MODE_SENSE_6_CACHING;
+         else
+            sequence->type = SATI_SEQUENCE_MODE_SENSE_10_CACHING;
+      break;
+
+      case SCSI_MODE_PAGE_ALL_PAGES:
+         if (sati_get_cdb_byte(cdb, 0) == SCSI_MODE_SENSE_6)
+            sequence->type = SATI_SEQUENCE_MODE_SENSE_6_ALL_PAGES;
+         else
+            sequence->type = SATI_SEQUENCE_MODE_SENSE_10_ALL_PAGES;
+      break;
+
+      case SCSI_MODE_PAGE_READ_WRITE_ERROR:
+         if (sati_get_cdb_byte(cdb, 0) == SCSI_MODE_SENSE_6)
+            sequence->type = SATI_SEQUENCE_MODE_SENSE_6_READ_WRITE_ERROR;
+         else
+            sequence->type = SATI_SEQUENCE_MODE_SENSE_10_READ_WRITE_ERROR;
+      break;
+
+      case SCSI_MODE_PAGE_DISCONNECT_RECONNECT:
+         if (sati_get_cdb_byte(cdb, 0) == SCSI_MODE_SENSE_6)
+            sequence->type = SATI_SEQUENCE_MODE_SENSE_6_DISCONNECT_RECONNECT;
+         else
+            sequence->type = SATI_SEQUENCE_MODE_SENSE_10_DISCONNECT_RECONNECT;
+      break;
+
+      case SCSI_MODE_PAGE_CONTROL:
+         if (sati_get_cdb_byte(cdb, 0) == SCSI_MODE_SENSE_6)
+            sequence->type = SATI_SEQUENCE_MODE_SENSE_6_CONTROL;
+         else
+            sequence->type = SATI_SEQUENCE_MODE_SENSE_10_CONTROL;
+      break;
+
+      case SCSI_MODE_PAGE_POWER_CONDITION:
+         if (sati_get_cdb_byte(cdb, 0) == SCSI_MODE_SENSE_6)
+            sequence->type = SATI_SEQUENCE_MODE_SENSE_6_POWER_CONDITION;
+         else
+            sequence->type = SATI_SEQUENCE_MODE_SENSE_10_POWER_CONDITION;
+      break;
+
+      case SCSI_MODE_PAGE_INFORMATIONAL_EXCP_CONTROL:
+         // The informational exceptions control page is only useful
+         // if SMART is supported.
+         if ((sequence->device->capabilities | SATI_DEVICE_CAP_SMART_SUPPORT)
+             == 0)
+         {
+            // For a MODE SENSE, utilize INVALID FIELD IN CDB,
+            // For a MODE SELECT, utilize INVALID FIELD IN PARAMETER LIST.
+            if (sati_get_cdb_byte(cdb, 0) == SCSI_MODE_SENSE_6)
+            {
+               sati_scsi_sense_data_construct(
+                  sequence,
+                  scsi_io,
+                  SCSI_STATUS_CHECK_CONDITION,
+                  SCSI_SENSE_ILLEGAL_REQUEST,
+                  SCSI_ASC_INVALID_FIELD_IN_CDB,
+                  SCSI_ASCQ_INVALID_FIELD_IN_CDB
+               );
+            }
+            else
+            {
+               sati_scsi_sense_data_construct(
+                  sequence,
+                  scsi_io,
+                  SCSI_STATUS_CHECK_CONDITION,
+                  SCSI_SENSE_ILLEGAL_REQUEST,
+                  SCSI_ASC_INVALID_FIELD_IN_PARM_LIST,
+                  SCSI_ASCQ_INVALID_FIELD_IN_PARM_LIST
+               );
+            }
+
+            return SATI_FAILURE_CHECK_RESPONSE_DATA;
+         }
+
+         if (sati_get_cdb_byte(cdb, 0) == SCSI_MODE_SENSE_6)
+            sequence->type = SATI_SEQUENCE_MODE_SENSE_6_INFORMATIONAL_EXCP_CONTROL;
+         else
+            sequence->type = SATI_SEQUENCE_MODE_SENSE_10_INFORMATIONAL_EXCP_CONTROL;
+      break;
+
+      default:
+         sati_scsi_sense_data_construct(
+            sequence,
+            scsi_io,
+            SCSI_STATUS_CHECK_CONDITION,
+            SCSI_SENSE_ILLEGAL_REQUEST,
+            SCSI_ASC_INVALID_FIELD_IN_CDB,
+            SCSI_ASCQ_INVALID_FIELD_IN_CDB
+         );
+         return SATI_FAILURE_CHECK_RESPONSE_DATA;
+      break;
+   }
+
+   return SATI_SUCCESS;
+}
+
+//******************************************************************************
+//* P R O T E C T E D   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method will calculate the size of the mode sense data header.
+ *        This includes the block descriptor if one is requested.
+ *
+ * @param[in] scsi_io This parameter specifies the user's SCSI IO object
+ *            for which to calculate the mode page header.
+ * @param[in] cdb_size This parameter specifies the number of bytes
+ *            associated with the CDB for which to calculate the header.
+ *
+ * @return This method returns the size, in bytes, for the mode page header.
+ */
+U16 sati_mode_sense_calculate_page_header(
+   void * scsi_io,
+   U8     cdb_size
+)
+{
+   U8 * cdb         = sati_cb_get_cdb_address(scsi_io);
+   U16  page_length = 0;
+
+   // The Mode page header length is different for 6-byte vs. 10-byte CDBs.
+   if (cdb_size == 6)
+      page_length += SCSI_MODE_SENSE_6_HEADER_LENGTH;
+   else
+      page_length += SCSI_MODE_SENSE_10_HEADER_LENGTH;
+
+   // Are block descriptors disabled (DBD)?  0 indicates they are enabled.
+   if ((sati_get_cdb_byte(cdb, 1) & SCSI_MODE_SENSE_DBD_ENABLE) == 0)
+   {
+      // The LLBAA bit is not defined for 6-byte mode sense requests.
+      if (  (cdb_size == 10)
+         && (sati_get_cdb_byte(cdb, 1) & SCSI_MODE_SENSE_LLBAA_ENABLE) )
+         page_length += SCSI_MODE_SENSE_LLBA_BLOCK_DESCRIPTOR_LENGTH;
+      else
+         page_length += SCSI_MODE_SENSE_STD_BLOCK_DESCRIPTOR_LENGTH;
+   }
+
+   return page_length;
+}
+
+/**
+ * @brief This method performs command translation common to all mode sense
+ *        requests (6 or 10 byte).
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @param[in] cdb_length This parameter specifies the number of bytes
+ *            in the CDB (6 or 10).
+ *
+ * @return This method returns an indication as to whether the translation
+ *         succeeded.
+ * @retval SCI_SUCCESS This value is returned if translation succeeded.
+ * @see sati_mode_sense_is_page_control_supported() or
+ *      sati_mode_sense_is_page_code_supported() for more information.
+ */
+SATI_STATUS sati_mode_sense_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io,
+   U8                           cdb_length
+)
+{
+   SATI_STATUS   status;
+
+   /**
+    * Validate that the supplied page control (PC) field is supported.
+    */
+   status = sati_mode_sense_is_page_control_supported(sequence, scsi_io);
+   if (status != SATI_SUCCESS)
+      return status;
+
+   /**
+    * Validate that the supplied page code is supported.
+    */
+   status = sati_mode_sense_is_page_code_supported(sequence,scsi_io,cdb_length);
+   if (status != SATI_SUCCESS)
+      return status;
+
+   sati_ata_identify_device_construct(ata_io, sequence);
+
+   return SATI_SUCCESS;
+}
+
+/**
+ * @brief This method will build the standard block descriptor for a MODE
+ *        SENSE 6 or 10 byte request.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @param[in] identify This parameter specifies the IDENTIFY DEVICE data
+ *            associated with the SCSI IO.
+ * @param[in] offset This parameter specifies the offset into the data
+ *            buffer at which to build the block descriptor.
+ *
+ * @return This method returns the size of the block descriptor built.
+ */
+U32 sati_mode_sense_build_std_block_descriptor(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   ATA_IDENTIFY_DEVICE_DATA_T * identify,
+   U32                          offset
+)
+{
+   U32  lba_low     = 0;
+   U32  lba_high    = 0;
+   U32  sector_size = 0;
+
+   // Extract the sector information (sector size, logical blocks) from
+   // the retrieved ATA identify device data.
+   sati_ata_identify_device_get_sector_info(
+      identify, &lba_high, &lba_low, &sector_size
+   );
+
+   // Fill in the 4-byte logical block address field.
+   sati_set_data_byte(sequence, scsi_io, offset,   (U8)((lba_low>>24) & 0xFF));
+   sati_set_data_byte(sequence, scsi_io, offset+1, (U8)((lba_low>>16) & 0xFF));
+   sati_set_data_byte(sequence, scsi_io, offset+2, (U8)((lba_low>>8)  & 0xFF));
+   sati_set_data_byte(sequence, scsi_io, offset+3, (U8)(lba_low & 0xFF));
+
+   // Clear the reserved field.
+   sati_set_data_byte(sequence, scsi_io, offset+4, 0);
+
+   // Fill in the three byte Block Length field
+   sati_set_data_byte(sequence,scsi_io, offset+5, (U8)((sector_size>>16) & 0xFF));
+   sati_set_data_byte(sequence,scsi_io, offset+6, (U8)((sector_size>>8)  & 0xFF));
+   sati_set_data_byte(sequence,scsi_io, offset+7, (U8)(sector_size & 0xFF));
+
+   return SCSI_MODE_SENSE_STD_BLOCK_DESCRIPTOR_LENGTH;
+}
+
+/**
+ * @brief This method simply copies the mode sense data into the buffer
+ *        at the location specified by page_start.  The buffer copied is
+ *        determined by page_control (e.g. current, default, or changeable
+ *        values).
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @param[in] page_start This parameter specifies the starting offset at
+ *            which to copy the mode page data.
+ * @param[in] page_control This parameter specifies the page control
+ *            indicating the source buffer to be copied.
+ * @param[in] page_code This specifies the mode sense page to copy.
+ *
+ * @return This method returns the size of the mode page data being copied.
+ */
+U32 sati_mode_sense_copy_initial_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   U32                          page_start,
+   U8                           page_control,
+   U8                           page_code
+)
+{
+   U16 page_index  = sati_mode_page_get_page_index(page_code);
+   U32 page_length = sat_mode_page_sizes[page_index];
+
+   // Find out if the current values are requested or if the default
+   // values are being requested.
+   if (page_control == SCSI_MODE_SENSE_PC_CHANGEABLE)
+   {
+      // Copy the changeable mode page information.
+      sati_copy_data(
+         sequence,
+         scsi_io,
+         page_start,
+         sat_changeable_mode_pages[page_index],
+         page_length
+      );
+   }
+   else
+   {
+      // Copy the default static values template to the user data area.
+      sati_copy_data(
+         sequence,
+         scsi_io,
+         page_start,
+         sat_default_mode_pages[page_index],
+         page_length
+      );
+   }
+
+   return page_length;
+}
+
+/**
+ * @brief This method performs the read/write error recovery mode page
+ *        specific data translation based upon the contents of the remote
+ *        device IDENTIFY DEVICE data.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @param[in] identify This parameter specifies the remote device's
+ *            IDENTIFY DEVICE data received as part of the IO request.
+ * @param[in] offset This parameter specifies the offset into the data
+ *            buffer where the translated data is to be written.
+ *
+ * @return This method returns the size of the mode page data that was
+ *         translated.
+ */
+U32 sati_mode_sense_read_write_error_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   ATA_IDENTIFY_DEVICE_DATA_T * identify,
+   U32                          offset
+)
+{
+   U8 * cdb          = sati_cb_get_cdb_address(scsi_io);
+   U8   page_control = sati_get_cdb_byte(cdb, 2) >> SCSI_MODE_SENSE_PC_SHIFT;
+   U32  page_length;
+
+   page_length = sati_mode_sense_copy_initial_data(
+                    sequence,
+                    scsi_io,
+                    offset,
+                    page_control,
+                    SCSI_MODE_PAGE_READ_WRITE_ERROR
+                 );
+
+   // Currently we do not override any bits in this mode page from the
+   // identify data.
+
+   return page_length;
+}
+
+/**
+ * @brief This method performs the disconnect/reconnect mode page
+ *        specific data translation based upon the contents of the remote
+ *        device IDENTIFY DEVICE data.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @param[in] identify This parameter specifies the remote device's
+ *            IDENTIFY DEVICE data received as part of the IO request.
+ * @param[in] offset This parameter specifies the offset into the data
+ *            buffer where the translated data is to be written.
+ *
+ * @return This method returns the size of the mode page data that was
+ *         translated.
+ */
+U32 sati_mode_sense_disconnect_reconnect_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   ATA_IDENTIFY_DEVICE_DATA_T * identify,
+   U32                          offset
+)
+{
+   U8 * cdb          = sati_cb_get_cdb_address(scsi_io);
+   U8   page_control = sati_get_cdb_byte(cdb, 2) >> SCSI_MODE_SENSE_PC_SHIFT;
+   U32  page_length;
+
+   page_length = sati_mode_sense_copy_initial_data(
+                    sequence,
+                    scsi_io,
+                    offset,
+                    page_control,
+                    SCSI_MODE_PAGE_DISCONNECT_RECONNECT
+                 );
+
+   // Currently we do not override any bits in this mode page from the
+   // identify data.
+
+   return page_length;
+}
+
+/**
+ * @brief This method performs the caching mode page specific data
+ *        translation based upon the contents of the remote device IDENTIFY
+ *        DEVICE data.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @param[in] identify This parameter specifies the remote device's
+ *            IDENTIFY DEVICE data received as part of the IO request.
+ * @param[in] offset This parameter specifies the offset into the data
+ *            buffer where the translated data is to be written.
+ *
+ * @return This method returns the size of the mode page data that was
+ *         translated.
+ */
+U32 sati_mode_sense_caching_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   ATA_IDENTIFY_DEVICE_DATA_T * identify,
+   U32                          offset
+)
+{
+   U8 * cdb          = sati_cb_get_cdb_address(scsi_io);
+   U8   page_control = sati_get_cdb_byte(cdb, 2) >> SCSI_MODE_SENSE_PC_SHIFT;
+   U32  page_length;
+
+   page_length = sati_mode_sense_copy_initial_data(
+                    sequence,
+                    scsi_io,
+                    offset,
+                    page_control,
+                    SCSI_MODE_PAGE_CACHING
+                 );
+
+   // If the request queried for the current values, then
+   // we need to translate the data from the IDENTIFY DEVICE request.
+   if (page_control == SCSI_MODE_SENSE_PC_CURRENT)
+   {
+      U8  value;
+
+      // Update the Write Cache Enabled (WCE) bit in the mode page data
+      // buffer based on the identify response.
+      if ((identify->command_set_enabled0 & ATA_IDENTIFY_DEVICE_WCE_ENABLE) != 0)
+      {
+         sati_get_data_byte(sequence, scsi_io, offset+2, &value);
+         value |= SCSI_MODE_PAGE_CACHE_PAGE_WCE_BIT;
+         sati_set_data_byte(sequence, scsi_io, offset+2, value);
+         //This byte has been set twice and needs to be decremented
+         sequence->number_data_bytes_set--;
+      }
+
+      // Update the Disable Read Ahead (DRA) bit in the mode page data
+      // buffer based on the identify response.
+      if ((identify->command_set_enabled0 & ATA_IDENTIFY_DEVICE_RA_ENABLE) == 0)
+      {
+         // In SATA the polarity of the bits is inverse.
+         // - SCSI = Disable Read Ahead
+         // - ATA = Read Ahead
+         sati_get_data_byte(sequence, scsi_io, offset+12, &value);
+         value |= SCSI_MODE_PAGE_CACHE_PAGE_DRA_BIT;
+         sati_set_data_byte(sequence, scsi_io, offset+12, value);
+
+         //This byte has been set twice, the first time in
+         //sati_mode_sense_copy_initial_data. number_data_bytes_set
+         //needs to be decremented
+         sequence->number_data_bytes_set--;
+      }
+   }
+
+   return page_length;
+}
+
+/**
+ * @brief This method performs the control mode page specific data
+ *        translation based upon the contents of the remote device
+ *        IDENTIFY DEVICE data.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @param[in] identify This parameter specifies the remote device's
+ *            IDENTIFY DEVICE data received as part of the IO request.
+ * @param[in] offset This parameter specifies the offset into the data
+ *            buffer where the translated data is to be written.
+ *
+ * @return This method returns the size of the mode page data that was
+ *         translated.
+ */
+U32 sati_mode_sense_control_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   ATA_IDENTIFY_DEVICE_DATA_T * identify,
+   U32                          offset
+)
+{
+   U8 * cdb          = sati_cb_get_cdb_address(scsi_io);
+   U8   page_control = sati_get_cdb_byte(cdb, 2) >> SCSI_MODE_SENSE_PC_SHIFT;
+   U32  page_length;
+   U8   value;
+
+   page_length = sati_mode_sense_copy_initial_data(
+                    sequence,
+                    scsi_io,
+                    offset,
+                    page_control,
+                    SCSI_MODE_PAGE_CONTROL
+                 );
+
+   if (sequence->device->descriptor_sense_enable)
+   {
+       sati_get_data_byte(sequence, scsi_io, offset+2,
+               &value);
+
+       sati_set_data_byte(sequence, scsi_io, offset+2,
+               value | SCSI_MODE_SELECT_MODE_PAGE_D_SENSE);
+   }
+
+   return page_length;
+}
+
+/**
+ * @brief This method performs the informational exceptions control mode
+ *        page specific data translation based upon the contents of the
+ *        remote device IDENTIFY DEVICE data.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @param[in] identify This parameter specifies the remote device's
+ *            IDENTIFY DEVICE data received as part of the IO request.
+ * @param[in] offset This parameter specifies the offset into the data
+ *            buffer where the translated data is to be written.
+ *
+ * @return This method returns the size of the mode page data that was
+ *         translated.
+ */
+U32 sati_mode_sense_informational_excp_control_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   ATA_IDENTIFY_DEVICE_DATA_T * identify,
+   U32                          offset
+)
+{
+   U8 * cdb          = sati_cb_get_cdb_address(scsi_io);
+   U8   page_control = sati_get_cdb_byte(cdb, 2) >> SCSI_MODE_SENSE_PC_SHIFT;
+   U32  page_length;
+
+   page_length = sati_mode_sense_copy_initial_data(
+                    sequence,
+                    scsi_io,
+                    offset,
+                    page_control,
+                    SCSI_MODE_PAGE_INFORMATIONAL_EXCP_CONTROL
+                 );
+
+   // If the request queried for the current values, then
+   // we need to translate the data from the IDENTIFY DEVICE request.
+   if (page_control == SCSI_MODE_SENSE_PC_CURRENT)
+   {
+      U8 value;
+
+      sati_get_data_byte(sequence, scsi_io, offset+2, &value);
+
+      // Determine if the SMART feature set is supported and enabled.
+      if (  (identify->command_set_supported0
+                & ATA_IDENTIFY_COMMAND_SET_SUPPORTED0_SMART_ENABLE)
+         && (identify->command_set_enabled0
+                & ATA_IDENTIFY_COMMAND_SET_ENABLED0_SMART_ENABLE) )
+      {
+         // Clear the DXCPT field since the SMART feature is supported/enabled.
+         value &= ~SCSI_MODE_PAGE_INFORMATIONAL_EXCP_DXCPT_ENABLE;
+      }
+      else
+      {
+         // Set the Disable Exception Control (DXCPT) field since the SMART
+         // feature is not supported or enabled.
+         value |= SCSI_MODE_PAGE_INFORMATIONAL_EXCP_DXCPT_ENABLE;
+      }
+
+      sati_set_data_byte(sequence, scsi_io, offset+2, value);
+
+      //This byte has been set twice, the first time in
+      //sati_mode_sense_copy_initial_data. number_data_bytes_set
+      //needs to be decremented
+      sequence->number_data_bytes_set--;
+   }
+
+   return page_length;
+}
+
+/**
+* @brief This method performs the Power Condition mode page
+*        specific data translation based upon the contents of the
+*        remote device IDENTIFY DEVICE data.
+*        For more information on the parameters passed to this method,
+*        please reference sati_translate_command().
+*
+* @param[in] identify This parameter specifies the remote device's
+*            IDENTIFY DEVICE data received as part of the IO request.
+* @param[in] offset This parameter specifies the offset into the data
+*            buffer where the translated data is to be written.
+*
+* @return This method returns the size of the mode page data that was
+*         translated.
+*/
+U32 sati_mode_sense_power_condition_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   ATA_IDENTIFY_DEVICE_DATA_T * identify,
+   U32                          offset
+)
+{
+   U8 * cdb          = sati_cb_get_cdb_address(scsi_io);
+   U8   page_control = sati_get_cdb_byte(cdb, 2) >> SCSI_MODE_SENSE_PC_SHIFT;
+
+   U8 ata_sb_timer;
+
+   //Represents tenths of seconds
+   U32 standby_timer = 0x00000000;
+
+   U8 standby_enabled = STANDBY_TIMER_DISABLED;
+
+   if ((page_control == SCSI_MODE_SENSE_PC_CURRENT) &&
+       (identify->capabilities1 & STANDBY_TIMER_SUPPORTED))
+   {
+      standby_enabled = STANDBY_TIMER_ENABLED;
+
+      ata_sb_timer = sequence->device->ata_standby_timer;
+
+      //converting ATA timer values into SCSI timer values
+      if(ata_sb_timer <= 0xF0)
+      {
+         standby_timer = ata_sb_timer * 50;
+      }
+      else if(ata_sb_timer <= 0xFB)
+      {
+         standby_timer = ((ata_sb_timer - 240) * 18000);
+      }
+      else if(ata_sb_timer == 0xFC)
+      {
+         standby_timer = 12600;
+      }
+      else if(ata_sb_timer == 0xFD)
+      {
+         standby_timer = 432000;
+      }
+      else if(ata_sb_timer == 0xFF)
+      {
+         standby_timer = 12750;
+      }
+      else
+      {
+         standby_timer = 0xFFFFFFFF;
+      }
+   }
+
+   sati_set_data_byte(sequence, scsi_io, offset, SCSI_MODE_PAGE_POWER_CONDITION);
+   sati_set_data_byte(sequence, scsi_io, offset + 1, (SCSI_MODE_PAGE_1A_LENGTH - 2));
+   sati_set_data_byte(sequence, scsi_io, offset + 2, 0x00);
+   sati_set_data_byte(sequence, scsi_io, offset + 3, standby_enabled);
+   sati_set_data_byte(sequence, scsi_io, offset + 4, 0x00);
+   sati_set_data_byte(sequence, scsi_io, offset + 5, 0x00);
+   sati_set_data_byte(sequence, scsi_io, offset + 6, 0x00);
+   sati_set_data_byte(sequence, scsi_io, offset + 7, 0x00);
+   sati_set_data_byte(sequence, scsi_io, offset + 8, (U8) (standby_timer >> 24));
+   sati_set_data_byte(sequence, scsi_io, offset + 9, (U8) (standby_timer >> 16));
+   sati_set_data_byte(sequence, scsi_io, offset + 10, (U8) (standby_timer >> 8));
+   sati_set_data_byte(sequence, scsi_io, offset + 11, (U8) standby_timer);
+
+   return SCSI_MODE_PAGE_1A_LENGTH;
+}
+
+/**
+ * @brief This method performs the all pages mode page specific data
+ *        translation based upon the contents of the remote device
+ *        IDENTIFY DEVICE data.  The ALL PAGES mode sense request asks
+ *        for all of mode pages and sub-pages in a single page.
+ *        The mode pages are added in ascending order.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @param[in] identify This parameter specifies the remote device's
+ *            IDENTIFY DEVICE data received as part of the IO request.
+ * @param[in] offset This parameter specifies the offset into the data
+ *            buffer where the translated data is to be written.
+ *
+ * @return This method returns the size of the mode page data that was
+ *         translated.
+ */
+U32 sati_mode_sense_all_pages_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   ATA_IDENTIFY_DEVICE_DATA_T * identify,
+   U32                          offset
+)
+{
+   offset += sati_mode_sense_read_write_error_translate_data(
+                sequence, scsi_io, identify, offset
+             );
+
+   offset += sati_mode_sense_disconnect_reconnect_translate_data(
+                sequence, scsi_io, identify, offset
+             );
+
+   offset += sati_mode_sense_caching_translate_data(
+                sequence, scsi_io, identify, offset
+             );
+
+   offset += sati_mode_sense_control_translate_data(
+                sequence, scsi_io, identify, offset
+             );
+
+   offset += sati_mode_sense_informational_excp_control_translate_data(
+                sequence, scsi_io, identify, offset
+             );
+
+   return offset;
+}
+
+#endif // !defined(DISABLE_SATI_MODE_SENSE)
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_mode_sense.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_mode_sense.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,146 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_MODE_SENSE_H_
+#define _SATI_MODE_SENSE_H_
+
+/**
+ * @file
+ * @brief This file contains the method declarations and type defintions
+ *        common to translations of the SCSI mode sense (6 and 10-byte)
+ *        commands.
+ */
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+#include <dev/isci/scil/intel_ata.h>
+
+U16 sati_mode_sense_calculate_page_header(
+   void * scsi_io,
+   U8     cdb_size
+);
+
+SATI_STATUS sati_mode_sense_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io,
+   U8                           cdb_length
+);
+
+U32 sati_mode_sense_build_std_block_descriptor(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   ATA_IDENTIFY_DEVICE_DATA_T * identify,
+   U32                          offset
+);
+
+U32 sati_mode_sense_copy_initial_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   U32                          page_start,
+   U8                           page_control,
+   U8                           page_code
+);
+
+U32 sati_mode_sense_caching_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   ATA_IDENTIFY_DEVICE_DATA_T * identify,
+   U32                          offset
+);
+
+U32 sati_mode_sense_informational_excp_control_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   ATA_IDENTIFY_DEVICE_DATA_T * identify,
+   U32                          offset
+);
+
+U32 sati_mode_sense_all_pages_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   ATA_IDENTIFY_DEVICE_DATA_T * identify,
+   U32                          offset
+);
+
+U32 sati_mode_sense_read_write_error_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   ATA_IDENTIFY_DEVICE_DATA_T * identify,
+   U32                          offset
+);
+
+U32 sati_mode_sense_control_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   ATA_IDENTIFY_DEVICE_DATA_T * identify,
+   U32                          offset
+);
+
+U32 sati_mode_sense_disconnect_reconnect_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   ATA_IDENTIFY_DEVICE_DATA_T * identify,
+   U32                          offset
+);
+
+U32 sati_mode_sense_power_condition_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   ATA_IDENTIFY_DEVICE_DATA_T * identify,
+   U32                          offset
+);
+
+
+#endif // _SATI_MODE_SENSE_H_
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_mode_sense_10.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_mode_sense_10.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,509 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ *        translate the SCSI mode sense 10-byte commands.
+ */
+
+#if !defined(DISABLE_SATI_MODE_SENSE)
+
+#include <dev/isci/scil/sati_mode_sense.h>
+#include <dev/isci/scil/sati_mode_sense_10.h>
+#include <dev/isci/scil/sati_mode_pages.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/intel_scsi.h>
+#include <dev/isci/scil/intel_ata.h>
+
+//******************************************************************************
+//* P R I V A T E   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method builds the mode parameter header for a 10-byte SCSI
+ *        mode sense data response.  The parameter header is 4 bytes in
+ *        size.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @param[in] identify This parameter specifies the ATA remote device's
+ *            received IDENTIFY DEVICE data.
+ * @param[in] mode_data_length This parameter specifies the amount of data
+ *            to be returned as part of this mode sense request.
+ *
+ * @return This method returns the number of bytes written into the
+ *         mode sense data buffer.
+ */
+static
+U32 sati_mode_sense_10_build_header(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   ATA_IDENTIFY_DEVICE_DATA_T * identify,
+   U16                          mode_data_length
+)
+{
+   U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+   // Fill in the length of the mode parameter data returned (do not include
+   // the size of the mode data length field in the total).  Adjust the
+   // mode data length to not include the mode data length fields itself
+   // (i.e. subtract 2).
+   mode_data_length -= 2;
+   sati_set_data_byte(sequence, scsi_io, 0, (U8)(mode_data_length >> 8) & 0xFF);
+   sati_set_data_byte(sequence, scsi_io, 1, (U8)(mode_data_length & 0xFF));
+
+   // Medium Type is 0 for SBC devices
+   sati_set_data_byte(sequence, scsi_io, 2, SCSI_MODE_HEADER_MEDIUM_TYPE_SBC);
+
+   // Write Protect (WP), Rsvd, DPOFUA, Rsvd
+   if (sequence->device->capabilities & SATI_DEVICE_CAP_DMA_FUA_ENABLE)
+      sati_set_data_byte(sequence,scsi_io,3,SCSI_MODE_SENSE_HEADER_FUA_ENABLE);
+   else
+      sati_set_data_byte(sequence, scsi_io, 3, 0);
+
+   // Set the reserved bytes to 0.  The LONGLBA field in byte 4 is overridden
+   // later in this method if LLBAA is enabled.
+   sati_set_data_byte(sequence, scsi_io, 4, 0);
+   sati_set_data_byte(sequence, scsi_io, 5, 0);
+
+   // The MSB for the block descriptor length is never used since the
+   // largest block descriptor in this translator is 16-bytes in size.
+   sati_set_data_byte(sequence, scsi_io, 6, 0);
+
+   // Set the LSB block descriptor length if block descriptors are utilized.
+   if (sati_get_cdb_byte(cdb, 1) & SCSI_MODE_SENSE_DBD_ENABLE)
+      sati_set_data_byte(sequence, scsi_io, 7, 0);
+   else
+   {
+      // If Long Logical Block Address are allowed, then the block descriptor
+      // is larger (16 bytes total).
+      if (sati_get_cdb_byte(cdb, 1) & SCSI_MODE_SENSE_LLBAA_ENABLE)
+      {
+         sati_set_data_byte(sequence, scsi_io, 4, 1);
+         sati_set_data_byte(
+            sequence, scsi_io, 7, SCSI_MODE_SENSE_LLBA_BLOCK_DESCRIPTOR_LENGTH
+         );
+      }
+      else
+      {
+         sati_set_data_byte(
+            sequence, scsi_io, 7, SCSI_MODE_SENSE_STD_BLOCK_DESCRIPTOR_LENGTH
+         );
+      }
+   }
+
+   return SCSI_MODE_SENSE_10_HEADER_LENGTH;
+}
+
+static
+U32 sati_mode_sense_10_build_llba_block_descriptor(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   ATA_IDENTIFY_DEVICE_DATA_T * identify,
+   U32                          offset
+)
+{
+   U32  lba_low     = 0;
+   U32  lba_high    = 0;
+   U32  sector_size = 0;
+
+   // Extract the sector information (sector size, logical blocks) from
+   // the retrieved ATA identify device data.
+   sati_ata_identify_device_get_sector_info(
+      identify, &lba_low, &lba_high, &sector_size
+   );
+
+   // Fill in the 8-byte logical block area
+   sati_set_data_byte(sequence, scsi_io, offset,   (U8)((lba_high>>24) & 0xFF));
+   sati_set_data_byte(sequence, scsi_io, offset+1, (U8)((lba_high>>16) & 0xFF));
+   sati_set_data_byte(sequence, scsi_io, offset+2, (U8)((lba_high>>8)  & 0xFF));
+   sati_set_data_byte(sequence, scsi_io, offset+3, (U8)(lba_high & 0xFF));
+   sati_set_data_byte(sequence, scsi_io, offset+4, (U8)((lba_low>>24) & 0xFF));
+   sati_set_data_byte(sequence, scsi_io, offset+5, (U8)((lba_low>>16) & 0xFF));
+   sati_set_data_byte(sequence, scsi_io, offset+6, (U8)((lba_low>>8)  & 0xFF));
+   sati_set_data_byte(sequence, scsi_io, offset+7, (U8)(lba_low & 0xFF));
+
+   // Clear the reserved fields.
+   sati_set_data_byte(sequence, scsi_io, offset+8, 0);
+   sati_set_data_byte(sequence, scsi_io, offset+9, 0);
+   sati_set_data_byte(sequence, scsi_io, offset+10, 0);
+   sati_set_data_byte(sequence, scsi_io, offset+11, 0);
+
+   // Fill in the four byte Block Length field
+   sati_set_data_byte(sequence,scsi_io, offset+12, (U8)((sector_size>>24) & 0xFF));
+   sati_set_data_byte(sequence,scsi_io, offset+13, (U8)((sector_size>>16) & 0xFF));
+   sati_set_data_byte(sequence,scsi_io, offset+14, (U8)((sector_size>>8)  & 0xFF));
+   sati_set_data_byte(sequence,scsi_io, offset+15, (U8)(sector_size & 0xFF));
+
+   return SCSI_MODE_SENSE_LLBA_BLOCK_DESCRIPTOR_LENGTH;
+}
+
+/**
+ * @brief This method perform the data translation common to all SCSI MODE
+ *        SENSE 10 byte commands.  This includes building the mode page
+ *        header and block descriptor (if requested).
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @param[in] identify This parameter specifies the remote device's IDENTIFY
+ *            DEVICE data to be used during translation.
+ * @param[in] transfer_length This parameter specifies the size of the
+ *            mode page (including header & block descriptor).
+ *
+ * @return This method returns the number of bytes written into the user's
+ *         mode page data buffer.
+ */
+static
+U32 sati_mode_sense_10_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   ATA_IDENTIFY_DEVICE_DATA_T * identify,
+   void                       * scsi_io,
+   U16                          transfer_length
+)
+{
+   U8  * cdb = sati_cb_get_cdb_address(scsi_io);
+   U32   offset;
+
+   offset = sati_mode_sense_10_build_header(
+               sequence, scsi_io, identify, transfer_length
+            );
+
+   // Determine if the caller disabled block descriptors (DBD).  If not,
+   // then generate a block descriptor.
+   if ((sati_get_cdb_byte(cdb, 1) & SCSI_MODE_SENSE_DBD_ENABLE) == 0)
+   {
+      // If the user requested the Long LBA format descriptor, then build
+      // it
+      if (sati_get_cdb_byte(cdb, 1) & SCSI_MODE_SENSE_LLBAA_ENABLE)
+         offset += sati_mode_sense_10_build_llba_block_descriptor(
+                      sequence, scsi_io, identify, offset
+                   );
+      else
+         offset += sati_mode_sense_build_std_block_descriptor(
+                      sequence, scsi_io, identify, offset
+                   );
+   }
+
+   return offset;
+}
+
+//******************************************************************************
+//* P R O T E C T E D   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method will translate the SCSI mode sense 6 byte command
+ *        into corresponding ATA commands.  If the command is well-formed,
+ *        then the translation will result in an ATA IDENTIFY DEVICE
+ *        command.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the command translation was
+ *         successful.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
+ *         sense data has been created as a result of something specified
+ *         in the CDB.
+ */
+SATI_STATUS sati_mode_sense_10_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+   sequence->command_specific_data.scratch = 0;
+
+   // Set the data length based on the allocation length field in the CDB.
+   sequence->allocation_length = (sati_get_cdb_byte(cdb, 7) << 8) |
+                                 (sati_get_cdb_byte(cdb, 8));
+
+   return sati_mode_sense_translate_command(sequence, scsi_io, ata_io, 10);
+}
+
+/**
+ * @brief This method will perform data translation from the supplied ATA
+ *        input data (i.e. an ATA IDENTIFY DEVICE block) into a CACHING
+ *        mode page format.  The data will be written into the user's mode
+ *        page data buffer.  This function operates specifically for MODE
+ *        SENSE 10 commands.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_data().
+ *
+ * @return none.
+ */
+void sati_mode_sense_10_caching_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+)
+{
+   ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
+                                           ata_input_data;
+   U16   data_length = sati_mode_sense_calculate_page_header(scsi_io, 10)
+                       + SCSI_MODE_PAGE_08_LENGTH;
+   U32   page_offset = sati_mode_sense_10_translate_data(
+                          sequence, identify, scsi_io, data_length
+                       );
+
+   sati_mode_sense_caching_translate_data(
+      sequence, scsi_io, identify, page_offset
+   );
+}
+
+/**
+ * @brief This method will perform data translation from the supplied ATA
+ *        input data (i.e. an ATA IDENTIFY DEVICE block) into a INFORMATIONAL
+ *        EXCEPTIONS CONTROL mode page format.  The data will be written
+ *        into the user's mode page data buffer.  This function operates
+ *        specifically for MODE SENSE 10 commands.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_data().
+ *
+ * @return none.
+ */
+void sati_mode_sense_10_informational_excp_control_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+)
+{
+   ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
+                                           ata_input_data;
+   U16   data_length  = sati_mode_sense_calculate_page_header(scsi_io, 10)
+                        + SCSI_MODE_PAGE_1C_LENGTH;
+   U32   page_offset  = sati_mode_sense_10_translate_data(
+                           sequence, identify, scsi_io, data_length
+                        );
+
+   sati_mode_sense_informational_excp_control_translate_data(
+      sequence, scsi_io, identify, page_offset
+   );
+}
+
+/**
+* @brief This method will perform data translation from the supplied ATA
+*        input data (i.e. an ATA IDENTIFY DEVICE block) into a Read Write Error
+*         mode page format.  The data will be written
+*        into the user's mode page data buffer.  This function operates
+*        specifically for MODE SENSE 10 commands.
+*        For more information on the parameters passed to this method,
+*        please reference sati_translate_data().
+*
+* @return none.
+*/
+void sati_mode_sense_10_read_write_error_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+)
+{
+   ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
+      ata_input_data;
+
+   U16   data_length  = sati_mode_sense_calculate_page_header(scsi_io, 10)
+      + SCSI_MODE_PAGE_01_LENGTH;
+
+   U32   page_offset  = sati_mode_sense_10_translate_data(
+                           sequence, identify, scsi_io, data_length
+                        );
+
+   sati_mode_sense_read_write_error_translate_data(
+      sequence, scsi_io, identify, page_offset
+   );
+}
+
+/**
+* @brief This method will perform data translation from the supplied ATA
+*        input data (i.e. an ATA IDENTIFY DEVICE block) into a Disconnect
+*        Reconnect mode page format.  The data will be written
+*        into the user's mode page data buffer.  This function operates
+*        specifically for MODE SENSE 10 commands.
+*        For more information on the parameters passed to this method,
+*        please reference sati_translate_data().
+*
+* @return none.
+*/
+void sati_mode_sense_10_disconnect_reconnect_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+)
+{
+   ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
+      ata_input_data;
+
+   U8   data_length = (U8) sati_mode_sense_calculate_page_header(scsi_io, 10)
+      + SCSI_MODE_PAGE_02_LENGTH;
+
+   U32  page_offset = sati_mode_sense_10_translate_data(
+                        sequence, identify, scsi_io, data_length
+                      );
+
+   sati_mode_sense_disconnect_reconnect_translate_data(
+      sequence, scsi_io, identify, page_offset
+   );
+}
+
+/**
+* @brief This method will perform data translation from the supplied ATA
+*        input data (i.e. an ATA IDENTIFY DEVICE block) into a Control
+*         mode page format.  The data will be written
+*        into the user's mode page data buffer.  This function operates
+*        specifically for MODE SENSE 10 commands.
+*        For more information on the parameters passed to this method,
+*        please reference sati_translate_data().
+*
+* @return none.
+*/
+void sati_mode_sense_10_control_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+)
+{
+   ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
+      ata_input_data;
+
+   U8   data_length = (U8) sati_mode_sense_calculate_page_header(scsi_io, 10)
+      + SCSI_MODE_PAGE_0A_LENGTH;
+
+   U32  page_offset = sati_mode_sense_10_translate_data(
+                         sequence, identify, scsi_io, data_length
+                      );
+
+   sati_mode_sense_control_translate_data(
+      sequence, scsi_io, identify, page_offset
+   );
+}
+
+/**
+* @brief This method will perform data translation from the supplied ATA
+*        input data (i.e. an ATA IDENTIFY DEVICE block) into a Power
+*        Condition mode page format.  The data will be written
+*        into the user's mode page data buffer.  This function operates
+*        specifically for MODE SENSE 10 commands.
+*        For more information on the parameters passed to this method,
+*        please reference sati_translate_data().
+*
+* @return none.
+*/
+void sati_mode_sense_10_power_condition_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+)
+{
+   ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
+      ata_input_data;
+
+   U8 data_length;
+   U32  page_offset;
+
+   data_length = (U8) sati_mode_sense_calculate_page_header(scsi_io, 10)
+      + SCSI_MODE_PAGE_1A_LENGTH;
+
+   page_offset = sati_mode_sense_10_translate_data(
+      sequence, identify, scsi_io, data_length
+   );
+
+   sati_mode_sense_power_condition_translate_data(
+      sequence, scsi_io, identify, page_offset
+   );
+}
+
+
+/**
+ * @brief This method will perform data translation from the supplied ATA
+ *        input data (i.e. an ATA IDENTIFY DEVICE block) into an ALL
+ *        PAGES mode page format.  The ALL PAGES mode page is basically a
+ *        conglomeration of all mode pages and sub-pages into a single
+ *        page.  The data will be written into the user's mode page
+ *        data buffer.  This function operates specifically for MODE
+ *        SENSE 10 commands.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_data().
+ *
+ * @return none.
+ */
+void sati_mode_sense_10_all_pages_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+)
+{
+   ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
+                                           ata_input_data;
+   U8   data_length = (U8) sati_mode_sense_calculate_page_header(scsi_io, 10)
+                           + SCSI_MODE_PAGE_01_LENGTH
+                           + SCSI_MODE_PAGE_02_LENGTH
+                           + SCSI_MODE_PAGE_08_LENGTH
+                           + SCSI_MODE_PAGE_0A_LENGTH
+                           + SCSI_MODE_PAGE_1C_LENGTH;
+   U32  page_offset = sati_mode_sense_10_translate_data(
+                         sequence, identify, scsi_io, data_length
+                      );
+
+   sati_mode_sense_all_pages_translate_data(
+      sequence, scsi_io, identify, page_offset
+   );
+}
+
+#endif // !defined(DISABLE_SATI_MODE_SENSE)
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_mode_sense_10.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_mode_sense_10.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,114 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_MODE_SENSE_10_H_
+#define _SATI_MODE_SENSE_10_H_
+
+/**
+ * @file
+ * @brief This file contains the method prototypes required to
+ *        translate the SCSI mode sense 10-byte commands.
+ */
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+SATI_STATUS sati_mode_sense_10_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+void sati_mode_sense_10_caching_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+);
+
+void sati_mode_sense_10_informational_excp_control_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+);
+
+void sati_mode_sense_10_read_write_error_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+);
+
+void sati_mode_sense_10_disconnect_reconnect_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+);
+
+void sati_mode_sense_10_control_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+);
+
+void sati_mode_sense_10_power_condition_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+);
+
+void sati_mode_sense_10_all_pages_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+);
+
+#endif // _SATI_MODE_SENSE_10_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_mode_sense_6.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_mode_sense_6.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,429 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ *        translate the SCSI mode sense 6-byte commands.
+ */
+
+#if !defined(DISABLE_SATI_MODE_SENSE)
+
+#include <dev/isci/scil/sati_mode_sense.h>
+#include <dev/isci/scil/sati_mode_sense_6.h>
+#include <dev/isci/scil/sati_mode_pages.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/intel_scsi.h>
+#include <dev/isci/scil/intel_ata.h>
+
+//******************************************************************************
+//* P R I V A T E   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method builds the mode parameter header for a 6-byte SCSI
+ *        mode sense data response.  The parameter header is 4 bytes in
+ *        size.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @param[in] identify This parameter specifies the ATA remote device's
+ *            received IDENTIFY DEVICE data.
+ * @param[in] mode_data_length This parameter specifies the amount of data
+ *            to be returned as part of this mode sense request.
+ *
+ * @return This method returns the number of bytes written into the
+ *         data buffer.
+ */
+static
+U32 sati_mode_sense_6_build_header(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   ATA_IDENTIFY_DEVICE_DATA_T * identify,
+   U8                           mode_data_length
+)
+{
+   U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+   // Fill in the length of the mode parameter data returned (do not include
+   // the size of the mode data length field in the total).
+   sati_set_data_byte(sequence, scsi_io, 0, (U8)mode_data_length-1);
+
+   // Medium Type is 0 for SBC devices
+   sati_set_data_byte(sequence, scsi_io, 1, SCSI_MODE_HEADER_MEDIUM_TYPE_SBC);
+
+   // Write Protect (WP), Rsvd, DPOFUA, Rsvd
+   if (sequence->device->capabilities & SATI_DEVICE_CAP_DMA_FUA_ENABLE)
+      sati_set_data_byte(sequence,scsi_io,2,SCSI_MODE_SENSE_HEADER_FUA_ENABLE);
+   else
+      sati_set_data_byte(sequence, scsi_io, 2, 0);
+
+   // Set the block descriptor length if block descriptors are utilized.
+   if (sati_get_cdb_byte(cdb, 1) & SCSI_MODE_SENSE_DBD_ENABLE)
+      sati_set_data_byte(sequence, scsi_io, 3, 0);
+   else
+      sati_set_data_byte(
+         sequence, scsi_io, 3, SCSI_MODE_SENSE_STD_BLOCK_DESCRIPTOR_LENGTH
+      );
+
+   return SCSI_MODE_SENSE_6_HEADER_LENGTH;
+}
+
+/**
+ * @brief This method perform the data translation common to all SCSI MODE
+ *        SENSE 6 byte commands.  This includes building the mode page
+ *        header and block descriptor (if requested).
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @param[in] identify This parameter specifies the remote device's IDENTIFY
+ *            DEVICE data to be used during translation.
+ * @param[in] transfer_length This parameter specifies the size of the
+ *            mode page (including header & block descriptor).
+ *
+ * @return This method returns the number of bytes written into the user's
+ *         mode page data buffer.
+ */
+static
+U32 sati_mode_sense_6_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   ATA_IDENTIFY_DEVICE_DATA_T * identify,
+   void                       * scsi_io,
+   U8                           transfer_length
+)
+{
+   U8  * cdb = sati_cb_get_cdb_address(scsi_io);
+   U32   offset;
+
+   offset = sati_mode_sense_6_build_header(
+               sequence, scsi_io, identify, transfer_length
+            );
+
+   // Determine if the caller disabled block descriptors (DBD).  If not,
+   // then generate a block descriptor.
+   if ((sati_get_cdb_byte(cdb, 1) & SCSI_MODE_SENSE_DBD_ENABLE) == 0)
+      offset += sati_mode_sense_build_std_block_descriptor(
+                   sequence, scsi_io, identify, offset
+                );
+
+   return offset;
+}
+
+//******************************************************************************
+//* P R O T E C T E D   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method will translate the SCSI mode sense 6 byte command
+ *        into corresponding ATA commands.  If the command is well-formed,
+ *        then the translation will result in an ATA IDENTIFY DEVICE
+ *        command.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the command translation was
+ *         successful.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
+ *         sense data has been created as a result of something specified
+ *         in the CDB.
+ */
+SATI_STATUS sati_mode_sense_6_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+   // Set the data length based on the allocation length field in the CDB.
+   sequence->allocation_length = sati_get_cdb_byte(cdb, 4);
+
+   return sati_mode_sense_translate_command(sequence, scsi_io, ata_io, 6);
+}
+
+/**
+ * @brief This method will perform data translation from the supplied ATA
+ *        input data (i.e. an ATA IDENTIFY DEVICE block) into a CACHING
+ *        mode page format.  The data will be written into the user's mode
+ *        page data buffer.  This function operates specifically for MODE
+ *        SENSE 6 commands.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_data().
+ *
+ * @return none.
+ */
+void sati_mode_sense_6_caching_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+)
+{
+   ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
+                                           ata_input_data;
+   U8   data_length = (U8) sati_mode_sense_calculate_page_header(scsi_io, 6)
+                           + SCSI_MODE_PAGE_08_LENGTH;
+   U32  page_offset = sati_mode_sense_6_translate_data(
+                         sequence, identify, scsi_io, data_length
+                      );
+
+   sati_mode_sense_caching_translate_data(
+      sequence, scsi_io, identify, page_offset
+   );
+}
+
+/**
+ * @brief This method will perform data translation from the supplied ATA
+ *        input data (i.e. an ATA IDENTIFY DEVICE block) into a INFORMATIONAL
+ *        EXCEPTIONS CONTROL mode page format.  The data will be written
+ *        into the user's mode page data buffer.  This function operates
+ *        specifically for MODE SENSE 6 commands.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_data().
+ *
+ * @return none.
+ */
+void sati_mode_sense_6_informational_excp_control_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+)
+{
+   ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
+                                           ata_input_data;
+   U8   data_length = (U8) sati_mode_sense_calculate_page_header(scsi_io, 6)
+                           + SCSI_MODE_PAGE_1C_LENGTH;
+   U32  page_offset = sati_mode_sense_6_translate_data(
+                         sequence, identify, scsi_io, data_length
+                      );
+
+   sati_mode_sense_informational_excp_control_translate_data(
+      sequence, scsi_io, identify, page_offset
+   );
+}
+
+/**
+* @brief This method will perform data translation from the supplied ATA
+*        input data (i.e. an ATA IDENTIFY DEVICE block) into a DISCONNECT
+*        RECONNECT mode page format.  The data will be written
+*        into the user's mode page data buffer.  This function operates
+*        specifically for MODE SENSE 6 commands.
+*        For more information on the parameters passed to this method,
+*        please reference sati_translate_data().
+*
+* @return none.
+*/
+void sati_mode_sense_6_disconnect_reconnect_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+)
+{
+   ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
+      ata_input_data;
+
+   U8   data_length = (U8) sati_mode_sense_calculate_page_header(scsi_io, 6)
+      + SCSI_MODE_PAGE_02_LENGTH ;
+
+   U32  page_offset = sati_mode_sense_6_translate_data(
+                         sequence, identify, scsi_io, data_length
+                      );
+
+   sati_mode_sense_disconnect_reconnect_translate_data(
+      sequence, scsi_io, identify, page_offset
+   );
+}
+
+/**
+* @brief This method will perform data translation from the supplied ATA
+*        input data (i.e. an ATA IDENTIFY DEVICE block) into a READ WRITE ERROR
+*        mode page format.  The data will be written
+*        into the user's mode page data buffer.  This function operates
+*        specifically for MODE SENSE 6 commands.
+*        For more information on the parameters passed to this method,
+*        please reference sati_translate_data().
+*
+* @return none.
+*/
+void sati_mode_sense_6_read_write_error_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+)
+{
+   ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
+      ata_input_data;
+
+   U8   data_length = (U8) sati_mode_sense_calculate_page_header(scsi_io, 6)
+      + SCSI_MODE_PAGE_01_LENGTH;
+
+   U32  page_offset = sati_mode_sense_6_translate_data(
+                         sequence, identify, scsi_io, data_length
+                      );
+
+   sati_mode_sense_read_write_error_translate_data(
+      sequence, scsi_io, identify, page_offset
+   );
+}
+
+/**
+* @brief This method will perform data translation from the supplied ATA
+*        input data (i.e. an ATA IDENTIFY DEVICE block) into a CONTROL
+*        mode page format.  The data will be written
+*        into the user's mode page data buffer.  This function operates
+*        specifically for MODE SENSE 6 commands.
+*        For more information on the parameters passed to this method,
+*        please reference sati_translate_data().
+*
+* @return none.
+*/
+void sati_mode_sense_6_control_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+)
+{
+   ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
+      ata_input_data;
+
+   U8   data_length = (U8) sati_mode_sense_calculate_page_header(scsi_io, 6)
+      + SCSI_MODE_PAGE_0A_LENGTH;
+
+   U32  page_offset = sati_mode_sense_6_translate_data(
+                         sequence, identify, scsi_io, data_length
+                      );
+
+   sati_mode_sense_control_translate_data(
+      sequence, scsi_io, identify, page_offset
+   );
+}
+
+/**
+* @brief This method will perform data translation from the supplied ATA
+*        input data (i.e. an ATA IDENTIFY DEVICE block) into a Power
+*        Condition mode page format.  The data will be written
+*        into the user's mode page data buffer.  This function operates
+*        specifically for MODE SENSE 6 commands.
+*        For more information on the parameters passed to this method,
+*        please reference sati_translate_data().
+*
+* @return none.
+*/
+void sati_mode_sense_6_power_condition_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+)
+{
+   ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
+      ata_input_data;
+
+   U8 data_length;
+   U32  page_offset;
+
+   data_length = (U8) sati_mode_sense_calculate_page_header(scsi_io, 6)
+         + SCSI_MODE_PAGE_1A_LENGTH;
+
+   page_offset = sati_mode_sense_6_translate_data(
+         sequence, identify, scsi_io, data_length
+   );
+
+   sati_mode_sense_power_condition_translate_data(
+      sequence, scsi_io, identify, page_offset
+   );
+}
+
+
+
+/**
+ * @brief This method will perform data translation from the supplied ATA
+ *        input data (i.e. an ATA IDENTIFY DEVICE block) into an ALL
+ *        PAGES mode page format.  The ALL PAGES mode page is basically a
+ *        conglomeration of all mode pages and sub-pages into a single
+ *        page.  The data will be written into the user's mode page
+ *        data buffer.  This function operates specifically for MODE
+ *        SENSE 6 commands.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_data().
+ *
+ * @return none.
+ */
+void sati_mode_sense_6_all_pages_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+)
+{
+   ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
+                                           ata_input_data;
+   U8   data_length = (U8) sati_mode_sense_calculate_page_header(scsi_io, 6)
+                           + SCSI_MODE_PAGE_01_LENGTH
+                           + SCSI_MODE_PAGE_02_LENGTH
+                           + SCSI_MODE_PAGE_08_LENGTH
+                           + SCSI_MODE_PAGE_0A_LENGTH
+                           + SCSI_MODE_PAGE_1C_LENGTH;
+
+   U32  page_offset = sati_mode_sense_6_translate_data(
+                         sequence, identify, scsi_io, data_length
+                      );
+
+   sati_mode_sense_all_pages_translate_data(
+      sequence, scsi_io, identify, page_offset
+   );
+}
+
+#endif // !defined(DISABLE_SATI_MODE_SENSE)
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_mode_sense_6.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_mode_sense_6.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,114 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_MODE_SENSE_6_H_
+#define _SATI_MODE_SENSE_6_H_
+
+/**
+ * @file
+ * @brief This file contains the method prototypes required to
+ *        translate the SCSI mode sense 6-byte commands.
+ */
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+SATI_STATUS sati_mode_sense_6_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+void sati_mode_sense_6_caching_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+);
+
+void sati_mode_sense_6_informational_excp_control_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+);
+
+void sati_mode_sense_6_read_write_error_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+);
+
+void sati_mode_sense_6_disconnect_reconnect_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+);
+
+void sati_mode_sense_6_control_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+);
+
+void sati_mode_sense_6_power_condition_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+);
+
+void sati_mode_sense_6_all_pages_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+);
+
+#endif // _SATI_MODE_SENSE_6_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_move.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_move.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,616 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains the method implementations common to
+ *        translations that move data (i.e. read, write).  It has code for
+ *        the various different size CDBs (6, 10, 12, 16).
+ */
+
+#include <dev/isci/scil/sati_move.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_scsi.h>
+#include <dev/isci/scil/intel_sat.h>
+
+//******************************************************************************
+//* P R I V A T E   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method simply sets the command register based upon the
+ *        supplied opcodes and the data direction.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command()
+ *
+ * @param[in] write_opcode This parameter specifies the value to be written
+ *            to the ATA command register for a write (data out) operation.
+ * @param[in] read_opcode This parameter specifies the value to be written
+ *            to the ATA command register for a read (data in) operation.
+ *
+ * @return none.
+ */
+static
+void sati_move_set_ata_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_io,
+   U8                           write_opcode,
+   U8                           read_opcode
+)
+{
+   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+   if (sequence->data_direction == SATI_DATA_DIRECTION_OUT)
+      sati_set_ata_command(register_fis, write_opcode);
+   else
+      sati_set_ata_command(register_fis, read_opcode);
+}
+
+/**
+ * @brief This method will translate the SCSI transfer count from the 6-byte
+ *        CDB into the appropriate amount in the ATA register FIS.  Please
+ *        note for 48-bit UDMA requests, the caller must set the sector
+ *        count extended field.  This method also sets protocol and
+ *        command fields.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command()
+ *
+ * @param[in] write_opcode This parameter specifies the value to be written
+ *            to the ATA command register for a write (data out) operation.
+ * @param[in] read_opcode This parameter specifies the value to be written
+ *            to the ATA command register for a read (data in) operation.
+ *
+ * @return none
+ */
+static
+void sati_move_small_udma_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io,
+   U8                           write_opcode,
+   U8                           read_opcode
+)
+{
+   U8 * cdb          = sati_cb_get_cdb_address(scsi_io);
+   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+   sati_move_set_ata_command(sequence, ata_io, write_opcode, read_opcode);
+   sati_set_ata_sector_count(register_fis, sati_get_cdb_byte(cdb, 4));
+
+   if (sequence->data_direction == SATI_DATA_DIRECTION_IN)
+      sequence->protocol = SAT_PROTOCOL_UDMA_DATA_IN;
+   else
+      sequence->protocol = SAT_PROTOCOL_UDMA_DATA_OUT;
+}
+
+/**
+ * @brief This method will translate the SCSI transfer count from the
+ *        supplied sector_count parameter into the ATA register FIS.
+ *        The translation is specific to 10,12, 16 byte CDBs.
+ *        This method also sets protocol and command fields.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command()
+ *
+ * @param[in] sector_count This parameter specifies the number of sectors
+ *            to be transfered.
+ * @param[in] write_opcode This parameter specifies the value to be written
+ *            to the ATA command register for a write (data out) operation.
+ * @param[in] read_opcode This parameter specifies the value to be written
+ *            to the ATA command register for a read (data in) operation.
+ *
+ * @return Please reference sati_move_set_sector_count() for information
+ *         on return codes from this method.
+ */
+static
+SATI_STATUS sati_move_large_udma_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io,
+   U32                          sector_count,
+   U8                           write_opcode,
+   U8                           read_opcode
+)
+{
+   sati_move_set_ata_command(sequence, ata_io, write_opcode, read_opcode);
+
+   if (sequence->data_direction == SATI_DATA_DIRECTION_IN)
+      sequence->protocol = SAT_PROTOCOL_UDMA_DATA_IN;
+   else
+      sequence->protocol = SAT_PROTOCOL_UDMA_DATA_OUT;
+
+   return sati_move_set_sector_count(
+             sequence, scsi_io, ata_io, sector_count, FALSE
+          );
+}
+
+/**
+ * @brief This method will translate the SCSI transfer count from the 6-byte
+ *        CDB into the appropriate amount in the ATA register FIS.
+ *        This is only used for translation of 6-byte SCSI CDBs.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command()
+ *
+ * @return none
+ */
+static
+void sati_move_ncq_translate_8_bit_sector_count(
+   void * scsi_io,
+   void * ata_io
+)
+{
+   U8 * cdb          = sati_cb_get_cdb_address(scsi_io);
+   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+   sati_set_ata_features(register_fis, sati_get_cdb_byte(cdb, 4));
+
+   // A read 6 with a 0 sector count indicates a transfer of 256 sectors.
+   // As a result update the MSB (features expanded register) to indicate
+   // 256 sectors (0x100).
+   if (sati_get_cdb_byte(cdb, 4) == 0)
+      sati_set_ata_features_exp(register_fis, 1);
+}
+
+//******************************************************************************
+//* P U B L I C   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method will process a 32-bit sector into the appropriate fields
+ *        in a register FIS.  This method works for both 8-bit and 16-bit sector
+ *        counts.
+ *        This is used for translation of 10, 12, and 16-byte SCSI CDBs.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @note This method should only be called for CDB sizes of 10-bytes or larger.
+ *
+ * @param[in] sector_count This parameter specifies the number of sectors
+ *            to be transfered.
+ * @param[in] is_fpdma_command This parameter indicates if the supplied
+ *            ata_io is a first party DMA request (NCQ).
+ *
+ * @return none
+ */
+SATI_STATUS sati_move_set_sector_count(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io,
+   U32                          sector_count,
+   U8                           is_fpdma_command
+)
+{
+   U32  max_sector_count;
+   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+   if (sequence->device->capabilities & SATI_DEVICE_CAP_48BIT_ENABLE)
+      max_sector_count = 65536;
+   else
+      max_sector_count = 256;
+
+   // Check the CDB transfer length count and set the register FIS sector
+   // count fields
+   if (0 == sector_count)
+   {
+      // A SCSI sector count of 0 for 10-byte CDBs and larger indicate no data
+      // transfer, so simply complete the command immediately.
+      return SATI_COMPLETE;
+   }
+   else if (sector_count >= max_sector_count)
+   {
+      // We have to perform multiple SATA commands to satisfy the sector
+      // count specified in the SCSI command.
+      sequence->command_specific_data.move_sector_count =
+         sector_count - max_sector_count;
+
+      // In ATA a sector count of 0 indicates use the maximum allowed for
+      // the command (i.e. 0 == 2^16 or 2^8).
+      sector_count = 0;
+   }
+
+   if (is_fpdma_command)
+   {
+      sati_set_ata_features(register_fis, sector_count & 0xFF);
+      sati_set_ata_features_exp(register_fis, (sector_count >> 8) & 0xFF);
+   }
+   else
+   {
+      sati_set_ata_sector_count(register_fis, sector_count & 0xFF);
+      sati_set_ata_sector_count_exp(register_fis, (sector_count >> 8) & 0xFF);
+   }
+
+   return SATI_SUCCESS;
+}
+
+/**
+ * @brief This method simply translates the 32-bit logical block address
+ *        field from the SCSI CDB (10 or 12-byte) into the ATA task
+ *        file (register FIS).
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command()
+ *
+ * @return none
+ */
+void sati_move_translate_32_bit_lba(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   U8 * cdb          = sati_cb_get_cdb_address(scsi_io);
+   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+   sati_set_ata_lba_low(register_fis, sati_get_cdb_byte(cdb, 5));
+   sati_set_ata_lba_mid(register_fis, sati_get_cdb_byte(cdb, 4));
+   sati_set_ata_lba_high(register_fis, sati_get_cdb_byte(cdb, 3));
+   sati_set_ata_lba_low_exp(register_fis, sati_get_cdb_byte(cdb, 2));
+   sati_set_ata_lba_mid_exp(register_fis, 0);
+   sati_set_ata_lba_high_exp(register_fis, 0);
+}
+
+/**
+ * @brief This method simply translates the 64-bit logical block address
+ *        field from the SCSI CDB (16 byte) into the ATA task
+ *        file (register FIS).  The 2 most significant bytes must be 0,
+ *        since ATA devices can, at most, support 48-bits of LBA.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command()
+ *
+ * @return Indicate if the LBA translation succeeded.
+ * @return SATI_SUCCESS This is returned if translation was successful.
+ * @return SATI_FAILURE_CHECK_RESPONSE_DATA This is returned if either
+ *         of the 2 most significant bytes contain a non-zero value.
+ */
+SATI_STATUS sati_move_translate_64_bit_lba(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   U8 * cdb          = sati_cb_get_cdb_address(scsi_io);
+   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+   // Ensure we receive a logical block address that is within range of
+   // addressibility per the ATA specification (i.e. 48-bit or 28-bit).
+   if ( (sati_get_cdb_byte(cdb, 2) == 0) && (sati_get_cdb_byte(cdb, 3) == 0) )
+   {
+      sati_set_ata_lba_low(register_fis, sati_get_cdb_byte(cdb, 9));
+      sati_set_ata_lba_mid(register_fis, sati_get_cdb_byte(cdb, 8));
+      sati_set_ata_lba_high(register_fis, sati_get_cdb_byte(cdb, 7));
+      sati_set_ata_lba_low_exp(register_fis, sati_get_cdb_byte(cdb, 6));
+      sati_set_ata_lba_mid_exp(register_fis, sati_get_cdb_byte(cdb, 5));
+      sati_set_ata_lba_high_exp(register_fis, sati_get_cdb_byte(cdb, 4));
+      return SATI_SUCCESS;
+   }
+   else
+   {
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_ILLEGAL_REQUEST,
+         SCSI_ASC_LBA_OUT_OF_RANGE,
+         SCSI_ASCQ_LBA_OUT_OF_RANGE
+      );
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+}
+
+/**
+ * @brief This method will translate the pieces common to SCSI read and
+ *        write 6 byte commands.  Depending upon the capabilities
+ *        supported by the target different ATA commands can be selected.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the command translation was
+ *         successful.
+ */
+SATI_STATUS sati_move_6_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   U8 * cdb          = sati_cb_get_cdb_address(scsi_io);
+   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+   // Translate the logical block address information from the SCSI CDB.
+   // There is only 5 bits of MSB located in byte 1 of the CDB.
+   sati_set_ata_lba_low(register_fis, sati_get_cdb_byte(cdb, 3));
+   sati_set_ata_lba_mid(register_fis, sati_get_cdb_byte(cdb, 2));
+   sati_set_ata_lba_high(register_fis, sati_get_cdb_byte(cdb, 1) & 0x1F);
+
+   sati_move_translate_command(sequence, scsi_io, ata_io, 0);
+
+   return SATI_SUCCESS;
+}
+
+/**
+ * @brief This method will translate the pieces common to SCSI read and
+ *        write 10/12 byte commands.  Depending upon the capabilities
+ *        supported by the target different ATA commands can be selected.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @param[in] device_head This parameter specifies the contents to be
+ *            written to the device head register.
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the command translation was
+ *         successful.
+ */
+SATI_STATUS sati_move_32_bit_lba_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io,
+   U8                           device_head
+)
+{
+   sati_move_translate_32_bit_lba(sequence, scsi_io, ata_io);
+   sati_move_translate_command(sequence, scsi_io, ata_io, device_head);
+
+   return SATI_SUCCESS;
+}
+
+/**
+ * @brief This method provides the common translation functionality for
+ *        the 6-byte move command descriptor blocks (CDBs).
+ *        This method will ensure that the following is performed:
+ *        - command register is set
+ *        - the SATI_TRANSLATOR_SEQUENCE::protocol field is set
+ *        - the sector count field(s) are set
+ *        - sati_move_6_translate_command() is invoked.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @pre The caller must ensure that the
+ *      SATI_TRANSLATOR_SEQUENCE::data_direction field has already been set.
+ *
+ * @return Indicate if the command translation succeeded.
+ * @see sati_move_6_translate_command() for additional return codes.
+ */
+SATI_STATUS sati_move_small_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   // Translation of the sector count is performed differently for NCQ vs.
+   // other protocols.
+   if (sequence->device->capabilities & SATI_DEVICE_CAP_NCQ_SUPPORTED_ENABLE)
+   {
+      sati_move_set_ata_command(
+         sequence, ata_io, ATA_WRITE_FPDMA, ATA_READ_FPDMA
+      );
+      sati_move_ncq_translate_8_bit_sector_count(scsi_io, ata_io);
+      sequence->protocol = SAT_PROTOCOL_FPDMA;
+   }
+   else if (sequence->device->capabilities & SATI_DEVICE_CAP_48BIT_ENABLE)
+   {
+      U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+      sati_move_small_udma_translate_command(
+         sequence, scsi_io, ata_io, ATA_WRITE_DMA_EXT, ATA_READ_DMA_EXT
+      );
+
+      // A read/write 6 with a 0 sector count indicates a transfer of 256
+      // sectors.  As a result update the MSB (features expanded register)
+      // to indicate 256 sectors (0x100).
+      if (sati_get_cdb_byte(cdb, 4) == 0)
+      {
+         U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+         sati_set_ata_sector_count_exp(register_fis, 1);
+      }
+   }
+   else if (sequence->device->capabilities & SATI_DEVICE_CAP_UDMA_ENABLE)
+   {
+      sati_move_small_udma_translate_command(
+         sequence, scsi_io, ata_io, ATA_WRITE_DMA, ATA_READ_DMA
+      );
+   }
+   else
+   {
+      /**
+       * Currently the translation does not support devices incapable of
+       * handling the 48-bit feature set (i.e. 16 bits of sector count).
+       */
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_ILLEGAL_REQUEST,
+         SCSI_ASC_INVALID_FIELD_IN_CDB,
+         SCSI_ASCQ_INVALID_FIELD_IN_CDB
+      );
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+
+   return sati_move_6_translate_command(sequence, scsi_io, ata_io);
+}
+
+/**
+ * @brief This method provides the common translation functionality for
+ *        the larger command descriptor blocks (10, 12, 16-byte CDBs).
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @param[in] sector_count This parameter specifies the number of sectors
+ *            to be transfered.
+ * @param[in] device_head This parameter specifies the contents to be
+ *            written to the device head register.
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SATI_FAILURE This value is returned if neither NCQ or DMA is
+ *         supported by the target device.
+ * @see sati_move_set_sector_count() for additional return codes.
+ */
+SATI_STATUS sati_move_large_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io,
+   U32                          sector_count,
+   U8                         * ata_device_head
+)
+{
+   SATI_STATUS   status = SATI_SUCCESS;
+   U8          * cdb    = sati_cb_get_cdb_address(scsi_io);
+
+   // Parts of translation (e.g. sector count) is performed differently
+   // for NCQ vs. other protocols.
+   if (sequence->device->capabilities & SATI_DEVICE_CAP_NCQ_SUPPORTED_ENABLE)
+   {
+      // if the user did not request to ignore FUA
+      if((sequence->device->capabilities & SATI_DEVICE_CAP_IGNORE_FUA)==0)
+      {
+         // Is the Force Unit Access bit set?
+         if (sati_get_cdb_byte(cdb, 1) & SCSI_MOVE_FUA_BIT_ENABLE)
+            *ata_device_head = ATA_DEV_HEAD_REG_FUA_ENABLE;
+      }
+
+      sati_move_set_ata_command(
+         sequence, ata_io, ATA_WRITE_FPDMA, ATA_READ_FPDMA
+      );
+      status = sati_move_set_sector_count(
+                  sequence, scsi_io, ata_io, sector_count, TRUE
+               );
+      sequence->protocol = SAT_PROTOCOL_FPDMA;
+   }
+   else if (sequence->device->capabilities & SATI_DEVICE_CAP_48BIT_ENABLE)
+   {
+      // Is the Force Unit Access bit set?  If it is, then error.  We
+      // aren't supporting this yet for normal DMA.
+      if (sati_get_cdb_byte(cdb, 1) & SCSI_MOVE_FUA_BIT_ENABLE)
+      {
+         sati_scsi_sense_data_construct(
+            sequence,
+            scsi_io,
+            SCSI_STATUS_CHECK_CONDITION,
+            SCSI_SENSE_ILLEGAL_REQUEST,
+            SCSI_ASC_INVALID_FIELD_IN_CDB,
+            SCSI_ASCQ_INVALID_FIELD_IN_CDB
+         );
+         return SATI_FAILURE_CHECK_RESPONSE_DATA;
+      }
+
+      status = sati_move_large_udma_translate_command(
+                  sequence,
+                  scsi_io,
+                  ata_io,
+                  sector_count,
+                  ATA_WRITE_DMA_EXT,
+                  ATA_READ_DMA_EXT
+               );
+   }
+   else if (sequence->device->capabilities & SATI_DEVICE_CAP_UDMA_ENABLE)
+   {
+      status = sati_move_large_udma_translate_command(
+                  sequence,
+                  scsi_io,
+                  ata_io,
+                  sector_count,
+                  ATA_WRITE_DMA,
+                  ATA_READ_DMA
+               );
+   }
+   else
+   {
+      /**
+       * Currently the translation does not support devices incapable of
+       * handling the 48-bit feature set (i.e. 16 bits of sector count).
+       */
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_ILLEGAL_REQUEST,
+         SCSI_ASC_INVALID_FIELD_IN_CDB,
+         SCSI_ASCQ_INVALID_FIELD_IN_CDB
+      );
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+
+   return status;
+}
+
+/**
+ * @brief This method simply performs the functionality common to all
+ *        payload data movement translations (i.e. READ/WRITE).
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @param[in] device_head This parameter specifies the current contents
+ *            to be written to the ATA task file (register FIS) device
+ *            head register.
+ *
+ * @return none
+ */
+void sati_move_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io,
+   U8                           device_head
+)
+{
+   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+   sati_set_ata_device_head(
+      register_fis, device_head | ATA_DEV_HEAD_REG_LBA_MODE_ENABLE
+   );
+}
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_move.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_move.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,121 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_MOVE_H_
+#define _SATI_MOVE_H_
+
+/**
+ * @file
+ * @brief This file contains the method declarations and type definitions
+ *        common to translations that move data (i.e. read, write).  It
+ *        has code for the various different size CDBs (6, 10, 12, 16).
+ */
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+SATI_STATUS sati_move_set_sector_count(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io,
+   U32                          sector_count,
+   U8                           is_fpdma_command
+);
+
+void sati_move_translate_32_bit_lba(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+SATI_STATUS sati_move_translate_64_bit_lba(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+SATI_STATUS sati_move_6_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+SATI_STATUS sati_move_32_bit_lba_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io,
+   U8                           device_head
+);
+
+SATI_STATUS sati_move_small_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+SATI_STATUS sati_move_large_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io,
+   U32                          sector_count,
+   U8                         * ata_device_head
+);
+
+void sati_move_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io,
+   U8                           device_head
+);
+
+#endif // _SATI_MOVE_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_passthrough.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_passthrough.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,465 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ *        translate the SCSI passthru command.
+ */
+
+#if !defined(DISABLE_SATI_PASSTHROUGH)
+
+#include <dev/isci/scil/sati.h>
+#include <dev/isci/scil/sati_passthrough.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/intel_ata.h>
+
+#define PASSTHROUGH_CDB_PROTOCOL_MASK       0x1E
+#define PASSTHROUGH_CDB_EXTEND_MASK         0x1
+#define PASSTHROUGH_CDB_CK_COND_MASK        0x20
+#define PASSTHROUGH_CDB_T_DIR_MASK          0x8
+
+#define PASSTHROUGH_ISOLATE_BITS(cdb, index, mask, shift) (((sati_get_cdb_byte(cdb, index) & mask) >> shift))
+
+#define PASSTHROUGH_CDB_PROTOCOL(cdb)      PASSTHROUGH_ISOLATE_BITS(cdb, 1, PASSTHROUGH_CDB_PROTOCOL_MASK, 1)
+#define PASSTHROUGH_CDB_EXTEND(cdb)        PASSTHROUGH_ISOLATE_BITS(cdb, 1, PASSTHROUGH_CDB_EXTEND_MASK, 0)
+#define PASSTHROUGH_CDB_CK_COND(cdb)       PASSTHROUGH_ISOLATE_BITS(cdb, 2, PASSTHROUGH_CDB_CK_COND_MASK, 5)
+#define PASSTHROUGH_CDB_T_DIR(cdb)         PASSTHROUGH_ISOLATE_BITS(cdb, 2, PASSTHROUGH_CDB_T_DIR_MASK, 3)
+
+#define PASSTHROUGH_CDB_MULTIPLE_COUNT(cdb)         (sati_get_cdb_byte(cdb, 1) >> 5)
+#define PASSTHROUGH_CDB_COMMAND(cdb, index)         sati_get_cdb_byte(cdb, index)
+
+// Protocols
+#define PASSTHROUGH_PIO_DATA_IN            0x4
+#define PASSTHROUGH_PIO_DATA_OUT           0x5
+#define PASSTHROUGH_UDMA_DATA_IN           0xA
+#define PASSTHROUGH_UDMA_DATA_OUT          0xB
+#define PASSTHROUGH_RETURN_RESPONSE        0xF
+
+/**
+* @brief This function will check the multiple_count field in the SCSI CDB
+*        and if multiple_count is nonzero the function will check the
+*        ATA command code. Only Read and Write Multiple commands are allowed
+*        when multiple_count is a nonzero value.
+*
+* @param[in]     cdb The SCSI cdb for the ATA pass-through command
+*
+* @return BOOL
+  @retval TRUE - multiple_count is nonzero with a unsupported command
+  @retval FALSE - multiple_count is zero or the command supports a nonzero value
+*/
+static
+BOOL sati_passthrough_multiple_count_error(
+   U8 *     cdb
+)
+{
+   U8 ata_command_code;
+
+   if(PASSTHROUGH_CDB_MULTIPLE_COUNT(cdb) > 0)
+   {
+      if(sati_get_cdb_byte(cdb, 0 ) == SCSI_ATA_PASSTHRU_12)
+      {
+         ata_command_code = PASSTHROUGH_CDB_COMMAND(cdb, 9);
+      }
+      else
+      {
+         ata_command_code = PASSTHROUGH_CDB_COMMAND(cdb, 14);
+      }
+
+      switch(ata_command_code)
+      {  //MULTICOUNT bit is supported
+         case ATA_READ_MULTIPLE:
+         case ATA_READ_MULTIPLE_EXT:
+         case ATA_WRITE_MULTIPLE:
+         case ATA_WRITE_MULTIPLE_EXT:
+         case ATA_WRITE_MULTIPLE_FUA_EXT:
+            return FALSE;
+         break;
+
+         default:
+            return TRUE;
+      }
+   }
+   //MULTICOUNT bit is not set
+   return FALSE;
+}
+
+/**
+ * @brief This method will construct the sense data buffer in the user's
+ *        sense data buffer location.  Additionally, it will set the user's
+ *        SCSI status.
+ *
+ * @param[in]     sequence This parameter specifies the translation sequence
+ *                for which to construct the sense data.
+ * @param[in]     register_fis This parameter specifies the fis from which
+ *                to get the data.
+ * @param[in,out] scsi_io This parameter specifies the user's IO request
+ *                for which to construct the sense data.
+ * @param[in]     scsi_status This parameter specifies the SCSI status
+ *                value for the user's IO request.
+ * @param[in]     sense_key This parameter specifies the sense key to
+ *                be set for the user's IO request.
+ * @param[in]     additional_sense_code This parameter specifies the
+ *                additional sense code (ASC) key to be set for the user's
+ *                IO request.
+ * @param[in]     additional_sense_code_qualifier This parameter specifies
+ *                the additional sense code qualifier (ASCQ) key to be set
+ *                for the user's IO request.
+ *
+ * @return none
+ */
+static
+void sati_passthrough_construct_sense(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   U8                         * register_fis,
+   void                       * scsi_io,
+   U8                           scsi_status,
+   U8                           sense_key,
+   U8                           additional_sense_code,
+   U8                           additional_sense_code_qualifier
+)
+{
+   U8                    * sense_data;
+   U32                     sense_len;
+   U8                    * cdb;
+   unsigned char           sector_count_upper;
+   unsigned char           lba_upper;
+
+#ifdef SATI_TRANSPORT_SUPPORTS_SAS
+   SCI_SSP_RESPONSE_IU_T * rsp_iu = (SCI_SSP_RESPONSE_IU_T*)
+                                    sati_cb_get_response_iu_address(scsi_io);
+
+   sati_scsi_common_response_iu_construct(
+      rsp_iu,
+      scsi_status,
+      SCSI_FIXED_SENSE_DATA_BASE_LENGTH,
+      SCSI_RESPONSE_DATA_PRES_SENSE_DATA
+   );
+
+   sense_data                   = (U8*) rsp_iu->data;
+   sense_len                    = SSP_RESPONSE_IU_MAX_DATA * 4;  // dwords to bytes
+#else
+   sense_data = sati_cb_get_sense_data_address(scsi_io);
+   sense_len  = sati_cb_get_sense_data_length(scsi_io);
+#endif // SATI_TRANSPORT_SUPPORTS_SAS
+
+   sati_scsi_sense_data_construct(
+      sequence,
+      scsi_io,
+      scsi_status,
+      sense_key,
+      additional_sense_code,
+      additional_sense_code_qualifier
+   );
+
+   cdb = sati_cb_get_cdb_address(scsi_io);
+
+   if (sati_get_ata_sector_count_ext(register_fis) != 0) {
+      sector_count_upper = 1;
+   } else {
+       sector_count_upper = 0;
+   }
+
+   if (sati_get_ata_lba_high_ext(register_fis) != 0 ||
+       sati_get_ata_lba_mid_ext(register_fis) != 0 ||
+       sati_get_ata_lba_low_ext(register_fis) != 0) {
+      lba_upper = 1;
+   } else {
+       lba_upper = 0;
+   }
+
+   // Information section
+   sati_set_sense_data_byte(sense_data, sense_len, 3,  (U8)sati_get_ata_error(register_fis));
+   sati_set_sense_data_byte(sense_data, sense_len, 4,  (U8)sati_get_ata_status(register_fis));
+   sati_set_sense_data_byte(sense_data, sense_len, 5,  sati_get_ata_device(register_fis));
+   sati_set_sense_data_byte(sense_data, sense_len, 6,  sati_get_ata_sector_count(register_fis));
+
+   // Command specific section
+   sati_set_sense_data_byte(sense_data, sense_len, 8,  (PASSTHROUGH_CDB_EXTEND(cdb) << 7) | (sector_count_upper << 6) | (lba_upper << 5));
+   sati_set_sense_data_byte(sense_data, sense_len, 9,  sati_get_ata_lba_high(register_fis));
+   sati_set_sense_data_byte(sense_data, sense_len, 10, sati_get_ata_lba_mid(register_fis));
+   sati_set_sense_data_byte(sense_data, sense_len, 11, sati_get_ata_lba_low(register_fis));
+
+   sequence->is_sense_response_set = TRUE;
+}
+
+/**
+ * @brief This method will verify that the T_DIR bit matches the protocol bit.
+ *        It will additionally set the direction on the sequence.
+ *
+ * @param[in,out] sequence This parameter specifies the translation sequence
+ *                for which to construct the sense data.
+ * @param[in]     cdb The CDB containing the passthrough command
+ *
+ * @return none
+ */
+static
+SATI_STATUS sati_passthrough_check_direction(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   U8           * cdb
+)
+{
+   if ((PASSTHROUGH_CDB_PROTOCOL(cdb) == PASSTHROUGH_PIO_DATA_IN) ||
+       (PASSTHROUGH_CDB_PROTOCOL(cdb) == PASSTHROUGH_UDMA_DATA_IN))
+   {
+      if (PASSTHROUGH_CDB_T_DIR(cdb) == 0x0)
+      {
+         return SATI_FAILURE;
+      }
+      else
+      {
+         sequence->data_direction = SATI_DATA_DIRECTION_IN;
+      }
+   }
+   else if ((PASSTHROUGH_CDB_PROTOCOL(cdb) == PASSTHROUGH_PIO_DATA_OUT) ||
+            (PASSTHROUGH_CDB_PROTOCOL(cdb) == PASSTHROUGH_UDMA_DATA_OUT))
+   {
+      if (PASSTHROUGH_CDB_T_DIR(cdb) == 0x1)
+      {
+         return SATI_FAILURE;
+      }
+      else
+      {
+         sequence->data_direction = SATI_DATA_DIRECTION_OUT;
+      }
+   }
+   else
+   {
+      sequence->data_direction = SATI_DATA_DIRECTION_NONE;
+   }
+
+   return SATI_COMPLETE;
+}
+
+//******************************************************************************
+//* P U B L I C   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method will translate the SCSI Passthrough command
+ *        into the corresponding ATA command.
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SATI_SUCCESS This is returned if the command translation was
+ *         successful.
+ * @retval SATI_FAILURE This is returned if the command translation was
+ *         unsuccessful
+ */
+
+SATI_STATUS sati_passthrough_12_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   SATI_STATUS   status;
+   U8          * cdb;
+   U8          * register_fis;
+
+   status = SATI_FAILURE;
+
+   sequence->type = SATI_SEQUENCE_ATA_PASSTHROUGH_12;
+   sequence->state = SATI_SEQUENCE_STATE_TRANSLATE_DATA;
+
+   cdb = sati_cb_get_cdb_address(scsi_io);
+   sequence->protocol = PASSTHROUGH_CDB_PROTOCOL (cdb);
+   register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+   if (sati_passthrough_check_direction(sequence, cdb) != SATI_COMPLETE
+       || sati_passthrough_multiple_count_error(cdb)
+      )
+   {
+      // Fail due to mismatch
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_ILLEGAL_REQUEST,
+         SCSI_ASC_INVALID_FIELD_IN_CDB,
+         SCSI_ASCQ_INVALID_FIELD_IN_CDB
+      );
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+
+   sati_set_ata_features(register_fis, sati_get_cdb_byte(cdb, 3));
+   sati_set_ata_sector_count(register_fis, sati_get_cdb_byte(cdb, 4));
+   sati_set_ata_lba_low(register_fis, sati_get_cdb_byte(cdb, 5));
+   sati_set_ata_lba_mid(register_fis, sati_get_cdb_byte(cdb, 6));
+   sati_set_ata_lba_high(register_fis, sati_get_cdb_byte(cdb, 7));
+   sati_set_ata_device_head(register_fis, sati_get_cdb_byte(cdb, 8));
+   sati_set_ata_command(register_fis, sati_get_cdb_byte(cdb, 9));
+
+   sequence->state = SATI_SEQUENCE_STATE_AWAIT_RESPONSE;
+
+   return SATI_SUCCESS;
+}
+
+/**
+ * @brief This method will translate the SCSI Passthrough command
+ *        into the corresponding ATA command.
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SATI_SUCCESS This is returned if the command translation was
+ *         successful.
+ * @retval SATI_FAILURE This is returned if the command translation was
+ *         unsuccessful
+ */
+SATI_STATUS sati_passthrough_16_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   SATI_STATUS   status;
+   U8          * cdb;
+   U8          * register_fis;
+
+   status = SATI_FAILURE;
+
+   sequence->type = SATI_SEQUENCE_ATA_PASSTHROUGH_16;
+   sequence->state = SATI_SEQUENCE_STATE_TRANSLATE_DATA;
+
+   cdb = sati_cb_get_cdb_address(scsi_io);
+   sequence->protocol = PASSTHROUGH_CDB_PROTOCOL(cdb);
+   register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+   if (sati_passthrough_check_direction(sequence, cdb) != SATI_COMPLETE
+       || sati_passthrough_multiple_count_error(cdb)
+      )
+   {
+      // Fail due to mismatch
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_ILLEGAL_REQUEST,
+         SCSI_ASC_INVALID_FIELD_IN_CDB,
+         SCSI_ASCQ_INVALID_FIELD_IN_CDB
+      );
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+
+   if (PASSTHROUGH_CDB_EXTEND(cdb) == 1)
+   {
+      sati_set_ata_features_exp(register_fis, sati_get_cdb_byte(cdb, 3));
+      sati_set_ata_sector_count_exp(register_fis, sati_get_cdb_byte(cdb, 5));
+      sati_set_ata_lba_low_exp(register_fis, sati_get_cdb_byte(cdb, 7));
+      sati_set_ata_lba_mid_exp(register_fis, sati_get_cdb_byte(cdb, 9));
+      sati_set_ata_lba_high_exp(register_fis, sati_get_cdb_byte(cdb, 11));
+   }
+   sati_set_ata_features(register_fis, sati_get_cdb_byte(cdb, 4));
+   sati_set_ata_sector_count(register_fis, sati_get_cdb_byte(cdb, 6));
+   sati_set_ata_lba_low(register_fis, sati_get_cdb_byte(cdb, 8));
+   sati_set_ata_lba_mid(register_fis, sati_get_cdb_byte(cdb, 10));
+   sati_set_ata_lba_high(register_fis, sati_get_cdb_byte(cdb, 12));
+   sati_set_ata_device_head(register_fis, sati_get_cdb_byte(cdb, 13));
+   sati_set_ata_command(register_fis, sati_get_cdb_byte(cdb, 14));
+
+   sequence->state = SATI_SEQUENCE_STATE_AWAIT_RESPONSE;
+
+   return SATI_SUCCESS;
+}
+
+/**
+ * @brief This method will translate the ATA command
+ *        response
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SATI_COMPLETE This is returned if the command translation was
+ *         successful.
+ * @retval SATI_FAILURE This is returned if the command translation was
+ *         unsuccessful
+ */
+SATI_STATUS sati_passthrough_translate_response(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   U8 * cdb;
+   U8 * register_fis;
+
+   cdb = sati_cb_get_cdb_address(scsi_io);
+   register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
+
+   // Check for device errors
+   if (sati_get_ata_status(register_fis) & ATA_STATUS_REG_ERROR_BIT)
+   {
+      sati_translate_error(sequence, scsi_io, (U8)sati_get_ata_error(register_fis));
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+
+   // If the user set the check condition bit, fill out the sense data
+   if (PASSTHROUGH_CDB_CK_COND(cdb) ||
+       PASSTHROUGH_CDB_PROTOCOL(cdb) == PASSTHROUGH_RETURN_RESPONSE)
+   {
+      sati_passthrough_construct_sense(
+         sequence,
+         register_fis,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_RECOVERED_ERROR,
+         SCSI_ASC_NO_ADDITIONAL_SENSE,
+         SCSI_ASCQ_ATA_PASS_THROUGH_INFORMATION_AVAILABLE
+      );
+   }
+
+   sequence->state = SATI_SEQUENCE_STATE_FINAL;
+
+   return SATI_COMPLETE;
+}
+
+#endif // !defined(DISABLE_SATI_PASSTHROUGH)
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_passthrough.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_passthrough.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,88 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_PASSTHROUGH_H_
+#define _SATI_PASSTHROUGH_H_
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ *        translate the SCSI passthrough command.
+ */
+
+#if !defined(DISABLE_SATI_PASSTHROUGH)
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+SATI_STATUS sati_passthrough_12_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+SATI_STATUS sati_passthrough_16_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+SATI_STATUS sati_passthrough_translate_response(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+#endif // !defined(DISABLE_SATI_PASSTHROUGH)
+
+#endif // _SATI_PASSTHROUGH_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_read.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_read.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,323 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ *        translate the SCSI read (6, 10, 12, or 16-byte) commands.
+ */
+
+#include <dev/isci/scil/sati_move.h>
+#include <dev/isci/scil/sati_read.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_util.h>
+
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_scsi.h>
+
+//******************************************************************************
+//* P R I V A T E   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method performs the common translation functionality for
+ *        all SCSI read operations that are 10 bytes in size or larger.
+ *        Translated/Written items include:
+ *        - Force Unit Access (FUA)
+ *        - Sector Count/Transfer Length
+ *        - Command register
+ *
+ * @param[in] sector_count This parameter specifies the number of sectors
+ *            to be transferred by this request.
+ * @param[in] device_head This parameter points to device head register
+ *            that is to be written into the ATA task file (register FIS).
+ *
+ * @return Indicate if the command translation succeeded.
+ * @see sati_move_set_sector_count() for additional return values.
+ */
+static
+SATI_STATUS sati_read_large_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io,
+   U32                          sector_count,
+   U8                         * device_head
+)
+{
+   sequence->data_direction = SATI_DATA_DIRECTION_IN;
+
+   return sati_move_large_translate_command(
+             sequence,
+             scsi_io,
+             ata_io,
+             sector_count,
+             device_head
+          );
+}
+
+/**
+ * @brief This method performs the common translation functionality for
+ *        all SCSI read operations containing a 32-bit logical block
+ *        address.
+ *        Translated/Written items include:
+ *        - Logical Block Address (LBA)
+ *        - Force Unit Access (FUA)
+ *        - Sector Count/Transfer Length
+ *        - Command register
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @param[in] sector_count This parameter specifies the number of sectors
+ *            to be transferred by this request.
+ * @param[in] control_byte_offset This parameter specifies the byte offset
+ *            into the command descriptor block at which the control byte
+ *            is located.
+ *
+ * @return Indicate if the command translation succeeded.
+ * @see sati_move_32_bit_lba_translate_command(), sati_move_set_sector_count()
+ *      for additional return values.
+ */
+static
+SATI_STATUS sati_read_32_bit_lba_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io,
+   U32                          sector_count,
+   U8                           control_byte_offset
+)
+{
+   U8           device_head = 0;
+   SATI_STATUS  status;
+
+   status = sati_read_large_translate_command(
+               sequence, scsi_io, ata_io, sector_count, &device_head
+            );
+
+   if (status == SATI_SUCCESS)
+   {
+      status = sati_move_32_bit_lba_translate_command(
+                  sequence, scsi_io, ata_io, device_head
+               );
+   }
+
+   return status;
+}
+
+//******************************************************************************
+//* P U B L I C   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method will translate the SCSI read command into a
+ *        corresponding ATA read 6 command.  Depending upon the capabilities
+ *        supported by the target different ATA commands can be selected.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the command translation was
+ *         successful.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
+ *         sense data has been created as a result of something specified
+ *         in the CDB.
+ */
+SATI_STATUS sati_read_6_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   if(sati_device_state_stopped(sequence, scsi_io))
+   {
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+   else
+   {
+      sequence->data_direction = SATI_DATA_DIRECTION_IN;
+      sequence->type           = SATI_SEQUENCE_READ_6;
+
+      return sati_move_small_translate_command(sequence, scsi_io, ata_io);
+   }
+}
+
+/**
+ * @brief This method will translate the SCSI read 10 command into a
+ *        corresponding ATA read command.  Depending upon the capabilities
+ *        supported by the target different ATA commands can be selected.
+ *        It ensures that all translation required for this command is
+ *        performed successfully.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @see sati_read_32_bit_lba_translate_command() for return values.
+ */
+SATI_STATUS sati_read_10_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+
+   U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+   U32 sector_count = (sati_get_cdb_byte(cdb, 7) << 8) |
+                      (sati_get_cdb_byte(cdb, 8));
+
+   if(sati_device_state_stopped(sequence, scsi_io))
+   {
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+   else
+   {
+      sequence->type = SATI_SEQUENCE_READ_10;
+
+      return sati_read_32_bit_lba_translate_command(
+                sequence, scsi_io, ata_io, sector_count, 9
+             );
+   }
+}
+
+/**
+ * @brief This method will translate the SCSI read 12 command into a
+ *        corresponding ATA read command.  Depending upon the capabilities
+ *        supported by the target different ATA commands can be selected.
+ *        It ensures that all translation required for this command is
+ *        performed successfully.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @see sati_read_32_bit_lba_translate_command() for return values.
+ */
+SATI_STATUS sati_read_12_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   U8  * cdb          = sati_cb_get_cdb_address(scsi_io);
+   U32   sector_count = (sati_get_cdb_byte(cdb, 6) << 24) |
+                        (sati_get_cdb_byte(cdb, 7) << 16) |
+                        (sati_get_cdb_byte(cdb, 8) << 8)  |
+                        (sati_get_cdb_byte(cdb, 9));
+
+   if(sati_device_state_stopped(sequence, scsi_io))
+   {
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+   else
+   {
+      sequence->type = SATI_SEQUENCE_READ_12;
+
+      return sati_read_32_bit_lba_translate_command(
+                sequence, scsi_io, ata_io, sector_count, 11
+             );
+   }
+}
+
+/**
+ * @brief This method will translate the SCSI read 16 command into a
+ *        corresponding ATA read command.  Depending upon the capabilities
+ *        supported by the target different ATA commands can be selected.
+ *        It ensures that all translation required for this command is
+ *        performed successfully.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @see sati_read_large_translate_command(), sati_move_translate_64_bit_lba()
+ *      for additional return values.
+ */
+SATI_STATUS sati_read_16_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   SATI_STATUS   status;
+   U8            device_head  = 0;
+   U8          * cdb          = sati_cb_get_cdb_address(scsi_io);
+   U32           sector_count = (sati_get_cdb_byte(cdb, 10) << 24) |
+                                (sati_get_cdb_byte(cdb, 11) << 16) |
+                                (sati_get_cdb_byte(cdb, 12) << 8)  |
+                                (sati_get_cdb_byte(cdb, 13));
+
+   if(sati_device_state_stopped(sequence, scsi_io))
+   {
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+   else
+   {
+      sequence->type = SATI_SEQUENCE_READ_16;
+
+      // Translate the sector count, write command register, and check various
+      // other parts of the CDB.
+      status = sati_read_large_translate_command(
+                  sequence, scsi_io, ata_io, sector_count, &device_head
+               );
+
+      // Attempt to translate the 64-bit LBA field from the SCSI request
+      // into the 48-bits of LBA in the ATA register FIS.
+      if (status == SATI_SUCCESS)
+      {
+         sati_move_translate_command(sequence, scsi_io, ata_io, device_head);
+         status = sati_move_translate_64_bit_lba(sequence, scsi_io, ata_io);
+      }
+
+      return status;
+   }
+}
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_read.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_read.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,91 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_READ_H_
+#define _SATI_READ_H_
+
+/**
+ * @file
+ * @brief This file contains the method declarations and type definitions
+ *        required to translate the SCSI read (6, 10, 12, or 16-byte)
+ *        commands.
+ */
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+SATI_STATUS sati_read_6_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+SATI_STATUS sati_read_10_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+SATI_STATUS sati_read_12_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+SATI_STATUS sati_read_16_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+#endif // _SATI_READ_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_read_buffer.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_read_buffer.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,235 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+*
+* GPL LICENSE SUMMARY
+*
+* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of version 2 of the GNU General Public License as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+* The full GNU General Public License is included in this distribution
+* in the file called LICENSE.GPL.
+*
+* BSD LICENSE
+*
+* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+*   * Redistributions of source code must retain the above copyright
+*     notice, this list of conditions and the following disclaimer.
+*   * Redistributions in binary form must reproduce the above copyright
+*     notice, this list of conditions and the following disclaimer in
+*     the documentation and/or other materials provided with the
+*     distribution.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+* @file
+* @brief This file contains the implementation to translate
+*        SCSI Read Buffer command based on the SAT spec.
+*/
+
+#if !defined(DISABLE_SATI_READ_BUFFER)
+
+#include <dev/isci/scil/sati_read_buffer.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_util.h>
+
+
+/**
+* @brief This method will translate the SCSI Read Buffer command
+*        into a corresponding ATA Read Buffer command.
+*        For more information on the parameters passed to this method,
+*        please reference sati_translate_command().
+*
+* @return Indicates if the command translation succeeded.
+* @retval SATI_SUCCESS indicates that the translation was supported and occurred
+*         without error.
+* @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
+*         there is a translation failure.
+* @retval SATI_COMPLETE indicates that the translation was supported, occurred without
+*         error, and no additional translation is necessary.
+*/
+SATI_STATUS sati_read_buffer_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+   SATI_STATUS status = SATI_FAILURE;
+   U32 allocation_length;
+   U32 buffer_offset;
+
+   allocation_length = ((sati_get_cdb_byte(cdb, 6) << 16) |
+                        (sati_get_cdb_byte(cdb, 7) << 8)  |
+                        (sati_get_cdb_byte(cdb, 8)));
+
+   buffer_offset = ((sati_get_cdb_byte(cdb, 3) << 16) |
+                    (sati_get_cdb_byte(cdb, 4) << 8)  |
+                    (sati_get_cdb_byte(cdb, 5)));
+
+   sequence->allocation_length = allocation_length;
+
+   switch(sati_get_cdb_byte(cdb, 1))
+   {
+      case SATI_READ_BUFFER_MODE_DATA:
+         if((allocation_length == 512) && (buffer_offset == 0) &&
+            (sati_get_cdb_byte(cdb, 2) == 0))
+         {
+            sati_ata_read_buffer_construct(ata_io, sequence);
+            sequence->type = SATI_SEQUENCE_READ_BUFFER;
+            sequence->state = SATI_SEQUENCE_STATE_AWAIT_RESPONSE;
+            status = SATI_SUCCESS;
+         }
+         else
+         {
+            sati_scsi_sense_data_construct(
+               sequence,
+               scsi_io,
+               SCSI_STATUS_CHECK_CONDITION,
+               SCSI_SENSE_ILLEGAL_REQUEST,
+               SCSI_ASC_INVALID_FIELD_IN_CDB,
+               SCSI_ASCQ_INVALID_FIELD_IN_CDB
+            );
+            sequence->state = SATI_SEQUENCE_STATE_FINAL;
+            status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+         }
+      break;
+
+      case SATI_READ_BUFFER_MODE_DESCRIPTOR:
+
+         //allocation legnth must be at least four to return translated data
+         if(allocation_length < 4)
+         {
+            sati_scsi_sense_data_construct(
+               sequence,
+               scsi_io,
+               SCSI_STATUS_CHECK_CONDITION,
+               SCSI_SENSE_ILLEGAL_REQUEST,
+               SCSI_ASC_INVALID_FIELD_IN_CDB,
+               SCSI_ASCQ_INVALID_FIELD_IN_CDB
+            );
+            sequence->state = SATI_SEQUENCE_STATE_FINAL;
+            status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+         }
+         else
+         {
+            //figure out if we support other buffer id's
+            sati_set_data_byte(sequence, scsi_io, 0, 0x09); //offset boundary
+            sati_set_data_byte(sequence, scsi_io, 1, 0x00);
+            sati_set_data_byte(sequence, scsi_io, 2, 0x02); //buffer capacity 0x200
+            sati_set_data_byte(sequence, scsi_io, 3, 0x00);
+            sequence->state = SATI_SEQUENCE_STATE_FINAL;
+            status = SATI_COMPLETE;
+         }
+      break;
+
+      default:
+         //Unspecified sat2v7, returning invalid cdb
+         sati_scsi_sense_data_construct(
+            sequence,
+            scsi_io,
+            SCSI_STATUS_CHECK_CONDITION,
+            SCSI_SENSE_ILLEGAL_REQUEST,
+            SCSI_ASC_INVALID_FIELD_IN_CDB,
+            SCSI_ASCQ_INVALID_FIELD_IN_CDB
+         );
+         sequence->state = SATI_SEQUENCE_STATE_FINAL;
+         status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+   return status;
+}
+
+/**
+* @brief This method will complete the Read Buffer Translation by copying the
+         ATA response data into the SCSI request DATA buffer.
+*        For more information on the parameters passed to this method,
+*        please reference sati_translate_command().
+*
+* @return Indicates if the command translation succeeded.
+* @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
+*         there is a translation failure.
+* @retval SATI_COMPLETE indicates that the translation was supported, occurred without
+*         error, and no additional translation is necessary.
+*/
+SATI_STATUS sati_read_buffer_translate_response(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
+   U8   ata_status = (U8) sati_get_ata_status(register_fis);
+   SATI_STATUS status = SATI_COMPLETE;
+
+   if (ata_status & ATA_STATUS_REG_ERROR_BIT)
+   {
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_ABORTED_COMMAND,
+         SCSI_ASC_NO_ADDITIONAL_SENSE,
+         SCSI_ASCQ_NO_ADDITIONAL_SENSE
+      );
+
+      status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+   else
+   {
+      void * ata_data = sati_cb_get_ata_data_address(ata_io);
+
+      if(ata_data == NULL)
+      {
+         status = SATI_FAILURE;
+      }
+      else
+      {
+         //copy ATA data into SCSI data buffer
+         sati_copy_data(
+            sequence,
+            scsi_io,
+            0,
+            ata_data,
+            512
+         );
+      }
+   }
+
+   sequence->state = SATI_SEQUENCE_STATE_FINAL;
+   return status;
+}
+
+
+#endif //!defined(DISABLE_SATI_READ_BUFFER)
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_read_buffer.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_read_buffer.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,82 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+*
+* GPL LICENSE SUMMARY
+*
+* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of version 2 of the GNU General Public License as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+* The full GNU General Public License is included in this distribution
+* in the file called LICENSE.GPL.
+*
+* BSD LICENSE
+*
+* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+*   * Redistributions of source code must retain the above copyright
+*     notice, this list of conditions and the following disclaimer.
+*   * Redistributions in binary form must reproduce the above copyright
+*     notice, this list of conditions and the following disclaimer in
+*     the documentation and/or other materials provided with the
+*     distribution.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+/**
+* @file
+* @brief This file contains the method definitions to translate
+*        SCSI Read Buffer command based of the SAT spec.
+*/
+
+#ifndef _SATI_READ_BUFFER_H_
+#define _SATI_READ_BUFFER_H_
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+#define SATI_READ_BUFFER_MODE_DATA       0x02
+#define SATI_READ_BUFFER_MODE_DESCRIPTOR 0x03
+
+
+SATI_STATUS sati_read_buffer_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+SATI_STATUS sati_read_buffer_translate_response(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+#endif // _SATI_READ_BUFFER_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_read_capacity.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_read_capacity.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,366 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ *        translate the SCSI read capacity (10 byte) command.
+ */
+
+#if !defined(DISABLE_SATI_READ_CAPACITY)
+
+#include <dev/isci/scil/sati_read_capacity.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_scsi.h>
+
+/**
+ * @brief This method will translate the read capacity 10 SCSI command into
+ *        an ATA IDENTIFY DEVICE command.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the command translation was
+ *         successful.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if the
+ *         LBA field is not 0, the PMI bit is not 0.
+ */
+SATI_STATUS sati_read_capacity_10_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+   /**
+    * SAT dictates:
+    * - the LBA field must be 0
+    * - the PMI bit must be 0
+    */
+   if (
+         (
+            (sati_get_cdb_byte(cdb, 2) != 0)
+         || (sati_get_cdb_byte(cdb, 3) != 0)
+         || (sati_get_cdb_byte(cdb, 4) != 0)
+         || (sati_get_cdb_byte(cdb, 5) != 0)
+         )
+         || ((sati_get_cdb_byte(cdb, 8) & SCSI_READ_CAPACITY_PMI_BIT_ENABLE)
+              == 1)
+      )
+   {
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_ILLEGAL_REQUEST,
+         SCSI_ASC_INVALID_FIELD_IN_CDB,
+         SCSI_ASCQ_INVALID_FIELD_IN_CDB
+      );
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+
+   // The CDB is properly formed.
+   sequence->allocation_length = SCSI_READ_CAPACITY_10_DATA_LENGTH;
+   sequence->type              = SATI_SEQUENCE_READ_CAPACITY_10;
+
+   sati_ata_identify_device_construct(ata_io, sequence);
+   return SATI_SUCCESS;
+}
+
+
+
+/**
+ * @brief This method will translate the read capacity 16 SCSI command into
+ *        an ATA IDENTIFY DEVICE command.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the command translation was
+ *         successful.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if the
+ *         LBA field is not 0, the PMI bit is not 0.
+ */
+SATI_STATUS sati_read_capacity_16_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+   /**
+    * SAT dictates:
+    * - the LBA field must be 0
+    * - the PMI bit must be 0
+    */
+   if (
+         (
+            (sati_get_cdb_byte(cdb, 2) != 0)
+         || (sati_get_cdb_byte(cdb, 3) != 0)
+         || (sati_get_cdb_byte(cdb, 4) != 0)
+         || (sati_get_cdb_byte(cdb, 5) != 0)
+         || (sati_get_cdb_byte(cdb, 6) != 0)
+         || (sati_get_cdb_byte(cdb, 7) != 0)
+         || (sati_get_cdb_byte(cdb, 8) != 0)
+         || (sati_get_cdb_byte(cdb, 9) != 0)
+         )
+         || ((sati_get_cdb_byte(cdb, 14) & SCSI_READ_CAPACITY_PMI_BIT_ENABLE)
+              == 1)
+      )
+   {
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_ILLEGAL_REQUEST,
+         SCSI_ASC_INVALID_FIELD_IN_CDB,
+         SCSI_ASCQ_INVALID_FIELD_IN_CDB
+      );
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+
+   // The CDB is properly formed.
+   sequence->allocation_length = (sati_get_cdb_byte(cdb, 10) << 24) |
+                                 (sati_get_cdb_byte(cdb, 11) << 16) |
+                                 (sati_get_cdb_byte(cdb, 12) << 8)  |
+                                 (sati_get_cdb_byte(cdb, 13));
+
+   sequence->type              = SATI_SEQUENCE_READ_CAPACITY_16;
+
+   sati_ata_identify_device_construct(ata_io, sequence);
+   return SATI_SUCCESS;
+}
+
+/**
+ * @brief This method will translate the ATA Identify Device data into
+ *        SCSI read capacity 10 data.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_data().
+ *
+ * @return none
+ */
+void sati_read_capacity_10_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+)
+{
+   U32  lba_low     = 0;
+   U32  lba_high    = 0;
+   U32  sector_size = 0;
+
+   // Extract the sector information (sector size, logical blocks) from
+   // the retrieved ATA identify device data.
+   sati_ata_identify_device_get_sector_info(
+      (ATA_IDENTIFY_DEVICE_DATA_T*)ata_input_data,
+      &lba_high,
+      &lba_low,
+      &sector_size
+   );
+
+   // SATA drives report a value that is one LBA larger than the last LBA.
+   // SCSI wants the last LBA.  Make the correction here.  lba_low is
+   // always decremented since it is an unsigned long the value 0 will
+   // wrap to 0xFFFFFFFF.
+   if ((lba_low == 0) && (lba_high == 0))
+      lba_high -= 1;
+   lba_low -= 1;
+
+   if(lba_high != 0)
+   {
+      sati_set_data_byte(sequence, scsi_io, 0, 0xFF);
+      sati_set_data_byte(sequence, scsi_io, 1, 0xFF);
+      sati_set_data_byte(sequence, scsi_io, 2, 0xFF);
+      sati_set_data_byte(sequence, scsi_io, 3, 0xFF);
+   }
+   else
+   {
+      // Build CDB for Read Capacity 10
+      // Fill in the Logical Block Address bytes.
+      sati_set_data_byte(sequence, scsi_io, 0, (U8)((lba_low >> 24) & 0xFF));
+      sati_set_data_byte(sequence, scsi_io, 1, (U8)((lba_low >> 16) & 0xFF));
+      sati_set_data_byte(sequence, scsi_io, 2, (U8)((lba_low >> 8)  & 0xFF));
+      sati_set_data_byte(sequence, scsi_io, 3, (U8)(lba_low & 0xFF));
+   }
+   // Fill in the sector size field.
+   sati_set_data_byte(sequence, scsi_io, 4, (U8)((sector_size >> 24) & 0xFF));
+   sati_set_data_byte(sequence, scsi_io, 5, (U8)((sector_size >> 16) & 0xFF));
+   sati_set_data_byte(sequence, scsi_io, 6, (U8)((sector_size >> 8)  & 0xFF));
+   sati_set_data_byte(sequence, scsi_io, 7, (U8)(sector_size & 0xFF));
+}
+
+/**
+ * @brief This method will translate the ATA Identify Device data into
+ *        SCSI read capacity 16 data.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_data().
+ *
+ * @return none
+ */
+void sati_read_capacity_16_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+)
+{
+   U32  lba_low     = 0;
+   U32  lba_high    = 0;
+   U32  sector_size = 0;
+   ATA_IDENTIFY_DEVICE_DATA_T * identify_device_data;
+   U16  physical_per_logical_enable_bit = 0;
+   U8   physical_per_logical_sector_exponent = 0;
+   U16  physical_per_logical_sector = 0;
+   U16  logical_sector_alignment = 0;
+   U16  scsi_logical_sector_alignment = 0;
+   U8   byte14 = 0;
+
+   //A number of data fields need to be extracted from ATA identify device data
+   identify_device_data = (ATA_IDENTIFY_DEVICE_DATA_T*)ata_input_data;
+
+   // Extract the sector information (sector size, logical blocks) from
+   // the retrieved ATA identify device data.
+   sati_ata_identify_device_get_sector_info(
+      (ATA_IDENTIFY_DEVICE_DATA_T*)ata_input_data,
+      &lba_high,
+      &lba_low,
+      &sector_size
+   );
+
+   // SATA drives report a value that is one LBA larger than the last LBA.
+   // SCSI wants the last LBA.  Make the correction here.  lba_low is
+   // always decremented since it is an unsigned long the value 0 will
+   // wrap to 0xFFFFFFFF.
+   if ((lba_low == 0) && (lba_high == 0))
+      lba_high -= 1;
+   lba_low -= 1;
+
+   // Build the CDB for Read Capacity 16
+   // Fill in the Logical Block Address bytes.
+   sati_set_data_byte(sequence, scsi_io, 0, (U8)((lba_high >> 24) & 0xFF));
+   sati_set_data_byte(sequence, scsi_io, 1, (U8)((lba_high >> 16) & 0xFF));
+   sati_set_data_byte(sequence, scsi_io, 2, (U8)((lba_high >> 8)  & 0xFF));
+   sati_set_data_byte(sequence, scsi_io, 3, (U8)(lba_high & 0xFF));
+
+   sati_set_data_byte(sequence, scsi_io, 4, (U8)((lba_low >> 24) & 0xFF));
+   sati_set_data_byte(sequence, scsi_io, 5, (U8)((lba_low >> 16) & 0xFF));
+   sati_set_data_byte(sequence, scsi_io, 6, (U8)((lba_low >> 8)  & 0xFF));
+   sati_set_data_byte(sequence, scsi_io, 7, (U8)(lba_low & 0xFF));
+
+   //Fill in the sector size field.
+   sati_set_data_byte(sequence, scsi_io, 8,  (U8)((sector_size >> 24) & 0xFF));
+   sati_set_data_byte(sequence, scsi_io, 9,  (U8)((sector_size >> 16) & 0xFF));
+   sati_set_data_byte(sequence, scsi_io, 10, (U8)((sector_size >> 8)  & 0xFF));
+   sati_set_data_byte(sequence, scsi_io, 11, (U8)(sector_size & 0xFF));
+
+   //Check Bit 13 of ATA_IDENTIFY_DEVICE_DATA physical_logical_sector_info
+   //(Word 106) is enabled
+   physical_per_logical_enable_bit = (identify_device_data->physical_logical_sector_info
+      & ATA_IDENTIFY_LOGICAL_SECTOR_PER_PHYSICAL_SECTOR_ENABLE);
+
+   //Extract the Physical per logical sector exponent field and calculate
+   //Physical per logical sector value
+   physical_per_logical_sector_exponent = (U8) (identify_device_data->physical_logical_sector_info
+      & ATA_IDENTIFY_LOGICAL_SECTOR_PER_PHYSICAL_SECTOR_MASK);
+   physical_per_logical_sector = 1 << (physical_per_logical_sector_exponent);
+
+   //If the data is valid, fill in the logical blocks per physical block exponent field.
+   //Else set logical blocks per physical block exponent to 1
+   if (physical_per_logical_enable_bit != 0)
+      sati_set_data_byte(
+         sequence,
+         scsi_io,
+         13,
+         (U8)(physical_per_logical_sector_exponent & 0xFF)
+      );
+   else
+      sati_set_data_byte(sequence, scsi_io, 13, 0);
+
+   //Fill in the lowest aligned logical block address field.
+   logical_sector_alignment = identify_device_data->logical_sector_alignment;
+   if (logical_sector_alignment == 0)
+      scsi_logical_sector_alignment = 0;
+   else
+      scsi_logical_sector_alignment = (physical_per_logical_sector - logical_sector_alignment)
+         % physical_per_logical_sector;
+
+   //Follow SAT for reporting tprz and tpe
+   if ((sequence->device->capabilities & SATI_DEVICE_CAP_DSM_TRIM_SUPPORT) &&
+       (sequence->device->capabilities & SATI_DEVICE_CAP_DETERMINISTIC_READ_AFTER_TRIM))
+   {
+      // tpe
+      byte14 |= 0x80;
+      // tprz
+      if (sequence->device->capabilities & SATI_DEVICE_CAP_READ_ZERO_AFTER_TRIM)
+          byte14 |= 0x40;
+   }
+   sati_set_data_byte(
+       sequence,
+       scsi_io,
+       14,
+       (U8)(((scsi_logical_sector_alignment >>8) & 0x3F) | byte14));
+
+   sati_set_data_byte(
+       sequence,
+       scsi_io,
+       15,
+       (U8)(scsi_logical_sector_alignment & 0xFF));
+}
+
+#endif // !defined(DISABLE_SATI_READ_CAPACITY)
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_read_capacity.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_read_capacity.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,91 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_READ_CAPACITY_H_
+#define _SATI_READ_CAPACITY_H_
+
+/**
+ * @file
+ * @brief This file contains the method interfaces required to
+ *        translate the SCSI read capacity (10 byte) command as well as
+ *        translate data for both 10 byte and 16 byte read capacity flavors.
+ */
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+SATI_STATUS sati_read_capacity_10_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+SATI_STATUS sati_read_capacity_16_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+void sati_read_capacity_10_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+);
+
+void sati_read_capacity_16_translate_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * ata_input_data,
+   void                       * scsi_io
+);
+
+#endif // _SATI_READ_CAPACITY_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_reassign_blocks.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_reassign_blocks.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,622 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ *        translate the SCSI reassign blocks command.
+ */
+
+#if !defined(DISABLE_SATI_REASSIGN_BLOCKS)
+
+#include <dev/isci/scil/sati_reassign_blocks.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_move.h>
+#include <dev/isci/scil/sati_write.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/intel_scsi.h>
+
+
+//******************************************************************************
+//* P R I V A T E   M E T H O D S
+//******************************************************************************
+// static SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T reassign_blocks_processing_state;
+
+/**
+ * @brief This method copies short 24bits LBA bytes to the command register
+ * @return Indicate if the method was successfully completed.
+ * @retval SATI_SUCCESS This is returned in all other cases.
+ */
+static
+void set_current_lba(U8 * lba, void  * ata_io)
+{
+   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+   sati_set_ata_lba_low(register_fis, lba[0]);
+   sati_set_ata_lba_mid(register_fis, lba[1]);
+   sati_set_ata_lba_high(register_fis, lba[2]);
+   sati_set_ata_device_head(register_fis, ATA_DEV_HEAD_REG_LBA_MODE_ENABLE | (lba[3] & 0x0F));
+
+
+}
+
+/**
+ * @brief This method copies short 48bits LBA bytes to the command register
+ * @return Indicate if the method was successfully completed.
+ * @retval SATI_SUCCESS This is returned in all other cases.
+ */
+static
+void set_current_long_lba(U8 * lba, void  * ata_io)
+{
+   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+   sati_set_ata_lba_low(register_fis, lba[0]);
+   sati_set_ata_lba_mid(register_fis, lba[1]);
+   sati_set_ata_lba_high(register_fis, lba[2]);
+   sati_set_ata_lba_low_exp(register_fis, lba[3]);
+   sati_set_ata_lba_mid_exp(register_fis, lba[4]);
+   sati_set_ata_lba_high_exp(register_fis, lba[5]);
+}
+
+/**
+ * @brief This method performs the SCSI VERIFY command translation
+ *        functionality.
+ *        This includes:
+ *        - setting the command register
+ *        - setting the device head register
+ *        - filling in fields in the SATI_TRANSLATOR_SEQUENCE object.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @return Indicate if the method was successfully completed.
+ * @retval SATI_SUCCESS This is returned in all other cases.
+ */
+static
+SATI_STATUS sati_reassign_blocks_verify_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+   sati_ata_non_data_command(ata_io, sequence);
+
+   // Ensure the device supports the 48 bit feature set.
+   if (sequence->device->capabilities & SATI_DEVICE_CAP_48BIT_ENABLE)
+      sati_set_ata_command(register_fis, ATA_READ_VERIFY_SECTORS_EXT);
+   else
+      sati_set_ata_command(register_fis, ATA_READ_VERIFY_SECTORS);
+
+   return SATI_SUCCESS;
+}
+
+/**
+ * @brief This method performs the SCSI Write sector command translation
+ *        functionality.
+ *        This includes:
+ *        - setting the command register
+ *        - setting the device head register
+ *        - filling in fields in the SATI_TRANSLATOR_SEQUENCE object.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @return Indicate if the method was successfully completed.
+ * @retval SATI_SUCCESS This is returned in all other cases.
+ */
+static
+SATI_STATUS sati_reassign_blocks_write_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+   sati_ata_non_data_command(ata_io, sequence);
+   sequence->data_direction = SATI_DATA_DIRECTION_OUT;
+
+//   sati_set_ata_sector_count(register_fis, 1);
+//   status=sati_move_set_sector_count(sequence,scsi_io,ata_io,1,0);
+
+   // Ensure the device supports the 48 bit feature set.
+   if (sequence->device->capabilities & SATI_DEVICE_CAP_48BIT_ENABLE)
+      sati_set_ata_command(register_fis, ATA_WRITE_DMA_EXT);
+   else
+      sati_set_ata_command(register_fis, ATA_WRITE_DMA);
+
+   return SATI_SUCCESS; //sati_move_set_sector_count(sequence,scsi_io,ata_io,1,0);
+}
+
+/**
+ * @brief This method performs the retrieving of parameter LBA praparation and setting
+ *        processing flags before/after calling SCSI Verify sector command.
+ * @return Indicate if the method was successfully completed.
+ * @retval SATI_SUCCESS This is returned in all other cases.
+ */
+static
+SATI_STATUS sati_reassign_blocks_verify_condition(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void     * scsi_io,
+   void     * ata_io
+)
+{
+   U8 current_lba_bytes[8] = {0,0,0,0,0,0,0,0};
+   U32 lba_offset;
+   U8 page_size;
+   U32 index;
+   SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+
+   lba_offset = sequence->command_specific_data.reassign_blocks_process_state.lba_offset;
+   page_size = sequence->command_specific_data.reassign_blocks_process_state.lba_size;
+
+   for(index = 0; index < page_size; index++)
+   {
+      sati_get_data_byte(sequence, scsi_io, lba_offset+index,   &current_lba_bytes[index]);
+   }
+
+   if (page_size == 4)
+      set_current_lba(current_lba_bytes, ata_io);
+   else
+      set_current_long_lba(current_lba_bytes, ata_io);
+
+   status = sati_reassign_blocks_verify_command(sequence, scsi_io, ata_io);
+   sequence->command_specific_data.reassign_blocks_process_state.ata_command_sent_for_current_lba++;
+   sequence->command_specific_data.reassign_blocks_process_state.ata_command_status = SATI_REASSIGN_BLOCKS_READY_TO_SEND;
+   return  status;
+}
+
+/**
+ * @brief This method performs the retrieving of parameter LBA praparation and setting
+ *        processing flags before/after calling SCSI Write sector command.
+ * @return Indicate if the method was successfully completed.
+ * @retval SATI_SUCCESS This is returned in all other cases.
+ */
+static
+SATI_STATUS sati_reassign_blocks_write_condition(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void     * scsi_io,
+   void     * ata_io
+)
+{
+   U8 current_lba_bytes[8] = {0,0,0,0,0,0,0,0};
+   U32 lba_offset;
+   U8 page_size;
+   U32 index;
+   SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+
+   lba_offset = sequence->command_specific_data.reassign_blocks_process_state.lba_offset;
+   page_size = sequence->command_specific_data.reassign_blocks_process_state.lba_size;
+
+   for(index = 0; index < page_size; index++)
+   {
+      sati_get_data_byte(sequence, scsi_io, lba_offset+index,   &current_lba_bytes[index]);
+   }
+
+   if (page_size == 4)
+      set_current_lba(current_lba_bytes, ata_io);
+   else
+      set_current_long_lba(current_lba_bytes, ata_io);
+
+   status = sati_reassign_blocks_write_command(sequence, scsi_io, ata_io);
+   sequence->command_specific_data.reassign_blocks_process_state.ata_command_sent_for_current_lba++;
+   sequence->command_specific_data.reassign_blocks_process_state.ata_command_status = SATI_REASSIGN_BLOCKS_READY_TO_SEND;
+   return  status ;
+}
+
+
+/**
+ * @brief This method will perform the pre-processing of Reassign Blocks command and parameter.
+ */
+static
+void  sati_reassign_blocks_initial_processing(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   U32 index;
+   U8 long_lba_bit;
+   U8 long_list_bit;
+   U8 lba_offset;
+   U8  page_size;
+   U32 data_transfer_length;
+   U8 header_bytes[4]={0,0,0,0};
+
+   U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+   //A long LBA (LONGLBA) bit set to zero specifies that the REASSIGN BLOCKS defective LBA list contains four-byte LBAs.
+   //A LONGLBA bit set to one specifies that the REASSIGN BLOCKS defective LBA list contains eight-byte LBAs.
+   if ((sati_get_cdb_byte(cdb, 1) & SCSI_REASSIGN_BLOCKS_LONGLBA_BIT) == 0)
+   {
+      long_lba_bit=0;
+      page_size = 4; //beginning of lba list
+   }
+   else
+   {
+      long_lba_bit=1;
+      page_size = 8;
+   }
+
+   //The long list (LONGLIST) bit specifies which parameter list header
+   if ((sati_get_cdb_byte(cdb, 1) & SCSI_REASSIGN_BLOCKS_LONGLIST_BIT) == 0)
+   {
+      long_list_bit=0;
+   }
+   else
+   {
+      long_list_bit=1;
+   }
+
+   sequence->allocation_length = 4; //Pre-set allocation_length so that the header can be retrieved
+
+   //Get 4 bytes for headers (byte 2 & byte 3 for short header; long header all 4 bytes)
+   for(index = 0; index < 4; index++)
+   {
+      sati_get_data_byte(sequence, scsi_io, index,   &header_bytes[index]);
+   }
+
+   lba_offset = 4; //beginning of lba list
+
+   if (long_list_bit==0)
+   {
+      //Header byte 2 and 3 is the parameter list length
+      data_transfer_length = (header_bytes[2]<<8) + header_bytes[3] + lba_offset;
+   }
+   else
+   {
+      //Header byte 0, 1, 2 and 3 contain the parameter list length
+      data_transfer_length = (header_bytes[0]<<24) + (header_bytes[1]<<16) +
+         (header_bytes[2]<<8) + header_bytes[3] + lba_offset;
+   }
+
+   sequence->allocation_length = data_transfer_length;
+
+   //Initialized the global processing state
+   sequence->command_specific_data.reassign_blocks_process_state.lba_size   =     page_size;
+   sequence->command_specific_data.reassign_blocks_process_state.lba_offset =     lba_offset;
+   sequence->command_specific_data.reassign_blocks_process_state.ata_command_sent_for_current_lba = 0;
+   sequence->command_specific_data.reassign_blocks_process_state.block_lists_size       = data_transfer_length  -  lba_offset;
+   sequence->command_specific_data.reassign_blocks_process_state.size_of_data_processed = 0;
+   sequence->command_specific_data.reassign_blocks_process_state.current_lba_processed  = FALSE;
+   sequence->command_specific_data.reassign_blocks_process_state.ata_command_status     = SATI_REASSIGN_BLOCKS_COMMAND_FAIL;
+}
+
+/**
+ * @brief This method will get the data size of not yet processed data.
+ *
+ * @param[in] lba_process_state This parameter points to the processing state fields
+ *            of current block lba.
+ *
+ * @return This method returns the sizeof not yet processed data.
+ */
+static
+U32 sati_reassign_blocks_unprocessed_data_size(
+   SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T * lba_process_state
+)
+{
+   U32 unprocessed_data_size;
+
+   if(lba_process_state->block_lists_size >= lba_process_state->size_of_data_processed)
+   {
+      unprocessed_data_size = lba_process_state->block_lists_size -
+         lba_process_state->size_of_data_processed;
+   }
+   else
+   {
+      unprocessed_data_size = 0;
+   }
+
+   return unprocessed_data_size;
+}
+
+
+/**
+ * @brief This method will check verify the sector and issue multiple ATA set feature commands to complete the translation.
+ *
+ * @param[in] reassign_blocks_process_state This parameter points to the processing state fields
+ *            of current lba block.
+ *
+ *
+ * @return Indicate if the translation was successful.
+ * @retval SATI_SUCCESS
+ * @retval SATI_COMPLETE
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA
+ */
+static
+SATI_STATUS sati_reassign_blocks_process_each_lba(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+   )
+{
+   SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+   SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T * reassign_blocks_process_state;
+
+   reassign_blocks_process_state = &sequence->command_specific_data.reassign_blocks_process_state;
+
+   if((reassign_blocks_process_state->ata_command_sent_for_current_lba == 0)&&
+      (reassign_blocks_process_state->ata_command_status == SATI_REASSIGN_BLOCKS_COMMAND_FAIL))
+   {
+      reassign_blocks_process_state->size_of_data_processed += reassign_blocks_process_state->lba_size;
+      status = sati_reassign_blocks_verify_condition(sequence, scsi_io, ata_io);
+   }
+   else if((reassign_blocks_process_state->ata_command_sent_for_current_lba == 0)&&
+      (reassign_blocks_process_state->ata_command_status == SATI_REASSIGN_BLOCKS_COMMAND_SUCCESS))
+   {
+      // point to next lba
+      reassign_blocks_process_state->size_of_data_processed += reassign_blocks_process_state->lba_size;
+      reassign_blocks_process_state->lba_offset += reassign_blocks_process_state->lba_size;
+      status = sati_reassign_blocks_verify_condition(sequence, scsi_io, ata_io);
+   }
+   else if((reassign_blocks_process_state->ata_command_sent_for_current_lba == 1)&&
+      (reassign_blocks_process_state->ata_command_status == SATI_REASSIGN_BLOCKS_COMMAND_FAIL))
+   {
+      reassign_blocks_process_state->size_of_data_processed += reassign_blocks_process_state->lba_size;
+      status = sati_reassign_blocks_write_condition(sequence, scsi_io, ata_io);
+   }
+   else if((reassign_blocks_process_state->ata_command_sent_for_current_lba == 2) &&
+      (reassign_blocks_process_state->ata_command_status == SATI_REASSIGN_BLOCKS_COMMAND_SUCCESS))
+   {
+      reassign_blocks_process_state->size_of_data_processed += reassign_blocks_process_state->lba_size;
+      status = sati_reassign_blocks_verify_condition(sequence, scsi_io, ata_io);
+   }
+   else //commands sent is 2; SATI_REASSIGN_BLOCKS_COMMAND_FAIL
+   {
+      status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+
+   return status;
+}
+
+/**
+ * @brief This method will process the each lba.
+ *
+ * @param[in] reassign_blocks_process_state This parameter points to the processing state fields
+ *            of current lba.
+ *
+ * @return Indicate if the translation was successful.
+ * @retval SATI_SUCCESS
+ * @retval SATI_COMPLETE
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA
+ */
+static
+SATI_STATUS sati_reassign_blocks_process(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+
+   U32 page_size = 0; // in bytes
+   U32 size_of_data_to_be_processed;
+   U32 lba_offset;
+   SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T * reassign_blocks_process_state;
+
+   reassign_blocks_process_state = &sequence->command_specific_data.reassign_blocks_process_state;
+
+   lba_offset = reassign_blocks_process_state->lba_offset;
+   page_size  = reassign_blocks_process_state->lba_size;
+
+
+   if(sati_reassign_blocks_unprocessed_data_size(reassign_blocks_process_state) < page_size)
+   {
+      return status;
+   }
+
+   // Any more lba blocks? If not, done.
+   if(reassign_blocks_process_state->block_lists_size ==
+      reassign_blocks_process_state->size_of_data_processed)
+   {
+      sequence->state = SATI_SEQUENCE_STATE_FINAL;
+      status = SATI_COMPLETE;
+   }
+   //start processing next lba
+   else
+   {
+      size_of_data_to_be_processed = reassign_blocks_process_state->block_lists_size
+         - reassign_blocks_process_state->size_of_data_processed;
+
+      status = sati_reassign_blocks_process_each_lba(sequence, scsi_io, ata_io);
+
+   }
+
+   return status;
+}
+
+//******************************************************************************
+//* P U B L I C   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method will translate the SCSI Reassign Blocks command
+ *        into corresponding ATA commands.  Depending upon the capabilities
+ *        supported by the target different ATA commands can be selected.
+ *        Additionally, in some cases more than a single ATA command may
+ *        be required.
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the command translation was
+ *         successful.
+ * @retval SCI_COMPLETE This is returned if the command translation was
+ *         successful and no ATA commands need to be set.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
+ *         sense data has been created as a result of something specified
+ *         in the parameter data fields.
+ */
+SATI_STATUS sati_reassign_blocks_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+   SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T * reassign_blocks_process_state;
+
+   reassign_blocks_process_state = &sequence->command_specific_data.reassign_blocks_process_state;
+
+   sequence->type = SATI_SEQUENCE_REASSIGN_BLOCKS;
+
+   //Initial processing if
+   if ( sequence->state != SATI_SEQUENCE_STATE_INCOMPLETE )
+   {
+      sati_reassign_blocks_initial_processing(
+         sequence,
+         scsi_io,
+         ata_io
+      );
+   }
+
+   // start processing current lba
+   if(reassign_blocks_process_state->current_lba_processed)
+   {
+      reassign_blocks_process_state->ata_command_sent_for_current_lba = 0;
+      reassign_blocks_process_state->current_lba_processed = FALSE;
+   }
+
+   status = sati_reassign_blocks_process(sequence, scsi_io, ata_io);
+
+   if(reassign_blocks_process_state->block_lists_size ==
+      reassign_blocks_process_state->size_of_data_processed)
+   {
+      // Done this lba
+      sequence->state = SATI_SEQUENCE_STATE_FINAL;
+   }
+   else
+   {
+      sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
+   }
+
+   if(status == SATI_FAILURE_CHECK_RESPONSE_DATA)
+   {
+      sequence->state = SATI_SEQUENCE_STATE_FINAL;
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_MEDIUM_ERROR,
+         SCSI_ASC_UNRECOVERED_READ_ERROR,
+         SCSI_ASCQ_UNRECOVERED_READ_ERROR_AUTO_REALLOCATE_FAIL
+      );
+   }
+
+   return status;
+}
+
+/**
+ * @brief This method will translate the ATA command register FIS
+ *        response into an appropriate SCSI response for Reassign Blocks
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_response().
+ *
+ * @return Indicate if the response translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the data translation was
+ *         successful.
+ */
+SATI_STATUS sati_reassign_blocks_translate_response(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
+   SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T * reassign_blocks_process_state;
+
+   reassign_blocks_process_state = &sequence->command_specific_data.reassign_blocks_process_state;
+
+   if (sati_get_ata_status(register_fis) & ATA_STATUS_REG_ERROR_BIT)
+   {
+      reassign_blocks_process_state->ata_command_status = SATI_REASSIGN_BLOCKS_COMMAND_FAIL;
+
+      //Checking for the number of ATA commands attempted on current LBA, stop
+      //the seaquence after 2 commands have returned errors.
+      if(reassign_blocks_process_state->ata_command_sent_for_current_lba < 2)
+      {
+         sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
+         reassign_blocks_process_state->size_of_data_processed -= reassign_blocks_process_state->lba_size;
+         return SATI_SEQUENCE_INCOMPLETE;
+      }
+      else
+      {
+         sati_scsi_sense_data_construct(
+            sequence,
+            scsi_io,
+            SCSI_STATUS_CHECK_CONDITION,
+            SCSI_SENSE_MEDIUM_ERROR,
+            SCSI_ASC_UNRECOVERED_READ_ERROR,
+            SCSI_ASCQ_UNRECOVERED_READ_ERROR_AUTO_REALLOCATE_FAIL
+         );
+      }
+
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+   else
+   {
+      reassign_blocks_process_state->ata_command_status = SATI_REASSIGN_BLOCKS_COMMAND_SUCCESS;
+      if (reassign_blocks_process_state->ata_command_sent_for_current_lba != 2)
+         reassign_blocks_process_state->current_lba_processed = TRUE;
+
+      if (sequence->state == SATI_SEQUENCE_STATE_INCOMPLETE)
+      {
+         return SATI_SEQUENCE_INCOMPLETE;
+      }
+   }
+   return SATI_COMPLETE;
+}
+
+#endif // !defined(DISABLE_SATI_REASSIGN_BLOCKS)
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_reassign_blocks.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_reassign_blocks.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,80 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_REASSIGN_BLOCKS_H_
+#define _SATI_REASSIGN_BLOCKS_H_
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ *        translate the SCSI reassign blocks command.
+ */
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+
+
+SATI_STATUS sati_reassign_blocks_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+SATI_STATUS sati_reassign_blocks_translate_response(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+#endif // _SATI_REASSIGN_BLOCKS_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_report_luns.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_report_luns.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,124 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ *        translate the SCSI REPORT LUNS command.
+ */
+
+#if !defined(DISABLE_SATI_REPORT_LUNS)
+
+#include <dev/isci/scil/sati_report_luns.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_scsi.h>
+
+/**
+ * @brief This method will translate the REPORT LUN SCSI command.  This
+ *        command is immediately completed, since there is no applicable
+ *        ATA/ATAPI command.  The data payload is written and SATI_COMPLETE
+ *        is always returned.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @return This method always indicates the translation is complete.
+ * @retval SATI_COMPLETE This value is always returned.
+ */
+SATI_STATUS sati_report_luns_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+   // Set the data length based on the allocation length field in the CDB.
+   sequence->allocation_length = (sati_get_cdb_byte(cdb, 6) << 24) |
+                                 (sati_get_cdb_byte(cdb, 7) << 16) |
+                                 (sati_get_cdb_byte(cdb, 8) << 8)  |
+                                 (sati_get_cdb_byte(cdb, 9));
+
+   // The first 4 bytes indicate the length of the LUN list.  Each
+   // LUN entry is 8 bytes.  There is only ever LUN 0 for ATA/ATAPI
+   // devices.  The value reported is: n-7, where n is the last byte
+   // offset (i.e. 15) in the REPORT LUN data.
+   sati_set_data_byte(sequence, scsi_io, 0, 0);
+   sati_set_data_byte(sequence, scsi_io, 1, 0);
+   sati_set_data_byte(sequence, scsi_io, 2, 0);
+   sati_set_data_byte(sequence, scsi_io, 3, 8);
+
+   // Bytes 4-7 are reserved.
+   sati_set_data_byte(sequence, scsi_io, 4, 0);
+   sati_set_data_byte(sequence, scsi_io, 5, 0);
+   sati_set_data_byte(sequence, scsi_io, 6, 0);
+   sati_set_data_byte(sequence, scsi_io, 7, 0);
+
+   // Add in our single LUN of zero.
+   sati_set_data_byte(sequence, scsi_io, 8, 0);
+   sati_set_data_byte(sequence, scsi_io, 9, 0);
+   sati_set_data_byte(sequence, scsi_io, 10, 0);
+   sati_set_data_byte(sequence, scsi_io, 11, 0);
+   sati_set_data_byte(sequence, scsi_io, 12, 0);
+   sati_set_data_byte(sequence, scsi_io, 13, 0);
+   sati_set_data_byte(sequence, scsi_io, 14, 0);
+   sati_set_data_byte(sequence, scsi_io, 15, 0);
+
+   return SATI_COMPLETE;
+}
+
+#endif // !defined(DISABLE_SATI_REPORT_LUNS)
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_report_luns.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_report_luns.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,75 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_REPORT_LUNS_H_
+#define _SATI_REPORT_LUNS_H_
+
+/**
+ * @file
+ * @brief This file contains the method declarations and type defintions
+ *        required to translate the SCSI REPORT LUNS command.
+ */
+
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+#if !defined(DISABLE_SATI_REPORT_LUNS)
+SATI_STATUS sati_report_luns_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+#else // !(defined)DISABLE_SATI_REPORT_LUNS
+#define sati_report_luns_translate_command(sequence, scsi_io, ata_io) SATI_FAILURE
+#endif // !(defined)DISABLE_SATI_REPORT_LUNS
+
+#endif // _SATI_REPORT_LUNS_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_request_sense.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_request_sense.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,353 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains the implementation to translate
+ *        SCSI Request Sense command based of the SAT spec.
+ */
+
+#if !defined(DISABLE_SATI_REQUEST_SENSE)
+
+#include <dev/isci/scil/sati_request_sense.h>
+#include <dev/isci/scil/sati_device.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/intel_scsi.h>
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_sat.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_mode_pages.h>
+
+#define MRIE_BYTE 3
+#define DEXCPT_BYTE 2
+
+/**
+ * @brief This method will translate the SCSI request sense command
+ *        into corresponding ATA commands.  Depending on supported and enabled
+ *        capabilities like SMART, different ATA commands can be selected.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @return Indicates if the command translation succeeded.
+ * @retval SATI_SUCCESS indicates that the translation was supported and occurred
+ *         without error.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
+ *         the SATII is processing a format unit commmand.
+ * @retval SATI_COMPLETE indicates that the translation was supported, occurred without
+ *         error, and no additional translation is necessary.
+ */
+SATI_STATUS sati_request_sense_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+   //check if SATI is processing format unit command
+   switch(sequence->device->state)
+   {
+      case SATI_DEVICE_STATE_FORMAT_UNIT_IN_PROGRESS:
+         sati_scsi_sense_data_construct(
+            sequence,
+            scsi_io,
+            SCSI_STATUS_GOOD,
+            SCSI_SENSE_NOT_READY,
+            SCSI_ASC_LUN_FORMAT_IN_PROGRESS,
+            SCSI_ASCQ_LUN_FORMAT_IN_PROGRESS
+         );
+         return SATI_COMPLETE;
+      break;
+
+      case SATI_DEVICE_STATE_UNIT_ATTENTION_CONDITION:
+         sati_scsi_sense_data_construct(
+            sequence,
+            scsi_io,
+            SCSI_STATUS_GOOD,
+            SCSI_SENSE_UNIT_ATTENTION,
+            sequence->device->unit_attention_asc,
+            sequence->device->unit_attention_ascq
+         );
+         return SATI_COMPLETE;
+      break;
+      //sending sense data status Idle, this is set by start_stop_unit
+      case SATI_DEVICE_STATE_IDLE:
+         sati_scsi_sense_data_construct(
+            sequence,
+            scsi_io,
+            SCSI_STATUS_GOOD,
+            SCSI_SENSE_NO_SENSE,
+            SCSI_ASC_POWER_STATE_CHANGE,
+            SCSI_ASCQ_IDLE_CONDITION_ACTIVATE_BY_COMMAND
+         );
+         return SATI_COMPLETE;
+      break;
+      //sending sense data status Standby, this is set by start_stop_unit
+      case SATI_DEVICE_STATE_STANDBY:
+         sati_scsi_sense_data_construct(
+            sequence,
+            scsi_io,
+            SCSI_STATUS_GOOD,
+            SCSI_SENSE_NO_SENSE,
+            SCSI_ASC_POWER_STATE_CHANGE,
+            SCSI_ASCQ_STANDBY_CONDITION_ACTIVATE_BY_COMMAND
+         );
+         return SATI_COMPLETE;
+      break;
+
+      case SATI_DEVICE_STATE_STOPPED:
+         sati_scsi_sense_data_construct(
+            sequence,
+            scsi_io,
+            SCSI_STATUS_GOOD,
+            SCSI_SENSE_NO_SENSE,
+            SCSI_ASC_NO_ADDITIONAL_SENSE,
+            SCSI_ASCQ_NO_ADDITIONAL_SENSE
+         );
+         return SATI_COMPLETE;
+      break;
+
+      default:
+      break;
+   }
+
+   sequence->allocation_length = sati_get_cdb_byte(cdb, 4);
+
+   //Check if the device has SMART support & SMART enabled
+   if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_SUPPORT)
+   {
+       if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_ENABLE)
+       {
+            sati_ata_smart_return_status_construct(
+                           ata_io,
+                           sequence,
+                           ATA_SMART_SUB_CMD_RETURN_STATUS
+            );
+
+            sequence->type = SATI_SEQUENCE_REQUEST_SENSE_SMART_RETURN_STATUS;
+            return SATI_SUCCESS;
+        }
+   }
+   sati_ata_check_power_mode_construct(ata_io, sequence);
+   sequence->type = SATI_SEQUENCE_REQUEST_SENSE_CHECK_POWER_MODE;
+   return SATI_SUCCESS;
+}
+
+/**
+ * @brief This method will translate the response to the SATI Request Sense
+ *        translation. ATA_Check_Power_Mode and ATA_SMART_Return_Status will
+ *        be translated into a SCSI sense data response.
+ *
+ * @return SATI_STATUS Indicates if the response translation succeeded.
+ *
+ */
+SATI_STATUS sati_request_sense_translate_response(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
+   U32 mid_register;
+   U32 high_register;
+   U32 sector_count;
+   SATI_STATUS status = SATI_FAILURE;
+
+   if(sati_get_ata_status(register_fis) & ATA_STATUS_REG_ERROR_BIT)
+   {
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_ABORTED_COMMAND,
+         SCSI_ASC_NO_ADDITIONAL_SENSE ,
+         SCSI_ASCQ_NO_ADDITIONAL_SENSE
+      );
+      status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+   else
+   {
+      switch(sequence->type)
+      {
+         case SATI_SEQUENCE_REQUEST_SENSE_SMART_RETURN_STATUS:
+
+            mid_register = sati_get_ata_lba_mid(register_fis);
+            high_register = sati_get_ata_lba_high(register_fis);
+            if(mid_register == ATA_MID_REGISTER_THRESHOLD_EXCEEDED
+               && high_register == ATA_HIGH_REGISTER_THRESHOLD_EXCEEDED)
+            {
+               sati_request_sense_data_response_construct(
+                  sequence,
+                  scsi_io,
+                  SCSI_SENSE_NO_SENSE,
+                  SCSI_ASC_HARDWARE_IMPENDING_FAILURE,
+                  SCSI_ASCQ_GENERAL_HARD_DRIVE_FAILURE
+               );
+               status = SATI_COMPLETE;
+            }
+            else
+            {
+               sati_request_sense_data_response_construct(
+                  sequence,
+                  scsi_io,
+                  SCSI_SENSE_NO_SENSE,
+                  SCSI_ASC_NO_ADDITIONAL_SENSE,
+                  SCSI_ASCQ_NO_ADDITIONAL_SENSE
+               );
+               status = SATI_COMPLETE;
+            }
+         break;
+
+         case SATI_SEQUENCE_REQUEST_SENSE_CHECK_POWER_MODE:
+
+            sector_count = sati_get_ata_sector_count(register_fis);
+
+            switch(sector_count)
+            {
+                case ATA_STANDBY_POWER_MODE:
+                   sati_request_sense_data_response_construct(
+                      sequence,
+                      scsi_io,
+                      SCSI_SENSE_NO_SENSE,
+                      SCSI_ASC_POWER_STATE_CHANGE,
+                      SCSI_ASCQ_POWER_STATE_CHANGE_TO_STANDBY
+                   );
+                   status = SATI_COMPLETE;
+                break;
+
+                case ATA_IDLE_POWER_MODE:
+                   sati_request_sense_data_response_construct(
+                      sequence,
+                      scsi_io,
+                      SCSI_SENSE_NO_SENSE,
+                      SCSI_ASC_POWER_STATE_CHANGE,
+                      SCSI_ASCQ_POWER_STATE_CHANGE_TO_IDLE
+                   );
+                   status = SATI_COMPLETE;
+                break;
+
+                case ATA_ACTIVE_POWER_MODE:
+                   sati_request_sense_data_response_construct(
+                      sequence,
+                      scsi_io,
+                      SCSI_SENSE_NO_SENSE,
+                      SCSI_ASC_NO_ADDITIONAL_SENSE,
+                      SCSI_ASCQ_NO_ADDITIONAL_SENSE
+                   );
+                   status = SATI_COMPLETE;
+                break;
+
+                default:
+                break;
+             }
+         break;
+
+         default:
+            sati_request_sense_data_response_construct(
+               sequence,
+               scsi_io,
+               SCSI_SENSE_NO_SENSE,
+               SCSI_ASC_NO_ADDITIONAL_SENSE,
+               SCSI_ASCQ_NO_ADDITIONAL_SENSE
+            );
+            status = SATI_COMPLETE;
+      }
+   }
+
+   return status;
+}
+
+/**
+ * @brief This method will construct a response for the sati_request_sense
+ *        translation. The response will be returned in the data buffer instead
+ *        of the response buffer, using sense data format described in SPC-4.
+ *
+ */
+void sati_request_sense_data_response_construct(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   U8                           sense_key,
+   U8                           additional_sense_code,
+   U8                           additional_sense_code_qualifier
+)
+{
+   sati_set_data_byte(
+      sequence,
+      scsi_io,
+      0,
+      SCSI_FIXED_CURRENT_RESPONSE_CODE | SCSI_FIXED_SENSE_DATA_VALID_BIT
+   );
+
+   sati_set_data_byte(sequence, scsi_io, 1, 0);
+   sati_set_data_byte(sequence, scsi_io, 2, sense_key);
+   sati_set_data_byte(sequence, scsi_io, 3, 0);
+   sati_set_data_byte(sequence, scsi_io, 4, 0);
+   sati_set_data_byte(sequence, scsi_io, 5, 0);
+   sati_set_data_byte(sequence, scsi_io, 6, 0);
+   sati_set_data_byte(sequence, scsi_io, 7, 0);
+   sati_set_data_byte(sequence, scsi_io, 8, 0);
+   sati_set_data_byte(sequence, scsi_io, 9, 0);
+   sati_set_data_byte(sequence, scsi_io, 10, 0);
+   sati_set_data_byte(sequence, scsi_io, 11, 0);
+   sati_set_data_byte(sequence, scsi_io, 12, additional_sense_code);
+   sati_set_data_byte(sequence, scsi_io, 13, additional_sense_code_qualifier);
+   sati_set_data_byte(sequence, scsi_io, 14, 0);
+   sati_set_data_byte(sequence, scsi_io, 15, 0);
+   sati_set_data_byte(sequence, scsi_io, 16, 0);
+   sati_set_data_byte(sequence, scsi_io, 17, 0);
+}
+
+#endif // !defined(DISABLE_SATI_REQUEST_SENSE)
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_request_sense.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_request_sense.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,86 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+/**
+ * @file
+ * @brief This file contains the method definitions to translate
+ *        SCSI Request Sense command based of the SAT spec.
+ */
+
+#ifndef _SATI_REQUEST_SENSE_H_
+#define _SATI_REQUEST_SENSE_H_
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+SATI_STATUS sati_request_sense_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+SATI_STATUS sati_request_sense_translate_response(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+void sati_request_sense_data_response_construct(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   U8                           sense_key,
+   U8                           additional_sense_code,
+   U8                           additional_sense_code_qualifier
+);
+
+#endif // _SATI_REQUEST_SENSE_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_start_stop_unit.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_start_stop_unit.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,404 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ *        translate the SCSI start stop unit command.
+ */
+
+#if !defined(DISABLE_SATI_START_STOP_UNIT)
+
+#include <dev/isci/scil/sati_start_stop_unit.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_scsi.h>
+
+/**
+ * @brief This method will translate the start stop unit SCSI command into
+ *        various ATA commands depends on the value in POWER CONTIDTION, LOEJ
+ *        and START fields.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the command translation was
+ *         successful.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA Please refer to spec.
+ *
+ */
+SATI_STATUS sati_start_stop_unit_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+   switch ( SATI_START_STOP_UNIT_POWER_CONDITION(cdb) )
+   {
+      case SCSI_START_STOP_UNIT_POWER_CONDITION_START_VALID:
+         if ( SATI_START_STOP_UNIT_START_BIT(cdb) == 0
+             && SATI_START_STOP_UNIT_LOEJ_BIT(cdb) == 0 )
+         {
+            if ( SATI_START_STOP_UNIT_NO_FLUSH_BIT(cdb) == 1 )
+            {
+               //directly send ATA STANDBY_IMMEDIATE
+               sati_ata_standby_immediate_construct(ata_io, sequence);
+               sequence->command_specific_data.translated_command = ATA_STANDBY_IMMED;
+            }
+            else
+            {
+               if ( sequence->state != SATI_SEQUENCE_STATE_INCOMPLETE )
+               {
+                  //First, send ATA flush command.
+                  sati_ata_flush_cache_construct(ata_io, sequence);
+                  sequence->command_specific_data.translated_command = ATA_FLUSH_CACHE;
+
+                  //remember there is next step.
+                  sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
+               }
+               else
+               {
+                  //the first step, flush cache command, has completed.
+                  //Send standby immediate now.
+                  sati_ata_standby_immediate_construct(ata_io, sequence);
+                  sequence->command_specific_data.translated_command = ATA_STANDBY_IMMED;
+
+               }
+            }
+         }
+         else if ( SATI_START_STOP_UNIT_START_BIT(cdb) == 0
+                  && SATI_START_STOP_UNIT_LOEJ_BIT(cdb) == 1 )
+         {
+            //need to know whether the device supports removable medial feature set.
+            if (sequence->device->capabilities & SATI_DEVICE_CAP_REMOVABLE_MEDIA)
+            {
+               //send ATA MEDIA EJECT command.
+               sati_ata_media_eject_construct(ata_io, sequence);
+               sequence->command_specific_data.translated_command = ATA_MEDIA_EJECT;
+            }
+            else
+            {
+               sati_scsi_sense_data_construct(
+                  sequence,
+                  scsi_io,
+                  SCSI_STATUS_CHECK_CONDITION,
+                  SCSI_SENSE_ILLEGAL_REQUEST,
+                  SCSI_ASC_INVALID_FIELD_IN_CDB,
+                  SCSI_ASCQ_INVALID_FIELD_IN_CDB
+               );
+               return SATI_FAILURE_CHECK_RESPONSE_DATA;
+            }
+         }
+         else if ( SATI_START_STOP_UNIT_START_BIT(cdb) == 1
+                  && SATI_START_STOP_UNIT_LOEJ_BIT(cdb) == 0 )
+         {
+            //send an ATA verify command
+            sati_ata_read_verify_sectors_construct(ata_io, sequence);
+            sequence->command_specific_data.translated_command = ATA_READ_VERIFY_SECTORS;
+         }
+         else if ( SATI_START_STOP_UNIT_START_BIT(cdb) == 1
+                  && SATI_START_STOP_UNIT_LOEJ_BIT(cdb) == 1 )
+         {
+            sati_scsi_sense_data_construct(
+               sequence,
+               scsi_io,
+               SCSI_STATUS_CHECK_CONDITION,
+               SCSI_SENSE_ILLEGAL_REQUEST,
+               SCSI_ASC_INVALID_FIELD_IN_CDB,
+               SCSI_ASCQ_INVALID_FIELD_IN_CDB
+            );
+            return SATI_FAILURE_CHECK_RESPONSE_DATA;
+         }
+
+         break;
+      //Power Condition Field is set to 0x01(Device to transition to Active state)
+      case SCSI_START_STOP_UNIT_POWER_CONDITION_ACTIVE:
+
+         if( sequence->state != SATI_SEQUENCE_STATE_INCOMPLETE )
+         {
+            sati_ata_idle_construct(ata_io, sequence);
+            sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
+            sequence->command_specific_data.translated_command = ATA_IDLE;
+         }
+         else
+         {
+            sati_ata_read_verify_sectors_construct(ata_io, sequence);
+            sequence->command_specific_data.translated_command = ATA_READ_VERIFY_SECTORS;
+         }
+         break;
+
+      //Power Condition Field is set to 0x02(Device to transition to Idle state)
+      case SCSI_START_STOP_UNIT_POWER_CONDITION_IDLE:
+
+         if( SATI_START_STOP_UNIT_NO_FLUSH_BIT(cdb) == 0 &&
+             sequence->state != SATI_SEQUENCE_STATE_INCOMPLETE )
+         {
+            sati_ata_flush_cache_construct(ata_io, sequence);
+            sequence->command_specific_data.translated_command = ATA_FLUSH_CACHE;
+            sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
+         }
+         else
+         {
+            if( SATI_START_STOP_UNIT_POWER_CONDITION_MODIFIER(cdb) == 0 )
+            {
+               sati_ata_idle_immediate_construct(ata_io, sequence);
+            }
+            else
+            {
+               sati_ata_idle_immediate_unload_construct(ata_io, sequence);
+            }
+            sequence->command_specific_data.translated_command = ATA_IDLE_IMMED;
+         }
+         break;
+
+      //Power Condition Field is set to 0x03(Device to transition to Standby state)
+      case SCSI_START_STOP_UNIT_POWER_CONDITION_STANDBY:
+         if( SATI_START_STOP_UNIT_NO_FLUSH_BIT(cdb) == 0 &&
+            sequence->state != SATI_SEQUENCE_STATE_INCOMPLETE )
+         {
+            sati_ata_flush_cache_construct(ata_io, sequence);
+            sequence->command_specific_data.translated_command = ATA_FLUSH_CACHE;
+            sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
+         }
+         else
+         {
+            sati_ata_standby_immediate_construct(ata_io, sequence);
+            sequence->command_specific_data.translated_command = ATA_STANDBY_IMMED;
+         }
+         break;
+
+      //Power Condition Field is set to 0xB(force Standby state)
+      case SCSI_START_STOP_UNIT_POWER_CONDITION_FORCE_S_CONTROL:
+
+         if( SATI_START_STOP_UNIT_NO_FLUSH_BIT(cdb) == 0 &&
+            sequence->state != SATI_SEQUENCE_STATE_INCOMPLETE )
+         {
+            sati_ata_flush_cache_construct(ata_io, sequence);
+            sequence->command_specific_data.translated_command = ATA_FLUSH_CACHE;
+            sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
+         }
+         else
+         {
+            sati_ata_standby_construct(ata_io, sequence, 0);
+            sequence->command_specific_data.translated_command = ATA_STANDBY;
+         }
+         break;
+
+      case SCSI_START_STOP_UNIT_POWER_CONDITION_LU_CONTROL:
+      default:  //TBD.
+         sati_scsi_sense_data_construct(
+            sequence,
+            scsi_io,
+            SCSI_STATUS_CHECK_CONDITION,
+            SCSI_SENSE_ILLEGAL_REQUEST,
+            SCSI_ASC_INVALID_FIELD_IN_CDB,
+            SCSI_ASCQ_INVALID_FIELD_IN_CDB
+         );
+         return SATI_FAILURE_CHECK_RESPONSE_DATA;
+         break;
+   }
+
+   if ( SATI_START_STOP_UNIT_IMMED_BIT(cdb) == 1 )
+   {
+      //@todo: return good status now.
+      ;
+   }
+   sequence->type = SATI_SEQUENCE_START_STOP_UNIT;
+   return SATI_SUCCESS;
+}
+
+
+/**
+ * @brief This method will translate the ATA command register FIS
+ *        response into an appropriate SCSI response for START STOP UNIT.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_response().
+ *
+ * @return Indicate if the response translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the data translation was
+ *         successful.
+ */
+SATI_STATUS sati_start_stop_unit_translate_response(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
+   U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+   if (sati_get_ata_status(register_fis) & ATA_STATUS_REG_ERROR_BIT)
+   {
+      switch ( sequence->command_specific_data.translated_command )
+      {
+         case ATA_FLUSH_CACHE:
+         case ATA_STANDBY_IMMED:
+         case ATA_IDLE_IMMED:
+         case ATA_IDLE:
+         case ATA_STANDBY:
+            //Note: There is lack of reference in spec of the error handling for
+            //READ_VERIFY command.
+         case ATA_READ_VERIFY_SECTORS:
+            sati_scsi_sense_data_construct(
+               sequence,
+               scsi_io,
+               SCSI_STATUS_CHECK_CONDITION,
+               SCSI_SENSE_ABORTED_COMMAND,
+               SCSI_ASC_COMMAND_SEQUENCE_ERROR,
+               SCSI_ASCQ_NO_ADDITIONAL_SENSE
+            );
+            break;
+
+         case ATA_MEDIA_EJECT:
+            sati_scsi_sense_data_construct(
+               sequence,
+               scsi_io,
+               SCSI_STATUS_CHECK_CONDITION,
+               SCSI_SENSE_ABORTED_COMMAND,
+               SCSI_ASC_MEDIA_LOAD_OR_EJECT_FAILED,
+               SCSI_ASCQ_NO_ADDITIONAL_SENSE
+            );
+            break;
+
+         default:
+            sati_scsi_sense_data_construct(
+               sequence,
+               scsi_io,
+               SCSI_STATUS_CHECK_CONDITION,
+               SCSI_SENSE_ILLEGAL_REQUEST,
+               SCSI_ASC_INVALID_FIELD_IN_CDB,
+               SCSI_ASCQ_INVALID_FIELD_IN_CDB
+            );
+            break;
+      }
+      sequence->state = SATI_SEQUENCE_STATE_FINAL;
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+   else
+   {
+      switch ( sequence->command_specific_data.translated_command )
+      {
+         case ATA_READ_VERIFY_SECTORS:
+
+            sati_scsi_sense_data_construct(
+               sequence,
+               scsi_io,
+               SCSI_STATUS_GOOD,
+               SCSI_SENSE_NO_SENSE,
+               SCSI_ASC_NO_ADDITIONAL_SENSE,
+               SCSI_ASCQ_NO_ADDITIONAL_SENSE
+            );
+            //device state is now operational(active)
+            sequence->device->state = SATI_DEVICE_STATE_OPERATIONAL;
+            sequence->state = SATI_SEQUENCE_STATE_FINAL;
+            break;
+
+         case ATA_IDLE_IMMED:
+
+            sati_scsi_sense_data_construct(
+               sequence,
+               scsi_io,
+               SCSI_STATUS_GOOD,
+               SCSI_SENSE_NO_SENSE,
+               SCSI_ASC_NO_ADDITIONAL_SENSE,
+               SCSI_ASCQ_NO_ADDITIONAL_SENSE
+            );
+            sequence->device->state = SATI_DEVICE_STATE_IDLE;
+            sequence->state = SATI_SEQUENCE_STATE_FINAL;
+            break;
+
+         //These three commands will be issued when the power condition is 0x00 or 0x03
+         case ATA_MEDIA_EJECT:
+         case ATA_STANDBY:
+         case ATA_STANDBY_IMMED:
+
+            sati_scsi_sense_data_construct(
+               sequence,
+               scsi_io,
+               SCSI_STATUS_GOOD,
+               SCSI_SENSE_NO_SENSE,
+               SCSI_ASC_NO_ADDITIONAL_SENSE,
+               SCSI_ASCQ_NO_ADDITIONAL_SENSE
+            );
+
+            if( SATI_START_STOP_UNIT_POWER_CONDITION(cdb) == 0 )
+            {
+               sequence->device->state = SATI_DEVICE_STATE_STOPPED;
+            }
+            else
+            {
+               sequence->device->state = SATI_DEVICE_STATE_STANDBY;
+            }
+            sequence->state = SATI_SEQUENCE_STATE_FINAL;
+            break;
+
+         default:
+            //FLUSH Cache command does not require any success handling
+            break;
+      }
+
+      if (sequence->state == SATI_SEQUENCE_STATE_INCOMPLETE)
+      {
+         return SATI_SEQUENCE_INCOMPLETE;
+      }
+   }
+   return SATI_COMPLETE;
+}
+
+#endif // !defined(DISABLE_SATI_START_STOP_UNIT)
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_start_stop_unit.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_start_stop_unit.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,102 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_START_STOP_UNIT_H_
+#define _SATI_START_STOP_UNIT_H_
+
+/**
+ * @file
+ * @brief This file contains the method declarations and type definitions
+ *        required to translate the SCSI start_stop_unit commands.
+ */
+
+#include <dev/isci/scil/intel_scsi.h>
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+#define SATI_START_STOP_UNIT_POWER_CONDITION(cdb) \
+   (( sati_get_cdb_byte(cdb, 4) & SCSI_START_STOP_UNIT_POWER_CONDITION_MASK ) \
+    >> SCSI_START_STOP_UNIT_POWER_CONDITION_SHIFT)
+
+#define SATI_START_STOP_UNIT_START_BIT(cdb) \
+   (( sati_get_cdb_byte(cdb, 4) & SCSI_START_STOP_UNIT_START_BIT_MASK ) \
+    >> SCSI_START_STOP_UNIT_START_BIT_SHIFT)
+
+#define SATI_START_STOP_UNIT_LOEJ_BIT(cdb) \
+   (( sati_get_cdb_byte(cdb, 4) & SCSI_START_STOP_UNIT_LOEJ_BIT_MASK ) \
+    >> SCSI_START_STOP_UNIT_LOEJ_BIT_SHIFT)
+
+#define SATI_START_STOP_UNIT_NO_FLUSH_BIT(cdb) \
+   (( sati_get_cdb_byte(cdb, 4) & SCSI_START_STOP_UNIT_NO_FLUSH_MASK ) \
+    >> SCSI_START_STOP_UNIT_NO_FLUSH_SHIFT)
+
+#define SATI_START_STOP_UNIT_IMMED_BIT(cdb) \
+   (( sati_get_cdb_byte(cdb, 1) & SCSI_START_STOP_UNIT_IMMED_MASK ) \
+    >> SCSI_START_STOP_UNIT_IMMED_SHIFT)
+
+#define SATI_START_STOP_UNIT_POWER_CONDITION_MODIFIER(cdb) \
+   (( sati_get_cdb_byte(cdb, 3) & SCSI_START_STOP_UNIT_POWER_CONDITION_MODIFIER_MASK) \
+   >> SCSI_START_STOP_UNIT_POWER_CONDITION_MODIFIER_SHIFT)
+
+SATI_STATUS sati_start_stop_unit_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+SATI_STATUS sati_start_stop_unit_translate_response(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+#endif // _SATI_START_STOP_UNIT_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_synchronize_cache.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_synchronize_cache.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,119 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains the method implementations for translating
+ *        the SCSI SYNCHRONIZE_CACHE (10, 16-byte) commands.
+ */
+
+#if !defined(DISABLE_SATI_SYNCHRONIZE_CACHE)
+
+#include <dev/isci/scil/sati_synchronize_cache.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_scsi.h>
+#include <dev/isci/scil/intel_sat.h>
+
+//******************************************************************************
+//* P R I V A T E   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method performs the SCSI SYNCHRONIZE_CACHE 10 and 16 command translation
+ *        functionality common to all SYNCHRONIZE_CACHE command sizes.
+ *        This includes:
+ *        - setting the command register
+ *        - setting the device head register
+ *        - filling in fields in the SATI_TRANSLATOR_SEQUENCE object.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @return Indicate if the method was successfully completed.
+ * @retval SATI_SUCCESS This is returned in all other cases.
+ */
+SATI_STATUS sati_synchronize_cache_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   U8 * cdb          = sati_cb_get_cdb_address(scsi_io);
+   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+   sequence->type           = SATI_SEQUENCE_SYNCHRONIZE_CACHE;
+   sequence->protocol       = SAT_PROTOCOL_NON_DATA;
+   sequence->data_direction = SATI_DATA_DIRECTION_NONE;
+
+   if (sati_get_cdb_byte(cdb, 1) & SCSI_SYNCHRONIZE_CACHE_IMMED_ENABLED)
+   {
+      //currently we ignore immed bit.
+      ;
+   }
+
+   // Ensure the device supports the 48 bit feature set.
+   if (sequence->device->capabilities & SATI_DEVICE_CAP_48BIT_ENABLE)
+      sati_set_ata_command(register_fis, ATA_FLUSH_CACHE_EXT);
+   else
+      sati_set_ata_command(register_fis, ATA_FLUSH_CACHE);
+
+   return SATI_SUCCESS;
+}
+
+#endif // !defined(DISABLE_SATI_SYNCHRONIZE_CACHE)
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_synchronize_cache.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_synchronize_cache.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,71 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_SYNCHRONIZE_CACHE_H_
+#define _SATI_SYNCHRONIZE_CACHE_H_
+
+/**
+ * @file
+ * @brief This file contains the method prototypes and constructs
+ *        for translating the SCSI SYNCHRONIZE CACHE (10, 16-byte) commands.
+ */
+
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+SATI_STATUS sati_synchronize_cache_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+#endif // _SATI_SYNCHRONIZE_CACHE_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_test_unit_ready.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_test_unit_ready.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,186 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ *        translate the SCSI test unit ready command.
+ */
+
+#if !defined(DISABLE_SATI_TEST_UNIT_READY)
+
+#include <dev/isci/scil/sati_test_unit_ready.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_scsi.h>
+
+/**
+ * @brief This method will translate the test unit ready SCSI command into
+ *        an ATA CHECK POWER MODE command.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the command translation was
+ *         successful.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if the
+ *         LBA field is not 0, the PMI bit is not 0.
+ */
+SATI_STATUS sati_test_unit_ready_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   /**
+    * SAT dictates:
+    * - the device should be in a state to receive commands
+    * - a stopped device should cause sense data.
+    * - a format unit in progresss should cause sense data.
+    * - a self-test in progress should cause sense data.
+    * - a device fault occurred on previous request should cause sense data.
+    * - handling the removable media feature set isn't supported according to
+    *   SAT specifications.
+    */
+   if (sequence->device->state == SATI_DEVICE_STATE_STOPPED)
+   {
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_NOT_READY,
+         SCSI_ASC_INITIALIZING_COMMAND_REQUIRED,
+         SCSI_ASCQ_INITIALIZING_COMMAND_REQUIRED
+      );
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+   else if (sequence->device->state
+            == SATI_DEVICE_STATE_SELF_TEST_IN_PROGRESS)
+   {
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_NOT_READY,
+         SCSI_ASC_LUN_SELF_TEST_IN_PROGRESS,
+         SCSI_ASCQ_LUN_SELF_TEST_IN_PROGRESS
+      );
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+   else if (sequence->device->state
+            == SATI_DEVICE_STATE_FORMAT_UNIT_IN_PROGRESS)
+   {
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_NOT_READY,
+         SCSI_ASC_LUN_FORMAT_IN_PROGRESS,
+         SCSI_ASCQ_LUN_FORMAT_IN_PROGRESS
+      );
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+
+   // The CDB is properly formed and the device is ready.
+   sequence->type = SATI_SEQUENCE_TEST_UNIT_READY;
+
+   sati_ata_check_power_mode_construct(ata_io, sequence);
+   return SATI_SUCCESS;
+}
+
+/**
+ * @brief This method will translate the ATA CHECK POWER MODE register FIS
+ *        response into an appropriate SCSI response.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_response().
+ *
+ * @return Indicate if the response translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the data translation was
+ *         successful.
+ */
+SATI_STATUS sati_test_unit_ready_translate_response(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
+
+   /**
+    * SAT dictates:
+    * - If the ATA CHECK POWER MODE command returns an error, then
+    *   return sense data indicating the LOGICAL UNIT DOES NOT RESPONSE
+    *   TO SELECTION.
+    * - All other cases are considered successful.
+    */
+   if (sati_get_ata_status(register_fis) & ATA_STATUS_REG_ERROR_BIT)
+   {
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_NOT_READY,
+         SCSI_ASC_LUN_NOT_RESPOND_TO_SELECTION,
+         SCSI_ASCQ_LUN_NOT_RESPOND_TO_SELECTION
+      );
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+
+   return SATI_COMPLETE;
+}
+
+#endif // !defined(DISABLE_SATI_TEST_UNIT_READY)
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_test_unit_ready.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_test_unit_ready.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,79 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_TEST_UNIT_READY_H_
+#define _SATI_TEST_UNIT_READY_H_
+
+/**
+ * @file
+ * @brief This file contains the method interfaces required to
+ *        translate the SCSI test unit ready command and corresponding
+ *        ATA responses.
+ */
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+SATI_STATUS sati_test_unit_ready_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * translator_sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+SATI_STATUS sati_test_unit_ready_translate_response(
+   SATI_TRANSLATOR_SEQUENCE_T * translator_sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+#endif // _SATI_TEST_UNIT_READY_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_translator_sequence.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_translator_sequence.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,361 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_TRANSLATOR_SEQUENCE_H_
+#define _SATI_TRANSLATOR_SEQUENCE_H_
+
+/**
+ * @file
+ * @brief This file contains all of the defintions for the SATI translator
+ *        sequence.  A translator sequence is simply a defintion for the
+ *        various sequences of commands that occur in this translator.
+ */
+
+#include <dev/isci/scil/sati_device.h>
+
+/**
+ * @enum _SATI_TRANSLATOR_SEQUENCE_TYPE
+ *
+ * @brief This enumeration defines the possible sequence types for the
+ *        translator.
+ */
+typedef enum _SATI_TRANSLATOR_SEQUENCE_TYPE
+{
+   // SCSI Primary Command (SPC) sequences.
+   SATI_SEQUENCE_REPORT_LUNS,
+   SATI_SEQUENCE_TEST_UNIT_READY,
+   SATI_SEQUENCE_INQUIRY_STANDARD,
+   SATI_SEQUENCE_INQUIRY_SUPPORTED_PAGES,
+   SATI_SEQUENCE_INQUIRY_SERIAL_NUMBER,
+   SATI_SEQUENCE_INQUIRY_DEVICE_ID,
+   SATI_SEQUENCE_INQUIRY_ATA_INFORMATION,
+   SATI_SEQUENCE_INQUIRY_BLOCK_DEVICE,
+   SATI_SEQUENCE_INQUIRY_EXECUTE_DEVICE_DIAG,
+   SATI_SEQUENCE_MODE_SENSE_6_CACHING,
+   SATI_SEQUENCE_MODE_SENSE_6_INFORMATIONAL_EXCP_CONTROL,
+   SATI_SEQUENCE_MODE_SENSE_6_READ_WRITE_ERROR,
+   SATI_SEQUENCE_MODE_SENSE_6_DISCONNECT_RECONNECT,
+   SATI_SEQUENCE_MODE_SENSE_6_CONTROL,
+   SATI_SEQUENCE_MODE_SENSE_6_POWER_CONDITION,
+   SATI_SEQUENCE_MODE_SENSE_6_ALL_PAGES,
+   SATI_SEQUENCE_MODE_SENSE_10_CACHING,
+   SATI_SEQUENCE_MODE_SENSE_10_INFORMATIONAL_EXCP_CONTROL,
+   SATI_SEQUENCE_MODE_SENSE_10_READ_WRITE_ERROR,
+   SATI_SEQUENCE_MODE_SENSE_10_DISCONNECT_RECONNECT,
+   SATI_SEQUENCE_MODE_SENSE_10_CONTROL,
+   SATI_SEQUENCE_MODE_SENSE_10_POWER_CONDITION,
+   SATI_SEQUENCE_MODE_SENSE_10_ALL_PAGES,
+   SATI_SEQUENCE_MODE_SELECT_MODE_PAGE_CACHING,
+   SATI_SEQUENCE_MODE_SELECT_MODE_POWER_CONDITION,
+   SATI_SEQUENCE_MODE_SELECT_MODE_INFORMATION_EXCEPT_CONTROL,
+
+      //Log Sense Sequences
+   SATI_SEQUENCE_LOG_SENSE_SELF_TEST_LOG_PAGE,
+   SATI_SEQUENCE_LOG_SENSE_EXTENDED_SELF_TEST_LOG_PAGE,
+   SATI_SEQUENCE_LOG_SENSE_SUPPORTED_LOG_PAGE,
+   SATI_SEQUENCE_LOG_SENSE_INFO_EXCEPTION_LOG_PAGE,
+
+   // SCSI Block Command (SBC) sequences.
+
+   SATI_SEQUENCE_READ_6,
+   SATI_SEQUENCE_READ_10,
+   SATI_SEQUENCE_READ_12,
+   SATI_SEQUENCE_READ_16,
+
+   SATI_SEQUENCE_READ_CAPACITY_10,
+   SATI_SEQUENCE_READ_CAPACITY_16,
+
+   SATI_SEQUENCE_SYNCHRONIZE_CACHE,
+
+   SATI_SEQUENCE_VERIFY_10,
+   SATI_SEQUENCE_VERIFY_12,
+   SATI_SEQUENCE_VERIFY_16,
+
+   SATI_SEQUENCE_WRITE_6,
+   SATI_SEQUENCE_WRITE_10,
+   SATI_SEQUENCE_WRITE_12,
+   SATI_SEQUENCE_WRITE_16,
+
+   SATI_SEQUENCE_WRITE_AND_VERIFY,
+
+   SATI_SEQUENCE_START_STOP_UNIT,
+
+   SATI_SEQUENCE_REASSIGN_BLOCKS,
+
+   // SCSI Task Requests sequences
+
+   SATI_SEQUENCE_LUN_RESET,
+   SATI_SEQUENCE_ABORT_TASK_SET,
+
+   SATI_SEQUENCE_REQUEST_SENSE_SMART_RETURN_STATUS,
+   SATI_SEQUENCE_REQUEST_SENSE_CHECK_POWER_MODE,
+
+   SATI_SEQUENCE_WRITE_LONG,
+
+   SATI_SEQUENCE_UNMAP,
+
+   SATI_SEQUENCE_ATA_PASSTHROUGH_12,
+   SATI_SEQUENCE_ATA_PASSTHROUGH_16,
+
+   SATI_SEQUENCE_READ_BUFFER,
+   SATI_SEQUENCE_WRITE_BUFFER,
+   SATI_SEQUENCE_WRITE_BUFFER_MICROCODE
+
+} SATI_TRANSLATOR_SEQUENCE_TYPE;
+
+#define SATI_SEQUENCE_TYPE_READ_MIN SATI_SEQUENCE_READ_6
+#define SATI_SEQUENCE_TYPE_READ_MAX SATI_SEQUENCE_READ_16
+
+/**
+ * @name SATI_SEQUENCE_STATES
+ *
+ * These constants depict the various state values associated with a
+ * translation sequence.
+ */
+/*@{*/
+#define SATI_SEQUENCE_STATE_INITIAL            0
+#define SATI_SEQUENCE_STATE_TRANSLATE_DATA     1
+#define SATI_SEQUENCE_STATE_AWAIT_RESPONSE     2
+#define SATI_SEQUENCE_STATE_FINAL              3
+#define SATI_SEQUENCE_STATE_INCOMPLETE         4
+#define SATI_SEQUENCE_STATE_READ_ERROR         5
+/*@}*/
+
+/**
+ * @name SATI_DATA_DIRECTIONS
+ *
+ * These constants depict the various types of data directions for a
+ * translation sequence.  Data can flow in/out (read/write) or no data at
+ * all.
+ */
+/*@{*/
+#define SATI_DATA_DIRECTION_NONE 0
+#define SATI_DATA_DIRECTION_IN   1
+#define SATI_DATA_DIRECTION_OUT  2
+/*@}*/
+
+/**
+ * @struct SATI_MODE_SELECT_PROCESSING_STATE
+ *
+ * @brief This structure contains all of the current processing states
+ *        for processing mode select 6 and 10 commands' parameter fields.
+ */
+typedef  struct SATI_MODE_SELECT_PROCESSING_STATE
+{
+   U8       * mode_pages;
+   U32      mode_page_offset;
+   U32      mode_pages_size;
+   U32      size_of_data_processed;
+   U32      total_ata_command_sent;
+   U32      ata_command_sent_for_cmp; // cmp: current mode page
+   BOOL     current_mode_page_processed;
+
+} SATI_MODE_SELECT_PROCESSING_STATE_T;
+
+
+enum SATI_REASSIGN_BLOCKS_ATA_COMMAND_STATUS
+{
+   SATI_REASSIGN_BLOCKS_READY_TO_SEND,
+   SATI_REASSIGN_BLOCKS_COMMAND_FAIL,
+   SATI_REASSIGN_BLOCKS_COMMAND_SUCCESS,
+};
+
+/**
+ * @struct SATI_REASSIGN_BLOCKS_PROCESSING_STATE
+ *
+ * @brief This structure contains all of the current processing states
+ *        for processing reassign block command's parameter fields.
+ */
+typedef struct SATI_REASSIGN_BLOCKS_PROCESSING_STATE
+{
+   U32      lba_offset;
+   U32      block_lists_size;
+   U8       lba_size;
+   U32      size_of_data_processed;
+   U32      ata_command_sent_for_current_lba;
+   BOOL     current_lba_processed;
+   enum     SATI_REASSIGN_BLOCKS_ATA_COMMAND_STATUS  ata_command_status;
+
+}SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T;
+
+#define SATI_ATAPI_REQUEST_SENSE_CDB_LENGTH 12
+
+/**
+ * @struct SATI_ATAPI_DATA
+ *
+ * @brief The SATI_ATAPI_DATA structure is for sati atapi IO specific data.
+ */
+typedef struct SATI_ATAPI_DATA
+{
+  U8 request_sense_cdb[SATI_ATAPI_REQUEST_SENSE_CDB_LENGTH];
+} SATI_ATAPI_DATA_T;
+
+
+enum SATI_UNMAP_ATA_COMMAND_STATUS
+{
+   SATI_UNMAP_READY_TO_SEND,
+   SATI_UNMAP_COMMAND_FAIL,
+   SATI_UNMAP_COMMAND_SUCCESS,
+};
+
+/**
+ * @struct SATI_UNMAP_PROCESSING_STATE
+ *
+ * @brief This structure contains all of the current processing states
+ *        for processing unmap command data translation.
+ */
+typedef struct SATI_UNMAP_PROCESSING_STATE
+{
+   U32      max_unmap_block_descriptors;
+   U32      current_unmap_block_descriptor_index;
+   U32      current_lba_count;
+   SATI_LBA current_lba;
+   SATI_LBA next_lba;
+   U32      max_lba_range_entries;
+   void *   current_dsm_descriptor;
+   void *   virtual_unmap_buffer;
+   U32      physical_unmap_buffer_low;
+   U32      physical_unmap_buffer_high;
+   void *   unmap_buffer_sgl_pair;
+} SATI_UNMAP_PROCESSING_STATE_T;
+
+/**
+ * @struct SATI_TRANSLATOR_SEQUENCE
+ *
+ * @brief This structure contains all of the translation information
+ *        associated with a particular request.
+ */
+typedef struct SATI_TRANSLATOR_SEQUENCE
+{
+   /**
+    * This field contains the sequence type determined by the SATI.
+    */
+   U8 type;
+
+   /**
+    * This field indicates the current state for the sequence.
+    */
+   U8 state;
+
+   /**
+    * This field indicates the data direction (none, read, or write) for
+    * the translated request.
+    */
+   U8 data_direction;
+
+   /**
+    * This field contains the SATA/ATA protocol to be utilized during
+    * the IO transfer.
+    */
+   U8 protocol;
+
+   /**
+    * This field is utilized for sequences requiring data translation.
+    * It specifies the amount of data requested by the caller from the
+    * operation.  It's necessary, because at times the user requests less
+    * data than is available.  Thus, we need to avoid overrunning the
+    * buffer.
+    */
+   U32 allocation_length;
+
+   /**
+    * This field specifies the amount of data that will actually be
+    * transfered across the wire for this ATA request.
+    */
+   U32 ata_transfer_length;
+
+   /**
+   * This field specifies the amount of data bytes that have been
+   * set in a translation sequence. It will be incremented every time
+   * a data byte has been set by a sati translation.
+   */
+   U16 number_data_bytes_set;
+
+   /**
+   * This field indicates whether or not the sense response has been set
+   * by the translation sequence.
+   */
+   BOOL is_sense_response_set;
+
+   /**
+    * This field indicates whether or not the translation requires
+    * response translation.
+    */
+   BOOL is_translate_response_required;
+
+   /**
+    * This field specifies the remote device context for which this
+    * translator sequence is destined.
+    */
+   SATI_DEVICE_T * device;
+
+   /**
+    * This field is utilized to provide the translator with memory space
+    * required for translations that utilize multiple requests.
+    */
+   union {
+      U32 translated_command;
+      U32 move_sector_count;
+      U32 scratch;
+      SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T   reassign_blocks_process_state;
+      SATI_MODE_SELECT_PROCESSING_STATE_T       process_state;
+      SATI_UNMAP_PROCESSING_STATE_T             unmap_process_state;
+      SATI_ATAPI_DATA_T                         sati_atapi_data;
+   } command_specific_data;
+
+} SATI_TRANSLATOR_SEQUENCE_T;
+
+
+
+#endif // _SATI_TRANSLATOR_SEQUENCE_H_
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_types.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_types.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,152 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_TYPES_H_
+#define _SATI_TYPES_H_
+
+/**
+ * @file
+ * @brief This file contains various type definitions to be utilized with
+ *        SCSI to ATA Translation Implementation.
+ */
+
+#include <dev/isci/types.h>
+
+/**
+ * @enum _SATI_STATUS
+ *
+ * @brief This enumeration defines the possible return values from the
+ *        SATI translation methods.
+ */
+typedef enum _SATI_STATUS
+{
+   /**
+    * This indicates that the translation was supported and occurred
+    * without error.
+    */
+   SATI_SUCCESS,
+
+   /**
+    * This indicates that the translation was supported and occurred
+    * without error.
+    * Additionally, this indicates the translation actually already
+    * translated the scatter gather list elements appropriately as
+    * well.
+    */
+   SATI_SUCCESS_SGL_TRANSLATED,
+
+   /**
+    * This indicates that the translation was supported, occurred without
+    * error, and no additional translation is necessary.  This is done in
+    * conditions where the SCSI command doesn't require any interaction with
+    * the remote device.
+    */
+   SATI_COMPLETE,
+
+   /**
+   * This indicated everything SATI_COMPLETE does in addition to the response data
+     not using all the memory allocated by the OS.
+   */
+   SATI_COMPLETE_IO_DONE_EARLY,
+
+   /**
+    * This indicates that translator sequence has finished some specific
+    * command in the sequence, but additional commands are necessary.
+    */
+   SATI_SEQUENCE_INCOMPLETE,
+
+   /**
+    * This indicates a general failure has occurred for which no further
+    * specification information is available.
+    */
+   SATI_FAILURE,
+
+   /**
+    * This indicates that the result of the IO request indicates a
+    * failure.  The caller should reference the corresponding response
+    * data for further details.
+    */
+   SATI_FAILURE_CHECK_RESPONSE_DATA,
+
+   /**
+    * This status indicates that the supplied sequence type doesn't map
+    * to an existing definition.
+    */
+   SATI_FAILURE_INVALID_SEQUENCE_TYPE,
+
+   /**
+    * This status indicates that the supplied sequence state doesn't match
+    * the operation being requested by the user.
+    */
+   SATI_FAILURE_INVALID_STATE
+
+} SATI_STATUS;
+
+#if (  !defined(DISABLE_SATI_MODE_SENSE)      \
+    || !defined(DISABLE_SATI_MODE_SELECT)     \
+    || !defined(DISABLE_SATI_REQUEST_SENSE) ) \
+
+#if !defined(ENABLE_SATI_MODE_PAGES)
+/**
+ * This macro enables the common mode page data structures and code.
+ * Currently, MODE SENSE, MODE SELECT, and REQUEST SENSE all make
+ * reference to this common code.  As a result, enable the common
+ * mode page code if any of these 3 are being translated.
+ */
+#define ENABLE_SATI_MODE_PAGES
+#endif // !defined(ENABLE_SATI_MODE_PAGES)
+
+#endif // MODE_SENSE/SELECT/REQUEST_SENSE
+
+#endif // _SATI_TYPES_H_
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_unmap.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_unmap.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,609 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ *        translate the SCSI unmap command.
+ */
+
+#if !defined(DISABLE_SATI_UNMAP)
+
+#include <dev/isci/scil/sati_unmap.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_scsi.h>
+#include <dev/isci/scil/intel_sat.h>
+
+//******************************************************************************
+//* P R I V A T E   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method translates a given number of DSM
+ *        requests into DSM blocks based on the devices logical block size
+ *
+ * @return Number of DSM blocks required for the DSM descriptor count
+ */
+U32 sati_unmap_calculate_dsm_blocks(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   U32                          dsm_descriptor_count
+)
+{
+   U32 blocks = (dsm_descriptor_count * sizeof(TRIM_PAIR))/sequence->device->logical_block_size;
+   if ((dsm_descriptor_count * sizeof(TRIM_PAIR)) % sequence->device->logical_block_size)
+   {
+       blocks++;
+   }
+   return blocks;
+}
+
+/**
+ * @brief This method performs the SCSI Unmap command translation
+ *        functionality.
+ *        This includes:
+ *        - setting the command register
+ *        - setting the device head register
+ *        - filling in fields in the SATI_TRANSLATOR_SEQUENCE object.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @return Indicate if the method was successfully completed.
+ * @retval SATI_SUCCESS This is returned in all other cases.
+ */
+SATI_STATUS sati_unmap_construct(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io,
+   U32                          sector_count
+)
+{
+   U8 * h2d_register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+   U8 * d2h_register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
+
+   sati_set_ata_command(h2d_register_fis, ATA_DATA_SET_MANAGEMENT);
+   sati_set_ata_features(h2d_register_fis, 0x01);
+   sati_set_ata_sector_count(h2d_register_fis, (U8)sector_count);
+   sati_set_ata_device_head(h2d_register_fis, ATA_DEV_HEAD_REG_LBA_MODE_ENABLE);
+
+   // Set the completion status since the core will not do that for
+   // the udma fast path.
+   sati_set_ata_status(d2h_register_fis, 0x00);
+
+   // Set up the direction and protocol for SCIC
+   sequence->data_direction                 = SATI_DATA_DIRECTION_OUT;
+   sequence->protocol                       = SAT_PROTOCOL_UDMA_DATA_OUT;
+   // The UNMAP translation will always require a callback
+   // on every response so it can free memory if an error
+   // occurs.
+   sequence->is_translate_response_required = TRUE;
+
+   ASSERT(sector_count < 0x100);
+
+   return SATI_SUCCESS;
+}
+
+/**
+ * @brief This method updates the unmap sequence state to the next
+ *        unmap descriptor
+ *
+ * @return Indicate if the method was successfully completed.
+ * @retval SATI_SUCCESS This is returned in all other cases.
+ */
+SATI_STATUS sati_unmap_load_next_descriptor(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io
+)
+{
+   SATI_UNMAP_PROCESSING_STATE_T * unmap_process_state;
+   U32                             index;
+   U8                              unmap_block_descriptor[16];
+
+   unmap_process_state = &sequence->command_specific_data.unmap_process_state;
+
+   // Load the next descriptor
+   for(index = unmap_process_state->current_unmap_block_descriptor_index;
+       index < unmap_process_state->current_unmap_block_descriptor_index +
+               SATI_UNMAP_SIZEOF_SCSI_UNMAP_BLOCK_DESCRIPTOR;
+       index++)
+   {
+      sati_get_data_byte(sequence,
+         scsi_io,
+         index,
+         &unmap_block_descriptor[index-unmap_process_state->current_unmap_block_descriptor_index]);
+   }
+
+   // Update the internal state for the next translation pass
+   unmap_process_state->current_lba_count = (unmap_block_descriptor[8] << 24) |
+                                            (unmap_block_descriptor[9] << 16) |
+                                            (unmap_block_descriptor[10] << 8) |
+                                            (unmap_block_descriptor[11]);
+   unmap_process_state->current_lba       = ((SATI_LBA)(unmap_block_descriptor[0]) << 56) |
+                                            ((SATI_LBA)(unmap_block_descriptor[1]) << 48) |
+                                            ((SATI_LBA)(unmap_block_descriptor[2]) << 40) |
+                                            ((SATI_LBA)(unmap_block_descriptor[3]) << 32) |
+                                            ((SATI_LBA)(unmap_block_descriptor[4]) << 24) |
+                                            ((SATI_LBA)(unmap_block_descriptor[5]) << 16) |
+                                            ((SATI_LBA)(unmap_block_descriptor[6]) << 8) |
+                                            ((SATI_LBA)(unmap_block_descriptor[7]));
+   unmap_process_state->next_lba          = 0;
+
+   // Update the index for the next descriptor to translate
+   unmap_process_state->current_unmap_block_descriptor_index += SATI_UNMAP_SIZEOF_SCSI_UNMAP_BLOCK_DESCRIPTOR;
+
+   return SATI_SUCCESS;
+}
+
+/**
+ * @brief This method determines the max number of blocks of DSM data
+ *        that can be satisfied by the device and the SW
+ *
+ * @return Number of blocks supported
+ * @retval Number of blocks supported
+ */
+U32 sati_unmap_get_max_buffer_size_in_blocks(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence
+)
+{
+   // Currently this SATI implementation only supports a single
+   // 4k block of memory for the DMA write operation for simplicity
+   // (no need to handle more than one SG element).
+   // Since most run time UNMAP requests use 1K or less buffer space,
+   // there is no performance degradation with only supporting a
+   // single physical page.  For best results allocate the maximum
+   // amount of memory the device can handle up to the maximum of 4K.
+   return MIN(SATI_DSM_MAX_BUFFER_SIZE/sequence->device->logical_block_size,
+              sequence->device->max_lba_range_entry_blocks);
+}
+
+/**
+ * @brief This method will be called before starting the first unmap translation
+ *
+ * @return Indicate if the translation was successful.
+ * @retval SATI_SUCCESS This is returned if the command translation was
+ *         successful and no further processing.
+ * @retval SATI_COMPLETE - The initial processing was completed successfully
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA - Failed the initial processing
+ */
+SATI_STATUS sati_unmap_initial_processing(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   SATI_UNMAP_PROCESSING_STATE_T * unmap_process_state;
+   U8 * cdb;
+   U16 unmap_length;
+   U32 descriptor_length;
+   U32 index;
+   U32 max_dsm_blocks;
+   U8  unmap_param_list[8];
+
+   unmap_process_state = &sequence->command_specific_data.unmap_process_state;
+
+   // Set up the sequence type for unmap translation
+   sequence->type = SATI_SEQUENCE_UNMAP;
+
+   // Make sure the device is TRIM capable
+   if ((sequence->device->capabilities & SATI_DEVICE_CAP_DSM_TRIM_SUPPORT)
+       != SATI_DEVICE_CAP_DSM_TRIM_SUPPORT)
+   {
+      // Can't send TRIM request to device that does not support it
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_ILLEGAL_REQUEST,
+         SCSI_ASC_INVALID_FIELD_IN_CDB,
+         SCSI_ASCQ_INVALID_FIELD_IN_CDB
+      );
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+
+   // get the amount of data being sent from the cdb
+   cdb = sati_cb_get_cdb_address(scsi_io);
+   unmap_length = (sati_get_cdb_byte(cdb, 7) << 8) | sati_get_cdb_byte(cdb, 8);
+
+   // If nothing has been requested return success now.
+   if (unmap_length == 0)
+   {
+       // SAT: This is not an error
+       return SATI_SUCCESS;
+   }
+   if (unmap_length < SATI_UNMAP_SIZEOF_SCSI_UNMAP_PARAMETER_LIST)
+   {
+      // Not enough length specified in the CDB
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_ILLEGAL_REQUEST,
+         SCSI_ASC_INVALID_FIELD_IN_CDB,
+         SCSI_ASCQ_INVALID_FIELD_IN_CDB
+      );
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+
+   sequence->allocation_length = unmap_length;
+
+   // Get the unmap parameter header
+   for(index = 0; index < SATI_UNMAP_SIZEOF_SCSI_UNMAP_PARAMETER_LIST; index++)
+   {
+      sati_get_data_byte(sequence, scsi_io, index,   &unmap_param_list[index]);
+   }
+   descriptor_length = (unmap_param_list[2] << 8) | unmap_param_list[3];
+
+   // Check length again
+   if (descriptor_length == 0)
+   {
+       // SAT: This is not an error
+       return SATI_SUCCESS;
+   }
+
+   if ((U32)(unmap_length - SATI_UNMAP_SIZEOF_SCSI_UNMAP_PARAMETER_LIST) < descriptor_length)
+   {
+      // Not enough length specified in the CDB
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_ILLEGAL_REQUEST,
+         SCSI_ASC_INVALID_FIELD_IN_CDB,
+         SCSI_ASCQ_INVALID_FIELD_IN_CDB
+      );
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+
+   // Save the maximum unmap block descriptors in this request
+   unmap_process_state->max_unmap_block_descriptors =
+       descriptor_length/SATI_UNMAP_SIZEOF_SCSI_UNMAP_BLOCK_DESCRIPTOR;
+
+   // Determine the maximum size of the write buffer that will be required
+   // for the translation in terms of number of blocks
+   max_dsm_blocks = sati_unmap_get_max_buffer_size_in_blocks(sequence);
+
+   // Save the maximum number of DSM descriptors we can send during the translation
+   unmap_process_state->max_lba_range_entries =
+       (max_dsm_blocks*sequence->device->logical_block_size)/sizeof(TRIM_PAIR);
+
+   // Get the write buffer for the translation
+   sati_cb_allocate_dma_buffer(
+      scsi_io,
+      max_dsm_blocks*sequence->device->logical_block_size,
+      &(unmap_process_state->virtual_unmap_buffer),
+      &(unmap_process_state->physical_unmap_buffer_low),
+      &(unmap_process_state->physical_unmap_buffer_high));
+
+   // Makes sure we have a buffer
+   if (unmap_process_state->virtual_unmap_buffer == NULL)
+   {
+      // Resource failure
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_ABORTED_COMMAND,
+         SCSI_ASC_NO_ADDITIONAL_SENSE,
+         SCSI_ASCQ_NO_ADDITIONAL_SENSE
+      );
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+
+   // Get the first SGL entry.  This code will only use one 4K page so will
+   // only utilize the first sge.
+   sati_cb_sgl_next_sge(scsi_io,
+                        ata_io,
+                        NULL,
+                        &(unmap_process_state->unmap_buffer_sgl_pair));
+
+   // Load the first descriptor to start the translation loop
+   unmap_process_state->current_unmap_block_descriptor_index =
+      SATI_UNMAP_SIZEOF_SCSI_UNMAP_PARAMETER_LIST;
+   sati_unmap_load_next_descriptor(sequence,scsi_io);
+
+   // Next state will be incomplete since translation
+   // will require a callback and possibly more requests.
+   sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
+
+   return SATI_COMPLETE;
+}
+
+/**
+ * @brief This method will process each unmap sequence.
+ *
+ * @return Indicate if the translation was successful.
+ * @retval SATI_SUCCESS
+ */
+SATI_STATUS sati_unmap_process(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   SATI_UNMAP_PROCESSING_STATE_T * unmap_process_state;
+   SATI_LBA dsm_descriptor_lba_count;
+   U32 dsm_descriptor;
+   U32 dsm_bytes;
+   U32 dsm_remainder_bytes;
+   U32 dsm_blocks;
+   U32 max_dsm_blocks;
+
+   unmap_process_state = &sequence->command_specific_data.unmap_process_state;
+
+   // Set up the starting address of the buffer for this portion of the translation
+   unmap_process_state->current_dsm_descriptor = unmap_process_state->virtual_unmap_buffer;
+   dsm_descriptor = 0;
+
+   // Translate as much as we can
+   while ((dsm_descriptor < unmap_process_state->max_lba_range_entries) &&
+          (unmap_process_state->current_lba_count > 0)) {
+      // See if the LBA count will fit in to a single descriptor
+      if (unmap_process_state->current_lba_count > SATI_DSM_MAX_SECTOR_COUNT) {
+         // Can't fit all of the lbas for this descriptor in to
+         // one DSM request.  Adjust the current LbaCount and total
+         // remaining for the next descriptor
+         dsm_descriptor_lba_count = SATI_DSM_MAX_SECTOR_COUNT;
+         unmap_process_state->current_lba_count -= SATI_DSM_MAX_SECTOR_COUNT;
+         unmap_process_state->next_lba =
+             unmap_process_state->current_lba + SATI_DSM_MAX_SECTOR_COUNT;
+      } else {
+         // It all fits in to one descriptor
+         dsm_descriptor_lba_count = unmap_process_state->current_lba_count;
+         unmap_process_state->current_lba_count = 0;
+      }
+
+      // Fill in the ATA DSM descriptor
+      ((PTRIM_PAIR)(unmap_process_state->current_dsm_descriptor))->sector_address =
+          unmap_process_state->current_lba;
+      ((PTRIM_PAIR)(unmap_process_state->current_dsm_descriptor))->sector_count =
+          dsm_descriptor_lba_count;
+
+      // See if we can move on to the next descriptor
+      if (unmap_process_state->current_lba_count == 0) {
+         // See if there is another descriptor
+         --unmap_process_state->max_unmap_block_descriptors;
+         if (unmap_process_state->max_unmap_block_descriptors > 0) {
+            // Move on to the next descriptor
+            sati_unmap_load_next_descriptor(sequence,scsi_io);
+         }
+      } else {
+         // Move to the next LBA in this descriptor
+         unmap_process_state->current_lba = unmap_process_state->next_lba;
+      }
+
+      // Make sure the LBA does not exceed 48 bits...
+      ASSERT(unmap_process_state->current_lba <= SATI_DSM_MAX_SECTOR_ADDRESS);
+
+      // Increment the number of descriptors used and point to the next entry
+      dsm_descriptor++;
+      unmap_process_state->current_dsm_descriptor =
+          (U8 *)(unmap_process_state->current_dsm_descriptor) + sizeof(TRIM_PAIR);
+   }
+
+   // Calculate number of blocks we have filled in
+   dsm_blocks     = sati_unmap_calculate_dsm_blocks(sequence,dsm_descriptor);
+   dsm_bytes      = dsm_blocks * sequence->device->logical_block_size;
+   max_dsm_blocks = sati_unmap_get_max_buffer_size_in_blocks(sequence);
+
+   // The current_dsm_descriptor points to the next location in the buffer
+   // Get the remaining bytes from the last translated descriptor
+   // to the end of the 4k buffer.
+   dsm_remainder_bytes = sequence->device->logical_block_size;
+   dsm_remainder_bytes -= (U32)((POINTER_UINT)unmap_process_state->current_dsm_descriptor &
+                                (sequence->device->logical_block_size-1));
+
+   // If there was no remainder, the complete buffer was filled in.
+   if (dsm_remainder_bytes != sequence->device->logical_block_size)
+   {
+       // Add on the remaining unfilled blocks
+       dsm_remainder_bytes += (sequence->device->logical_block_size * (max_dsm_blocks - dsm_blocks));
+
+       // According to ATA-8, if the DSM buffer is not completely filled with
+       // valid DSM descriptor data, the remaining portion of the
+       // buffer must be filled in with zeros.
+       memset((U8 *)unmap_process_state->current_dsm_descriptor, 0, dsm_remainder_bytes);
+   }
+
+   // Tell scic to utilize this sgl pair for write DMA processing of
+   // the SCSI UNMAP translation with the total number of bytes for this transfer
+   sati_cb_sge_write(unmap_process_state->unmap_buffer_sgl_pair,
+                     unmap_process_state->physical_unmap_buffer_low,
+                     unmap_process_state->physical_unmap_buffer_high,
+                     dsm_bytes);
+
+   // Construct the unmap ATA request
+   sati_unmap_construct(sequence,
+                        scsi_io,
+                        ata_io,
+                        dsm_blocks);
+
+   // Determine sequence next state based on whether there is more translation
+   // to complete
+   if (unmap_process_state->current_lba_count == 0)
+   {
+       // used for completion routine to determine if there is more processing
+       sequence->state = SATI_SEQUENCE_STATE_FINAL;
+   }
+   // This requests has already translated the SGL, have SCIC skip SGL translataion
+   return SATI_SUCCESS_SGL_TRANSLATED;
+}
+
+//******************************************************************************
+//* P U B L I C   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method will handle termination of the
+ *        SCSI unmap translation and frees previously allocated
+ *        dma buffer.
+ *
+ * @return None
+ */
+void sati_unmap_terminate(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   SATI_UNMAP_PROCESSING_STATE_T * unmap_process_state;
+   unmap_process_state = &sequence->command_specific_data.unmap_process_state;
+
+   if (unmap_process_state->virtual_unmap_buffer != NULL)
+   {
+      sati_cb_free_dma_buffer(scsi_io, unmap_process_state->virtual_unmap_buffer);
+      unmap_process_state->virtual_unmap_buffer = NULL;
+   }
+}
+
+/**
+ * @brief This method will translate the SCSI Unmap command
+ *        into corresponding ATA commands.  Depending upon the capabilities
+ *        supported by the target different ATA commands can be selected.
+ *        Additionally, in some cases more than a single ATA command may
+ *        be required.
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SATI_SUCCESS This is returned if the command translation was
+ *         successful.
+ * @retval SATI_COMPLETE This is returned if the command translation was
+ *         successful and no ATA commands need to be set.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
+ *         sense data has been created as a result of something specified
+ *         in the parameter data fields.
+ */
+SATI_STATUS sati_unmap_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+   SATI_UNMAP_PROCESSING_STATE_T * unmap_process_state;
+
+   unmap_process_state = &sequence->command_specific_data.unmap_process_state;
+
+   // Determine if this is the first step in the unmap sequence
+   if ( sequence->state == SATI_SEQUENCE_STATE_INITIAL )
+   {
+       status = sati_unmap_initial_processing(sequence,scsi_io,ata_io);
+       if (status != SATI_COMPLETE)
+       {
+          return status;
+       }
+   }
+   // Translate the next portion of the UNMAP request
+   return sati_unmap_process(sequence, scsi_io, ata_io);
+}
+
+/**
+ * @brief This method will translate the ATA command register FIS
+ *        response into an appropriate SCSI response for Unmap.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_response().
+ *
+ * @return Indicate if the response translation succeeded.
+ * @retval SATI_SUCCESS This is returned if the command translation was
+ *         successful.
+ * @retval SATI_COMPLETE This is returned if the command translation was
+ *         successful and no ATA commands need to be set.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
+ *         sense data has been created as a result of something specified
+ *         in the parameter data fields.
+ */
+SATI_STATUS sati_unmap_translate_response(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
+   SATI_UNMAP_PROCESSING_STATE_T * unmap_process_state;
+   SATI_STATUS sati_status = SATI_COMPLETE;
+
+   unmap_process_state = &sequence->command_specific_data.unmap_process_state;
+
+   if (sati_get_ata_status(register_fis) & ATA_STATUS_REG_ERROR_BIT)
+   {
+      sequence->state = SATI_SEQUENCE_STATE_FINAL;
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_ABORTED_COMMAND,
+         SCSI_ASC_NO_ADDITIONAL_SENSE,
+         SCSI_ASCQ_NO_ADDITIONAL_SENSE
+      );
+      // All done, terminate the translation
+      sati_unmap_terminate(sequence, scsi_io, ata_io);
+   }
+   else
+   {
+      if (sequence->state != SATI_SEQUENCE_STATE_INCOMPLETE)
+      {
+          // All done, terminate the translation
+          sati_unmap_terminate(sequence, scsi_io, ata_io);
+      }
+      else
+      {
+          // Still translating
+          sati_status = SATI_SEQUENCE_STATE_INCOMPLETE;
+      }
+   }
+   return sati_status;
+}
+
+#endif // !defined(DISABLE_SATI_UNMAP)
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_unmap.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_unmap.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,135 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_UNMAP_H_
+#define _SATI_UNMAP_H_
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ *        translate the SCSI reassign blocks command.
+ */
+
+#if !defined(DISABLE_SATI_UNMAP)
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+#define SATI_DSM_MAX_SECTOR_COUNT                     0xFFFF
+#define SATI_DSM_MAX_SECTOR_ADDRESS                   0xFFFFFFFFFFFF
+#define SATI_DSM_MAX_BUFFER_SIZE                      4096
+
+#define SATI_UNMAP_SIZEOF_SCSI_UNMAP_BLOCK_DESCRIPTOR 16
+#define SATI_UNMAP_SIZEOF_SCSI_UNMAP_PARAMETER_LIST   8
+
+typedef struct _TRIM_PAIR
+{
+    U64 sector_address:48;
+    U64 sector_count:16;
+} TRIM_PAIR, *PTRIM_PAIR;
+
+U32 sati_unmap_calculate_dsm_blocks(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   U32                          dsm_descriptor_count
+);
+
+SATI_STATUS sati_unmap_construct(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io,
+   U32                          sector_count
+);
+
+SATI_STATUS sati_unmap_load_next_descriptor(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io
+);
+
+U32 sati_unmap_get_max_buffer_size_in_blocks(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence
+);
+
+SATI_STATUS sati_unmap_initial_processing(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+SATI_STATUS sati_unmap_process(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+SATI_STATUS sati_unmap_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+SATI_STATUS sati_unmap_translate_response(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+void sati_unmap_terminate(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+#else // !defined(DISABLE_SATI_UNMAP)
+#define sati_unmap_terminate(sequence,scsi_io,ata_io)
+#endif // !defined(DISABLE_SATI_UNMAP)
+
+#endif // _SATI_UNMAP_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_util.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_util.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,2005 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains all of the method implementations that
+ *        provide generic support for SATI.  Some methods can be utilized
+ *        by a user to construct ATA/ATAPI commands, copy ATA device
+ *        structure data, fill in sense data, etc.
+ */
+
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/intel_scsi.h>
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_sat.h>
+#include <dev/isci/scil/intel_sas.h>
+
+/**
+ * @brief This method will set the data direction, protocol, and transfer
+ *        kength for an ATA non-data command.
+ *
+ * @pre It is expected that the user will use this method for setting these
+ *      values in a non-data ATA command constuct.
+ *
+ * @param[out] ata_io This parameter specifies the ATA IO request structure
+ *             for which to build the IDENTIFY DEVICE command.
+ * @param[in]  sequence This parameter specifies the translator sequence
+ *             for which the command is being constructed.
+ *
+ * @return none.
+ */
+void sati_ata_non_data_command(
+   void                        * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T  * sequence
+)
+{
+   sequence->data_direction      = SATI_DATA_DIRECTION_NONE;
+   sequence->protocol            = SAT_PROTOCOL_NON_DATA;
+   sequence->ata_transfer_length = 0;
+}
+
+/**
+ * @brief This method will construct the ATA identify device command.
+ *
+ * @pre It is expected that the user has properly set the current contents
+ *      of the register FIS to 0.
+ *
+ * @param[out] ata_io This parameter specifies the ATA IO request structure
+ *             for which to build the IDENTIFY DEVICE command.
+ * @param[in]  sequence This parameter specifies the translator sequence
+ *             for which the command is being constructed.
+ *
+ * @return none.
+ */
+void sati_ata_identify_device_construct(
+   void                       * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T * sequence
+)
+{
+   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+   sati_set_ata_command(register_fis, ATA_IDENTIFY_DEVICE);
+   sequence->data_direction      = SATI_DATA_DIRECTION_IN;
+   sequence->protocol            = SAT_PROTOCOL_PIO_DATA_IN;
+   sequence->ata_transfer_length = sizeof(ATA_IDENTIFY_DEVICE_DATA_T);
+}
+
+/**
+* @brief This method will construct the ATA Execute Device Diagnostic command.
+*
+* @param[out] ata_io This parameter specifies the ATA IO request structure
+*             for which to build the IDENTIFY DEVICE command.
+* @param[in]  sequence This parameter specifies the translator sequence
+*             for which the command is being constructed.
+*
+* @return none.
+*/
+void sati_ata_execute_device_diagnostic_construct(
+   void                       * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T * sequence
+)
+{
+   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+   sati_set_ata_command(register_fis, ATA_EXECUTE_DEVICE_DIAG);
+
+   sequence->data_direction = SATI_DATA_DIRECTION_IN;
+   sequence->protocol = SAT_PROTOCOL_DEVICE_DIAGNOSTIC;
+   sequence->ata_transfer_length = 16;
+}
+
+/**
+ * @brief This method will set data bytes in the user data area.  If the
+ *        caller requests it, the data written will be forced to ascii
+ *        printable characters if it isn't already a printable character.
+ *        A printable character is considered to be >= 0x20 and <= 0x70.
+ *
+ * @param[in]  sequence This parameter specifies the translation sequence
+ *             for which to copy and swap the data.
+ * @param[out] destination_scsi_io This parameter specifies the SCSI IO
+ *             request containing the destination buffer into which to copy.
+ * @param[in]  destination_offset This parameter specifies the offset into
+ *             the data buffer where the information will be copied to.
+ * @param[in]  source_value This parameter specifies the value retrieved
+ *             from the source buffer that is to be copied into the user
+ *             buffer area.
+ * @param[in]  use_printable_chars This parameter indicates if the copy should
+ *             ensure that the value copied is considered an ASCII printable
+ *             character (e.g. A, B, " ", etc.).  These characters reside
+ *             in the 0x20 - 0x7E ASCII range.
+ *
+ * @return none
+ */
+static
+void sati_set_ascii_data_byte(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * destination_scsi_io,
+   U32                          destination_offset,
+   U8                           source_value,
+   BOOL                         use_printable_chars
+)
+{
+   // if the user requests that the copied data be ascii printable, then
+   // default to " " (i.e. 0x20) for all non-ascii printable characters.
+   if((use_printable_chars == TRUE)
+     && ((source_value < 0x20) || (source_value > 0x7E)))
+   {
+      source_value = 0x20;
+   }
+
+   sati_set_data_byte(
+      sequence, destination_scsi_io, destination_offset, source_value
+   );
+}
+
+/**
+ * @brief This method performs a copy operation using an offset into the
+ *        source buffer, an offset into the destination buffer, and a length.
+ *        It will perform the byte swap from the 16-bit identify field
+ *        into the network byte order SCSI location.
+ *
+ * @param[in]  sequence This parameter specifies the translation sequence
+ *             for which to copy and swap the data.
+ * @param[out] destination_scsi_io This parameter specifies the SCSI IO
+ *             request containing the destination buffer into which to copy.
+ * @param[in]  destination_offset This parameter specifies the offset into
+ *             the data buffer where the information will be copied to.
+ * @param[in]  source_buffer This parameter specifies the source buffer from
+ *             which the data will be copied.
+ * @param[in]  source_offset This parameter specifies the offset into the
+ *             source buffer where the copy shall begin.
+ * @param[in]  length This parameter specifies the number of bytes to copy
+ *             during this operation.
+ * @param[in]  use_printable_chars This parameter indicates if the copy should
+ *             ensure that the value copied is considered an ASCII printable
+ *             character (e.g. A, B, " ", etc.).  These characters reside
+ *             in the 0x20 - 0x7E ASCII range.
+ *
+ * @return none
+ */
+void sati_ata_identify_device_copy_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * destination_scsi_io,
+   U32                          destination_offset,
+   U8                         * source_buffer,
+   U32                          source_offset,
+   U32                          length,
+   BOOL                         use_printable_chars
+)
+{
+   source_buffer += source_offset;
+   while (length > 0)
+   {
+      sati_set_ascii_data_byte(
+         sequence,
+         destination_scsi_io,
+         destination_offset,
+         *(source_buffer+1),
+         use_printable_chars
+      );
+
+      sati_set_ascii_data_byte(
+         sequence,
+         destination_scsi_io,
+         destination_offset+1,
+         *source_buffer,
+         use_printable_chars
+      );
+
+      destination_offset += 2;
+      source_buffer      += 2;
+      length             -= 2;
+   }
+}
+
+/**
+ * @brief This method performs a copy operation using a source buffer,
+ *        an offset into the destination buffer, and a length.
+ *
+ * @param[in]  sequence This parameter specifies the translation sequence
+ *             for which to copy and swap the data.
+ * @param[out] destination_scsi_io This parameter specifies the SCSI IO
+ *             request containing the destination buffer into which to copy.
+ * @param[in]  destination_offset This parameter specifies the offset into
+ *             the data buffer where the information will be copied to.
+ * @param[in]  source_buffer This parameter specifies the source buffer from
+ *             which the data will be copied.
+ * @param[in]  length This parameter specifies the number of bytes to copy
+ *             during this operation.
+ *
+ * @return none
+ */
+void sati_copy_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * destination_scsi_io,
+   U32                          destination_offset,
+   U8                         * source_buffer,
+   U32                          length
+)
+{
+   while (length > 0)
+   {
+      sati_set_data_byte(
+         sequence, destination_scsi_io, destination_offset, *source_buffer
+      );
+
+      destination_offset++;
+      source_buffer++;
+      length--;
+   }
+}
+
+/**
+ * @brief This method extracts the Logical Block Address high and low 32-bit
+ *        values and the sector count 32-bit value from the ATA identify
+ *        device data.
+ *
+ * @param[in]  identify This parameter specifies the ATA_IDENTIFY_DEVICE_DATA
+ *             from which to extract the sector information.
+ * @param[out] lba_high This parameter specifies the upper 32 bits for the
+ *             number of logical block addresses for the device. The upper
+ *             16-bits should always be 0, since 48-bits of LBA is the most
+ *             supported by an ATA device.
+ * @param[out] lba_low This parameter specifies the lower 32 bits for the
+ *             number of logical block addresses for the device.
+ * @param[out] sector_size This parameter specifies the 32-bits of sector
+ *             size.  If the ATA device doesn't support reporting it's
+ *             sector size, then 512 bytes is utilized as the default value.
+ *
+ * @return none
+ */
+void sati_ata_identify_device_get_sector_info(
+   ATA_IDENTIFY_DEVICE_DATA_T * identify,
+   U32                        * lba_high,
+   U32                        * lba_low,
+   U32                        * sector_size
+)
+{
+   // Calculate the values to be returned
+   // Calculation will be different if the SATA device supports
+   // 48-bit addressing.  Bit 10 of Word 86 of ATA Identify
+   if (identify->command_set_enabled1
+       & ATA_IDENTIFY_COMMAND_SET_SUPPORTED1_48BIT_ENABLE)
+   {
+      // This drive supports 48-bit addressing
+
+      *lba_high  = identify->max_48bit_lba[7] << 24;
+      *lba_high |= identify->max_48bit_lba[6] << 16;
+      *lba_high |= identify->max_48bit_lba[5] << 8;
+      *lba_high |= identify->max_48bit_lba[4];
+
+      *lba_low  = identify->max_48bit_lba[3] << 24;
+      *lba_low |= identify->max_48bit_lba[2] << 16;
+      *lba_low |= identify->max_48bit_lba[1] << 8;
+      *lba_low |= identify->max_48bit_lba[0];
+   }
+   else
+   {
+      // This device doesn't support 48-bit addressing
+      // Pull out the largest LBA from words 60 and 61.
+      *lba_high  = 0;
+      *lba_low   = identify->total_num_sectors[3] << 24;
+      *lba_low  |= identify->total_num_sectors[2] << 16;
+      *lba_low  |= identify->total_num_sectors[1] << 8;
+      *lba_low  |= identify->total_num_sectors[0];
+   }
+
+   // If the ATA device reports its sector size (bit 12 of Word 106),
+   // then use that instead.
+   if (identify->physical_logical_sector_info
+       & ATA_IDENTIFY_SECTOR_LARGER_THEN_512_ENABLE)
+   {
+      *sector_size  = identify->words_per_logical_sector[3] << 24;
+      *sector_size |= identify->words_per_logical_sector[2] << 16;
+      *sector_size |= identify->words_per_logical_sector[1] << 8;
+      *sector_size |= identify->words_per_logical_sector[0];
+   }
+   else
+   {
+      // Default the sector size to 512 bytes
+      *sector_size = 512;
+   }
+}
+
+/**
+ * @brief This method will construct the ATA check power mode command.
+ *
+ * @pre It is expected that the user has properly set the current contents
+ *      of the register FIS to 0.
+ *
+ * @param[out] ata_io This parameter specifies the ATA IO request structure
+ *             for which to build the CHECK POWER MODE command.
+ * @param[in]  sequence This parameter specifies the translator sequence
+ *             for which the command is being constructed.
+ *
+ * @return none.
+ */
+void sati_ata_check_power_mode_construct(
+   void                       * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T * sequence
+)
+{
+   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+   sati_set_ata_command(register_fis, ATA_CHECK_POWER_MODE);
+   sati_ata_non_data_command(ata_io, sequence);
+}
+
+/**
+ * @brief This method is utilized to set a specific byte in the sense
+ *        data area.  It will ensure that the supplied byte offset
+ *        isn't larger then the length of the requested sense data.
+ *
+ * @param[in] scsi_io This parameter specifies the user SCSI IO request
+ *            for which to set the sense data byte.
+ * @param[in] byte_offset This parameter specifies the byte offset into
+ *            the sense data buffer where the data should be written.
+ * @param[in] value This parameter specifies the 8-bit value to be written
+ *            into the sense data area.
+ *
+ * @return none
+ */
+void sati_set_sense_data_byte(
+   U8  * sense_data,
+   U32   max_sense_data_len,
+   U32   byte_offset,
+   U8    value
+)
+{
+   // Ensure that we don't attempt to write past the end of the sense
+   // data buffer.
+   if (byte_offset < max_sense_data_len)
+      sense_data[byte_offset] = value;
+}
+
+/**
+ * @brief This method will construct the common response IU in the user
+ *           request's response IU location.
+ *
+ * @param[out] rsp_iu This parameter specifies the user request's
+ *                response IU to be constructed.
+ * @param[in]  scsi_status This parameter specifies the SCSI status
+ *                value for the user's IO request.
+ * @param[in]  sense_data_length This parameter specifies the sense data
+ *                length for response IU.
+ * @param[in]  data_present The parameter specifies the specific
+ *                data present value for response IU.
+ *
+ * @return none
+ */
+void sati_scsi_common_response_iu_construct(
+   SCI_SSP_RESPONSE_IU_T * rsp_iu,
+   U8                      scsi_status,
+   U8                      sense_data_length,
+   U8                      data_present
+)
+{
+   rsp_iu->sense_data_length[3] = sense_data_length;
+   rsp_iu->sense_data_length[2] = 0;
+   rsp_iu->sense_data_length[1] = 0;
+   rsp_iu->sense_data_length[0] = 0;
+   rsp_iu->status               = scsi_status;
+   rsp_iu->data_present         = data_present;
+}
+
+/**
+ * @brief This method will construct the buffer for sense data
+ *        sense data buffer location.  Additionally, it will set the user's
+ *        SCSI status.
+ *
+ * @param[in,out] scsi_io This parameter specifies the user's IO request
+ *                for which to construct the buffer for sense data.
+ * @param[in]     scsi_status This parameter specifies the SCSI status
+ *                value for the user's IO request.
+ * @param[out]    sense_data This paramater
+ *
+ * @return none
+ */
+static
+void sati_scsi_get_sense_data_buffer(
+    SATI_TRANSLATOR_SEQUENCE_T      * sequence,
+    void                            * scsi_io,
+    U8                                scsi_status,
+    U8                             ** sense_data,
+    U32                             * sense_len)
+{
+#ifdef SATI_TRANSPORT_SUPPORTS_SAS
+   SCI_SSP_RESPONSE_IU_T * rsp_iu = (SCI_SSP_RESPONSE_IU_T*)
+                                    sati_cb_get_response_iu_address(scsi_io);
+
+   sati_scsi_common_response_iu_construct(
+      rsp_iu,
+      scsi_status,
+      sati_scsi_get_sense_data_length(sequence, scsi_io),
+      SCSI_RESPONSE_DATA_PRES_SENSE_DATA
+   );
+
+   *sense_data                   = (U8*) rsp_iu->data;
+   *sense_len                    = SSP_RESPONSE_IU_MAX_DATA * 4;  // dwords to bytes
+#else
+   *sense_data = sati_cb_get_sense_data_address(scsi_io);
+   *sense_len  = sati_cb_get_sense_data_length(scsi_io);
+   sati_cb_set_scsi_status(scsi_io, scsi_status);
+#endif // SATI_TRANSPORT_SUPPORTS_SAS
+}
+
+/**
+ * @brief This method extract response code based on on device settings.
+ *
+ * @return response code
+ */
+static
+U8 sati_scsi_get_sense_data_response_code(SATI_TRANSLATOR_SEQUENCE_T * sequence)
+{
+    if (sequence->device->descriptor_sense_enable)
+    {
+       return SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE;
+    }
+    else
+    {
+       return SCSI_FIXED_CURRENT_RESPONSE_CODE;
+    }
+}
+
+/**
+ * @brief This method will return length of descriptor sense data for executed command.
+ *
+ * @return sense data length
+ */
+static
+U8 sati_scsi_get_descriptor_sense_data_length(SATI_TRANSLATOR_SEQUENCE_T * sequence,
+        void * scsi_io)
+{
+    U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+    //Initial value is descriptor header length
+    U8 length = 8;
+
+    switch (sati_get_cdb_byte(cdb, 0))
+    {
+#if !defined(DISABLE_SATI_WRITE_LONG)
+    case SCSI_WRITE_LONG_10:
+    case SCSI_WRITE_LONG_16:
+        length += SCSI_BLOCK_DESCRIPTOR_LENGTH +
+            SCSI_INFORMATION_DESCRIPTOR_LENGTH;
+        break;
+#endif // !defined(DISABLE_SATI_WRITE_LONG)
+#if !defined(DISABLE_SATI_REASSIGN_BLOCKS)
+    case SCSI_REASSIGN_BLOCKS:
+        length += SCSI_CMD_SPECIFIC_DESCRIPTOR_LENGTH +
+            SCSI_INFORMATION_DESCRIPTOR_LENGTH;
+        break;
+#endif // !defined(DISABLE_SATI_REASSIGN_BLOCKS)
+    case SCSI_READ_6:
+    case SCSI_READ_10:
+    case SCSI_READ_12:
+    case SCSI_READ_16:
+    case SCSI_WRITE_6:
+    case SCSI_WRITE_10:
+    case SCSI_WRITE_12:
+    case SCSI_WRITE_16:
+#if !defined(DISABLE_SATI_VERIFY)
+    case SCSI_VERIFY_10:
+    case SCSI_VERIFY_12:
+    case SCSI_VERIFY_16:
+#endif // !defined(DISABLE_SATI_VERIFY)
+#if    !defined(DISABLE_SATI_WRITE_AND_VERIFY)  \
+    && !defined(DISABLE_SATI_VERIFY)            \
+    && !defined(DISABLE_SATI_WRITE)
+
+    case SCSI_WRITE_AND_VERIFY_10:
+    case SCSI_WRITE_AND_VERIFY_12:
+    case SCSI_WRITE_AND_VERIFY_16:
+#endif //    !defined(DISABLE_SATI_WRITE_AND_VERIFY)
+       // && !defined(DISABLE_SATI_VERIFY)
+       // && !defined(DISABLE_SATI_WRITE)
+        length += SCSI_INFORMATION_DESCRIPTOR_LENGTH;
+        break;
+    }
+
+    return length;
+}
+
+/**
+ * @brief This method will return length of sense data.
+ *
+ * @return sense data length
+ */
+U8 sati_scsi_get_sense_data_length(SATI_TRANSLATOR_SEQUENCE_T * sequence, void * scsi_io)
+{
+    U8 response_code;
+
+    response_code = sati_scsi_get_sense_data_response_code(sequence);
+
+    switch (response_code)
+    {
+    case SCSI_FIXED_CURRENT_RESPONSE_CODE:
+    case SCSI_FIXED_DEFERRED_RESPONSE_CODE:
+        return SCSI_FIXED_SENSE_DATA_BASE_LENGTH;
+    break;
+    case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE:
+    case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE:
+        return sati_scsi_get_descriptor_sense_data_length(sequence, scsi_io);
+    break;
+    }
+
+    return SCSI_FIXED_SENSE_DATA_BASE_LENGTH;
+}
+
+/**
+ * @brief This method will construct the sense data buffer in the user's
+ *        sense data buffer location.  Additionally, it will set the user's
+ *        SCSI status.
+ *
+ * @param[in]     sequence This parameter specifies the translation sequence
+ *                for which to construct the sense data.
+ * @param[in,out] scsi_io This parameter specifies the user's IO request
+ *                for which to construct the sense data.
+ * @param[in]     scsi_status This parameter specifies the SCSI status
+ *                value for the user's IO request.
+ * @param[in]     sense_key This parameter specifies the sense key to
+ *                be set for the user's IO request.
+ * @param[in]     additional_sense_code This parameter specifies the
+ *                additional sense code (ASC) key to be set for the user's
+ *                IO request.
+ * @param[in]     additional_sense_code_qualifier This parameter specifies
+ *                the additional sense code qualifier (ASCQ) key to be set
+ *                for the user's IO request.
+ *
+ * @return none
+ */
+void sati_scsi_sense_data_construct(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   U8                           scsi_status,
+   U8                           sense_key,
+   U8                           additional_sense_code,
+   U8                           additional_sense_code_qualifier
+)
+{
+    U8 response_code;
+
+    response_code = sati_scsi_get_sense_data_response_code(sequence);
+
+    switch (response_code)
+    {
+    case SCSI_FIXED_CURRENT_RESPONSE_CODE:
+    case SCSI_FIXED_DEFERRED_RESPONSE_CODE:
+    sati_scsi_fixed_sense_data_construct(sequence, scsi_io, scsi_status, response_code,
+                sense_key, additional_sense_code, additional_sense_code_qualifier);
+    break;
+    case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE:
+    case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE:
+        sati_scsi_descriptor_sense_data_construct(sequence, scsi_io, scsi_status, response_code,
+                sense_key, additional_sense_code, additional_sense_code_qualifier);
+        break;
+    }
+
+    sequence->is_sense_response_set = TRUE;
+}
+
+/**
+ * @brief This method will construct the block descriptor in the user's descriptor
+ *            sense data buffer location.
+ *
+ * @param[in]     sense_data This parameter specifies the user SCSI IO request
+ *                for which to set the sense data byte.
+ * @param[in]     sense_len This parameter specifies length of the sense data
+ *                to be returned by SATI.
+ * @param[out]    descriptor_len This parameter returns the length of constructed
+ *                descriptor.
+ *
+ * @return none
+ */
+static
+void sati_scsi_block_descriptor_construct(
+        U8 * sense_data,
+        U32 sense_len)
+{
+    U8 ili = 1;
+
+    sati_set_sense_data_byte(sense_data, sense_len, 0,  SCSI_BLOCK_DESCRIPTOR_TYPE);
+    sati_set_sense_data_byte(sense_data, sense_len, 1,  SCSI_BLOCK_DESCRIPTOR_ADDITIONAL_LENGTH);
+    sati_set_sense_data_byte(sense_data, sense_len, 2,  0);
+    sati_set_sense_data_byte(sense_data, sense_len, 3,  (ili << 5));
+}
+
+/**
+ * @brief This method will construct the command-specific descriptor for
+ *           the descriptor sense data buffer in the user's sense data buffer
+ *           location.
+ *
+ * @param[in]     sense_data This parameter specifies the user SCSI IO request
+ *                for which to set the sense data byte.
+ * @param[in]     sense_len This parameter specifies length of the sense data
+ *                to be returned by SATI.
+ * @param[out]    descriptor_len This parameter returns the length of constructed
+ *                descriptor.
+ * @param[in]     information_buff This parameter specifies the address for which
+ *                to set the command-specific information buffer.
+ *
+ * @return none
+ */
+static
+void sati_scsi_command_specific_descriptor_construct(
+    U8       * sense_data,
+    U32        sense_len,
+    U8       * information_buff)
+{
+    U8 i;
+
+    sati_set_sense_data_byte(sense_data, sense_len, 0,  SCSI_CMD_SPECIFIC_DESCRIPTOR_TYPE);
+    sati_set_sense_data_byte(sense_data, sense_len, 1,  SCSI_CMD_SPECIFIC_DESCRIPTOR_ADDITIONAL_LENGTH);
+    sati_set_sense_data_byte(sense_data, sense_len, 2,  0);
+    sati_set_sense_data_byte(sense_data, sense_len, 3,  0);
+
+    // fill information buffer
+    // SBC 5.20.1 REASSIGN BLOCKS command overview
+    // If information about the first LBA not reassigned is not available
+    // COMMAND-SPECIFIC INFORMATION field shall be set to FFFF_FFFF_FFFF_FFFFh
+    for (i=0; i<8; i++)
+        sati_set_sense_data_byte(sense_data, sense_len, 4 + i, information_buff==NULL?0xFF:information_buff[i]);
+}
+
+/**
+ * @brief This method will construct the information descriptor for
+ *           the descriptor sense data buffer in the user's sense data buffer
+ *           location.
+ *
+ * @param[in]     sense_data This parameter specifies the user SCSI IO request
+ *                for which to set the sense data byte.
+ * @param[in]     sense_len This parameter specifies length of the sense data
+ *                to be returned by SATI.
+ * @param[out]    descriptor_len This parameter returns the length of constructed
+ *                descriptor.
+ * @param[in]     information_buff This parameter specifies the address for which
+ *                to set the information buffer.
+ *
+ * @return none
+ */
+static
+void sati_scsi_information_descriptor_construct(
+    U8      * sense_data,
+    U32       sense_len,
+    U8      * information_buff)
+{
+    U8 i;
+    U8 valid = 1;
+
+    sati_set_sense_data_byte(sense_data, sense_len, 0,  SCSI_INFORMATION_DESCRIPTOR_TYPE);
+    sati_set_sense_data_byte(sense_data, sense_len, 1,  SCSI_INFORMATION_DESCRIPTOR_ADDITIONAL_LENGTH);
+    sati_set_sense_data_byte(sense_data, sense_len, 2,  (valid << 7));
+    sati_set_sense_data_byte(sense_data, sense_len, 3,  0);
+
+    // fill information buffer
+    for (i=0; i<8; i++)
+        sati_set_sense_data_byte(sense_data, sense_len, 4 + i, information_buff==NULL?0:information_buff[i]);
+}
+
+/**
+ * @brief This method will construct the descriptors in the user's descriptor
+ *           sense data buffer location.
+ *
+ * @param[in,out] scsi_io This parameter specifies the user's IO request
+ *                for which to construct the sense data.
+ * @param[in]     sense_data This parameter specifies the user SCSI IO request
+ *                for which to set the sense data byte.
+ * @param[in]     sense_len This parameter specifies length of the sense data
+ *                to be returned by SATI.
+ * @param[out]    descriptor_len This parameter returns the length of constructed
+ *                descriptor.
+ * @param[in]     information_buff This parameter specifies the address for which
+ *                to set the information buffer.
+ *
+ * @return none
+ */
+static
+void sati_scsi_common_descriptors_construct(
+    void    * scsi_io,
+    U8      * sense_data,
+    U32       sense_len,
+    U8      * information_buff)
+{
+    U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+    U8 offset = 0;
+
+    switch (sati_get_cdb_byte(cdb, 0))
+    {
+#if !defined(DISABLE_SATI_WRITE_LONG)
+    case SCSI_WRITE_LONG_10:
+    case SCSI_WRITE_LONG_16:
+        sati_scsi_block_descriptor_construct(
+                sense_data + offset,
+                sense_len - offset);
+
+        offset += SCSI_BLOCK_DESCRIPTOR_LENGTH;
+        sati_scsi_information_descriptor_construct(
+                  sense_data + offset,
+                  sense_len - offset,
+                  information_buff);
+
+        offset += SCSI_INFORMATION_DESCRIPTOR_LENGTH;
+        break;
+#endif // !defined(DISABLE_SATI_WRITE_LONG)
+#if !defined(DISABLE_SATI_REASSIGN_BLOCKS)
+    case SCSI_REASSIGN_BLOCKS:
+        sati_scsi_command_specific_descriptor_construct(
+          sense_data + offset,
+          sense_len - offset,
+          NULL);
+
+        offset += SCSI_CMD_SPECIFIC_DESCRIPTOR_LENGTH;
+        sati_scsi_information_descriptor_construct(
+                  sense_data + offset,
+                  sense_len - offset,
+                  information_buff);
+
+        offset += SCSI_INFORMATION_DESCRIPTOR_LENGTH;
+        break;
+#endif // !defined(DISABLE_SATI_REASSIGN_BLOCKS)
+    case SCSI_READ_6:
+    case SCSI_READ_10:
+    case SCSI_READ_12:
+    case SCSI_READ_16:
+    case SCSI_WRITE_6:
+    case SCSI_WRITE_10:
+    case SCSI_WRITE_12:
+    case SCSI_WRITE_16:
+#if !defined(DISABLE_SATI_VERIFY)
+    case SCSI_VERIFY_10:
+    case SCSI_VERIFY_12:
+    case SCSI_VERIFY_16:
+#endif // !defined(DISABLE_SATI_VERIFY)
+#if    !defined(DISABLE_SATI_WRITE_AND_VERIFY)  \
+    && !defined(DISABLE_SATI_VERIFY)            \
+    && !defined(DISABLE_SATI_WRITE)
+
+    case SCSI_WRITE_AND_VERIFY_10:
+    case SCSI_WRITE_AND_VERIFY_12:
+    case SCSI_WRITE_AND_VERIFY_16:
+#endif //    !defined(DISABLE_SATI_WRITE_AND_VERIFY)
+       // && !defined(DISABLE_SATI_VERIFY)
+       // && !defined(DISABLE_SATI_WRITE)
+        sati_scsi_information_descriptor_construct(
+                  sense_data + offset,
+                  sense_len - offset,
+                  information_buff);
+
+        offset += SCSI_INFORMATION_DESCRIPTOR_LENGTH;
+        break;
+    }
+}
+
+/**
+ * @brief This method will construct the descriptor sense data buffer in
+ *           the user's sense data buffer location.  Additionally, it will set
+ *           the user's SCSI status.
+ *
+ * @param[in]     sequence This parameter specifies the translation sequence
+ *                for which to construct the sense data.
+ * @param[in,out] scsi_io This parameter specifies the user's IO request
+ *                for which to construct the sense data.
+ * @param[in]     scsi_status This parameter specifies the SCSI status
+ *                value for the user's IO request.
+ * @param[in]     sense_key This parameter specifies the sense key to
+ *                be set for the user's IO request.
+ * @param[in]     additional_sense_code This parameter specifies the
+ *                additional sense code (ASC) key to be set for the user's
+ *                IO request.
+ * @param[in]     additional_sense_code_qualifier This parameter specifies
+ *                the additional sense code qualifier (ASCQ) key to be set
+ *                for the user's IO request.
+ *
+ * @return none
+ */
+void sati_scsi_descriptor_sense_data_construct(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   U8                           scsi_status,
+   U8                           response_code,
+   U8                           sense_key,
+   U8                           additional_sense_code,
+   U8                           additional_sense_code_qualifier
+)
+{
+   U8 * sense_data;
+   U32    sense_len;
+
+   sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
+
+   sati_set_sense_data_byte(
+      sense_data,
+      sense_len,
+      0,
+      response_code
+   );
+
+   sati_set_sense_data_byte(sense_data, sense_len, 1,  sense_key);
+   sati_set_sense_data_byte(sense_data, sense_len, 2,  additional_sense_code);
+   sati_set_sense_data_byte(sense_data, sense_len, 3,  additional_sense_code_qualifier);
+   sati_set_sense_data_byte(sense_data, sense_len, 4,  0);
+   sati_set_sense_data_byte(sense_data, sense_len, 5,  0);
+   sati_set_sense_data_byte(sense_data, sense_len, 6,  0);
+
+   sati_scsi_common_descriptors_construct(scsi_io, sense_data + 8, sense_len, NULL);
+
+   sati_set_sense_data_byte(sense_data, sense_len, 7,  sati_scsi_get_descriptor_sense_data_length(sequence, scsi_io) - 8);
+}
+
+/**
+ * @brief This method will construct the fixed format sense data buffer
+ *           in the user's sense data buffer location.  Additionally, it will
+ *          set the user's SCSI status.
+ *
+ * @param[in]     sequence This parameter specifies the translation sequence
+ *                for which to construct the sense data.
+ * @param[in,out] scsi_io This parameter specifies the user's IO request
+ *                for which to construct the sense data.
+ * @param[in]     scsi_status This parameter specifies the SCSI status
+ *                value for the user's IO request.
+ * @param[in]     sense_key This parameter specifies the sense key to
+ *                be set for the user's IO request.
+ * @param[in]     additional_sense_code This parameter specifies the
+ *                additional sense code (ASC) key to be set for the user's
+ *                IO request.
+ * @param[in]     additional_sense_code_qualifier This parameter specifies
+ *                the additional sense code qualifier (ASCQ) key to be set
+ *                for the user's IO request.
+ *
+ * @return none
+ */
+void sati_scsi_fixed_sense_data_construct(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   U8                           scsi_status,
+   U8                           response_code,
+   U8                           sense_key,
+   U8                           additional_sense_code,
+   U8                           additional_sense_code_qualifier
+)
+{
+    U8 * sense_data;
+    U32  sense_len;
+
+    sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
+
+    // Write out the sense data format per SPC-4.
+    // We utilize the fixed format sense data format.
+
+    sati_set_sense_data_byte(
+      sense_data,
+      sense_len,
+      0,
+      response_code | SCSI_FIXED_SENSE_DATA_VALID_BIT
+    );
+
+    sati_set_sense_data_byte(sense_data, sense_len, 1,  0);
+    sati_set_sense_data_byte(sense_data, sense_len, 2,  sense_key);
+    sati_set_sense_data_byte(sense_data, sense_len, 3,  0);
+    sati_set_sense_data_byte(sense_data, sense_len, 4,  0);
+    sati_set_sense_data_byte(sense_data, sense_len, 5,  0);
+    sati_set_sense_data_byte(sense_data, sense_len, 6,  0);
+    sati_set_sense_data_byte(sense_data, sense_len, 7,  0);
+    sati_set_sense_data_byte(sense_data, sense_len, 8,  0);
+    sati_set_sense_data_byte(sense_data, sense_len, 9,  0);
+    sati_set_sense_data_byte(sense_data, sense_len, 10, 0);
+    sati_set_sense_data_byte(sense_data, sense_len, 11, 0);
+    sati_set_sense_data_byte(sense_data, sense_len, 12, additional_sense_code);
+    sati_set_sense_data_byte(sense_data, sense_len, 13, additional_sense_code_qualifier);
+    sati_set_sense_data_byte(sense_data, sense_len, 14, 0);
+    sati_set_sense_data_byte(sense_data, sense_len, 15, 0);
+    sati_set_sense_data_byte(sense_data, sense_len, 16, 0);
+    sati_set_sense_data_byte(sense_data, sense_len, 17, 0);
+}
+
+/**
+* @brief This method will construct common sense data that will be identical in
+*        both read error sense construct functions.
+*        sati_scsi_read_ncq_error_sense_construct,
+*        sati_scsi_read_error_sense_construct
+*
+ * @param[in]    sense_data This parameter specifies the user SCSI IO request
+ *               for which to set the sense data byte.
+* @param[in]     sense_len This parameter specifies length of the sense data
+*                to be returned by SATI.
+* @param[in]     sense_key This parameter specifies the sense key to
+*                be set for the user's IO request.
+* @param[in]     additional_sense_code This parameter specifies the
+*                additional sense code (ASC) key to be set for the user's
+*                IO request.
+* @param[in]     additional_sense_code_qualifier This parameter specifies
+*                the additional sense code qualifier (ASCQ) key to be set
+*                for the user's IO request.
+*
+* @return none
+*/
+static
+void sati_scsi_common_fixed_sense_construct(
+   U8                         * sense_data,
+   U32                          sense_len,
+   U8                           sense_key,
+   U8                           additional_sense_code,
+   U8                           additional_sense_code_qualifier
+)
+{
+
+   sati_set_sense_data_byte(sense_data, sense_len, 1,  0);
+   sati_set_sense_data_byte(sense_data, sense_len, 2,  sense_key);
+
+   //Bytes 3, 4, 5, 6 are set in read_error_sense_construct functions
+
+   sati_set_sense_data_byte(sense_data, sense_len, 7,  0);
+   sati_set_sense_data_byte(sense_data, sense_len, 8,  0);
+   sati_set_sense_data_byte(sense_data, sense_len, 9,  0);
+   sati_set_sense_data_byte(sense_data, sense_len, 10, 0);
+   sati_set_sense_data_byte(sense_data, sense_len, 11, 0);
+   sati_set_sense_data_byte(sense_data, sense_len, 12, additional_sense_code);
+   sati_set_sense_data_byte(sense_data, sense_len, 13, additional_sense_code_qualifier);
+   sati_set_sense_data_byte(sense_data, sense_len, 14, 0);
+   sati_set_sense_data_byte(sense_data, sense_len, 15, 0x80);
+   sati_set_sense_data_byte(sense_data, sense_len, 16, 0);
+   sati_set_sense_data_byte(sense_data, sense_len, 17, 0);
+}
+
+/**
+ * @brief This method will construct the descriptor sense data buffer in
+ *           the user's sense data buffer location.  Additionally, it will set
+ *           the user's SCSI status.
+ *
+ * @param[in]     sequence This parameter specifies the translation sequence
+ *                for which to construct the sense data.
+ * @param[in,out] scsi_io This parameter specifies the user's IO request
+ *                for which to construct the sense data.
+ * @param[in]     scsi_status This parameter specifies the SCSI status
+ *                value for the user's IO request.
+ * @param[in]     sense_key This parameter specifies the sense key to
+ *                be set for the user's IO request.
+ * @param[in]     additional_sense_code This parameter specifies the
+ *                additional sense code (ASC) key to be set for the user's
+ *                IO request.
+ * @param[in]     additional_sense_code_qualifier This parameter specifies
+ *                the additional sense code qualifier (ASCQ) key to be set
+ *                for the user's IO request.
+ *
+ * @return none
+ */
+static
+void sati_scsi_common_descriptor_sense_construct(
+    SATI_TRANSLATOR_SEQUENCE_T * sequence,
+    void                       * scsi_io,
+    U8                         * sense_data,
+    U32                          sense_len,
+    U8                           sense_key,
+    U8                           additional_sense_code,
+    U8                           additional_sense_code_qualifier,
+    U8                         * information_buff
+)
+{
+    sati_set_sense_data_byte(sense_data, sense_len, 1,  sense_key);
+    sati_set_sense_data_byte(sense_data, sense_len, 2,  additional_sense_code);
+    sati_set_sense_data_byte(sense_data, sense_len, 3,  additional_sense_code_qualifier);
+    sati_set_sense_data_byte(sense_data, sense_len, 4,  0);
+    sati_set_sense_data_byte(sense_data, sense_len, 5,  0);
+    sati_set_sense_data_byte(sense_data, sense_len, 6,  0);
+
+    sati_scsi_common_descriptors_construct(scsi_io, sense_data + 8, sense_len, information_buff);
+
+    sati_set_sense_data_byte(sense_data, sense_len, 7,  sati_scsi_get_descriptor_sense_data_length(sequence, scsi_io) - 8);
+}
+
+/**
+* @brief This method will construct the sense data buffer in the user's
+*        descriptor sense data buffer location.  Additionally, it will set
+*        the user's SCSI status. This is only used for NCQ uncorrectable
+*        read errors
+*
+* @param[in]     sequence This parameter specifies the translation sequence
+*                for which to construct the sense data.
+* @param[in,out] scsi_io This parameter specifies the user's IO request
+*                for which to construct the sense data.
+* @param[in]     ata_input_data This parameter specifies the user's ATA IO
+*                response from a Read Log Ext command.
+* @param[in]     scsi_status This parameter specifies the SCSI status
+*                value for the user's IO request.
+* @param[in]     sense_key This parameter specifies the sense key to
+*                be set for the user's IO request.
+* @param[in]     additional_sense_code This parameter specifies the
+*                additional sense code (ASC) key to be set for the user's
+*                IO request.
+* @param[in]     additional_sense_code_qualifier This parameter specifies
+*                the additional sense code qualifier (ASCQ) key to be set
+*                for the user's IO request.
+*
+* @return none
+*/
+static
+void sati_scsi_read_ncq_error_descriptor_sense_construct(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_input_data,
+   U8                           scsi_status,
+   U8                           response_code,
+   U8                           sense_key,
+   U8                           additional_sense_code,
+   U8                           additional_sense_code_qualifier
+)
+{
+   U8 * sense_data;
+   U32  sense_len;
+
+   U8 information_buff[8] = {0};
+
+   ATA_NCQ_COMMAND_ERROR_LOG_T * ncq_log = (ATA_NCQ_COMMAND_ERROR_LOG_T *) ata_input_data;
+
+   sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
+
+   sati_set_sense_data_byte(
+      sense_data,
+      sense_len,
+      0,
+      response_code
+   );
+
+   information_buff[2] = ncq_log->lba_47_40;
+   information_buff[3] = ncq_log->lba_39_32;
+   information_buff[4] = ncq_log->lba_31_24;
+   information_buff[5] = ncq_log->lba_23_16;
+   information_buff[6] = ncq_log->lba_15_8;
+   information_buff[7] = ncq_log->lba_7_0;
+
+   sati_scsi_common_descriptor_sense_construct(
+           sequence,
+           scsi_io,
+           sense_data,
+           sense_len,
+           sense_key,
+           additional_sense_code,
+           additional_sense_code_qualifier,
+           information_buff
+   );
+}
+
+/**
+* @brief This method will construct the sense data buffer in the user's
+*        sense data buffer location.  Additionally, it will set the user's
+*        SCSI status. This is only used for NCQ uncorrectable read errors
+*
+* @param[in]     sequence This parameter specifies the translation sequence
+*                for which to construct the sense data.
+* @param[in,out] scsi_io This parameter specifies the user's IO request
+*                for which to construct the sense data.
+* @param[in]     ata_input_data This parameter specifies the user's ATA IO
+*                response from a Read Log Ext command.
+* @param[in]     scsi_status This parameter specifies the SCSI status
+*                value for the user's IO request.
+* @param[in]     sense_key This parameter specifies the sense key to
+*                be set for the user's IO request.
+* @param[in]     additional_sense_code This parameter specifies the
+*                additional sense code (ASC) key to be set for the user's
+*                IO request.
+* @param[in]     additional_sense_code_qualifier This parameter specifies
+*                the additional sense code qualifier (ASCQ) key to be set
+*                for the user's IO request.
+*
+* @return none
+*/
+static
+void sati_scsi_read_ncq_error_fixed_sense_construct(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_input_data,
+   U8                           scsi_status,
+   U8                           response_code,
+   U8                           sense_key,
+   U8                           additional_sense_code,
+   U8                           additional_sense_code_qualifier
+)
+{
+   U8 * sense_data;
+   U32  sense_len;
+   U8   valid = TRUE;
+
+   ATA_NCQ_COMMAND_ERROR_LOG_T * ncq_log = (ATA_NCQ_COMMAND_ERROR_LOG_T *) ata_input_data;
+
+   sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
+
+   if(ncq_log->lba_39_32 > 0)
+   {
+      valid = FALSE;
+   }
+
+   sati_set_sense_data_byte(
+      sense_data,
+      sense_len,
+      0,
+      (valid << 7) | response_code
+   );
+
+   sati_set_sense_data_byte(sense_data, sense_len, 3,  ncq_log->lba_31_24);
+   sati_set_sense_data_byte(sense_data, sense_len, 4,  ncq_log->lba_23_16);
+   sati_set_sense_data_byte(sense_data, sense_len, 5,  ncq_log->lba_15_8);
+   sati_set_sense_data_byte(sense_data, sense_len, 6,  ncq_log->lba_7_0);
+
+   sati_scsi_common_fixed_sense_construct(
+      sense_data,
+      sense_len,
+      sense_key,
+      additional_sense_code,
+      additional_sense_code_qualifier
+   );
+}
+
+void sati_scsi_read_ncq_error_sense_construct(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_input_data,
+   U8                           scsi_status,
+   U8                           sense_key,
+   U8                           additional_sense_code,
+   U8                           additional_sense_code_qualifier
+)
+{
+    U8 response_code;
+
+    response_code = sati_scsi_get_sense_data_response_code(sequence);
+
+    switch (response_code)
+    {
+    case SCSI_FIXED_CURRENT_RESPONSE_CODE:
+    case SCSI_FIXED_DEFERRED_RESPONSE_CODE:
+        sati_scsi_read_ncq_error_fixed_sense_construct(sequence, scsi_io, ata_input_data, scsi_status,
+                response_code, sense_key, additional_sense_code, additional_sense_code_qualifier);
+    break;
+    case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE:
+    case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE:
+        sati_scsi_read_ncq_error_descriptor_sense_construct(sequence, scsi_io, ata_input_data, scsi_status,
+                response_code, sense_key, additional_sense_code, additional_sense_code_qualifier);
+        break;
+    }
+
+    sequence->is_sense_response_set = TRUE;
+}
+
+/**
+* @brief This method will construct the sense data buffer in the user's
+*        sense data buffer location.  Additionally, it will set the user's
+*        SCSI status. This is used for uncorrectable read errors.
+*
+* @param[in]     sequence This parameter specifies the translation sequence
+*                for which to construct the sense data.
+* @param[in,out] scsi_io This parameter specifies the user's IO request
+*                for which to construct the sense data.
+* @param[in]     ata_io This parameter is a pointer to the ATA IO data used
+*                to get the ATA register fis.
+* @param[in]     scsi_status This parameter specifies the SCSI status
+*                value for the user's IO request.
+* @param[in]     sense_key This parameter specifies the sense key to
+*                be set for the user's IO request.
+* @param[in]     additional_sense_code This parameter specifies the
+*                additional sense code (ASC) key to be set for the user's
+*                IO request.
+* @param[in]     additional_sense_code_qualifier This parameter specifies
+*                the additional sense code qualifier (ASCQ) key to be set
+*                for the user's IO request.
+*
+* @return none
+*/
+static
+void sati_scsi_read_error_descriptor_sense_construct(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io,
+   U8                           scsi_status,
+   U8                           response_code,
+   U8                           sense_key,
+   U8                           additional_sense_code,
+   U8                           additional_sense_code_qualifier
+)
+{
+   U8 * sense_data;
+   U32  sense_len;
+   U8 information_buff[8] = {0};
+
+   U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
+
+   sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
+
+   information_buff[2] = sati_get_ata_lba_high_ext(register_fis);
+   information_buff[3] = sati_get_ata_lba_mid_ext(register_fis);
+   information_buff[4] = sati_get_ata_lba_low_ext(register_fis);
+   information_buff[5] = sati_get_ata_lba_high(register_fis);
+   information_buff[6] = sati_get_ata_lba_mid(register_fis);
+   information_buff[7] = sati_get_ata_lba_low(register_fis);
+
+   sati_set_sense_data_byte(
+      sense_data,
+      sense_len,
+      0,
+      SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE
+   );
+
+   sati_scsi_common_descriptor_sense_construct(
+      sequence,
+      scsi_io,
+      sense_data,
+      sense_len,
+      sense_key,
+      additional_sense_code,
+      additional_sense_code_qualifier,
+      information_buff
+   );
+}
+
+/**
+* @brief This method will construct the sense data buffer in the user's
+*        sense data buffer location.  Additionally, it will set the user's
+*        SCSI status. This is used for uncorrectable read errors.
+*
+* @param[in]     sequence This parameter specifies the translation sequence
+*                for which to construct the sense data.
+* @param[in,out] scsi_io This parameter specifies the user's IO request
+*                for which to construct the sense data.
+* @param[in]     ata_io This parameter is a pointer to the ATA IO data used
+*                to get the ATA register fis.
+* @param[in]     scsi_status This parameter specifies the SCSI status
+*                value for the user's IO request.
+* @param[in]     sense_key This parameter specifies the sense key to
+*                be set for the user's IO request.
+* @param[in]     additional_sense_code This parameter specifies the
+*                additional sense code (ASC) key to be set for the user's
+*                IO request.
+* @param[in]     additional_sense_code_qualifier This parameter specifies
+*                the additional sense code qualifier (ASCQ) key to be set
+*                for the user's IO request.
+*
+* @return none
+*/
+static
+void sati_scsi_read_error_fixed_sense_construct(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io,
+   U8                           scsi_status,
+   U8                           response_code,
+   U8                           sense_key,
+   U8                           additional_sense_code,
+   U8                           additional_sense_code_qualifier
+)
+{
+   U8 * sense_data;
+   U32  sense_len;
+   U8   valid = TRUE;
+
+   U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
+
+   sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
+
+   if(sati_get_ata_lba_mid_ext(register_fis) > 0)
+   {
+      valid = FALSE;
+   }
+
+   sati_set_sense_data_byte(sense_data, sense_len, 3,  sati_get_ata_lba_low_ext(register_fis));
+   sati_set_sense_data_byte(sense_data, sense_len, 4,  sati_get_ata_lba_high(register_fis));
+   sati_set_sense_data_byte(sense_data, sense_len, 5,  sati_get_ata_lba_mid(register_fis));
+   sati_set_sense_data_byte(sense_data, sense_len, 6,  sati_get_ata_lba_low(register_fis));
+
+
+   sati_set_sense_data_byte(
+      sense_data,
+      sense_len,
+      0,
+      (valid << 7) | SCSI_FIXED_CURRENT_RESPONSE_CODE
+   );
+
+   sati_scsi_common_fixed_sense_construct(
+      sense_data,
+      sense_len,
+      sense_key,
+      additional_sense_code,
+      additional_sense_code_qualifier
+   );
+}
+
+void sati_scsi_read_error_sense_construct(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_input_data,
+   U8                           scsi_status,
+   U8                           sense_key,
+   U8                           additional_sense_code,
+   U8                           additional_sense_code_qualifier
+)
+{
+    U8 response_code;
+
+    response_code = sati_scsi_get_sense_data_response_code(sequence);
+
+    switch (response_code)
+    {
+    case SCSI_FIXED_CURRENT_RESPONSE_CODE:
+    case SCSI_FIXED_DEFERRED_RESPONSE_CODE:
+        sati_scsi_read_error_fixed_sense_construct(sequence, scsi_io, ata_input_data, scsi_status,
+                response_code, sense_key, additional_sense_code, additional_sense_code_qualifier);
+    break;
+    case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE:
+    case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE:
+        sati_scsi_read_error_descriptor_sense_construct(sequence, scsi_io, ata_input_data, scsi_status,
+                response_code, sense_key, additional_sense_code, additional_sense_code_qualifier);
+        break;
+    }
+
+    sequence->is_sense_response_set = TRUE;
+}
+
+/*
+ * @brief This method builds the scsi response data for a sata task management
+ *        request.
+ *
+ * @param[in]     sequence This parameter specifies the translation sequence
+ *                for which to construct the sense data.
+ * @param[in,out] scsi_io This parameter specifies the user's IO request
+ *                for which to construct the sense data.
+ * @param[in]     response_data The response status for the task management
+ *                request.
+ */
+void sati_scsi_response_data_construct(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   U8                           response_data
+)
+{
+#ifdef SATI_TRANSPORT_SUPPORTS_SAS
+   SCI_SSP_RESPONSE_IU_T * rsp_iu  = (SCI_SSP_RESPONSE_IU_T*)
+                                        sati_cb_get_response_iu_address(scsi_io);
+   rsp_iu->data_present            = 0x01;
+   rsp_iu->response_data_length[3] = sizeof(U32);
+   rsp_iu->status                  = 0;
+   ((U8 *)rsp_iu->data)[3]         = response_data;
+#else
+#endif // SATI_TRANSPORT_SUPPORTS_SAS
+}
+
+/**
+ * @brief This method checks to make sure that the translation isn't
+ *        exceeding the allocation length specified in the CDB prior
+ *        to retrieving the payload data byte from the user's buffer.
+ *
+ * @param[in,out] scsi_io This parameter specifies the user's IO request
+ *                for which to set the user payload data byte.
+ * @param[in]     byte_offset This parameter specifies the offset into
+ *                the user's payload buffer at which to write the supplied
+ *                value.
+ * @param[in]     value This parameter specifies the memory location into
+ *                which to read the value from the user's payload buffer.
+ *
+ * @return none
+ */
+void sati_get_data_byte(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   U32                          byte_offset,
+   U8                         * value
+)
+{
+   if (byte_offset < sequence->allocation_length)
+      sati_cb_get_data_byte(scsi_io, byte_offset, value);
+}
+
+/**
+ * @brief This method checks to make sure that the translation isn't
+ *        exceeding the allocation length specified in the CDB while
+ *        translating payload data into the user's buffer.
+ *
+ * @param[in]     sequence This parameter specifies the translation sequence
+ *                for which to set the user payload data byte.
+ * @param[in,out] scsi_io This parameter specifies the user's IO request
+ *                for which to set the user payload data byte.
+ * @param[in]     byte_offset This parameter specifies the offset into
+ *                the user's payload buffer at which to write the supplied
+ *                value.
+ * @param[in]     value This parameter specifies the new value to be
+ *                written out into the user's payload buffer.
+ *
+ * @return none
+ */
+void sati_set_data_byte(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   U32                          byte_offset,
+   U8                           value
+)
+{
+   if (byte_offset < sequence->allocation_length)
+   {
+      sequence->number_data_bytes_set++;
+      sati_cb_set_data_byte(scsi_io, byte_offset, value);
+   }
+}
+
+/**
+ * @brief This method checks to make sure that the translation isn't
+ *        exceeding the allocation length specified in the CDB while
+ *        translating payload data into the user's buffer.
+ *
+ * @param[in]     sequence This parameter specifies the translation sequence
+ *                for which to set the user payload data dword.
+ * @param[in,out] scsi_io This parameter specifies the user's IO request
+ *                for which to set the user payload data dword.
+ * @param[in]     byte_offset This parameter specifies the offset into
+ *                the user's payload buffer at which to write the supplied
+ *                value.
+ * @param[in]     value This parameter specifies the new value to be
+ *                written out into the user's payload buffer.
+ *
+ * @return none
+ */
+void sati_set_data_dword(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   U32                          byte_offset,
+   U32                          value
+)
+{
+   /// @todo Check to ensure that the bytes appear correctly (SAS Address).
+
+   sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)value & 0xFF);
+       byte_offset++;
+   sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)(value >> 8) & 0xFF);
+       byte_offset++;
+   sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)(value >> 16) & 0xFF);
+       byte_offset++;
+   sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)(value >> 24) & 0xFF);
+}
+
+/**
+ * @brief This method will construct the ATA flush cache command.
+ *
+ * @pre It is expected that the user has properly set the current contents
+ *      of the register FIS to 0.
+ *
+ * @param[out] ata_io This parameter specifies the ATA IO request structure
+ *             for which to build the FLUSH CACHE command.
+ * @param[in]  sequence This parameter specifies the translator sequence
+ *             for which the command is being constructed.
+ *
+ * @return none.
+ */
+void sati_ata_flush_cache_construct(
+   void                       * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T * sequence
+)
+{
+   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+   sati_set_ata_command(register_fis, ATA_FLUSH_CACHE);
+   sati_ata_non_data_command(ata_io, sequence);
+}
+
+/**
+ * @brief This method will construct the ATA standby immediate command.
+ *
+ * @pre It is expected that the user has properly set the current contents
+ *      of the register FIS to 0.
+ *
+ * @param[out] ata_io This parameter specifies the ATA IO request structure
+ *             for which to build the STANDBY IMMEDIATE command.
+ * @param[in]  sequence This parameter specifies the translator sequence
+ *             for which the command is being constructed.
+ *
+ * @param[in]  count This parameter specifies the time period programmed
+ *             into the Standby Timer. See ATA8 spec for more details
+ * @return none.
+ */
+void sati_ata_standby_construct(
+   void                       * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   U16                          count
+)
+{
+   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+   sati_set_ata_command(register_fis, ATA_STANDBY);
+   sati_set_ata_sector_count(register_fis, count);
+
+   sequence->device->ata_standby_timer = (U8) count;
+
+   sati_ata_non_data_command(ata_io, sequence);
+}
+
+/**
+ * @brief This method will construct the ATA standby immediate command.
+ *
+ * @pre It is expected that the user has properly set the current contents
+ *      of the register FIS to 0.
+ *
+ * @param[out] ata_io This parameter specifies the ATA IO request structure
+ *             for which to build the STANDBY IMMEDIATE command.
+ * @param[in]  sequence This parameter specifies the translator sequence
+ *             for which the command is being constructed.
+ *
+ * @return none.
+ */
+void sati_ata_standby_immediate_construct(
+   void                       * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T * sequence
+)
+{
+   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+   sati_set_ata_command(register_fis, ATA_STANDBY_IMMED);
+   sati_ata_non_data_command(ata_io, sequence);
+}
+
+/**
+ * @brief This method will construct the ATA idle immediate command.
+ *
+ * @pre It is expected that the user has properly set the current contents
+ *      of the register FIS to 0.
+ *
+ * @param[out] ata_io This parameter specifies the ATA IO request structure
+ *             for which to build the IDLE IMMEDIATE command.
+ * @param[in]  sequence This parameter specifies the translator sequence
+ *             for which the command is being constructed.
+ *
+ * @return none.
+ */
+void sati_ata_idle_immediate_construct(
+   void                       * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T * sequence
+)
+{
+   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+   sati_set_ata_command(register_fis, ATA_IDLE_IMMED);
+   sati_set_ata_features(register_fis, 0x00);
+   sati_set_ata_sector_count(register_fis, 0x00);
+   sati_set_ata_lba_high(register_fis, 0x00);
+   sati_set_ata_lba_mid(register_fis, 0x00);
+   sati_set_ata_lba_low(register_fis, 0x00);
+   sati_ata_non_data_command(ata_io, sequence);
+}
+
+/**
+ * @brief This method will construct the ATA idle immediate command
+          for Unload Features.
+ *
+ * @pre It is expected that the user has properly set the current contents
+ *      of the register FIS to 0.
+ *
+ * @param[out] ata_io This parameter specifies the ATA IO request structure
+ *             for which to build the IDLE IMMEDIATE command.
+ * @param[in]  sequence This parameter specifies the translator sequence
+ *             for which the command is being constructed.
+ *
+ * @return none.
+ */
+void sati_ata_idle_immediate_unload_construct(
+   void                       * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T * sequence
+)
+{
+   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+   sati_set_ata_command(register_fis, ATA_IDLE_IMMED);
+   sati_set_ata_features(register_fis, 0x44);
+   sati_set_ata_sector_count(register_fis, 0x00);
+   sati_set_ata_lba_high(register_fis, 0x55);
+   sati_set_ata_lba_mid(register_fis, 0x4E);
+   sati_set_ata_lba_low(register_fis, 0x4C);
+   sati_ata_non_data_command(ata_io, sequence);
+}
+
+/**
+ * @brief This method will construct the ATA IDLE command.\
+ *
+ * @pre It is expected that the user has properly set the current contents
+ *      of the register FIS to 0.
+ *
+ * @param[out] ata_io This parameter specifies the ATA IO request structure
+ *             for which to build the ATA IDLE command.
+ * @param[in]  sequence This parameter specifies the translator sequence
+ *             for which the command is being constructed.
+ *
+ * @return none.
+ */
+void sati_ata_idle_construct(
+   void                       * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T * sequence
+)
+{
+   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+   sati_set_ata_command(register_fis, ATA_IDLE);
+   sati_set_ata_features(register_fis, 0x00);
+   sati_set_ata_sector_count(register_fis, 0x00);
+
+   sequence->device->ata_standby_timer = 0x00;
+
+   sati_set_ata_lba_high(register_fis, 0x00);
+   sati_set_ata_lba_mid(register_fis, 0x00);
+   sati_set_ata_lba_low(register_fis, 0x00);
+   sati_ata_non_data_command(ata_io, sequence);
+}
+
+/**
+ * @brief This method will construct the ATA MEDIA EJECT command.
+ *
+ * @pre It is expected that the user has properly set the current contents
+ *      of the register FIS to 0.
+ *
+ * @param[out] ata_io This parameter specifies the ATA IO request structure
+ *             for which to build the MEDIA EJCT command.
+ * @param[in]  sequence This parameter specifies the translator sequence
+ *             for which the command is being constructed.
+ *
+ * @return none.
+ */
+void sati_ata_media_eject_construct(
+   void                       * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T * sequence
+)
+{
+   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+   sati_set_ata_command(register_fis, ATA_MEDIA_EJECT);
+   sati_ata_non_data_command(ata_io, sequence);
+}
+
+
+/**
+ * @brief This method will construct the ATA read verify sector(s) command.
+ *
+ * @pre It is expected that the user has properly set the current contents
+ *      of the register FIS to 0.
+ *
+ * @param[out] ata_io This parameter specifies the ATA IO request structure
+ *             for which to build the ATA READ VERIFY SECTOR(S) command.
+ * @param[in]  sequence This parameter specifies the translator sequence
+ *             for which the command is being constructed.
+ *
+ * @return none.
+ */
+void sati_ata_read_verify_sectors_construct(
+   void                       * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T * sequence
+)
+{
+   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+   sati_set_ata_command(register_fis, ATA_READ_VERIFY_SECTORS);
+
+   //According to SAT-2 (v7) 9.11.3
+   sati_set_ata_sector_count(register_fis, 1);
+
+   //According to SAT-2 (v7) 9.11.3, set LBA to a value between zero and the
+   //maximum LBA supported by the ATA device in its current configuration.
+   //From the unit test, it seems we have to set LBA to a non-zero value.
+   sati_set_ata_lba_low(register_fis, 1);
+
+   sati_ata_non_data_command(ata_io, sequence);
+}
+
+/**
+ * @brief This method will construct a ATA SMART Return Status command so the
+ *        status of the ATA device can be returned. The status of the SMART
+ *        threshold will be returned by this command.
+ *
+ * @return N/A
+ *
+ */
+void sati_ata_smart_return_status_construct(
+   void                       * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   U8                           feature_value
+)
+{
+   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+   sati_set_ata_command(register_fis, ATA_SMART);
+
+   sati_set_ata_features(register_fis, feature_value);
+
+   sati_set_ata_lba_high(register_fis, 0xC2);
+   sati_set_ata_lba_mid(register_fis, 0x4F);
+
+   sati_ata_non_data_command(ata_io, sequence);
+}
+
+/**
+ * @brief This method will construct a ATA SMART Return Status command so the
+ *        status of the ATA device can be returned. The status of the SMART
+ *        threshold will be returned by this command.
+ *
+ * @return N/A
+ *
+ */
+void sati_ata_smart_read_log_construct(
+   void                       * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   U8                           log_address,
+   U32                          transfer_length
+)
+{
+   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+   sati_set_ata_command(register_fis, ATA_SMART);
+   sati_set_ata_features(register_fis, ATA_SMART_SUB_CMD_READ_LOG);
+
+   sati_set_ata_lba_high(register_fis, 0xC2);
+   sati_set_ata_lba_mid(register_fis, 0x4F);
+   sati_set_ata_lba_low(register_fis, log_address);
+
+   sequence->data_direction      = SATI_DATA_DIRECTION_IN;
+   sequence->protocol            = SAT_PROTOCOL_PIO_DATA_IN;
+   sequence->ata_transfer_length = transfer_length;
+}
+
+/**
+ * @brief This method will construct a Write Uncorrectable ATA command that
+ *        will write one sector with a psuedo or flagged error. The type of
+ *        error is specified by the feature value.
+ *
+ * @return N/A
+ *
+ */
+void sati_ata_write_uncorrectable_construct(
+   void                       * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   U8                           feature_value
+)
+{
+   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+   sati_set_ata_command(register_fis, ATA_WRITE_UNCORRECTABLE);
+   sati_set_ata_features(register_fis, feature_value);
+   sati_set_ata_sector_count(register_fis, 0x0001);
+   sati_ata_non_data_command(ata_io, sequence);
+}
+
+/**
+ * @brief This method will construct a Mode Select ATA SET FEATURES command
+ *        For example, Enable/Disable Write Cache, Enable/Disable Read Ahead
+ *
+ * @return N/A
+ *
+ */
+void sati_ata_set_features_construct(
+   void                       * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   U8                           feature
+)
+{
+   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+   sati_set_ata_command(register_fis, ATA_SET_FEATURES);
+   sati_set_ata_features(register_fis, feature);
+   sati_ata_non_data_command(ata_io, sequence);
+}
+
+
+
+/**
+ * @brief This method will construct a Read Log ext ATA command that
+ *        will request a log page based on the log_address.
+ *
+ * @param[in]  log_address This parameter specifies the log page
+ *             to be returned from Read Log Ext.
+ *
+ * @param[in]  transfer_length This parameter specifies the size of the
+ *             log page response returned by Read Log Ext.
+ *
+ * @return N/A
+ *
+ */
+void sati_ata_read_log_ext_construct(
+   void                          * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T    * sequence,
+   U8                              log_address,
+   U32                             transfer_length
+)
+{
+   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+   sati_set_ata_command(register_fis, ATA_READ_LOG_EXT);
+
+   sati_set_ata_lba_low(register_fis, log_address);
+   sati_set_ata_lba_mid(register_fis, 0x00);
+   sati_set_ata_lba_mid_exp(register_fis, 0x00);
+
+   sati_set_ata_sector_count(register_fis, 0x01);
+
+   sequence->data_direction      = SATI_DATA_DIRECTION_IN;
+   sequence->protocol            = SAT_PROTOCOL_PIO_DATA_IN;
+   sequence->ata_transfer_length = transfer_length;
+
+}
+
+/**
+* @brief This method will check if the ATA device is in the stopped power
+*        state. This is used for all medium access commands for SAT
+*        compliance. See SAT2r07 section 9.11.1
+*
+* @param[in] sequence - SATI sequence data with the device state.
+*
+* @return TRUE If device is stopped
+*
+*/
+BOOL sati_device_state_stopped(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io
+)
+{
+   if(sequence->device->state == SATI_DEVICE_STATE_STOPPED)
+   {
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_NOT_READY ,
+         SCSI_ASC_INITIALIZING_COMMAND_REQUIRED,
+         SCSI_ASCQ_INITIALIZING_COMMAND_REQUIRED
+      );
+      return TRUE;
+   }
+   return FALSE;
+}
+
+/**
+* @brief This method will construct a ATA Read Buffer command that
+*        will request PIO in data containing the target device's buffer.
+*
+* @param[out] ata_io This parameter specifies the ATA IO request structure
+*             for which to build the ATA READ VERIFY SECTOR(S) command.
+* @param[in]  sequence This parameter specifies the translator sequence
+*             for which the command is being constructed.
+* @return N/A
+*
+*/
+void sati_ata_read_buffer_construct(
+   void                       * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T * sequence
+)
+{
+   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+   sati_set_ata_command(register_fis, ATA_READ_BUFFER);
+   sequence->data_direction      = SATI_DATA_DIRECTION_IN;
+   sequence->protocol            = SAT_PROTOCOL_PIO_DATA_IN;
+   sequence->ata_transfer_length = 512;
+}
+
+
+/**
+* @brief This method will construct a ATA Write Buffer command that
+*        will send PIO out data to the target device's buffer.
+*
+* @param[out] ata_io This parameter specifies the ATA IO request structure
+*             for which to build the ATA READ VERIFY SECTOR(S) command.
+* @param[in]  sequence This parameter specifies the translator sequence
+*             for which the command is being constructed.
+* @return N/A
+*
+*/
+void sati_ata_write_buffer_construct(
+   void                       * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T * sequence
+)
+{
+   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+   sati_set_ata_command(register_fis, ATA_WRITE_BUFFER);
+
+   sequence->data_direction      = SATI_DATA_DIRECTION_OUT;
+   sequence->protocol            = SAT_PROTOCOL_PIO_DATA_OUT;
+   sequence->ata_transfer_length = 512;
+}
+
+
+/**
+* @brief This method will construct a ATA Download Microcode command that
+*        will send PIO out data containing new firmware for the target drive.
+*
+* @param[out] ata_io This parameter specifies the ATA IO request structure
+*             for which to build the ATA READ VERIFY SECTOR(S) command.
+* @param[in]  sequence This parameter specifies the translator sequence
+*             for which the command is being constructed.
+* @param[in]  mode This parameter specifies the download microcode sub-command
+*             code.
+* @param[in]  allocation_length This parameter specifies the number of bytes
+*             being sent to the target device.
+* @param[in]  buffer_offset This parameter specifies the buffer offset for the
+*             data sent to the target device.
+*
+* @return N/A
+*
+*/
+void sati_ata_download_microcode_construct(
+   void                       * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   U8                           mode,
+   U32                          allocation_length,
+   U32                          buffer_offset
+)
+{
+   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+   sati_set_ata_command(register_fis, ATA_DOWNLOAD_MICROCODE);
+   sati_set_ata_features(register_fis, mode);
+
+   if(mode == ATA_MICROCODE_DOWNLOAD_SAVE)
+   {
+      sati_set_ata_sector_count(register_fis, (U8) (allocation_length >> 9));
+      sati_set_ata_lba_low(register_fis, (U8) (allocation_length >> 17));
+   }
+   else //mode == 0x03
+   {
+      sati_set_ata_sector_count(register_fis, (U8) (allocation_length >> 9));
+      sati_set_ata_lba_low(register_fis, (U8) (allocation_length >> 17));
+      sati_set_ata_lba_high(register_fis, (U8) (buffer_offset >> 9));
+   }
+
+   if((allocation_length == 0) && (buffer_offset == 0))
+   {
+      sati_ata_non_data_command(ata_io, sequence);
+   }
+   else
+   {
+      sequence->data_direction      = SATI_DATA_DIRECTION_OUT;
+      sequence->protocol            = SAT_PROTOCOL_PIO_DATA_OUT;
+      sequence->ata_transfer_length = allocation_length;
+   }
+}
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_util.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_util.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,393 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_UTIL_H_
+#define _SATI_UTIL_H_
+
+/**
+ * @file
+ * @brief This file contains all of the interface methods, macros, structures
+ *        that provide general support for SATI.  Some methods can be utilized
+ *        by a user to construct ATA/ATAPI commands, copy ATA device
+ *        structure data, fill in sense data, etc.
+ */
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+#include <dev/isci/scil/intel_sata.h>
+#include <dev/isci/scil/intel_sas.h>
+
+/**
+ * This macro allows the translator to be able to handle environments where
+ * the contents of the CDB are of a different endian nature of byte swapped
+ * in some fashion.
+ */
+#define sati_get_cdb_byte(the_cdb, index)    (the_cdb)[(index)]
+
+#define sati_get_ata_status(the_reg_fis) ((SATA_FIS_REG_D2H_T*)(the_reg_fis))->status
+#define sati_get_ata_error(the_reg_fis) ((SATA_FIS_REG_D2H_T*)(the_reg_fis))->error
+
+#define sati_get_ata_command(the_reg_fis)   \
+   ((SATA_FIS_REG_H2D_T*)(the_reg_fis))->command
+
+#define sati_get_ata_sector_count(the_reg_fis) \
+   ((SATA_FIS_REG_D2H_T*)(the_reg_fis))->sector_count
+#define sati_get_ata_sector_count_exp(the_reg_fis) \
+   ((SATA_FIS_REG_D2H_T*)(the_reg_fis))->sector_count_exp
+#define sati_get_ata_lba_low(the_reg_fis) \
+   ((SATA_FIS_REG_D2H_T*)(the_reg_fis))->lba_low
+#define sati_get_ata_lba_mid(the_reg_fis) \
+   ((SATA_FIS_REG_D2H_T*)(the_reg_fis))->lba_mid
+#define sati_get_ata_lba_high(the_reg_fis) \
+   ((SATA_FIS_REG_D2H_T*)(the_reg_fis))->lba_high
+#define sati_get_ata_sector_count_ext(the_reg_fis) \
+   ((SATA_FIS_REG_D2H_T*)(the_reg_fis))->sector_count_exp
+#define sati_get_ata_lba_low_ext(the_reg_fis) \
+   ((SATA_FIS_REG_D2H_T*)(the_reg_fis))->lba_low_exp
+#define sati_get_ata_lba_mid_ext(the_reg_fis) \
+   ((SATA_FIS_REG_D2H_T*)(the_reg_fis))->lba_mid_exp
+#define sati_get_ata_lba_high_ext(the_reg_fis) \
+   ((SATA_FIS_REG_D2H_T*)(the_reg_fis))->lba_high_exp
+#define sati_get_ata_device(the_reg_fis) \
+   ((SATA_FIS_REG_D2H_T*)(the_reg_fis))->device
+
+#define sati_set_ata_status(the_reg_fis, value) \
+   ((SATA_FIS_REG_D2H_T*)(the_reg_fis))->status = (value)
+#define sati_set_sata_fis_type(the_reg_fis, value) \
+   ((SATA_FIS_REG_H2D_T*)(the_reg_fis))->fis_type = (value)
+#define sati_set_sata_command_flag(the_reg_fis) \
+   ((SATA_FIS_REG_H2D_T*)(the_reg_fis))->command_flag = 1
+#define sati_clear_sata_command_flag(the_reg_fis) \
+   ((SATA_FIS_REG_H2D_T*)(the_reg_fis))->command_flag = 0
+
+#define sati_set_ata_command(the_reg_fis, value)          \
+   ((SATA_FIS_REG_H2D_T*)(the_reg_fis))->command = (value)
+#define sati_set_ata_features(the_reg_fis, value)         \
+   ((SATA_FIS_REG_H2D_T*)(the_reg_fis))->features = (value)
+#define sati_set_ata_features_exp(the_reg_fis, value)     \
+   ((SATA_FIS_REG_H2D_T*)(the_reg_fis))->features_exp = (value)
+#define sati_set_ata_control(the_reg_fis, value)          \
+   ((SATA_FIS_REG_H2D_T*)(the_reg_fis))->control = (value)
+#define sati_set_ata_sector_count(the_reg_fis, value)     \
+   ((SATA_FIS_REG_H2D_T*)(the_reg_fis))->sector_count = (value)
+#define sati_set_ata_sector_count_exp(the_reg_fis, value) \
+   ((SATA_FIS_REG_H2D_T*)(the_reg_fis))->sector_count_exp = (value)
+#define sati_set_ata_lba_low(the_reg_fis, value)          \
+   ((SATA_FIS_REG_H2D_T*)(the_reg_fis))->lba_low = (value)
+#define sati_set_ata_lba_mid(the_reg_fis, value)          \
+   ((SATA_FIS_REG_H2D_T*)(the_reg_fis))->lba_mid = (value)
+#define sati_set_ata_lba_high(the_reg_fis, value)         \
+   ((SATA_FIS_REG_H2D_T*)(the_reg_fis))->lba_high = (value)
+#define sati_set_ata_lba_low_exp(the_reg_fis, value)      \
+   ((SATA_FIS_REG_H2D_T*)(the_reg_fis))->lba_low_exp = (value)
+#define sati_set_ata_lba_mid_exp(the_reg_fis, value)      \
+   ((SATA_FIS_REG_H2D_T*)(the_reg_fis))->lba_mid_exp = (value)
+#define sati_set_ata_lba_high_exp(the_reg_fis, value)     \
+   ((SATA_FIS_REG_H2D_T*)(the_reg_fis))->lba_high_exp = (value)
+#define sati_set_ata_device_head(the_reg_fis, value)      \
+   ((SATA_FIS_REG_H2D_T*)(the_reg_fis))->device = (value)
+
+#define ATA_MID_REGISTER_THRESHOLD_EXCEEDED    0xF4
+#define ATA_HIGH_REGISTER_THRESHOLD_EXCEEDED   0x2C
+
+#define ATA_MICROCODE_OFFSET_DOWNLOAD        0x03
+#define ATA_MICROCODE_DOWNLOAD_SAVE          0x07
+
+#ifndef MIN
+#define MIN(x,y) ((x) < (y) ? (x) : (y))
+#endif
+
+#ifndef MAX
+#define MAX(x,y) ((x) > (y) ? (x) : (y))
+#endif
+
+
+void sati_ata_non_data_command(
+   void                        * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T  * sequence
+);
+
+void sati_ata_identify_device_construct(
+   void                       * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T * sequence
+);
+
+void sati_ata_execute_device_diagnostic_construct(
+   void                       * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T * sequence
+);
+
+void sati_ata_identify_device_copy_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * destination_scsi_io,
+   U32                          destination_offset,
+   U8                         * source_buffer,
+   U32                          source_offset,
+   U32                          length,
+   BOOL                         use_printable_chars
+);
+
+void sati_copy_data(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * destination_scsi_io,
+   U32                          destination_offset,
+   U8                         * source_buffer,
+   U32                          length
+);
+
+void sati_ata_identify_device_get_sector_info(
+   ATA_IDENTIFY_DEVICE_DATA_T * identify,
+   U32                        * lba_high,
+   U32                        * lba_low,
+   U32                        * sector_size
+);
+
+void sati_ata_check_power_mode_construct(
+   void                       * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T * sequence
+);
+
+U8 sati_scsi_get_sense_data_length(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void * scsi_io
+);
+
+void sati_scsi_common_response_iu_construct(
+   SCI_SSP_RESPONSE_IU_T *      rsp_iu,
+   U8                           scsi_status,
+   U8                           sense_data_length,
+   U8                           data_present
+);
+
+void sati_scsi_sense_data_construct(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   U8                           status,
+   U8                           sense_key,
+   U8                           additional_sense_code,
+   U8                           additional_sense_code_qualifier
+);
+
+void sati_scsi_fixed_sense_data_construct(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   U8                           response_code,
+   U8                           scsi_status,
+   U8                           sense_key,
+   U8                           additional_sense_code,
+   U8                           additional_sense_code_qualifier
+);
+
+void sati_scsi_descriptor_sense_data_construct(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   U8                           response_code,
+   U8                           scsi_status,
+   U8                           sense_key,
+   U8                           additional_sense_code,
+   U8                           additional_sense_code_qualifier
+);
+
+void sati_scsi_read_ncq_error_sense_construct(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_input_data,
+   U8                           scsi_status,
+   U8                           sense_key,
+   U8                           additional_sense_code,
+   U8                           additional_sense_code_qualifier
+);
+
+void sati_scsi_read_error_sense_construct(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io,
+   U8                           status,
+   U8                           sense_key,
+   U8                           additional_sense_code,
+   U8                           additional_sense_code_qualifier
+);
+
+void sati_scsi_response_data_construct(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   U8                           response_data
+);
+
+void sati_get_data_byte(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   U32                          byte_offset,
+   U8                         * value
+);
+
+void sati_set_data_byte(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   U32                          byte_offset,
+   U8                           value
+);
+
+void sati_set_data_dword(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   U32                          byte_offset,
+   U32                          value
+);
+
+void sati_set_sense_data_byte(
+   U8  * sense_data,
+   U32   max_sense_data_len,
+   U32   byte_offset,
+   U8    value
+);
+
+void sati_ata_flush_cache_construct(
+   void                       * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T * sequence
+);
+
+void sati_ata_standby_construct(
+   void                       * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   U16                          count
+);
+
+void sati_ata_standby_immediate_construct(
+   void                       * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T * sequence
+);
+
+void sati_ata_idle_immediate_construct(
+   void                       * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T * sequence
+);
+
+void sati_ata_idle_immediate_unload_construct(
+   void                       * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T * sequence
+);
+
+void sati_ata_idle_construct(
+   void                       * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T * sequence
+);
+
+void sati_ata_media_eject_construct(
+   void                       * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T * sequence
+);
+
+void sati_ata_read_verify_sectors_construct(
+   void                       * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T * sequence
+);
+
+void sati_ata_smart_return_status_construct(
+   void                       * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   U8                           feature_value
+);
+
+void sati_ata_smart_read_log_construct(
+   void                       * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   U8                           log_address,
+   U32                          transfer_length
+);
+
+void sati_ata_write_uncorrectable_construct(
+   void                       * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   U8                           feature_value
+);
+
+void sati_ata_set_features_construct(
+   void                       * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   U8                           feature
+);
+
+void sati_ata_read_log_ext_construct(
+   void                          * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T    * sequence,
+   U8                              log_address,
+   U32                             transfer_length
+);
+
+BOOL sati_device_state_stopped(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io
+);
+
+void sati_ata_read_buffer_construct(
+   void                       * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T * sequence
+);
+
+void sati_ata_write_buffer_construct(
+   void                       * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T * sequence
+);
+
+void sati_ata_download_microcode_construct(
+   void                       * ata_io,
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   U8                           mode,
+   U32                          block_count,
+   U32                          buffer_offset
+);
+
+#endif // _SATI_UTIL_H_
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_verify.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_verify.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,273 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains the method implementations for translating
+ *        the SCSI VERIFY (10, 12, 16-byte) commands.
+ */
+
+#if !defined(DISABLE_SATI_VERIFY)
+
+#include <dev/isci/scil/sati_verify.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/sati_move.h>
+
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_scsi.h>
+#include <dev/isci/scil/intel_sat.h>
+
+//******************************************************************************
+//* P R I V A T E   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method performs the SCSI VERIFY command translation
+ *        functionality common to all VERIFY command sizes.
+ *        This includes:
+ *        - setting the command register
+ *        - setting the device head register
+ *        - filling in fields in the SATI_TRANSLATOR_SEQUENCE object.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @return Indicate if the method was successfully completed.
+ * @retval SATI_SUCCESS This is returned in all other cases.
+ */
+static
+SATI_STATUS sati_verify_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   U8 * cdb          = sati_cb_get_cdb_address(scsi_io);
+   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+   /**
+    * The translator doesn't support performing the byte check operation.
+    * As a result, error the request if the BYTCHK bit is set.
+    */
+   if ((sati_get_cdb_byte(cdb, 1) & SCSI_VERIFY_BYTCHK_ENABLED))
+   {
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_ILLEGAL_REQUEST,
+         SCSI_ASC_INVALID_FIELD_IN_CDB,
+         SCSI_ASCQ_INVALID_FIELD_IN_CDB
+      );
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+
+   sequence->protocol       = SAT_PROTOCOL_NON_DATA;
+   sequence->data_direction = SATI_DATA_DIRECTION_NONE;
+
+   sati_set_ata_device_head(register_fis, ATA_DEV_HEAD_REG_LBA_MODE_ENABLE);
+
+   // Ensure the device supports the 48 bit feature set.
+   if (sequence->device->capabilities & SATI_DEVICE_CAP_48BIT_ENABLE)
+      sati_set_ata_command(register_fis, ATA_READ_VERIFY_SECTORS_EXT);
+   else
+      sati_set_ata_command(register_fis, ATA_READ_VERIFY_SECTORS);
+
+   return SATI_SUCCESS;
+}
+
+//******************************************************************************
+//* P U B L I C   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method performs all of the translation required for a
+ *        SCSI VERIFY 10 byte CDB.
+ *        This includes:
+ *        - logical block address translation
+ *        - transfer length (sector count) translation
+ *        - translation items common to all VERIFY CDB sizes.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation was successful.
+ *         For more information on return values please reference
+ *         sati_move_set_sector_count(), sati_verify_translate_command()
+ */
+SATI_STATUS sati_verify_10_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   SATI_STATUS   status;
+   U8          * cdb          = sati_cb_get_cdb_address(scsi_io);
+   U32           sector_count = (sati_get_cdb_byte(cdb, 7) << 8) |
+                                (sati_get_cdb_byte(cdb, 8));
+
+   if(sati_device_state_stopped(sequence, scsi_io))
+   {
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+   else
+   {
+      sequence->type = SATI_SEQUENCE_VERIFY_10;
+
+      // Fill in the Logical Block Address fields and sector count registers.
+      sati_move_translate_32_bit_lba(sequence, scsi_io, ata_io);
+      status = sati_move_set_sector_count(sequence,scsi_io,ata_io,sector_count,0);
+      if (status != SATI_SUCCESS)
+         return status;
+
+      return sati_verify_translate_command(sequence, scsi_io, ata_io);
+   }
+}
+
+/**
+ * @brief This method performs all of the translation required for a
+ *        SCSI VERIFY 12 byte CDB.
+ *        This includes:
+ *        - logical block address translation
+ *        - transfer length (sector count) translation
+ *        - translation items common to all VERIFY CDB sizes.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation was successful.
+ *         For more information on return values please reference
+ *         sati_move_set_sector_count(), sati_verify_translate_command()
+ */
+SATI_STATUS sati_verify_12_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   SATI_STATUS   status;
+   U8          * cdb          = sati_cb_get_cdb_address(scsi_io);
+   U32           sector_count = (sati_get_cdb_byte(cdb, 6) << 24) |
+                                (sati_get_cdb_byte(cdb, 7) << 16) |
+                                (sati_get_cdb_byte(cdb, 8) << 8)  |
+                                (sati_get_cdb_byte(cdb, 9));
+
+   if(sati_device_state_stopped(sequence, scsi_io))
+   {
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+   else
+   {
+      sequence->type = SATI_SEQUENCE_VERIFY_12;
+
+      // Fill in the Logical Block Address fields and sector count registers.
+      sati_move_translate_32_bit_lba(sequence, scsi_io, ata_io);
+      status = sati_move_set_sector_count(sequence,scsi_io,ata_io,sector_count,0);
+      if (status != SATI_SUCCESS)
+         return status;
+
+      return sati_verify_translate_command(sequence, scsi_io, ata_io);
+   }
+}
+
+/**
+ * @brief This method performs all of the translation required for a
+ *        SCSI VERIFY 16 byte CDB.
+ *        This includes:
+ *        - logical block address translation
+ *        - transfer length (sector count) translation
+ *        - translation items common to all VERIFY CDB sizes.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation was successful.
+ *         For more information on return values please reference
+ *         sati_move_set_sector_count(), sati_verify_translate_command()
+ */
+SATI_STATUS sati_verify_16_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   SATI_STATUS   status;
+   U8          * cdb          = sati_cb_get_cdb_address(scsi_io);
+   U32           sector_count = (sati_get_cdb_byte(cdb, 10) << 24) |
+                                (sati_get_cdb_byte(cdb, 11) << 16) |
+                                (sati_get_cdb_byte(cdb, 12) << 8)  |
+                                (sati_get_cdb_byte(cdb, 13));
+
+   if(sati_device_state_stopped(sequence, scsi_io))
+   {
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+   else
+   {
+      sequence->type = SATI_SEQUENCE_VERIFY_16;
+
+      // Fill in the Logical Block Address field.
+      status = sati_move_translate_64_bit_lba(sequence, scsi_io, ata_io);
+      if (status != SATI_SUCCESS)
+         return status;
+
+      // Fill in the Sector Count fields.
+      status = sati_move_set_sector_count(sequence,scsi_io,ata_io,sector_count,0);
+      if (status != SATI_SUCCESS)
+         return status;
+
+      return sati_verify_translate_command(sequence, scsi_io, ata_io);
+   }
+}
+
+#endif // !defined(DISABLE_SATI_VERIFY)
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_verify.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_verify.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,83 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_VERIFY_H_
+#define _SATI_VERIFY_H_
+
+/**
+ * @file
+ * @brief This file contains the method prototypes and constructs
+ *        for translating the SCSI VERIFY (10, 12, 16-byte) commands.
+ */
+
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+SATI_STATUS sati_verify_10_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+SATI_STATUS sati_verify_12_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+SATI_STATUS sati_verify_16_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+#endif // _SATI_VERIFY_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_write.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_write.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,321 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ *        translate the SCSI write (6, 10, 12, or 16-byte) commands.
+ */
+
+#include <dev/isci/scil/sati_move.h>
+#include <dev/isci/scil/sati_write.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_util.h>
+
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_scsi.h>
+
+//******************************************************************************
+//* P R I V A T E   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method performs the common translation functionality for
+ *        all SCSI write operations that are 10 bytes in size or larger.
+ *        Translated/Written items include:
+ *        - Force Unit Access (FUA)
+ *        - Sector Count/Transfer Length
+ *        - Command register
+ *
+ * @param[in] sector_count This parameter specifies the number of sectors
+ *            to be transferred by this request.
+ * @param[in] device_head This parameter points to device head register
+ *            that is to be written into the ATA task file (register FIS).
+ *
+ * @return Indicate if the command translation succeeded.
+ * @see sati_move_set_sector_count() for additional return values.
+ */
+static
+SATI_STATUS sati_write_large_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io,
+   U32                          sector_count,
+   U8                         * device_head
+)
+{
+   sequence->data_direction = SATI_DATA_DIRECTION_OUT;
+
+   return sati_move_large_translate_command(
+             sequence,
+             scsi_io,
+             ata_io,
+             sector_count,
+             device_head
+          );
+}
+
+/**
+ * @brief This method performs the common translation functionality for
+ *        all SCSI write operations containing a 32-bit logical block
+ *        address.
+ *        Translated/Written items include:
+ *        - Logical Block Address (LBA)
+ *        - Force Unit Access (FUA)
+ *        - Sector Count/Transfer Length
+ *        - Command register
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @param[in] sector_count This parameter specifies the number of sectors
+ *            to be transferred by this request.
+ * @param[in] control_byte_offset This parameter specifies the byte offset
+ *            into the command descriptor block at which the control byte
+ *            is located.
+ *
+ * @return Indicate if the command translation succeeded.
+ * @see sati_move_32_bit_lba_translate_command(), sati_move_set_sector_count()
+ *      for additional return values.
+ */
+static
+SATI_STATUS sati_write_32_bit_lba_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io,
+   U32                          sector_count,
+   U8                           control_byte_offset
+)
+{
+   U8           device_head = 0;
+   SATI_STATUS  status;
+
+   status = sati_write_large_translate_command(
+               sequence, scsi_io, ata_io, sector_count, &device_head
+            );
+
+   if (status == SATI_SUCCESS)
+   {
+      status = sati_move_32_bit_lba_translate_command(
+                  sequence, scsi_io, ata_io, device_head
+               );
+   }
+
+   return status;
+}
+
+//******************************************************************************
+//* P U B L I C   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method will translate the SCSI write command into a
+ *        corresponding ATA write 6 command.  Depending upon the capabilities
+ *        supported by the target different ATA commands can be selected.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the command translation was
+ *         successful.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
+ *         sense data has been created as a result of something specified
+ *         in the CDB.
+ */
+SATI_STATUS sati_write_6_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   if(sati_device_state_stopped(sequence, scsi_io))
+   {
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+   else
+   {
+      sequence->data_direction = SATI_DATA_DIRECTION_OUT;
+      sequence->type           = SATI_SEQUENCE_WRITE_6;
+
+      return sati_move_small_translate_command(sequence, scsi_io, ata_io);
+   }
+}
+
+/**
+ * @brief This method will translate the SCSI write 10 command into a
+ *        corresponding ATA write command.  Depending upon the capabilities
+ *        supported by the target different ATA commands can be selected.
+ *        It ensures that all translation required for this command is
+ *        performed successfully.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @see sati_write_32_bit_lba_translate_command() for return values.
+ */
+SATI_STATUS sati_write_10_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   U8  * cdb          = sati_cb_get_cdb_address(scsi_io);
+   U32   sector_count = (sati_get_cdb_byte(cdb, 7) << 8) |
+                        (sati_get_cdb_byte(cdb, 8));
+
+   if(sati_device_state_stopped(sequence, scsi_io))
+   {
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+   else
+   {
+      sequence->type     = SATI_SEQUENCE_WRITE_10;
+
+      return sati_write_32_bit_lba_translate_command(
+                sequence, scsi_io, ata_io, sector_count, 9
+             );
+   }
+}
+
+/**
+ * @brief This method will translate the SCSI write 12 command into a
+ *        corresponding ATA write command.  Depending upon the capabilities
+ *        supported by the target different ATA commands can be selected.
+ *        It ensures that all translation required for this command is
+ *        performed successfully.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @see sati_write_32_bit_lba_translate_command() for return values.
+ */
+SATI_STATUS sati_write_12_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   U8  * cdb          = sati_cb_get_cdb_address(scsi_io);
+   U32   sector_count = (sati_get_cdb_byte(cdb, 6) << 24) |
+                        (sati_get_cdb_byte(cdb, 7) << 16) |
+                        (sati_get_cdb_byte(cdb, 8) << 8)  |
+                        (sati_get_cdb_byte(cdb, 9));
+
+   if(sati_device_state_stopped(sequence, scsi_io))
+   {
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+   else
+   {
+      sequence->type = SATI_SEQUENCE_WRITE_12;
+
+      return sati_write_32_bit_lba_translate_command(
+                sequence, scsi_io, ata_io, sector_count, 11
+             );
+   }
+}
+
+/**
+ * @brief This method will translate the SCSI write 16 command into a
+ *        corresponding ATA write command.  Depending upon the capabilities
+ *        supported by the target different ATA commands can be selected.
+ *        It ensures that all translation required for this command is
+ *        performed successfully.
+ *        For more information on the parameters passed to this method,
+ *        please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @see sati_write_large_translate_command(), sati_move_translate_64_bit_lba()
+ *      for additional return values.
+ */
+SATI_STATUS sati_write_16_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   SATI_STATUS   status;
+   U8            device_head  = 0;
+   U8          * cdb          = sati_cb_get_cdb_address(scsi_io);
+   U32           sector_count = (sati_get_cdb_byte(cdb, 10) << 24) |
+                                (sati_get_cdb_byte(cdb, 11) << 16) |
+                                (sati_get_cdb_byte(cdb, 12) << 8)  |
+                                (sati_get_cdb_byte(cdb, 13));
+
+   if(sati_device_state_stopped(sequence, scsi_io))
+   {
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+   else
+   {
+      sequence->type   = SATI_SEQUENCE_WRITE_16;
+
+      // Translate the sector count, write command register, and check various
+      // other parts of the CDB.
+      status = sati_write_large_translate_command(
+                  sequence, scsi_io, ata_io, sector_count, &device_head
+               );
+
+      // Attempt to translate the 64-bit LBA field from the SCSI request
+      // into the 48-bits of LBA in the ATA register FIS.
+      if (status == SATI_SUCCESS)
+      {
+         sati_move_translate_command(sequence, scsi_io, ata_io, device_head);
+         status = sati_move_translate_64_bit_lba(sequence, scsi_io, ata_io);
+      }
+
+      return status;
+   }
+}
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_write.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_write.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,91 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_WRITE_H_
+#define _SATI_WRITE_H_
+
+/**
+ * @file
+ * @brief This file contains the method declarations and type definitions
+ *        required to translate the SCSI write (6, 10, 12, or 16-byte)
+ *        commands.
+ */
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+SATI_STATUS sati_write_6_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+SATI_STATUS sati_write_10_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+SATI_STATUS sati_write_12_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+SATI_STATUS sati_write_16_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+#endif // _SATI_WRITE_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_write_and_verify.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_write_and_verify.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,243 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+*
+* GPL LICENSE SUMMARY
+*
+* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of version 2 of the GNU General Public License as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+* The full GNU General Public License is included in this distribution
+* in the file called LICENSE.GPL.
+*
+* BSD LICENSE
+*
+* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+*   * Redistributions of source code must retain the above copyright
+*     notice, this list of conditions and the following disclaimer.
+*   * Redistributions in binary form must reproduce the above copyright
+*     notice, this list of conditions and the following disclaimer in
+*     the documentation and/or other materials provided with the
+*     distribution.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+* @file
+* @brief This file contains the method implementations to translate
+*        SCSI Write and Verify command based of the SAT spec.
+*/
+
+#if !defined(DISABLE_SATI_WRITE_AND_VERIFY)
+
+#include <dev/isci/scil/sati_write_and_verify.h>
+#include <dev/isci/scil/sati_write.h>
+#include <dev/isci/scil/sati_verify.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_util.h>
+
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_scsi.h>
+
+/**
+* @brief This function translates a SCSI Write and Verify 10 command
+*        into both ATA write and ATA read verify commands. This
+*        happens by passing the SCSI IO, ATA IO, and Sequence pointers
+*        to both the sati_write_10_translate_command and the
+*        sati_verify_10_translate_command.
+*
+* @return Indicate if the command translation succeeded.
+* @retval SCI_SUCCESS This is returned if the command translation was
+*         successful.
+* @retval SATI_FAILURE_CHECK_RESPONSE_DATA is returned if there was
+*         a problem with the translation of write long.
+* @retval SATI_FAILURE is returned if there the sequence is out of
+*         state for a sati_write_and_verify_10 translation.
+*
+*/
+SATI_STATUS sati_write_and_verify_10_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   SATI_STATUS status;
+
+   if(sequence->state == SATI_SEQUENCE_STATE_INITIAL)
+   {
+      status = sati_write_10_translate_command(sequence, scsi_io, ata_io);
+      sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
+      sequence->is_translate_response_required = TRUE;
+   }
+   else if(sequence->state == SATI_SEQUENCE_STATE_INCOMPLETE)
+   {
+      status = sati_verify_10_translate_command(sequence, scsi_io, ata_io);
+      sequence->state = SATI_SEQUENCE_STATE_AWAIT_RESPONSE;
+   }
+   else
+   {
+      //SATI sequence is in the wrong state
+      return SATI_FAILURE;
+   }
+
+   sequence->type = SATI_SEQUENCE_WRITE_AND_VERIFY;
+   return status;
+}
+
+/**
+* @brief This function translates a SCSI Write and Verify 12 command
+*        into both ATA write and ATA read verify commands. This
+*        happens by passing the SCSI IO, ATA IO, and Sequence pointers
+*        to both the sati_write_12_translate_command and the
+*        sati_verify_12_translate_command.
+*
+* @return Indicate if the command translation succeeded.
+* @retval SCI_SUCCESS This is returned if the command translation was
+*         successful.
+* @retval SATI_FAILURE_CHECK_RESPONSE_DATA is returned if there was
+*         a problem with the translation of write long.
+* @retval SATI_FAILURE is returned if there the sequence is out of
+*         state for a sati_write_and_verify_12 translation.
+*
+*/
+SATI_STATUS sati_write_and_verify_12_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   SATI_STATUS status;
+
+   if(sequence->state == SATI_SEQUENCE_STATE_INITIAL)
+   {
+      status = sati_write_12_translate_command(sequence, scsi_io, ata_io);
+      sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
+      sequence->is_translate_response_required = TRUE;
+   }
+   else if(sequence->state == SATI_SEQUENCE_STATE_INCOMPLETE)
+   {
+      status = sati_verify_12_translate_command(sequence, scsi_io, ata_io);
+      sequence->state = SATI_SEQUENCE_STATE_AWAIT_RESPONSE;
+   }
+   else
+   {
+      //SATI sequence is in the wrong state
+      return SATI_FAILURE;
+   }
+
+   sequence->type = SATI_SEQUENCE_WRITE_AND_VERIFY;
+   return status;
+}
+
+/**
+* @brief This function translates a SCSI Write and Verify 16 command
+*        into both ATA write and ATA read verify commands. This
+*        happens by passing the SCSI IO, ATA IO, and Sequence pointers
+*        to both the sati_write_16_translate_command and the
+*        sati_verify_16_translate_command.
+*
+* @return Indicate if the command translation succeeded.
+* @retval SCI_SUCCESS This is returned if the command translation was
+*         successful.
+* @retval SATI_FAILURE_CHECK_RESPONSE_DATA is returned if there was
+*         a problem with the translation of write long.
+* @retval SATI_FAILURE is returned if there the sequence is out of
+*         state for a sati_write_and_verify_16 translation.
+*
+*/
+SATI_STATUS sati_write_and_verify_16_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   SATI_STATUS status;
+
+   if(sequence->state == SATI_SEQUENCE_STATE_INITIAL)
+   {
+      status = sati_write_16_translate_command(sequence, scsi_io, ata_io);
+      sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
+      sequence->is_translate_response_required = TRUE;
+   }
+   else if(sequence->state == SATI_SEQUENCE_STATE_INCOMPLETE)
+   {
+      status = sati_verify_16_translate_command(sequence, scsi_io, ata_io);
+      sequence->state = SATI_SEQUENCE_STATE_AWAIT_RESPONSE;
+   }
+   else
+   {
+      //SATI sequence is in the wrong state
+      return SATI_FAILURE;
+   }
+
+   sequence->type = SATI_SEQUENCE_WRITE_AND_VERIFY;
+   return status;
+}
+
+/**
+* @brief This function is the response to a sati_write_and_verify
+         translation. Since no response translation is required
+         this function will only check the sequence state and return
+         status.
+*
+* @return Indicate if the command response translation succeeded.
+* @retval SCI_COMPLETE This is returned if the command translation
+          is successful and requires no more work.
+* @retval SATI_SEQUENCE_INCOMPLETE This is returned if the command
+          translation has finished sending the ATA Write command but
+          still needs to complete the Verify portion.
+* @retval SATI_FAILURE is returned if there the sequence is out of
+*         state for a sati_write_and_verify translation.
+*
+*/
+SATI_STATUS sati_write_and_verify_translate_response(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   if(sequence->state == SATI_SEQUENCE_STATE_INCOMPLETE)
+   {
+      return SATI_SEQUENCE_INCOMPLETE;
+   }
+   else if(sequence->state == SATI_SEQUENCE_STATE_AWAIT_RESPONSE)
+   {
+      sequence->state = SATI_SEQUENCE_STATE_FINAL;
+      return SATI_COMPLETE;
+   }
+
+   return SATI_FAILURE;
+}
+
+#endif //!defined(DISABLE_SATI_WRITE_AND_VERIFY)
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_write_and_verify.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_write_and_verify.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,90 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+*
+* GPL LICENSE SUMMARY
+*
+* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of version 2 of the GNU General Public License as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+* The full GNU General Public License is included in this distribution
+* in the file called LICENSE.GPL.
+*
+* BSD LICENSE
+*
+* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+*   * Redistributions of source code must retain the above copyright
+*     notice, this list of conditions and the following disclaimer.
+*   * Redistributions in binary form must reproduce the above copyright
+*     notice, this list of conditions and the following disclaimer in
+*     the documentation and/or other materials provided with the
+*     distribution.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+/**
+* @file
+* @brief This file contains the method definitions to translate
+*        SCSI Write and Verify command based of the SAT spec.
+*/
+
+#ifndef _SATI_WRITE_AND_VERIFY_H_
+#define _SATI_WRITE_AND_VERIFY_H_
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+SATI_STATUS sati_write_and_verify_10_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+SATI_STATUS sati_write_and_verify_12_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+SATI_STATUS sati_write_and_verify_16_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+SATI_STATUS sati_write_and_verify_translate_response(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+#endif //#ifndef _SATI_WRITE_AND_VERIFY_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_write_buffer.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_write_buffer.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,254 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+*
+* GPL LICENSE SUMMARY
+*
+* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of version 2 of the GNU General Public License as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+* The full GNU General Public License is included in this distribution
+* in the file called LICENSE.GPL.
+*
+* BSD LICENSE
+*
+* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+*   * Redistributions of source code must retain the above copyright
+*     notice, this list of conditions and the following disclaimer.
+*   * Redistributions in binary form must reproduce the above copyright
+*     notice, this list of conditions and the following disclaimer in
+*     the documentation and/or other materials provided with the
+*     distribution.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+* @file
+* @brief This file contains the method implementations to translate
+*        SCSI Write Buffer command based of the SAT2v07 spec.
+*/
+
+#include <dev/isci/scil/sati_write_buffer.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_util.h>
+
+#define WRITE_BUFFER_WRITE_DATA              0x02
+#define WRITE_BUFFER_DOWNLOAD_SAVE           0x05
+#define WRITE_BUFFER_OFFSET_DOWNLOAD_SAVE    0x07
+#define BLOCK_SIZE                           512
+
+/**
+* @brief This method will translate the SCSI Write Buffer command
+*        into a corresponding ATA Write Buffer and Download Microcode commands.
+*        For more information on the parameters passed to this method,
+*        please reference sati_translate_command().
+*
+* @return Indicates if the command translation succeeded.
+* @retval SATI_SUCCESS indicates that the translation was supported and occurred
+*         without error.
+* @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
+*         there is a translation failure.
+*/
+SATI_STATUS sati_write_buffer_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+   SATI_STATUS status = SATI_FAILURE;
+   U32 allocation_length;
+   U32 buffer_offset;
+
+   allocation_length = ((sati_get_cdb_byte(cdb, 6) << 16) |
+                        (sati_get_cdb_byte(cdb, 7) << 8)  |
+                        (sati_get_cdb_byte(cdb, 8)));
+
+   buffer_offset = ((sati_get_cdb_byte(cdb, 3) << 16) |
+                    (sati_get_cdb_byte(cdb, 4) << 8)  |
+                    (sati_get_cdb_byte(cdb, 5)));
+
+   sequence->allocation_length = allocation_length;
+
+   switch(sati_get_cdb_byte(cdb, 1))
+   {
+      case WRITE_BUFFER_WRITE_DATA:
+         if((allocation_length == BLOCK_SIZE) && (buffer_offset == 0) &&
+            (sati_get_cdb_byte(cdb, 2) == 0))
+         {
+            sati_ata_write_buffer_construct(ata_io, sequence);
+            sequence->type = SATI_SEQUENCE_WRITE_BUFFER;
+            sequence->state = SATI_SEQUENCE_STATE_AWAIT_RESPONSE;
+            status = SATI_SUCCESS;
+         }
+         else
+         {
+            sati_scsi_sense_data_construct(
+               sequence,
+               scsi_io,
+               SCSI_STATUS_CHECK_CONDITION,
+               SCSI_SENSE_ILLEGAL_REQUEST,
+               SCSI_ASC_INVALID_FIELD_IN_CDB,
+               SCSI_ASCQ_INVALID_FIELD_IN_CDB
+            );
+
+            sequence->state = SATI_SEQUENCE_STATE_FINAL;
+            status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+         }
+      break;
+
+      case WRITE_BUFFER_DOWNLOAD_SAVE:
+
+         sati_ata_download_microcode_construct(
+            ata_io,
+            sequence,
+            ATA_MICROCODE_DOWNLOAD_SAVE,
+            allocation_length,
+            buffer_offset
+         );
+
+         sequence->type = SATI_SEQUENCE_WRITE_BUFFER_MICROCODE;
+         sequence->state = SATI_SEQUENCE_STATE_AWAIT_RESPONSE;
+         status = SATI_SUCCESS;
+      break;
+
+      case WRITE_BUFFER_OFFSET_DOWNLOAD_SAVE:
+         if(((allocation_length & 0x000001FF) == 0) && //Bits 08:00 need to be zero per SAT2v7
+            ((buffer_offset & 0x000001FF) == 0)     &&
+            (allocation_length <= sequence->device->max_blocks_per_microcode_command) &&
+            (allocation_length >= sequence->device->min_blocks_per_microcode_command))
+         {
+            sati_ata_download_microcode_construct(
+               ata_io,
+               sequence,
+               ATA_MICROCODE_OFFSET_DOWNLOAD,
+               allocation_length,
+               buffer_offset
+            );
+
+            sequence->type = SATI_SEQUENCE_WRITE_BUFFER_MICROCODE;
+            sequence->state = SATI_SEQUENCE_STATE_AWAIT_RESPONSE;
+            status = SATI_SUCCESS;
+         }
+         else
+         {
+            sati_scsi_sense_data_construct(
+               sequence,
+               scsi_io,
+               SCSI_STATUS_CHECK_CONDITION,
+               SCSI_SENSE_ILLEGAL_REQUEST,
+               SCSI_ASC_INVALID_FIELD_IN_CDB,
+               SCSI_ASCQ_INVALID_FIELD_IN_CDB
+            );
+
+            sequence->state = SATI_SEQUENCE_STATE_FINAL;
+            status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+         }
+      break;
+
+      default: //unsupported Write Buffer Mode
+         sati_scsi_sense_data_construct(
+            sequence,
+            scsi_io,
+            SCSI_STATUS_CHECK_CONDITION,
+            SCSI_SENSE_ILLEGAL_REQUEST,
+            SCSI_ASC_INVALID_FIELD_IN_CDB,
+            SCSI_ASCQ_INVALID_FIELD_IN_CDB
+         );
+
+         sequence->state = SATI_SEQUENCE_STATE_FINAL;
+         status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+      break;
+   }
+   return status;
+}
+
+/**
+* @brief This method will complete the Write Buffer Translation by checking
+*        for ATA errors and then creating a unit attention condition for
+*        changed microcode.
+*
+* @return Indicates if the command translation succeeded.
+* @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
+*         there is a translation failure.
+* @retval SATI_COMPLETE indicates that the translation was supported, occurred without
+*         error, and no additional translation is necessary.
+*/
+SATI_STATUS sati_write_buffer_translate_response(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
+   U8 ata_status = (U8) sati_get_ata_status(register_fis);
+   SATI_STATUS status = SATI_FAILURE;
+
+   if (ata_status & ATA_STATUS_REG_ERROR_BIT)
+   {
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_ABORTED_COMMAND,
+         SCSI_ASC_NO_ADDITIONAL_SENSE,
+         SCSI_ASCQ_NO_ADDITIONAL_SENSE
+      );
+      status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+   else
+   {
+      switch(sequence->type)
+      {
+         case SATI_SEQUENCE_WRITE_BUFFER_MICROCODE:
+            sati_scsi_sense_data_construct(
+               sequence,
+               scsi_io,
+               SCSI_STATUS_GOOD,
+               SCSI_SENSE_UNIT_ATTENTION,
+               SCSI_ASC_MICROCODE_HAS_CHANGED,
+               SCSI_ASCQ_MICROCODE_HAS_CHANGED
+            );
+            status = SATI_COMPLETE;
+         break;
+
+         default:
+            status = SATI_COMPLETE;
+         break;
+      }
+   }
+
+   sequence->state = SATI_SEQUENCE_STATE_FINAL;
+   return status;
+}
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_write_buffer.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_write_buffer.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,78 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+*
+* GPL LICENSE SUMMARY
+*
+* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of version 2 of the GNU General Public License as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+* The full GNU General Public License is included in this distribution
+* in the file called LICENSE.GPL.
+*
+* BSD LICENSE
+*
+* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+*   * Redistributions of source code must retain the above copyright
+*     notice, this list of conditions and the following disclaimer.
+*   * Redistributions in binary form must reproduce the above copyright
+*     notice, this list of conditions and the following disclaimer in
+*     the documentation and/or other materials provided with the
+*     distribution.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+/**
+* @file
+* @brief This file contains the method definitions to translate
+*        SCSI Write Buffer command based of the SAT2v07 spec.
+*/
+
+#ifndef _SATI_WRITE_BUFFER_H_
+#define _SATI_WRITE_BUFFER_H_
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+SATI_STATUS sati_write_buffer_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+SATI_STATUS sati_write_buffer_translate_response(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+#endif // _SATI_WRITE_BUFFER_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_write_long.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_write_long.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,259 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains the implementation to translate
+ *        SCSI Write Long 10 and 16 commands based on the SAT spec.
+ */
+
+#if !defined(DISABLE_SATI_WRITE_LONG)
+
+#include <dev/isci/scil/sati_write_long.h>
+#include <dev/isci/scil/sati_device.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/intel_scsi.h>
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_sat.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_move.h>
+
+#define LOGICAL_PER_PHYSICAL_SECTOR 0xF
+
+#define WR_UNCOR_BIT          0x02
+#define WR_UNCOR_PBLOCK_BIT   0x03
+#define COR_DIS_WR_UNCORR_BIT 0x06
+
+
+/**
+ * @brief This method will translate the write long 10 & 16 SCSI commands into
+ *        ATA write uncorrectable commands. For more information on the
+ *        parameters passed to this method, please reference
+ *        sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the command translation was
+ *         successful.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA is returned if there was
+ *         a problem with the translation of write long.
+ *
+ */
+SATI_STATUS sati_write_long_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+   SATI_STATUS status = SATI_FAILURE;
+   U16 byte_transfer_length;
+   U8 device_head  = 0;
+
+   if((sequence->device->capabilities &
+       SATI_DEVICE_CAP_WRITE_UNCORRECTABLE_ENABLE) == 0)
+   {
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_ILLEGAL_REQUEST,
+         SCSI_ASC_INVALID_COMMAND_OPERATION_CODE,
+         SCSI_ASCQ_INVALID_COMMAND_OPERATION_CODE
+      );
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+
+   //Write Long 10
+   if(sati_get_cdb_byte(cdb, 0) == SCSI_WRITE_LONG_10)
+   {
+      byte_transfer_length = (sati_get_cdb_byte(cdb, 7) << 8) |
+                             (sati_get_cdb_byte(cdb, 8));
+
+      sati_move_translate_32_bit_lba(sequence, scsi_io, ata_io);
+   }
+   else //Write Long 16
+   {
+      byte_transfer_length = (sati_get_cdb_byte(cdb, 12) << 8) |
+                             (sati_get_cdb_byte(cdb, 13));
+
+      status = sati_move_translate_64_bit_lba(sequence, scsi_io, ata_io);
+
+      if( status == SATI_FAILURE_CHECK_RESPONSE_DATA)
+      {
+         return status;
+      }
+   }
+
+
+   sati_move_translate_command(sequence, scsi_io, ata_io, device_head);
+
+   if( byte_transfer_length != 0 )
+   {
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_ILLEGAL_REQUEST,
+         SCSI_ASC_INVALID_FIELD_IN_CDB,
+         SCSI_ASCQ_INVALID_FIELD_IN_CDB
+      );
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+
+   switch(SATI_WRITE_LONG_GET_COR_WR_PB_BITS(cdb))
+   {
+      case WR_UNCOR_BIT :
+
+         if( (sequence->device->capabilities &
+              SATI_DEVICE_CAP_MULTIPLE_SECTORS_PER_PHYSCIAL_SECTOR) != 0 )
+         {
+            sati_scsi_sense_data_construct(
+               sequence,
+               scsi_io,
+               SCSI_STATUS_CHECK_CONDITION,
+               SCSI_SENSE_ILLEGAL_REQUEST,
+               SCSI_ASC_INVALID_FIELD_IN_CDB,
+               SCSI_ASCQ_INVALID_FIELD_IN_CDB
+            );
+            return SATI_FAILURE_CHECK_RESPONSE_DATA;
+         }
+         else
+         {
+            sati_ata_write_uncorrectable_construct(
+               ata_io,
+               sequence,
+               ATA_WRITE_UNCORRECTABLE_PSUEDO
+            );
+            sequence->type = SATI_SEQUENCE_WRITE_LONG;
+            status = SATI_SUCCESS;
+         }
+         break;
+
+      case WR_UNCOR_PBLOCK_BIT :
+
+         sati_ata_write_uncorrectable_construct(
+            ata_io,
+            sequence,
+            ATA_WRITE_UNCORRECTABLE_PSUEDO
+         );
+         sequence->type = SATI_SEQUENCE_WRITE_LONG;
+         status = SATI_SUCCESS;
+         break;
+
+      case COR_DIS_WR_UNCORR_BIT :
+
+         sati_ata_write_uncorrectable_construct(
+            ata_io,
+            sequence,
+            ATA_WRITE_UNCORRECTABLE_FLAGGED
+         );
+         sequence->type = SATI_SEQUENCE_WRITE_LONG;
+         status = SATI_SUCCESS;
+         break;
+
+      default :
+
+         sati_scsi_sense_data_construct(
+            sequence,
+            scsi_io,
+            SCSI_STATUS_CHECK_CONDITION,
+            SCSI_SENSE_ILLEGAL_REQUEST,
+            SCSI_ASC_INVALID_FIELD_IN_CDB,
+            SCSI_ASCQ_INVALID_FIELD_IN_CDB
+         );
+         return SATI_FAILURE_CHECK_RESPONSE_DATA;
+         break;
+   }
+   return status;
+}
+
+/**
+ * @brief This method will translate the response to the SATI Write Long
+ *        translation. This response is only error checking the
+ *        ATA Write Uncorrectable command.
+ *
+ * @return SATI_STATUS Indicates if the response translation succeeded.
+ * @retval SCI_COMPLETE This is returned if the command translation was
+ *         successful.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA is returned if there was
+ *         a problem with the translation of write long.
+ */
+SATI_STATUS sati_write_long_translate_response(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+)
+{
+   U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
+
+   if (sati_get_ata_status(register_fis) & ATA_STATUS_REG_ERROR_BIT)
+   {
+      sati_scsi_sense_data_construct(
+         sequence,
+         scsi_io,
+         SCSI_STATUS_CHECK_CONDITION,
+         SCSI_SENSE_ABORTED_COMMAND,
+         SCSI_ASC_COMMAND_SEQUENCE_ERROR,
+         SCSI_ASCQ_NO_ADDITIONAL_SENSE
+      );
+      return SATI_FAILURE_CHECK_RESPONSE_DATA;
+   }
+   else
+   {
+      return SATI_COMPLETE;
+   }
+}
+
+#endif // !defined(DISABLE_SATI_WRITE_LONG)
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_write_long.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_write_long.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,83 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+/**
+ * @file
+ * @brief This file contains the method definitions to translate
+ *        SCSI Write Long command based of the SAT spec.
+ */
+
+#ifndef _SATI_WRITE_LONG_H_
+#define _SATI_WRITE_LONG_H_
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+#define SATI_WRITE_LONG_GET_COR_WR_PB_BITS(cdb) \
+   (( sati_get_cdb_byte(cdb, 1) &  0xE0) \
+    >> 5)
+
+
+SATI_STATUS sati_write_long_translate_command(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+SATI_STATUS sati_write_long_translate_response(
+   SATI_TRANSLATOR_SEQUENCE_T * sequence,
+   void                       * scsi_io,
+   void                       * ata_io
+);
+
+#endif // _SATI_WRITE_LONG_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sci_abstract_list.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sci_abstract_list.c	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,599 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ *
+ * @brief This file contains the implementation of an abstract list class.
+ *        This class will allow for the same item to occur multiple times in
+ *        the list.  It will provide an interface that is similar to the
+ *        C++ standard template list interface.
+ */
+
+//******************************************************************************
+//*
+//*     I N C L U D E S
+//*
+//******************************************************************************
+
+#include <dev/isci/scil/sci_abstract_list.h>
+
+
+//******************************************************************************
+//*
+//*     P R I V A T E   M E M B E R S
+//*
+//******************************************************************************
+
+//******************************************************************************
+//*
+//*     P R O T E C T E D   M E T H O D S
+//*
+//******************************************************************************
+
+/**
+ * @brief Initialize the abstract list
+ *
+ * @pre The supplied free pool should be constructed prior to utilization
+ *      of this abstract list.  It isn't mandatory for the free pool to be
+ *      constructed before invoking this method, but suggested.
+ *
+ * @param[in] list This parameter specifies the abstract list to be
+ *            constructed.
+ * @param[in] free_pool This parameter specifies the free pool to be
+ *            utilized as the repository of free elements for list usage.
+ *
+ * @return none
+ */
+void sci_abstract_list_construct(
+   SCI_ABSTRACT_LIST_T         * list,
+   SCI_ABSTRACT_ELEMENT_POOL_T * free_pool
+)
+{
+   memset(list, 0, sizeof(SCI_ABSTRACT_LIST_T));
+   list->free_pool = free_pool;
+}
+
+/**
+ * Initialize the abstract list with its free pool
+ *
+ * @param[in] pool
+ *    the free pool from which the elements will be extracted
+ * @param[in] list_elements
+ *    the array of list elements to be added to the free list
+ * @param[in] element_count
+ *    the count of the elements to be added to the free list these should be
+ *    the same as the array size of list elements
+ *
+ * @return none
+ */
+void sci_abstract_element_pool_construct(
+   SCI_ABSTRACT_ELEMENT_POOL_T * pool,
+   SCI_ABSTRACT_ELEMENT_T      * list_elements,
+   int                           element_count
+)
+{
+   int index;
+
+   memset(pool, 0, sizeof(SCI_ABSTRACT_ELEMENT_POOL_T));
+   memset(list_elements, 0, sizeof(SCI_ABSTRACT_ELEMENT_T) * element_count);
+
+   pool->elements     = list_elements;
+   pool->max_elements = element_count;
+
+   // Loop through all of the elements in the array and push them onto the
+   // pool's free list.
+   for (index = element_count - 1; index >= 0; index--)
+   {
+      private_pool_free(pool, &(list_elements[index]));
+   }
+}
+
+
+#ifdef USE_ABSTRACT_LIST_FUNCTIONS
+
+//******************************************************************************
+//*
+//*     P U B L I C   M E T H O D S
+//*
+//******************************************************************************
+
+/**
+ * Simply return the front element pointer of the list.  This returns an element
+ * element as opposed to what the element is pointing to.
+ */
+SCI_ABSTRACT_ELEMENT_T * sci_abstract_list_get_front(
+   SCI_ABSTRACT_LIST_T * list_p
+)
+{
+   return (list_p)->elements.front_p;
+}
+
+/**
+ * This method simply returns the object pointed to by the head (front) of
+ * the list.
+ */
+void * sci_abstract_list_front(
+   SCI_ABSTRACT_LIST_T * list_p
+)
+{
+   return
+      ( ( (list_p)->elements.front_p ) ? ((list_p)->elements.front_p->object_p) : NULL );
+}
+
+/**
+ * This method simply returns the object pointed to by the tail (back) of
+ * the list.
+ */
+void * sci_abstract_list_back(
+   SCI_ABSTRACT_LIST_T * list_p
+)
+{
+   return
+      ( ( (list_p)->elements.back_p ) ? ((list_p)->elements.back_p->object_p) : NULL );
+}
+
+/**
+ * This method will return FALSE if the list is not empty.
+ */
+BOOL sci_abstract_list_is_empty(
+   SCI_ABSTRACT_LIST_T * list_p
+)
+{
+   return ( (list_p)->elements.front_p == NULL );
+}
+
+
+/**
+ * This method will return the number of elements queued in the list.
+ */
+U32 sci_abstract_list_size(
+   SCI_ABSTRACT_LIST_T * list_p
+)
+{
+   return ( (list_p)->elements.size );
+}
+
+
+/**
+ * This method simply returns the next list element in the list.
+ */
+SCI_ABSTRACT_ELEMENT_T * sci_abstract_list_get_next(
+   SCI_ABSTRACT_ELEMENT_T * alElement_p
+)
+{
+   return ( (alElement_p)->next_p );
+}
+
+
+#if defined(SCI_LOGGING)
+/**
+ * This method simply prints the contents of the list.
+ */
+void  sci_abstract_list_print(
+   SCI_ABSTRACT_LIST_T * list_p
+)
+{
+   SCI_ABSTRACT_ELEMENT_T * alElement_p = list_p->elements.front_p;
+
+   while (alElement_p != NULL)
+   {
+#ifdef UNIT_TEST_DEBUG
+      /* Check to see if we found the object for which we are searching. */
+      printf("ITEM next_p 0x%x prev_p 0x%x obj_p 0x%x, 0x%x\n",
+             alElement_p->next_p,
+             alElement_p->previous_p,
+             (U32*) (alElement_p->object_p));
+#endif
+      alElement_p = alElement_p->next_p;
+   }
+}
+#endif // defined(SCI_LOGGING)
+
+
+/**
+ * This method will simply search the supplied list for the desired object.
+ * It will return a pointer to the object, if it is found.  Otherwise
+ * it will return NULL.
+ */
+void * sci_abstract_list_find(
+   SCI_ABSTRACT_LIST_T * list_p,
+   void * obj_p
+)
+{
+   return
+      sci_abstract_list_get_object(private_find(&(list_p)->elements, (obj_p)));
+}
+
+
+/**
+ * This method will simply remove the element at the back (tail) of the list.
+ * It will return a pointer to the object that was removed or NULL if not
+ * found.
+ */
+void * sci_abstract_list_popback(
+   SCI_ABSTRACT_LIST_T * list_p
+)
+{
+   SCI_ABSTRACT_ELEMENT_LIST_T * elem_list = &(list_p)->elements;
+   SCI_ABSTRACT_ELEMENT_T      * alElement_p = elem_list->back_p;
+   void * obj_p = NULL;
+
+   if (alElement_p != NULL)
+   {
+      obj_p = alElement_p->object_p;
+      if (elem_list->back_p == elem_list->front_p)
+      {
+         elem_list->back_p = elem_list->front_p = NULL;
+      }
+      else
+      {
+         elem_list->back_p = elem_list->back_p->previous_p;
+         elem_list->back_p->next_p = NULL;
+      }
+
+      elem_list->size--;
+      private_pool_free((list_p)->free_pool, alElement_p);
+   }
+
+   return obj_p;
+}
+
+/**
+ * This method simply removes the list element at the head of the list
+ * and returns the pointer to the object that was removed.
+ */
+void * sci_abstract_list_popfront(
+   SCI_ABSTRACT_LIST_T * list_p
+)
+{
+   SCI_ABSTRACT_ELEMENT_T * alElement_p =
+                              private_pop_front(&(list_p)->elements);
+   void * obj_p = NULL;
+
+   if (alElement_p != NULL)
+   {
+      obj_p = alElement_p->object_p;
+      private_pool_free((list_p)->free_pool, alElement_p);
+   }
+
+   return obj_p;
+}
+
+
+
+/**
+ * This method will erase (remove) all instances of the supplied object from
+ * anywhere in the list.
+ */
+void sci_abstract_list_erase(
+   SCI_ABSTRACT_LIST_T * list_p,
+   void * obj_p
+)
+{
+   SCI_ABSTRACT_ELEMENT_LIST_T * elem_list = &(list_p)->elements;
+   SCI_ABSTRACT_ELEMENT_T      * alElement_p;
+
+   while ((alElement_p = private_find(elem_list, (obj_p))) != NULL)
+   {
+      if (alElement_p == elem_list->front_p)
+      {
+         sci_abstract_list_popfront(list_p);
+      }
+      else if (alElement_p == elem_list->back_p)
+      {
+         sci_abstract_list_popback(list_p);
+      }
+      else
+      {
+         alElement_p->previous_p->next_p = alElement_p->next_p;
+         alElement_p->next_p->previous_p = alElement_p->previous_p;
+         elem_list->size--;
+         private_pool_free((list_p)->free_pool, alElement_p);
+      }
+   }
+   return;
+}
+
+/**
+ * This method simply adds a LIST_ELEMENT for the supplied object to the back
+ * (tail) of the supplied list.
+ */
+void sci_abstract_list_pushback(
+   SCI_ABSTRACT_LIST_T * list_p,
+   void * obj_p
+)
+{
+   SCI_ABSTRACT_ELEMENT_LIST_T * elem_list = &(list_p)->elements;
+   SCI_ABSTRACT_ELEMENT_T      * alElement_p
+      = private_pool_allocate((list_p)->free_pool);
+//   assert(alElement_p != NULL);
+
+   alElement_p->object_p = (obj_p);
+
+   if (elem_list->front_p == NULL)
+   {
+      elem_list->front_p = elem_list->back_p = alElement_p;
+   }
+   else
+   {
+      elem_list->back_p->next_p = alElement_p;
+      alElement_p->previous_p   = elem_list->back_p;
+      elem_list->back_p         = alElement_p;
+   }
+
+   elem_list->size++;
+}
+
+
+
+/**
+ * This method simply adds a LIST_ELEMENT for the supplied object to the front
+ * (head) of the supplied list.
+ */
+void sci_abstract_list_pushfront(
+   SCI_ABSTRACT_LIST_T * list_p,
+   void * obj_p
+)
+{
+   SCI_ABSTRACT_ELEMENT_T * alElement_p =
+         private_pool_allocate((list_p)->free_pool);
+   alElement_p->object_p = (obj_p);
+   private_push_front(&(list_p)->elements, alElement_p);
+}
+
+
+/**
+ * This method will add the objToAdd_p object to the list before the obj_p.
+ *
+ */
+void sci_abstract_list_insert(
+   SCI_ABSTRACT_LIST_T * list_p,
+   void * obj_p,
+   void * objToAdd_p
+)
+{
+   SCI_ABSTRACT_ELEMENT_LIST_T * elem_list = &(list_p)->elements;
+
+   SCI_ABSTRACT_ELEMENT_T * obj_element = private_find(elem_list, obj_p);
+
+   SCI_ABSTRACT_ELEMENT_T * objToAdd_element =
+      private_pool_allocate((list_p)->free_pool);
+
+   objToAdd_element->object_p = objToAdd_p;
+
+   ASSERT(obj_element != NULL);
+   ASSERT(objToAdd_element != NULL);
+
+   if (obj_element == elem_list->front_p)
+   {
+      objToAdd_element->object_p = (objToAdd_p);
+      private_push_front(&(list_p)->elements, objToAdd_element);
+   }
+   else
+   {
+      obj_element->previous_p->next_p = objToAdd_element;
+      objToAdd_element->previous_p = obj_element->previous_p;
+
+      obj_element->previous_p = objToAdd_element;
+      objToAdd_element->next_p = obj_element;
+
+      elem_list->size++;
+   }
+}
+
+/**
+ * This method simply frees all the items from the list.
+ */
+void sci_abstract_list_clear(
+   SCI_ABSTRACT_LIST_T * list_p
+)
+{
+   while ((list_p)->elements.size > 0)
+      sci_abstract_list_popfront((list_p));
+}
+
+/**
+ * This method simply returns the object being pointed to by the list element
+ * (The item being listed).
+ */
+void * sci_abstract_list_get_object(
+   SCI_ABSTRACT_ELEMENT_T * alElement_p
+)
+{
+   void * obj_p = NULL;
+   if ((alElement_p) != NULL)
+      obj_p = (alElement_p)->object_p;
+
+   return obj_p;
+}
+
+
+/**
+ * This method is simply a wrapper to provide the number of elements in
+ * the free list.
+ */
+U32 sci_abstract_list_freeList_size(
+   SCI_ABSTRACT_LIST_T * freeList
+)
+{
+   return (sci_abstract_list_size(freeList));
+}
+
+//******************************************************************************
+//*
+//*     P R I V A T E   M E T H O D S
+//*
+//******************************************************************************
+
+/**
+ * This method simply performs the common portion of pushing a list element
+ * onto a list.
+ *
+ * WARNING: This is a private helper method that should not be called directly
+ *          by any users.
+ */
+void private_push_front(
+   SCI_ABSTRACT_ELEMENT_LIST_T * privateList_p,
+   SCI_ABSTRACT_ELEMENT_T * alElement_p
+)
+{
+   if ((privateList_p)->front_p == NULL)
+   {
+      (privateList_p)->front_p = (privateList_p)->back_p = (alElement_p);
+      (alElement_p)->next_p = (alElement_p)->previous_p = NULL;
+   }
+   else
+   {
+      (alElement_p)->next_p                = (privateList_p)->front_p;
+      (alElement_p)->previous_p            = NULL;
+      (privateList_p)->front_p->previous_p = (alElement_p);
+      (privateList_p)->front_p             = (alElement_p);
+   }
+
+   (privateList_p)->size++;
+}
+
+/**
+ * This method simply performs the common portion of popping a list element
+ * from a list.
+ *
+ * WARNING: This is a private helper method that should not be called directly
+ *          by any users.
+ */
+SCI_ABSTRACT_ELEMENT_T * private_pop_front(
+   SCI_ABSTRACT_ELEMENT_LIST_T * privateList_p
+)
+{
+   SCI_ABSTRACT_ELEMENT_T * alElement_p = (privateList_p)->front_p;
+
+   if (alElement_p != NULL)
+   {
+      if ((privateList_p)->front_p == (privateList_p)->back_p)
+      {
+         (privateList_p)->front_p = (privateList_p)->back_p = NULL;
+      }
+      else
+      {
+         (privateList_p)->front_p = (privateList_p)->front_p->next_p;
+         (privateList_p)->front_p->previous_p = NULL;
+      }
+
+      (privateList_p)->size--;
+   }
+
+   return alElement_p;
+}
+
+/**
+ * This method will simply search the supplied list for the desired object.
+ * It will return a pointer to the abstract_list_element if found, otherwise
+ * it will return NULL.
+ */
+SCI_ABSTRACT_ELEMENT_T * private_find(
+   SCI_ABSTRACT_ELEMENT_LIST_T * list_p,
+   void * obj_p
+)
+{
+   SCI_ABSTRACT_ELEMENT_T * alElement_p = (list_p)->front_p;
+
+   while (alElement_p != NULL)
+   {
+      /* Check to see if we found the object for which we are searching. */
+      if (alElement_p->object_p == (void*) (obj_p))
+      {
+         break;
+      }
+
+      alElement_p = alElement_p->next_p;
+   }
+
+   return alElement_p;
+}
+
+/**
+ * This private method will free the supplied list element back to the pool
+ * of free list elements.
+ */
+void private_pool_free(
+   SCI_ABSTRACT_ELEMENT_POOL_T * free_pool,
+   SCI_ABSTRACT_ELEMENT_T * alElement_p
+)
+{
+   /* Push the list element back to the head to get better locality of */
+   /* reference with the cache.                                        */
+   private_push_front(&(free_pool)->free_list, (alElement_p));
+}
+
+/**
+ * This private method will allocate a list element from the pool of free
+ * list elements.
+ */
+SCI_ABSTRACT_ELEMENT_T * private_pool_allocate(
+   SCI_ABSTRACT_ELEMENT_POOL_T * free_pool
+)
+{
+   SCI_ABSTRACT_ELEMENT_T * alElement_p;
+
+   alElement_p = private_pop_front(&(free_pool)->free_list);
+
+   alElement_p->next_p     = NULL;
+   alElement_p->previous_p = NULL;
+   alElement_p->object_p   = NULL;
+
+   return alElement_p;
+}
+
+#endif // USE_ABSTRACT_LIST_FUNCTIONS
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sci_abstract_list.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sci_abstract_list.h	Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,871 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+/**
+ * @file
+ *
+ * @brief This file contains the interface to the abstract list class.
+ *        This class will allow for the same item to occur multiple times in
+ *        a list or multiple lists.  It will provide an interface that is
+ *        similar to the C++ standard template list interface.
+ *        Methods Provided:
+ *        - sci_abstract_list_front()
+ *        - sci_abstract_list_back()
+ *        - sci_abstract_list_is_empty()
+ *        - sci_abstract_list_size()
+ *        - sci_abstract_list_print()
+ *        - sci_abstract_list_find()
+ *        - sci_abstract_list_popback()
+ *        - sci_abstract_list_popfront()
+ *        - sci_abstract_list_erase()
+ *        - sci_abstract_list_pushback()
+ *        - sci_abstract_list_pushfront()
+ *        - sci_abstract_list_get_object()
+ *        - sci_abstract_list_get_next()
+ *        - sci_abstract_list_insert() UNIMPLEMENTED
+ *        - sci_abstract_list_clear()
+ */
+
+#ifndef _SCI_ABSTRACT_LIST_H_
+#define _SCI_ABSTRACT_LIST_H_
+
+//******************************************************************************
+//*
+//*     I N C L U D E S
+//*
+//******************************************************************************
+
+#include <dev/isci/scil/sci_types.h>
+
+//******************************************************************************
+//*
+//*     C O N S T A N T S
+//*
+//*******