From 1c01930d89a1a3542c5a5e6c5ff5d624432c60e1 Mon Sep 17 00:00:00 2001
From: Sascha Wildner <saw@online.de>
Date: Wed, 28 Sep 2016 19:01:29 +0200
Subject: [PATCH] WIP isci(4) port (as of May 13, 2012).

---
 share/man/man4/Makefile                            |    1 +
 share/man/man4/isci.4                              |  112 +
 sys/conf/files                                     |  109 +
 sys/conf/options                                   |    3 +
 sys/config/LINT64                                  |    5 +
 sys/config/X86_64_GENERIC                          |    1 +
 sys/dev/disk/Makefile                              |    2 +-
 sys/dev/disk/isci/Makefile                         |   88 +
 sys/dev/disk/isci/README                           |   14 +
 sys/dev/disk/isci/environment.h                    |   99 +
 sys/dev/disk/isci/isci.c                           |  657 ++
 sys/dev/disk/isci/isci.h                           |  304 +
 sys/dev/disk/isci/isci_controller.c                |  704 ++
 sys/dev/disk/isci/isci_domain.c                    |  339 +
 sys/dev/disk/isci/isci_interrupt.c                 |  242 +
 sys/dev/disk/isci/isci_io_request.c                |  934 +++
 sys/dev/disk/isci/isci_logger.c                    |  350 +
 sys/dev/disk/isci/isci_oem_parameters.c            |  175 +
 sys/dev/disk/isci/isci_remote_device.c             |  320 +
 sys/dev/disk/isci/isci_sysctl.c                    |  233 +
 sys/dev/disk/isci/isci_task_request.c              |  256 +
 sys/dev/disk/isci/isci_timer.c                     |  169 +
 sys/dev/disk/isci/sci_environment.h                |    1 +
 sys/dev/disk/isci/scil/intel_ata.h                 |  653 ++
 sys/dev/disk/isci/scil/intel_pci.h                 |   90 +
 sys/dev/disk/isci/scil/intel_sas.h                 |  976 +++
 sys/dev/disk/isci/scil/intel_sat.h                 |   93 +
 sys/dev/disk/isci/scil/intel_sata.h                |  284 +
 sys/dev/disk/isci/scil/intel_scsi.h                |  539 ++
 sys/dev/disk/isci/scil/sati.c                      | 1249 ++++
 sys/dev/disk/isci/scil/sati.h                      |  270 +
 sys/dev/disk/isci/scil/sati_abort_task_set.c       |  175 +
 sys/dev/disk/isci/scil/sati_abort_task_set.h       |   83 +
 sys/dev/disk/isci/scil/sati_atapi.c                |  256 +
 sys/dev/disk/isci/scil/sati_atapi.h                |  177 +
 sys/dev/disk/isci/scil/sati_callbacks.h            |  480 ++
 sys/dev/disk/isci/scil/sati_design.h               |  168 +
 sys/dev/disk/isci/scil/sati_device.c               |  243 +
 sys/dev/disk/isci/scil/sati_device.h               |  202 +
 sys/dev/disk/isci/scil/sati_inquiry.c              |  797 +++
 sys/dev/disk/isci/scil/sati_inquiry.h              |  114 +
 sys/dev/disk/isci/scil/sati_log_sense.c            |  805 +++
 sys/dev/disk/isci/scil/sati_log_sense.h            |   86 +
 sys/dev/disk/isci/scil/sati_lun_reset.c            |  120 +
 sys/dev/disk/isci/scil/sati_lun_reset.h            |   79 +
 sys/dev/disk/isci/scil/sati_mode_pages.c           |  370 +
 sys/dev/disk/isci/scil/sati_mode_pages.h           |  143 +
 sys/dev/disk/isci/scil/sati_mode_select.c          | 1114 ++++
 sys/dev/disk/isci/scil/sati_mode_select.h          |   84 +
 sys/dev/disk/isci/scil/sati_mode_sense.c           |  835 +++
 sys/dev/disk/isci/scil/sati_mode_sense.h           |  145 +
 sys/dev/disk/isci/scil/sati_mode_sense_10.c        |  507 ++
 sys/dev/disk/isci/scil/sati_mode_sense_10.h        |  114 +
 sys/dev/disk/isci/scil/sati_mode_sense_6.c         |  427 ++
 sys/dev/disk/isci/scil/sati_mode_sense_6.h         |  114 +
 sys/dev/disk/isci/scil/sati_move.c                 |  614 ++
 sys/dev/disk/isci/scil/sati_move.h                 |  121 +
 sys/dev/disk/isci/scil/sati_passthrough.c          |  464 ++
 sys/dev/disk/isci/scil/sati_passthrough.h          |   88 +
 sys/dev/disk/isci/scil/sati_read.c                 |  321 +
 sys/dev/disk/isci/scil/sati_read.h                 |   91 +
 sys/dev/disk/isci/scil/sati_read_buffer.c          |  234 +
 sys/dev/disk/isci/scil/sati_read_buffer.h          |   82 +
 sys/dev/disk/isci/scil/sati_read_capacity.c        |  368 +
 sys/dev/disk/isci/scil/sati_read_capacity.h        |   91 +
 sys/dev/disk/isci/scil/sati_reassign_blocks.c      |  620 ++
 sys/dev/disk/isci/scil/sati_reassign_blocks.h      |   80 +
 sys/dev/disk/isci/scil/sati_report_luns.c          |  122 +
 sys/dev/disk/isci/scil/sati_report_luns.h          |   75 +
 sys/dev/disk/isci/scil/sati_request_sense.c        |  351 +
 sys/dev/disk/isci/scil/sati_request_sense.h        |   86 +
 sys/dev/disk/isci/scil/sati_start_stop_unit.c      |  402 ++
 sys/dev/disk/isci/scil/sati_start_stop_unit.h      |  102 +
 sys/dev/disk/isci/scil/sati_synchronize_cache.c    |  117 +
 sys/dev/disk/isci/scil/sati_synchronize_cache.h    |   71 +
 sys/dev/disk/isci/scil/sati_test_unit_ready.c      |  184 +
 sys/dev/disk/isci/scil/sati_test_unit_ready.h      |   79 +
 sys/dev/disk/isci/scil/sati_translator_sequence.h  |  360 +
 sys/dev/disk/isci/scil/sati_types.h                |  151 +
 sys/dev/disk/isci/scil/sati_unmap.c                |  608 ++
 sys/dev/disk/isci/scil/sati_unmap.h                |  135 +
 sys/dev/disk/isci/scil/sati_util.c                 | 2004 ++++++
 sys/dev/disk/isci/scil/sati_util.h                 |  392 ++
 sys/dev/disk/isci/scil/sati_verify.c               |  271 +
 sys/dev/disk/isci/scil/sati_verify.h               |   83 +
 sys/dev/disk/isci/scil/sati_write.c                |  319 +
 sys/dev/disk/isci/scil/sati_write.h                |   91 +
 sys/dev/disk/isci/scil/sati_write_and_verify.c     |  242 +
 sys/dev/disk/isci/scil/sati_write_and_verify.h     |   90 +
 sys/dev/disk/isci/scil/sati_write_buffer.c         |  253 +
 sys/dev/disk/isci/scil/sati_write_buffer.h         |   78 +
 sys/dev/disk/isci/scil/sati_write_long.c           |  258 +
 sys/dev/disk/isci/scil/sati_write_long.h           |   83 +
 sys/dev/disk/isci/scil/sci_abstract_list.c         |  598 ++
 sys/dev/disk/isci/scil/sci_abstract_list.h         |  871 +++
 sys/dev/disk/isci/scil/sci_base_controller.c       |  103 +
 sys/dev/disk/isci/scil/sci_base_controller.h       |  347 +
 sys/dev/disk/isci/scil/sci_base_domain.c           |   87 +
 sys/dev/disk/isci/scil/sci_base_domain.h           |  309 +
 sys/dev/disk/isci/scil/sci_base_iterator.c         |  180 +
 sys/dev/disk/isci/scil/sci_base_iterator.h         |  134 +
 sys/dev/disk/isci/scil/sci_base_library.c          |  101 +
 sys/dev/disk/isci/scil/sci_base_library.h          |  197 +
 sys/dev/disk/isci/scil/sci_base_logger.c           |  290 +
 sys/dev/disk/isci/scil/sci_base_logger.h           |  131 +
 .../isci/scil/sci_base_memory_descriptor_list.c    |  166 +
 .../isci/scil/sci_base_memory_descriptor_list.h    |  168 +
 .../sci_base_memory_descriptor_list_decorator.c    |  147 +
 sys/dev/disk/isci/scil/sci_base_object.c           |  116 +
 sys/dev/disk/isci/scil/sci_base_object.h           |  141 +
 sys/dev/disk/isci/scil/sci_base_observer.c         |  106 +
 sys/dev/disk/isci/scil/sci_base_observer.h         |  167 +
 sys/dev/disk/isci/scil/sci_base_phy.c              |   87 +
 sys/dev/disk/isci/scil/sci_base_phy.h              |  213 +
 sys/dev/disk/isci/scil/sci_base_port.c             |   86 +
 sys/dev/disk/isci/scil/sci_base_port.h             |  233 +
 sys/dev/disk/isci/scil/sci_base_remote_device.c    |   78 +
 sys/dev/disk/isci/scil/sci_base_remote_device.h    |  298 +
 sys/dev/disk/isci/scil/sci_base_request.c          |   78 +
 sys/dev/disk/isci/scil/sci_base_request.h          |  209 +
 sys/dev/disk/isci/scil/sci_base_state.h            |  110 +
 sys/dev/disk/isci/scil/sci_base_state_machine.c    |  210 +
 sys/dev/disk/isci/scil/sci_base_state_machine.h    |  157 +
 .../disk/isci/scil/sci_base_state_machine_logger.c |  215 +
 .../disk/isci/scil/sci_base_state_machine_logger.h |  137 +
 .../isci/scil/sci_base_state_machine_observer.c    |   98 +
 .../isci/scil/sci_base_state_machine_observer.h    |  138 +
 sys/dev/disk/isci/scil/sci_base_subject.c          |  148 +
 sys/dev/disk/isci/scil/sci_base_subject.h          |  157 +
 sys/dev/disk/isci/scil/sci_controller.h            |  112 +
 sys/dev/disk/isci/scil/sci_controller_constants.h  |  216 +
 sys/dev/disk/isci/scil/sci_fast_list.h             |  339 +
 sys/dev/disk/isci/scil/sci_iterator.h              |  129 +
 sys/dev/disk/isci/scil/sci_library.h               |  110 +
 sys/dev/disk/isci/scil/sci_logger.h                |  249 +
 .../disk/isci/scil/sci_memory_descriptor_list.h    |  180 +
 .../scil/sci_memory_descriptor_list_decorator.h    |  128 +
 sys/dev/disk/isci/scil/sci_object.h                |  138 +
 sys/dev/disk/isci/scil/sci_overview.h              |  250 +
 sys/dev/disk/isci/scil/sci_pool.h                  |  188 +
 sys/dev/disk/isci/scil/sci_simple_list.h           |  350 +
 sys/dev/disk/isci/scil/sci_status.h                |  417 ++
 sys/dev/disk/isci/scil/sci_types.h                 |  279 +
 sys/dev/disk/isci/scil/sci_util.c                  |   70 +
 sys/dev/disk/isci/scil/sci_util.h                  |  164 +
 sys/dev/disk/isci/scil/scic_config_parameters.h    |  345 +
 sys/dev/disk/isci/scil/scic_controller.h           |  855 +++
 sys/dev/disk/isci/scil/scic_io_request.h           |  760 +++
 sys/dev/disk/isci/scil/scic_library.h              |  274 +
 sys/dev/disk/isci/scil/scic_logger.h               |  135 +
 sys/dev/disk/isci/scil/scic_overview.h             |   87 +
 sys/dev/disk/isci/scil/scic_phy.h                  |  461 ++
 sys/dev/disk/isci/scil/scic_port.h                 |  238 +
 sys/dev/disk/isci/scil/scic_remote_device.h        |  441 ++
 sys/dev/disk/isci/scil/scic_sds_controller.c       | 7040 ++++++++++++++++++++
 sys/dev/disk/isci/scil/scic_sds_controller.h       |  840 +++
 .../disk/isci/scil/scic_sds_controller_registers.h |  598 ++
 sys/dev/disk/isci/scil/scic_sds_library.c          |  285 +
 sys/dev/disk/isci/scil/scic_sds_library.h          |  118 +
 sys/dev/disk/isci/scil/scic_sds_logger.h           |   93 +
 sys/dev/disk/isci/scil/scic_sds_pci.c              |  246 +
 sys/dev/disk/isci/scil/scic_sds_pci.h              |  138 +
 sys/dev/disk/isci/scil/scic_sds_phy.c              | 4034 +++++++++++
 sys/dev/disk/isci/scil/scic_sds_phy.h              |  531 ++
 sys/dev/disk/isci/scil/scic_sds_phy_registers.h    |  270 +
 sys/dev/disk/isci/scil/scic_sds_port.c             | 3660 ++++++++++
 sys/dev/disk/isci/scil/scic_sds_port.h             |  595 ++
 .../isci/scil/scic_sds_port_configuration_agent.c  | 1132 ++++
 .../isci/scil/scic_sds_port_configuration_agent.h  |  128 +
 sys/dev/disk/isci/scil/scic_sds_port_registers.h   |  139 +
 sys/dev/disk/isci/scil/scic_sds_remote_device.c    | 2725 ++++++++
 sys/dev/disk/isci/scil/scic_sds_remote_device.h    |  646 ++
 .../disk/isci/scil/scic_sds_remote_node_context.c  | 1498 +++++
 .../disk/isci/scil/scic_sds_remote_node_context.h  |  381 ++
 .../disk/isci/scil/scic_sds_remote_node_table.c    |  658 ++
 .../disk/isci/scil/scic_sds_remote_node_table.h    |  190 +
 sys/dev/disk/isci/scil/scic_sds_request.c          | 2888 ++++++++
 sys/dev/disk/isci/scil/scic_sds_request.h          |  543 ++
 sys/dev/disk/isci/scil/scic_sds_sgpio.c            |  297 +
 .../disk/isci/scil/scic_sds_smp_remote_device.c    |  369 +
 sys/dev/disk/isci/scil/scic_sds_smp_request.c      |  869 +++
 sys/dev/disk/isci/scil/scic_sds_smp_request.h      |   82 +
 sys/dev/disk/isci/scil/scic_sds_ssp_request.c      |  337 +
 .../disk/isci/scil/scic_sds_stp_packet_request.c   |  976 +++
 .../disk/isci/scil/scic_sds_stp_packet_request.h   |  170 +
 sys/dev/disk/isci/scil/scic_sds_stp_pio_request.h  |  131 +
 .../disk/isci/scil/scic_sds_stp_remote_device.c    | 1096 +++
 sys/dev/disk/isci/scil/scic_sds_stp_request.c      | 2578 +++++++
 sys/dev/disk/isci/scil/scic_sds_stp_request.h      |  280 +
 .../isci/scil/scic_sds_unsolicited_frame_control.c |  400 ++
 .../isci/scil/scic_sds_unsolicited_frame_control.h |  305 +
 sys/dev/disk/isci/scil/scic_sgpio.h                |  299 +
 sys/dev/disk/isci/scil/scic_task_request.h         |  180 +
 sys/dev/disk/isci/scil/scic_user_callback.h        | 1145 ++++
 sys/dev/disk/isci/scil/scif_config_parameters.h    |  180 +
 sys/dev/disk/isci/scil/scif_controller.h           |  453 ++
 sys/dev/disk/isci/scil/scif_domain.h               |  184 +
 sys/dev/disk/isci/scil/scif_io_request.h           |  242 +
 sys/dev/disk/isci/scil/scif_library.h              |  195 +
 sys/dev/disk/isci/scil/scif_logger.h               |  117 +
 sys/dev/disk/isci/scil/scif_overview.h             |  115 +
 sys/dev/disk/isci/scil/scif_remote_device.h        |  294 +
 sys/dev/disk/isci/scil/scif_sas_constants.h        |   79 +
 sys/dev/disk/isci/scil/scif_sas_controller.c       | 1254 ++++
 sys/dev/disk/isci/scil/scif_sas_controller.h       |  307 +
 .../isci/scil/scif_sas_controller_state_handlers.c | 1843 +++++
 .../disk/isci/scil/scif_sas_controller_states.c    |  458 ++
 sys/dev/disk/isci/scil/scif_sas_design.h           |  348 +
 sys/dev/disk/isci/scil/scif_sas_domain.c           | 1535 +++++
 sys/dev/disk/isci/scil/scif_sas_domain.h           |  327 +
 .../isci/scil/scif_sas_domain_state_handlers.c     | 1628 +++++
 sys/dev/disk/isci/scil/scif_sas_domain_states.c    |  610 ++
 .../scil/scif_sas_high_priority_request_queue.c    |  159 +
 .../scil/scif_sas_high_priority_request_queue.h    |  123 +
 .../disk/isci/scil/scif_sas_internal_io_request.c  |  280 +
 .../disk/isci/scil/scif_sas_internal_io_request.h  |  156 +
 sys/dev/disk/isci/scil/scif_sas_io_request.c       |  819 +++
 sys/dev/disk/isci/scil/scif_sas_io_request.h       |  151 +
 .../isci/scil/scif_sas_io_request_state_handlers.c |  415 ++
 .../disk/isci/scil/scif_sas_io_request_states.c    |  284 +
 sys/dev/disk/isci/scil/scif_sas_library.c          |  267 +
 sys/dev/disk/isci/scil/scif_sas_library.h          |  104 +
 sys/dev/disk/isci/scil/scif_sas_logger.h           |   93 +
 sys/dev/disk/isci/scil/scif_sas_remote_device.c    |  792 +++
 sys/dev/disk/isci/scil/scif_sas_remote_device.h    |  501 ++
 ...cif_sas_remote_device_ready_substate_handlers.c |  777 +++
 .../scil/scif_sas_remote_device_ready_substates.c  |  288 +
 ..._sas_remote_device_starting_substate_handlers.c |  315 +
 .../scif_sas_remote_device_starting_substates.c    |  141 +
 .../scil/scif_sas_remote_device_state_handlers.c   | 1159 ++++
 .../disk/isci/scil/scif_sas_remote_device_states.c |  547 ++
 sys/dev/disk/isci/scil/scif_sas_request.c          |  181 +
 sys/dev/disk/isci/scil/scif_sas_request.h          |  220 +
 sys/dev/disk/isci/scil/scif_sas_sati_binding.h     |  252 +
 .../scil/scif_sas_smp_activity_clear_affiliation.c |  249 +
 sys/dev/disk/isci/scil/scif_sas_smp_io_request.c   |  598 ++
 sys/dev/disk/isci/scil/scif_sas_smp_io_request.h   |  138 +
 sys/dev/disk/isci/scil/scif_sas_smp_phy.c          |  334 +
 sys/dev/disk/isci/scil/scif_sas_smp_phy.h          |  186 +
 .../disk/isci/scil/scif_sas_smp_remote_device.c    | 2621 ++++++++
 .../disk/isci/scil/scif_sas_smp_remote_device.h    |  431 ++
 sys/dev/disk/isci/scil/scif_sas_stp_io_request.c   |  621 ++
 sys/dev/disk/isci/scil/scif_sas_stp_io_request.h   |  100 +
 .../disk/isci/scil/scif_sas_stp_remote_device.c    |  214 +
 .../disk/isci/scil/scif_sas_stp_remote_device.h    |  118 +
 sys/dev/disk/isci/scil/scif_sas_stp_task_request.c |  264 +
 sys/dev/disk/isci/scil/scif_sas_stp_task_request.h |  105 +
 sys/dev/disk/isci/scil/scif_sas_task_request.c     |  479 ++
 sys/dev/disk/isci/scil/scif_sas_task_request.h     |  142 +
 .../scil/scif_sas_task_request_state_handlers.c    |  402 ++
 .../disk/isci/scil/scif_sas_task_request_states.c  |  285 +
 sys/dev/disk/isci/scil/scif_sas_timer.c            |  121 +
 sys/dev/disk/isci/scil/scif_task_request.h         |  128 +
 sys/dev/disk/isci/scil/scif_user_callback.h        | 1048 +++
 sys/dev/disk/isci/scil/scu_bios_definitions.h      | 1001 +++
 sys/dev/disk/isci/scil/scu_completion_codes.h      |  263 +
 sys/dev/disk/isci/scil/scu_constants.h             |  154 +
 sys/dev/disk/isci/scil/scu_event_codes.h           |  343 +
 sys/dev/disk/isci/scil/scu_registers.h             | 2121 ++++++
 sys/dev/disk/isci/scil/scu_remote_node_context.h   |  242 +
 sys/dev/disk/isci/scil/scu_task_context.h          |  965 +++
 sys/dev/disk/isci/scil/scu_unsolicited_frame.h     |  122 +
 sys/dev/disk/isci/scil/scu_viit_data.h             |  186 +
 sys/dev/disk/isci/types.h                          |   53 +
 264 files changed, 112133 insertions(+), 1 deletion(-)
 create mode 100644 share/man/man4/isci.4
 create mode 100644 sys/dev/disk/isci/Makefile
 create mode 100644 sys/dev/disk/isci/README
 create mode 100644 sys/dev/disk/isci/environment.h
 create mode 100644 sys/dev/disk/isci/isci.c
 create mode 100644 sys/dev/disk/isci/isci.h
 create mode 100644 sys/dev/disk/isci/isci_controller.c
 create mode 100644 sys/dev/disk/isci/isci_domain.c
 create mode 100644 sys/dev/disk/isci/isci_interrupt.c
 create mode 100644 sys/dev/disk/isci/isci_io_request.c
 create mode 100644 sys/dev/disk/isci/isci_logger.c
 create mode 100644 sys/dev/disk/isci/isci_oem_parameters.c
 create mode 100644 sys/dev/disk/isci/isci_remote_device.c
 create mode 100644 sys/dev/disk/isci/isci_sysctl.c
 create mode 100644 sys/dev/disk/isci/isci_task_request.c
 create mode 100644 sys/dev/disk/isci/isci_timer.c
 create mode 100644 sys/dev/disk/isci/sci_environment.h
 create mode 100644 sys/dev/disk/isci/scil/intel_ata.h
 create mode 100644 sys/dev/disk/isci/scil/intel_pci.h
 create mode 100644 sys/dev/disk/isci/scil/intel_sas.h
 create mode 100644 sys/dev/disk/isci/scil/intel_sat.h
 create mode 100644 sys/dev/disk/isci/scil/intel_sata.h
 create mode 100644 sys/dev/disk/isci/scil/intel_scsi.h
 create mode 100644 sys/dev/disk/isci/scil/sati.c
 create mode 100644 sys/dev/disk/isci/scil/sati.h
 create mode 100644 sys/dev/disk/isci/scil/sati_abort_task_set.c
 create mode 100644 sys/dev/disk/isci/scil/sati_abort_task_set.h
 create mode 100644 sys/dev/disk/isci/scil/sati_atapi.c
 create mode 100644 sys/dev/disk/isci/scil/sati_atapi.h
 create mode 100644 sys/dev/disk/isci/scil/sati_callbacks.h
 create mode 100644 sys/dev/disk/isci/scil/sati_design.h
 create mode 100644 sys/dev/disk/isci/scil/sati_device.c
 create mode 100644 sys/dev/disk/isci/scil/sati_device.h
 create mode 100644 sys/dev/disk/isci/scil/sati_inquiry.c
 create mode 100644 sys/dev/disk/isci/scil/sati_inquiry.h
 create mode 100644 sys/dev/disk/isci/scil/sati_log_sense.c
 create mode 100644 sys/dev/disk/isci/scil/sati_log_sense.h
 create mode 100644 sys/dev/disk/isci/scil/sati_lun_reset.c
 create mode 100644 sys/dev/disk/isci/scil/sati_lun_reset.h
 create mode 100644 sys/dev/disk/isci/scil/sati_mode_pages.c
 create mode 100644 sys/dev/disk/isci/scil/sati_mode_pages.h
 create mode 100644 sys/dev/disk/isci/scil/sati_mode_select.c
 create mode 100644 sys/dev/disk/isci/scil/sati_mode_select.h
 create mode 100644 sys/dev/disk/isci/scil/sati_mode_sense.c
 create mode 100644 sys/dev/disk/isci/scil/sati_mode_sense.h
 create mode 100644 sys/dev/disk/isci/scil/sati_mode_sense_10.c
 create mode 100644 sys/dev/disk/isci/scil/sati_mode_sense_10.h
 create mode 100644 sys/dev/disk/isci/scil/sati_mode_sense_6.c
 create mode 100644 sys/dev/disk/isci/scil/sati_mode_sense_6.h
 create mode 100644 sys/dev/disk/isci/scil/sati_move.c
 create mode 100644 sys/dev/disk/isci/scil/sati_move.h
 create mode 100644 sys/dev/disk/isci/scil/sati_passthrough.c
 create mode 100644 sys/dev/disk/isci/scil/sati_passthrough.h
 create mode 100644 sys/dev/disk/isci/scil/sati_read.c
 create mode 100644 sys/dev/disk/isci/scil/sati_read.h
 create mode 100644 sys/dev/disk/isci/scil/sati_read_buffer.c
 create mode 100644 sys/dev/disk/isci/scil/sati_read_buffer.h
 create mode 100644 sys/dev/disk/isci/scil/sati_read_capacity.c
 create mode 100644 sys/dev/disk/isci/scil/sati_read_capacity.h
 create mode 100644 sys/dev/disk/isci/scil/sati_reassign_blocks.c
 create mode 100644 sys/dev/disk/isci/scil/sati_reassign_blocks.h
 create mode 100644 sys/dev/disk/isci/scil/sati_report_luns.c
 create mode 100644 sys/dev/disk/isci/scil/sati_report_luns.h
 create mode 100644 sys/dev/disk/isci/scil/sati_request_sense.c
 create mode 100644 sys/dev/disk/isci/scil/sati_request_sense.h
 create mode 100644 sys/dev/disk/isci/scil/sati_start_stop_unit.c
 create mode 100644 sys/dev/disk/isci/scil/sati_start_stop_unit.h
 create mode 100644 sys/dev/disk/isci/scil/sati_synchronize_cache.c
 create mode 100644 sys/dev/disk/isci/scil/sati_synchronize_cache.h
 create mode 100644 sys/dev/disk/isci/scil/sati_test_unit_ready.c
 create mode 100644 sys/dev/disk/isci/scil/sati_test_unit_ready.h
 create mode 100644 sys/dev/disk/isci/scil/sati_translator_sequence.h
 create mode 100644 sys/dev/disk/isci/scil/sati_types.h
 create mode 100644 sys/dev/disk/isci/scil/sati_unmap.c
 create mode 100644 sys/dev/disk/isci/scil/sati_unmap.h
 create mode 100644 sys/dev/disk/isci/scil/sati_util.c
 create mode 100644 sys/dev/disk/isci/scil/sati_util.h
 create mode 100644 sys/dev/disk/isci/scil/sati_verify.c
 create mode 100644 sys/dev/disk/isci/scil/sati_verify.h
 create mode 100644 sys/dev/disk/isci/scil/sati_write.c
 create mode 100644 sys/dev/disk/isci/scil/sati_write.h
 create mode 100644 sys/dev/disk/isci/scil/sati_write_and_verify.c
 create mode 100644 sys/dev/disk/isci/scil/sati_write_and_verify.h
 create mode 100644 sys/dev/disk/isci/scil/sati_write_buffer.c
 create mode 100644 sys/dev/disk/isci/scil/sati_write_buffer.h
 create mode 100644 sys/dev/disk/isci/scil/sati_write_long.c
 create mode 100644 sys/dev/disk/isci/scil/sati_write_long.h
 create mode 100644 sys/dev/disk/isci/scil/sci_abstract_list.c
 create mode 100644 sys/dev/disk/isci/scil/sci_abstract_list.h
 create mode 100644 sys/dev/disk/isci/scil/sci_base_controller.c
 create mode 100644 sys/dev/disk/isci/scil/sci_base_controller.h
 create mode 100644 sys/dev/disk/isci/scil/sci_base_domain.c
 create mode 100644 sys/dev/disk/isci/scil/sci_base_domain.h
 create mode 100644 sys/dev/disk/isci/scil/sci_base_iterator.c
 create mode 100644 sys/dev/disk/isci/scil/sci_base_iterator.h
 create mode 100644 sys/dev/disk/isci/scil/sci_base_library.c
 create mode 100644 sys/dev/disk/isci/scil/sci_base_library.h
 create mode 100644 sys/dev/disk/isci/scil/sci_base_logger.c
 create mode 100644 sys/dev/disk/isci/scil/sci_base_logger.h
 create mode 100644 sys/dev/disk/isci/scil/sci_base_memory_descriptor_list.c
 create mode 100644 sys/dev/disk/isci/scil/sci_base_memory_descriptor_list.h
 create mode 100644 sys/dev/disk/isci/scil/sci_base_memory_descriptor_list_decorator.c
 create mode 100644 sys/dev/disk/isci/scil/sci_base_object.c
 create mode 100644 sys/dev/disk/isci/scil/sci_base_object.h
 create mode 100644 sys/dev/disk/isci/scil/sci_base_observer.c
 create mode 100644 sys/dev/disk/isci/scil/sci_base_observer.h
 create mode 100644 sys/dev/disk/isci/scil/sci_base_phy.c
 create mode 100644 sys/dev/disk/isci/scil/sci_base_phy.h
 create mode 100644 sys/dev/disk/isci/scil/sci_base_port.c
 create mode 100644 sys/dev/disk/isci/scil/sci_base_port.h
 create mode 100644 sys/dev/disk/isci/scil/sci_base_remote_device.c
 create mode 100644 sys/dev/disk/isci/scil/sci_base_remote_device.h
 create mode 100644 sys/dev/disk/isci/scil/sci_base_request.c
 create mode 100644 sys/dev/disk/isci/scil/sci_base_request.h
 create mode 100644 sys/dev/disk/isci/scil/sci_base_state.h
 create mode 100644 sys/dev/disk/isci/scil/sci_base_state_machine.c
 create mode 100644 sys/dev/disk/isci/scil/sci_base_state_machine.h
 create mode 100644 sys/dev/disk/isci/scil/sci_base_state_machine_logger.c
 create mode 100644 sys/dev/disk/isci/scil/sci_base_state_machine_logger.h
 create mode 100644 sys/dev/disk/isci/scil/sci_base_state_machine_observer.c
 create mode 100644 sys/dev/disk/isci/scil/sci_base_state_machine_observer.h
 create mode 100644 sys/dev/disk/isci/scil/sci_base_subject.c
 create mode 100644 sys/dev/disk/isci/scil/sci_base_subject.h
 create mode 100644 sys/dev/disk/isci/scil/sci_controller.h
 create mode 100644 sys/dev/disk/isci/scil/sci_controller_constants.h
 create mode 100644 sys/dev/disk/isci/scil/sci_fast_list.h
 create mode 100644 sys/dev/disk/isci/scil/sci_iterator.h
 create mode 100644 sys/dev/disk/isci/scil/sci_library.h
 create mode 100644 sys/dev/disk/isci/scil/sci_logger.h
 create mode 100644 sys/dev/disk/isci/scil/sci_memory_descriptor_list.h
 create mode 100644 sys/dev/disk/isci/scil/sci_memory_descriptor_list_decorator.h
 create mode 100644 sys/dev/disk/isci/scil/sci_object.h
 create mode 100644 sys/dev/disk/isci/scil/sci_overview.h
 create mode 100644 sys/dev/disk/isci/scil/sci_pool.h
 create mode 100644 sys/dev/disk/isci/scil/sci_simple_list.h
 create mode 100644 sys/dev/disk/isci/scil/sci_status.h
 create mode 100644 sys/dev/disk/isci/scil/sci_types.h
 create mode 100644 sys/dev/disk/isci/scil/sci_util.c
 create mode 100644 sys/dev/disk/isci/scil/sci_util.h
 create mode 100644 sys/dev/disk/isci/scil/scic_config_parameters.h
 create mode 100644 sys/dev/disk/isci/scil/scic_controller.h
 create mode 100644 sys/dev/disk/isci/scil/scic_io_request.h
 create mode 100644 sys/dev/disk/isci/scil/scic_library.h
 create mode 100644 sys/dev/disk/isci/scil/scic_logger.h
 create mode 100644 sys/dev/disk/isci/scil/scic_overview.h
 create mode 100644 sys/dev/disk/isci/scil/scic_phy.h
 create mode 100644 sys/dev/disk/isci/scil/scic_port.h
 create mode 100644 sys/dev/disk/isci/scil/scic_remote_device.h
 create mode 100644 sys/dev/disk/isci/scil/scic_sds_controller.c
 create mode 100644 sys/dev/disk/isci/scil/scic_sds_controller.h
 create mode 100644 sys/dev/disk/isci/scil/scic_sds_controller_registers.h
 create mode 100644 sys/dev/disk/isci/scil/scic_sds_library.c
 create mode 100644 sys/dev/disk/isci/scil/scic_sds_library.h
 create mode 100644 sys/dev/disk/isci/scil/scic_sds_logger.h
 create mode 100644 sys/dev/disk/isci/scil/scic_sds_pci.c
 create mode 100644 sys/dev/disk/isci/scil/scic_sds_pci.h
 create mode 100644 sys/dev/disk/isci/scil/scic_sds_phy.c
 create mode 100644 sys/dev/disk/isci/scil/scic_sds_phy.h
 create mode 100644 sys/dev/disk/isci/scil/scic_sds_phy_registers.h
 create mode 100644 sys/dev/disk/isci/scil/scic_sds_port.c
 create mode 100644 sys/dev/disk/isci/scil/scic_sds_port.h
 create mode 100644 sys/dev/disk/isci/scil/scic_sds_port_configuration_agent.c
 create mode 100644 sys/dev/disk/isci/scil/scic_sds_port_configuration_agent.h
 create mode 100644 sys/dev/disk/isci/scil/scic_sds_port_registers.h
 create mode 100644 sys/dev/disk/isci/scil/scic_sds_remote_device.c
 create mode 100644 sys/dev/disk/isci/scil/scic_sds_remote_device.h
 create mode 100644 sys/dev/disk/isci/scil/scic_sds_remote_node_context.c
 create mode 100644 sys/dev/disk/isci/scil/scic_sds_remote_node_context.h
 create mode 100644 sys/dev/disk/isci/scil/scic_sds_remote_node_table.c
 create mode 100644 sys/dev/disk/isci/scil/scic_sds_remote_node_table.h
 create mode 100644 sys/dev/disk/isci/scil/scic_sds_request.c
 create mode 100644 sys/dev/disk/isci/scil/scic_sds_request.h
 create mode 100644 sys/dev/disk/isci/scil/scic_sds_sgpio.c
 create mode 100644 sys/dev/disk/isci/scil/scic_sds_smp_remote_device.c
 create mode 100644 sys/dev/disk/isci/scil/scic_sds_smp_request.c
 create mode 100644 sys/dev/disk/isci/scil/scic_sds_smp_request.h
 create mode 100644 sys/dev/disk/isci/scil/scic_sds_ssp_request.c
 create mode 100644 sys/dev/disk/isci/scil/scic_sds_stp_packet_request.c
 create mode 100644 sys/dev/disk/isci/scil/scic_sds_stp_packet_request.h
 create mode 100644 sys/dev/disk/isci/scil/scic_sds_stp_pio_request.h
 create mode 100644 sys/dev/disk/isci/scil/scic_sds_stp_remote_device.c
 create mode 100644 sys/dev/disk/isci/scil/scic_sds_stp_request.c
 create mode 100644 sys/dev/disk/isci/scil/scic_sds_stp_request.h
 create mode 100644 sys/dev/disk/isci/scil/scic_sds_unsolicited_frame_control.c
 create mode 100644 sys/dev/disk/isci/scil/scic_sds_unsolicited_frame_control.h
 create mode 100644 sys/dev/disk/isci/scil/scic_sgpio.h
 create mode 100644 sys/dev/disk/isci/scil/scic_task_request.h
 create mode 100644 sys/dev/disk/isci/scil/scic_user_callback.h
 create mode 100644 sys/dev/disk/isci/scil/scif_config_parameters.h
 create mode 100644 sys/dev/disk/isci/scil/scif_controller.h
 create mode 100644 sys/dev/disk/isci/scil/scif_domain.h
 create mode 100644 sys/dev/disk/isci/scil/scif_io_request.h
 create mode 100644 sys/dev/disk/isci/scil/scif_library.h
 create mode 100644 sys/dev/disk/isci/scil/scif_logger.h
 create mode 100644 sys/dev/disk/isci/scil/scif_overview.h
 create mode 100644 sys/dev/disk/isci/scil/scif_remote_device.h
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_constants.h
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_controller.c
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_controller.h
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_controller_state_handlers.c
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_controller_states.c
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_design.h
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_domain.c
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_domain.h
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_domain_state_handlers.c
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_domain_states.c
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_high_priority_request_queue.c
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_high_priority_request_queue.h
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_internal_io_request.c
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_internal_io_request.h
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_io_request.c
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_io_request.h
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_io_request_state_handlers.c
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_io_request_states.c
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_library.c
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_library.h
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_logger.h
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_remote_device.c
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_remote_device.h
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_remote_device_ready_substate_handlers.c
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_remote_device_ready_substates.c
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_remote_device_starting_substate_handlers.c
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_remote_device_starting_substates.c
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_remote_device_state_handlers.c
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_remote_device_states.c
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_request.c
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_request.h
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_sati_binding.h
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_smp_activity_clear_affiliation.c
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_smp_io_request.c
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_smp_io_request.h
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_smp_phy.c
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_smp_phy.h
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_smp_remote_device.c
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_smp_remote_device.h
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_stp_io_request.c
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_stp_io_request.h
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_stp_remote_device.c
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_stp_remote_device.h
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_stp_task_request.c
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_stp_task_request.h
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_task_request.c
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_task_request.h
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_task_request_state_handlers.c
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_task_request_states.c
 create mode 100644 sys/dev/disk/isci/scil/scif_sas_timer.c
 create mode 100644 sys/dev/disk/isci/scil/scif_task_request.h
 create mode 100644 sys/dev/disk/isci/scil/scif_user_callback.h
 create mode 100644 sys/dev/disk/isci/scil/scu_bios_definitions.h
 create mode 100644 sys/dev/disk/isci/scil/scu_completion_codes.h
 create mode 100644 sys/dev/disk/isci/scil/scu_constants.h
 create mode 100644 sys/dev/disk/isci/scil/scu_event_codes.h
 create mode 100644 sys/dev/disk/isci/scil/scu_registers.h
 create mode 100644 sys/dev/disk/isci/scil/scu_remote_node_context.h
 create mode 100644 sys/dev/disk/isci/scil/scu_task_context.h
 create mode 100644 sys/dev/disk/isci/scil/scu_unsolicited_frame.h
 create mode 100644 sys/dev/disk/isci/scil/scu_viit_data.h
 create mode 100644 sys/dev/disk/isci/types.h

diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile
index da84ed8..98d0e6d 100644
--- a/share/man/man4/Makefile
+++ b/share/man/man4/Makefile
@@ -141,6 +141,7 @@ MAN=	aac.4 \
 	ips.4 \
 	ipsec.4 \
 	isa.4 \
+	isci.4 \
 	iscsi_initiator.4 \
 	isp.4 \
 	ispfw.4 \
diff --git a/share/man/man4/isci.4 b/share/man/man4/isci.4
new file mode 100644
index 0000000..2e3bd1a
--- /dev/null
+++ b/share/man/man4/isci.4
@@ -0,0 +1,112 @@
+.\"
+.\" Copyright (c) 2012 Intel Corporation
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions, and the following disclaimer,
+.\"    without modification.
+.\" 2. Redistributions in binary form must reproduce at minimum a disclaimer
+.\"    substantially similar to the "NO WARRANTY" disclaimer below
+.\"    ("Disclaimer") and any redistribution must be conditioned upon
+.\"    including a substantially similar Disclaimer requirement for further
+.\"    binary redistribution.
+.\"
+.\" NO WARRANTY
+.\" 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 MERCHANTIBILITY AND FITNESS FOR
+.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+.\" HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+.\"
+.\" isci driver man page.
+.\"
+.\" Author: Jim Harris <jimharris@FreeBSD.org>
+.\"
+.\" $FreeBSD: src/share/man/man4/isci.4,v 1.5 2012/03/29 05:02:12 eadler Exp $
+.\"
+.Dd January 23, 2012
+.Dt ISCI 4
+.Os
+.Sh NAME
+.Nm isci
+.Nd Intel C600 Serial Attached SCSI driver
+.Sh SYNOPSIS
+To compile this driver into your kernel,
+place the following lines in your kernel configuration file:
+.Bd -ragged -offset indent
+.Cd "device scbus"
+.Cd "device isci"
+.Ed
+.Pp
+Or, to load the driver as a module at boot, place the following line in
+.Xr loader.conf 5 :
+.Bd -literal -offset indent
+isci_load="YES"
+.Ed
+.Sh HARDWARE
+The
+.Nm
+driver provides support for Intel C600
+.Tn SAS
+controllers.
+.Sh CONFIGURATION
+To force legacy interrupts for all
+.Nm
+driver instances, set the following tunable value in
+.Xr loader.conf 5 :
+.Bd -literal -offset indent
+hw.isci.force_legacy_interrupts=1
+.Ed
+.Sh DEBUGGING
+To enable debugging prints from the
+.Nm
+driver, set the
+.Bd -literal -offset indent
+hw.isci.debug_level
+.Ed
+.Pp
+variable to a value between 1 and 4 in
+.Xr loader.conf 5 .
+.Pp
+The hardware layer in the
+.Nm
+driver has extensive logging capabilities
+which are disabled by default for performance reasons.
+These can be enabled by adding
+.Bd -literal -offset indent
+options ISCI_LOGGING
+.Ed
+.Pp
+to the kernel configuration file.
+.Sh SEE ALSO
+.Xr cd 4 ,
+.Xr ch 4 ,
+.Xr da 4 ,
+.Xr pci 4 ,
+.Xr sa 4 ,
+.Xr scsi 4
+.Sh HISTORY
+The
+.Nm
+driver first appeared in
+.Fx 8.3 and 9.1 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+driver was developed by Intel and originally written by
+.An Jim Harris Aq jimharris@FreeBSD.org
+with contributions from Sohaib Ahsan and input from
+.An Scott Long Aq scottl@FreeBSD.org .
+.Pp
+This man page was written by
+.An Jim Harris Aq jimharris@FreeBSD.org .
diff --git a/sys/conf/files b/sys/conf/files
index 5217e1e..b8f81d9 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -446,6 +446,115 @@ dev/misc/cpuctl/cpuctl.c	optional cpuctl
 dev/raid/ida/ida.c		optional ida
 dev/raid/ida/ida_disk.c	optional ida
 dev/raid/ida/ida_pci.c	optional ida pci
+dev/disk/isci/isci.c						optional isci
+dev/disk/isci/isci_controller.c					optional isci
+dev/disk/isci/isci_domain.c					optional isci
+dev/disk/isci/isci_interrupt.c					optional isci
+dev/disk/isci/isci_io_request.c					optional isci
+dev/disk/isci/isci_logger.c					optional isci
+dev/disk/isci/isci_oem_parameters.c				optional isci
+dev/disk/isci/isci_remote_device.c				optional isci
+dev/disk/isci/isci_sysctl.c					optional isci
+dev/disk/isci/isci_task_request.c				optional isci
+dev/disk/isci/isci_timer.c					optional isci
+dev/disk/isci/scil/sati.c					optional isci
+dev/disk/isci/scil/sati_abort_task_set.c			optional isci
+dev/disk/isci/scil/sati_atapi.c					optional isci
+dev/disk/isci/scil/sati_device.c				optional isci
+dev/disk/isci/scil/sati_inquiry.c				optional isci
+dev/disk/isci/scil/sati_log_sense.c				optional isci
+dev/disk/isci/scil/sati_lun_reset.c				optional isci
+dev/disk/isci/scil/sati_mode_pages.c				optional isci
+dev/disk/isci/scil/sati_mode_select.c				optional isci
+dev/disk/isci/scil/sati_mode_sense.c				optional isci
+dev/disk/isci/scil/sati_mode_sense_10.c				optional isci
+dev/disk/isci/scil/sati_mode_sense_6.c				optional isci
+dev/disk/isci/scil/sati_move.c					optional isci
+dev/disk/isci/scil/sati_passthrough.c				optional isci
+dev/disk/isci/scil/sati_read.c					optional isci
+dev/disk/isci/scil/sati_read_buffer.c				optional isci
+dev/disk/isci/scil/sati_read_capacity.c				optional isci
+dev/disk/isci/scil/sati_reassign_blocks.c			optional isci
+dev/disk/isci/scil/sati_report_luns.c				optional isci
+dev/disk/isci/scil/sati_request_sense.c				optional isci
+dev/disk/isci/scil/sati_start_stop_unit.c			optional isci
+dev/disk/isci/scil/sati_synchronize_cache.c			optional isci
+dev/disk/isci/scil/sati_test_unit_ready.c			optional isci
+dev/disk/isci/scil/sati_unmap.c					optional isci
+dev/disk/isci/scil/sati_util.c					optional isci
+dev/disk/isci/scil/sati_verify.c				optional isci
+dev/disk/isci/scil/sati_write.c					optional isci
+dev/disk/isci/scil/sati_write_and_verify.c			optional isci
+dev/disk/isci/scil/sati_write_buffer.c				optional isci
+dev/disk/isci/scil/sati_write_long.c				optional isci
+dev/disk/isci/scil/sci_abstract_list.c				optional isci
+dev/disk/isci/scil/sci_base_controller.c			optional isci
+dev/disk/isci/scil/sci_base_domain.c				optional isci
+dev/disk/isci/scil/sci_base_iterator.c				optional isci
+dev/disk/isci/scil/sci_base_library.c				optional isci
+dev/disk/isci/scil/sci_base_logger.c				optional isci
+dev/disk/isci/scil/sci_base_memory_descriptor_list.c		optional isci
+dev/disk/isci/scil/sci_base_memory_descriptor_list_decorator.c	optional isci
+dev/disk/isci/scil/sci_base_object.c				optional isci
+dev/disk/isci/scil/sci_base_observer.c				optional isci
+dev/disk/isci/scil/sci_base_phy.c				optional isci
+dev/disk/isci/scil/sci_base_port.c				optional isci
+dev/disk/isci/scil/sci_base_remote_device.c			optional isci
+dev/disk/isci/scil/sci_base_request.c				optional isci
+dev/disk/isci/scil/sci_base_state_machine.c			optional isci
+dev/disk/isci/scil/sci_base_state_machine_logger.c		optional isci
+dev/disk/isci/scil/sci_base_state_machine_observer.c		optional isci
+dev/disk/isci/scil/sci_base_subject.c				optional isci
+dev/disk/isci/scil/sci_util.c					optional isci
+dev/disk/isci/scil/scic_sds_controller.c			optional isci
+dev/disk/isci/scil/scic_sds_library.c				optional isci
+dev/disk/isci/scil/scic_sds_pci.c				optional isci
+dev/disk/isci/scil/scic_sds_phy.c				optional isci
+dev/disk/isci/scil/scic_sds_port.c				optional isci
+dev/disk/isci/scil/scic_sds_port_configuration_agent.c		optional isci
+dev/disk/isci/scil/scic_sds_remote_device.c			optional isci
+dev/disk/isci/scil/scic_sds_remote_node_context.c		optional isci
+dev/disk/isci/scil/scic_sds_remote_node_table.c			optional isci
+dev/disk/isci/scil/scic_sds_request.c				optional isci
+dev/disk/isci/scil/scic_sds_sgpio.c				optional isci
+dev/disk/isci/scil/scic_sds_smp_remote_device.c			optional isci
+dev/disk/isci/scil/scic_sds_smp_request.c			optional isci
+dev/disk/isci/scil/scic_sds_ssp_request.c			optional isci
+dev/disk/isci/scil/scic_sds_stp_packet_request.c		optional isci
+dev/disk/isci/scil/scic_sds_stp_remote_device.c			optional isci
+dev/disk/isci/scil/scic_sds_stp_request.c			optional isci
+dev/disk/isci/scil/scic_sds_unsolicited_frame_control.c		optional isci
+dev/disk/isci/scil/scif_sas_controller.c			optional isci
+dev/disk/isci/scil/scif_sas_controller_state_handlers.c		optional isci
+dev/disk/isci/scil/scif_sas_controller_states.c			optional isci
+dev/disk/isci/scil/scif_sas_domain.c				optional isci
+dev/disk/isci/scil/scif_sas_domain_state_handlers.c		optional isci
+dev/disk/isci/scil/scif_sas_domain_states.c			optional isci
+dev/disk/isci/scil/scif_sas_high_priority_request_queue.c	optional isci
+dev/disk/isci/scil/scif_sas_internal_io_request.c		optional isci
+dev/disk/isci/scil/scif_sas_io_request.c			optional isci
+dev/disk/isci/scil/scif_sas_io_request_state_handlers.c		optional isci
+dev/disk/isci/scil/scif_sas_io_request_states.c			optional isci
+dev/disk/isci/scil/scif_sas_library.c				optional isci
+dev/disk/isci/scil/scif_sas_remote_device.c			optional isci
+dev/disk/isci/scil/scif_sas_remote_device_ready_substate_handlers.c optional isci
+dev/disk/isci/scil/scif_sas_remote_device_ready_substates.c	optional isci
+dev/disk/isci/scil/scif_sas_remote_device_starting_substate_handlers.c optional isci
+dev/disk/isci/scil/scif_sas_remote_device_starting_substates.c	optional isci
+dev/disk/isci/scil/scif_sas_remote_device_state_handlers.c	optional isci
+dev/disk/isci/scil/scif_sas_remote_device_states.c		optional isci
+dev/disk/isci/scil/scif_sas_request.c				optional isci
+dev/disk/isci/scil/scif_sas_smp_activity_clear_affiliation.c	optional isci
+dev/disk/isci/scil/scif_sas_smp_io_request.c			optional isci
+dev/disk/isci/scil/scif_sas_smp_phy.c				optional isci
+dev/disk/isci/scil/scif_sas_smp_remote_device.c			optional isci
+dev/disk/isci/scil/scif_sas_stp_io_request.c			optional isci
+dev/disk/isci/scil/scif_sas_stp_remote_device.c			optional isci
+dev/disk/isci/scil/scif_sas_stp_task_request.c			optional isci
+dev/disk/isci/scil/scif_sas_task_request.c			optional isci
+dev/disk/isci/scil/scif_sas_task_request_state_handlers.c	optional isci
+dev/disk/isci/scil/scif_sas_task_request_states.c		optional isci
+dev/disk/isci/scil/scif_sas_timer.c				optional isci
 dev/disk/isp/isp.c		optional isp
 dev/disk/isp/isp_freebsd.c	optional isp
 dev/disk/isp/isp_library.c	optional isp
diff --git a/sys/conf/options b/sys/conf/options
index d9abdcc..f6774cf 100644
--- a/sys/conf/options
+++ b/sys/conf/options
@@ -237,6 +237,9 @@ SCSI_NCR_MYADDR		opt_ncr.h
 # Options used only in pci/isp_pci.c
 ISP_TARGET_MODE		opt_isp.h
 
+# options for the Intel C600 SAS driver (isci)
+ISCI_LOGGING		opt_isci.h
+
 # Options used in the 'nata' ATA/ATAPI driver
 ATA_STATIC_ID		opt_ata.h
 
diff --git a/sys/config/LINT64 b/sys/config/LINT64
index 59a94dd..88f56c5 100644
--- a/sys/config/LINT64
+++ b/sys/config/LINT64
@@ -1012,6 +1012,11 @@ device		tws		# 3ware 9750 series SATA/SAS RAID
 #
 device	ips
 
+#
+# Intel C600 (Patsburg) integrated SAS controller
+device		isci
+options		ISCI_LOGGING	# enable debugging in isci HAL
+
 # AHCI driver, this will override NATA for AHCI devices,
 # both drivers may be included.
 #
diff --git a/sys/config/X86_64_GENERIC b/sys/config/X86_64_GENERIC
index f92dfc0..56612bf 100644
--- a/sys/config/X86_64_GENERIC
+++ b/sys/config/X86_64_GENERIC
@@ -106,6 +106,7 @@ device		aic
 device		ncv		# NCR 53C500
 device		nsp		# Workbit Ninja SCSI-3
 device		stg		# TMC 18C30/18C50
+device		isci		# Intel C600 SAS controller
 
 # SCSI peripherals
 device		scbus		# SCSI bus (required)
diff --git a/sys/dev/disk/Makefile b/sys/dev/disk/Makefile
index adde16a..46e9d42 100644
--- a/sys/dev/disk/Makefile
+++ b/sys/dev/disk/Makefile
@@ -1,6 +1,6 @@
 .include "${.CURDIR}/../../platform/${MACHINE_PLATFORM}/Makefile.inc"
 
-SUBDIR= ahci aic aic7xxx ccd dm iscsi isp ispfw md mmcsd mpt nata ncv nsp
+SUBDIR= ahci aic aic7xxx ccd dm isci iscsi isp ispfw md mmcsd mpt nata ncv nsp
 SUBDIR+= nvme sbp sdhci sili stg sym trm vn vpo
 
 .for dir in ${SUBDIR}
diff --git a/sys/dev/disk/isci/Makefile b/sys/dev/disk/isci/Makefile
new file mode 100644
index 0000000..0aabe4d
--- /dev/null
+++ b/sys/dev/disk/isci/Makefile
@@ -0,0 +1,88 @@
+# isci driver Makefile
+#
+# $FreeBSD: src/sys/modules/isci/Makefile,v 1.2 2012/02/09 17:50:24 jimharris Exp $
+
+.PATH:  ${.CURDIR}/scil
+
+KMOD    = isci
+SRCS    = isci.c isci_oem_parameters.c \
+		isci_controller.c isci_domain.c isci_io_request.c \
+		isci_timer.c isci_remote_device.c isci_logger.c \
+		isci_task_request.c isci_sysctl.c isci_interrupt.c
+
+SRCS += \
+		sci_base_controller.c \
+		sci_base_domain.c \
+		sci_base_iterator.c \
+		sci_base_library.c \
+		sci_base_logger.c \
+		sci_base_memory_descriptor_list.c \
+		sci_base_memory_descriptor_list_decorator.c \
+		sci_base_object.c \
+		sci_base_observer.c \
+		sci_base_phy.c \
+		sci_base_port.c \
+		sci_base_remote_device.c \
+		sci_base_request.c \
+		sci_base_state_machine.c \
+		sci_base_state_machine_logger.c \
+		sci_base_state_machine_observer.c \
+		sci_base_subject.c
+
+SRCS += \
+		sci_abstract_list.c \
+		sci_util.c
+
+SRCS += \
+		scic_sds_controller.c \
+		scic_sds_library.c scic_sds_pci.c \
+		scic_sds_phy.c scic_sds_port.c \
+		scic_sds_port_configuration_agent.c \
+		scic_sds_remote_device.c scic_sds_remote_node_context.c \
+		scic_sds_remote_node_table.c scic_sds_request.c \
+		scic_sds_sgpio.c scic_sds_smp_remote_device.c \
+		scic_sds_smp_request.c scic_sds_ssp_request.c \
+		scic_sds_stp_packet_request.c scic_sds_stp_remote_device.c \
+		scic_sds_stp_request.c scic_sds_unsolicited_frame_control.c
+
+SRCS += \
+		scif_sas_controller.c \
+		scif_sas_controller_state_handlers.c \
+		scif_sas_controller_states.c scif_sas_domain.c \
+		scif_sas_domain_state_handlers.c scif_sas_domain_states.c \
+		scif_sas_high_priority_request_queue.c \
+		scif_sas_internal_io_request.c scif_sas_io_request.c \
+		scif_sas_io_request_state_handlers.c \
+		scif_sas_io_request_states.c scif_sas_library.c \
+		scif_sas_remote_device.c \
+		scif_sas_remote_device_ready_substate_handlers.c \
+		scif_sas_remote_device_ready_substates.c \
+		scif_sas_remote_device_starting_substate_handlers.c \
+		scif_sas_remote_device_starting_substates.c \
+		scif_sas_remote_device_state_handlers.c \
+		scif_sas_remote_device_states.c scif_sas_request.c \
+		scif_sas_smp_activity_clear_affiliation.c \
+		scif_sas_smp_io_request.c scif_sas_smp_phy.c \
+		scif_sas_smp_remote_device.c scif_sas_stp_io_request.c \
+		scif_sas_stp_remote_device.c scif_sas_stp_task_request.c \
+		scif_sas_task_request.c scif_sas_task_request_state_handlers.c \
+		scif_sas_task_request_states.c scif_sas_timer.c
+
+SRCS += \
+		sati.c \
+		sati_abort_task_set.c sati_atapi.c \
+		sati_device.c sati_inquiry.c sati_log_sense.c \
+		sati_lun_reset.c sati_mode_pages.c sati_mode_select.c \
+		sati_mode_sense.c sati_mode_sense_6.c sati_mode_sense_10.c \
+		sati_move.c sati_passthrough.c sati_read.c sati_read_buffer.c \
+		sati_read_capacity.c  \
+		sati_report_luns.c sati_request_sense.c sati_reassign_blocks.c \
+		sati_start_stop_unit.c sati_synchronize_cache.c \
+		sati_test_unit_ready.c sati_unmap.c sati_util.c \
+		sati_verify.c sati_write.c  \
+		sati_write_buffer.c sati_write_long.c sati_write_and_verify.c
+
+SRCS += opt_scsi.h opt_cam.h opt_isci.h
+SRCS += device_if.h bus_if.h pci_if.h
+
+.include <bsd.kmod.mk>
diff --git a/sys/dev/disk/isci/README b/sys/dev/disk/isci/README
new file mode 100644
index 0000000..1261d83
--- /dev/null
+++ b/sys/dev/disk/isci/README
@@ -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 --git a/sys/dev/disk/isci/environment.h b/sys/dev/disk/isci/environment.h
new file mode 100644
index 0000000..b9bde24
--- /dev/null
+++ b/sys/dev/disk/isci/environment.h
@@ -0,0 +1,99 @@
+/*-
+ * 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: src/sys/dev/isci/environment.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+#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 <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 --git a/sys/dev/disk/isci/isci.c b/sys/dev/disk/isci/isci.c
new file mode 100644
index 0000000..db47c99
--- /dev/null
+++ b/sys/dev/disk/isci/isci.c
@@ -0,0 +1,657 @@
+/*-
+ * 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: src/sys/dev/isci/isci.c,v 1.2 2012/02/27 17:04:18 sbruno Exp $
+ */
+
+#include <dev/disk/isci/isci.h>
+
+#include <sys/sysctl.h>
+#include <sys/malloc.h>
+
+#include <bus/cam/cam_periph.h>
+
+#include <bus/pci/pcireg.h>
+#include <bus/pci/pcivar.h>
+
+#include <dev/disk/isci/scil/scic_logger.h>
+#include <dev/disk/isci/scil/scic_library.h>
+#include <dev/disk/isci/scil/scic_user_callback.h>
+
+#include <dev/disk/isci/scil/scif_controller.h>
+#include <dev/disk/isci/scil/scif_library.h>
+#include <dev/disk/isci/scil/scif_logger.h>
+#include <dev/disk/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)"  },
+	 { 0x1d6c8086,	"Intel(R) C600 Series Chipset SAS Controller"  },
+	 { 0x1d6d8086,	"Intel(R) C600 Series Chipset SAS Controller"  },
+	 { 0x1d6e8086,	"Intel(R) C600 Series Chipset SAS Controller"  },
+	 { 0x1d6f8086,	"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 (BUS_PROBE_DEFAULT);
+	}
+	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));
+
+			lockmgr(&controller->lock, LK_EXCLUSIVE);
+			status = scif_controller_stop(controller->scif_controller_handle, 0);
+			lockmgr(&controller->lock, LK_RELEASE);
+
+			while (controller->is_started == TRUE) {
+				/* Now poll for interrupts until the controller stop complete
+				 *  callback is received.
+				 */
+				lockmgr(&controller->lock, LK_EXCLUSIVE);
+				isci_interrupt_poll_handler(controller);
+				lockmgr(&controller->lock, LK_RELEASE);
+				tsleep(isci_detach, 0, "pause", 1);
+			}
+
+			if(controller->sim != NULL) {
+				lockmgr(&controller->lock, LK_EXCLUSIVE);
+				xpt_free_path(controller->path);
+				xpt_bus_deregister(cam_sim_path(controller->sim));
+				cam_sim_free(controller->sim);
+				lockmgr(&controller->lock, LK_RELEASE);
+			}
+		}
+
+		if (controller->timer_memory != NULL)
+			kfree(controller->timer_memory, M_ISCI);
+
+		if (controller->remote_device_memory != NULL)
+			kfree(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)
+		kfree(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);
+
+		if(interrupt_info->type == PCI_INTR_TYPE_MSI)
+			pci_release_msi(device);
+	}
+
+	if (isci->sysctl_tree != NULL)
+		sysctl_ctx_free(&isci->sysctl_ctx);
+
+	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 =
+	    kmalloc(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(NULL,
+	    0x40 /* cacheline alignment */, 0x0, BUS_SPACE_MAXADDR,
+	    BUS_SPACE_MAXADDR, NULL, NULL, memory->size,
+	    0x1 /* we want physically contiguous */,
+	    memory->size, 0, &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 --git a/sys/dev/disk/isci/isci.h b/sys/dev/disk/isci/isci.h
new file mode 100644
index 0000000..fefda01
--- /dev/null
+++ b/sys/dev/disk/isci/isci.h
@@ -0,0 +1,304 @@
+/*-
+ * 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: src/sys/dev/isci/isci.h,v 1.5 2012/04/10 16:33:19 jimharris Exp $
+ */
+
+#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 <bus/cam/cam.h>
+#include <bus/cam/cam_ccb.h>
+#include <bus/cam/cam_sim.h>
+#include <bus/cam/cam_xpt_sim.h>
+
+#include <dev/disk/isci/environment.h>
+#include <dev/disk/isci/scil/intel_pci.h>
+
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/sci_object.h>
+#include <dev/disk/isci/scil/sci_status.h>
+#include <dev/disk/isci/scil/sci_pool.h>
+#include <dev/disk/isci/scil/sci_fast_list.h>
+
+#include <dev/disk/isci/scil/sci_controller_constants.h>
+
+#include <dev/disk/isci/scil/scic_controller.h>
+#include <dev/disk/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;
+	struct lock		*lock;
+	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;
+	TAILQ_HEAD(,ccb_hdr)		queued_ccbs;
+};
+
+struct ISCI_DOMAIN {
+	struct ISCI_CONTROLLER		*controller;
+	SCI_DOMAIN_HANDLE_T		sci_object;
+	uint8_t				index;
+	struct ISCI_REMOTE_DEVICE	*da_remote_device;
+};
+
+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;
+	int					type;
+	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;
+	BOOL			has_been_scanned;
+	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 lock		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_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;
+	struct sysctl_ctx_list			sysctl_ctx;
+	struct sysctl_oid			*sysctl_tree;
+};
+
+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 --git a/sys/dev/disk/isci/isci_controller.c b/sys/dev/disk/isci/isci_controller.c
new file mode 100644
index 0000000..65fb582
--- /dev/null
+++ b/sys/dev/disk/isci/isci_controller.c
@@ -0,0 +1,704 @@
+/*-
+ * 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: src/sys/dev/isci/isci_controller.c,v 1.5 2012/04/10 16:33:19 jimharris Exp $
+ */
+
+#include <dev/disk/isci/isci.h>
+
+#include <sys/conf.h>
+#include <sys/malloc.h>
+
+#include <bus/cam/cam_periph.h>
+#include <bus/cam/cam_xpt_periph.h>
+
+#include <dev/disk/isci/scil/sci_memory_descriptor_list.h>
+#include <dev/disk/isci/scil/sci_memory_descriptor_list_decorator.h>
+
+#include <dev/disk/isci/scil/scif_controller.h>
+#include <dev/disk/isci/scil/scif_library.h>
+#include <dev/disk/isci/scil/scif_io_request.h>
+#include <dev/disk/isci/scil/scif_task_request.h>
+#include <dev/disk/isci/scil/scif_remote_device.h>
+#include <dev/disk/isci/scil/scif_domain.h>
+#include <dev/disk/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);
+
+	lockinit(&controller->lock, "isci", 0, LK_CANRECURSE);
+
+	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 = kmalloc(
+	    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;
+
+	/* Attach to CAM using xpt_bus_register now, then immediately freeze
+	 *  the simq.  It will get released later when initial domain discovery
+	 *  is complete.
+	 */
+	controller->has_been_scanned = FALSE;
+	lockmgr(&controller->lock, LK_EXCLUSIVE);
+	isci_controller_attach_to_cam(controller);
+	xpt_freeze_simq(controller->sim, 1);
+	lockmgr(&controller->lock, LK_RELEASE);
+
+	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(NULL, 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,
+	    &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 *) kmalloc(
+	    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);
+		TAILQ_INIT(&remote_device->queued_ccbs);
+
+		/*
+		 * For the first SCI_MAX_DOMAINS device objects, do not put
+		 *  them in the pool, rather assign them to each domain.  This
+		 *  ensures that any device attached directly to port "i" will
+		 *  always get CAM target id "i".
+		 */
+		if (i < SCI_MAX_DOMAINS)
+			controller->domain[i].da_remote_device = remote_device;
+		else
+			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));
+}
+
+static void
+isci_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb)
+{
+    kfree(ccb, M_TEMP);
+}
+
+void isci_controller_domain_discovery_complete(
+    struct ISCI_CONTROLLER *isci_controller, struct ISCI_DOMAIN *isci_domain)
+{
+	if (!isci_controller->has_been_scanned)
+	{
+		/* Controller has not been scanned 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 proceed with initial
+		 *  scan.
+		 */
+
+		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->has_been_scanned = TRUE;
+
+			/* Unfreeze simq to allow initial scan to proceed. */
+			xpt_release_simq(isci_controller->sim, TRUE);
+
+#if __FreeBSD_version < 800000
+			/* When driver is loaded after boot, we need to
+			 *  explicitly rescan here for versions <8.0, because
+			 *  CAM only automatically scans new buses at boot
+			 *  time.
+			 */
+			union ccb *ccb = xpt_alloc_ccb();
+
+			xpt_create_path(&ccb->ccb_h.path, xpt_periph,
+			    cam_sim_path(isci_controller->sim),
+			    CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
+
+			xpt_setup_ccb(&ccb->ccb_h, ccb->ccb_h.path,
+			    5/*priority (low)*/);
+			ccb->ccb_h.func_code = XPT_SCAN_LUN;
+			ccb->ccb_h.cbfcnp = isci_cam_rescan_callback;
+			ccb->crcn.flags = CAM_FLAG_NONE;
+			xpt_action(ccb);
+#endif
+
+			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;
+	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_release(isci_devq);
+		return (-1);
+	}
+
+	if(xpt_bus_register(controller->sim, controller->index)
+	    != CAM_SUCCESS) {
+		isci_log_message(0, "ISCI", "xpt_bus_register...fails \n");
+		cam_sim_free(controller->sim);
+		lockmgr(&controller->lock, LK_RELEASE);
+		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);
+		lockmgr(&controller->lock, LK_RELEASE);
+		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 >= 800102
+			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 --git a/sys/dev/disk/isci/isci_domain.c b/sys/dev/disk/isci/isci_domain.c
new file mode 100644
index 0000000..ecb1a37
--- /dev/null
+++ b/sys/dev/disk/isci/isci_domain.c
@@ -0,0 +1,339 @@
+/*-
+ * 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: src/sys/dev/isci/isci_domain.c,v 1.2 2012/03/28 18:38:13 jimharris Exp $
+ */
+
+#include <dev/disk/isci/isci.h>
+
+#include <bus/cam/cam_periph.h>
+#include <bus/cam/cam_xpt_periph.h>
+
+#include <dev/disk/isci/scil/scif_domain.h>
+#include <dev/disk/isci/scil/scif_remote_device.h>
+#include <dev/disk/isci/scil/scif_controller.h>
+#include <dev/disk/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);
+
+	/*
+	 * For direct-attached devices, do not pull the device object from
+	 *  the pool.  Rather, use the one stored in the domain object which
+	 *  will ensure that we always get consistent target ids for direct
+	 *  attached devices.
+	 */
+	remote_device = isci_domain->da_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;
+}
+
+static void
+isci_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb)
+{
+    kfree(ccb, M_TEMP);
+}
+
+/**
+ * @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_DOMAIN *isci_domain =
+	    (struct ISCI_DOMAIN *)sci_object_get_association(domain);
+	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();
+
+	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_setup_ccb(&ccb->ccb_h, ccb->ccb_h.path, 5/*priority (low)*/);
+	ccb->ccb_h.func_code = XPT_SCAN_LUN;
+	ccb->ccb_h.cbfcnp = isci_cam_rescan_callback;
+	ccb->crcn.flags = CAM_FLAG_NONE;
+	xpt_action(ccb);
+
+	scif_remote_device_destruct(remote_device);
+
+	/*
+	 * Only put the remote device back into the pool if it was an
+	 *  expander-attached device.
+	 */
+	if (isci_remote_device != isci_domain->da_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 --git a/sys/dev/disk/isci/isci_interrupt.c b/sys/dev/disk/isci/isci_interrupt.c
new file mode 100644
index 0000000..0ae79fd
--- /dev/null
+++ b/sys/dev/disk/isci/isci_interrupt.c
@@ -0,0 +1,242 @@
+/*-
+ * 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: src/sys/dev/isci/isci_interrupt.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+#include <dev/disk/isci/isci.h>
+
+#include <bus/pci/pcireg.h>
+#include <bus/pci/pcivar.h>
+
+#include <dev/disk/isci/scil/scif_controller.h>
+
+void isci_interrupt_legacy_handler(void *arg);
+void isci_interrupt_msix_handler(void *arg);
+
+static int isci_msi_enable = 1;
+TUNABLE_INT("hw.isci.msi.enable", &isci_msi_enable);
+
+static int
+isci_interrupt_setup_legacy(struct isci_softc *isci)
+{
+	struct ISCI_INTERRUPT_INFO *interrupt_info = &isci->interrupt_info[0];
+	u_int irq_flags;
+
+	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->type = pci_alloc_1intr(isci->device, isci_msi_enable,
+	    &interrupt_info->rid, &irq_flags);
+	interrupt_info->res = bus_alloc_resource_any(isci->device, SYS_RES_IRQ,
+	    &interrupt_info->rid, irq_flags);
+
+	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_MPSAFE, isci_interrupt_legacy_handler,
+	    interrupt_info, &interrupt_info->tag, NULL)) {
+		isci_log_message(0, "ISCI", "bus_setup_intr failed\n");
+		return (-1);
+	}
+
+	return (0);
+}
+
+#if 0 /* XXX swildner: set up MSI-X? */
+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_MPSAFE, isci_interrupt_msix_handler,
+			    info, &info->tag, NULL)) {
+				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);
+}
+#else
+void
+isci_interrupt_setup(struct isci_softc *isci)
+{
+	isci_interrupt_setup_legacy(isci);
+}
+#endif
+
+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)) {
+				lockmgr(&controller->lock, LK_EXCLUSIVE);
+				completion_handler(scic_controller_handle);
+				lockmgr(&controller->lock, LK_RELEASE);
+			}
+		}
+	}
+}
+
+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)) {
+		lockmgr(&controller->lock, LK_EXCLUSIVE);
+		completion_handler(scic_controller_handle);
+		lockmgr(&controller->lock, LK_RELEASE);
+	}
+}
+
+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 --git a/sys/dev/disk/isci/isci_io_request.c b/sys/dev/disk/isci/isci_io_request.c
new file mode 100644
index 0000000..b766f0b
--- /dev/null
+++ b/sys/dev/disk/isci/isci_io_request.c
@@ -0,0 +1,934 @@
+/*-
+ * 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: src/sys/dev/isci/isci_io_request.c,v 1.3 2012/04/10 16:33:19 jimharris Exp $
+ */
+
+#include <dev/disk/isci/isci.h>
+
+#include <bus/cam/scsi/scsi_all.h>
+#include <bus/cam/scsi/scsi_message.h>
+
+#include <dev/disk/isci/scil/intel_sas.h>
+
+#include <dev/disk/isci/scil/sci_util.h>
+
+#include <dev/disk/isci/scil/scif_io_request.h>
+#include <dev/disk/isci/scil/scif_controller.h>
+#include <dev/disk/isci/scil/scif_remote_device.h>
+#include <dev/disk/isci/scil/scif_user_callback.h>
+
+#include <dev/disk/isci/scil/scic_io_request.h>
+#include <dev/disk/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;
+	BOOL complete_ccb;
+
+	complete_ccb = TRUE;
+	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:
+		complete_ccb = FALSE;
+		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);
+			complete_ccb = FALSE;
+		}
+		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;
+	}
+
+	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);
+
+	isci_request->ccb = NULL;
+
+	sci_pool_put(isci_controller->request_pool,
+	    (struct ISCI_REQUEST *)isci_request);
+
+	if (complete_ccb) {
+		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);
+		}
+
+		if (isci_remote_device->frozen_lun_mask != 0) {
+			isci_remote_device_release_device_queue(isci_remote_device);
+		}
+
+		xpt_done(ccb);
+
+		if (isci_controller->is_frozen == TRUE) {
+			isci_controller->is_frozen = FALSE;
+			xpt_release_simq(isci_controller->sim, TRUE);
+		}
+	} else {
+		isci_remote_device_freeze_lun_queue(isci_remote_device,
+		    ccb->ccb_h.target_lun);
+
+		isci_log_message(1, "ISCI", "queue %p %x\n", ccb,
+		    ccb->csio.cdb_io.cdb_bytes[0]);
+		ccb->ccb_h.status |= CAM_SIM_QUEUED;
+		TAILQ_INSERT_TAIL(&isci_remote_device->queued_ccbs,
+		    &ccb->ccb_h, sim_links.tqe);
+	}
+}
+
+/**
+ * @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_mp(&request->timer);
+}
+
+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;
+	}
+
+	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 (status != SCI_SUCCESS) {
+		isci_io_request_complete(io_request->parent.controller_handle,
+		    device, io_request, (SCI_IO_STATUS)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, (SCI_IO_STATUS)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;
+
+	lockmgr(&controller->lock, LK_EXCLUSIVE);
+	isci_remote_device_reset(remote_device, NULL);
+	lockmgr(&controller->lock, LK_RELEASE);
+}
+
+#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, (SCI_IO_STATUS)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, (SCI_IO_STATUS)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 --git a/sys/dev/disk/isci/isci_logger.c b/sys/dev/disk/isci/isci_logger.c
new file mode 100644
index 0000000..26f845b
--- /dev/null
+++ b/sys/dev/disk/isci/isci_logger.c
@@ -0,0 +1,350 @@
+/*-
+ * 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: src/sys/dev/isci/isci_logger.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+#include <dev/disk/isci/isci.h>
+
+#include <dev/disk/isci/scil/scif_user_callback.h>
+#include <dev/disk/isci/scil/scic_user_callback.h>
+#include <dev/disk/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);
+	kvsnprintf(buffer, sizeof(buffer)-1, log_message, argp);
+	__va_end(argp);
+	microtime(&tv);
+
+	kprintf("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);		\
+	kvsnprintf(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 --git a/sys/dev/disk/isci/isci_oem_parameters.c b/sys/dev/disk/isci/isci_oem_parameters.c
new file mode 100644
index 0000000..d68010d
--- /dev/null
+++ b/sys/dev/disk/isci/isci_oem_parameters.c
@@ -0,0 +1,175 @@
+/*-
+ * 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: src/sys/dev/isci/isci_oem_parameters.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+#include <dev/disk/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/disk/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 --git a/sys/dev/disk/isci/isci_remote_device.c b/sys/dev/disk/isci/isci_remote_device.c
new file mode 100644
index 0000000..ac312be
--- /dev/null
+++ b/sys/dev/disk/isci/isci_remote_device.c
@@ -0,0 +1,320 @@
+/*-
+ * 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: src/sys/dev/isci/isci_remote_device.c,v 1.4 2012/04/10 16:33:19 jimharris Exp $
+ */
+
+#include <dev/disk/isci/isci.h>
+
+#include <bus/cam/cam_periph.h>
+#include <bus/cam/cam_xpt_periph.h>
+
+#include <dev/disk/isci/scil/scif_task_request.h>
+#include <dev/disk/isci/scil/scif_controller.h>
+#include <dev/disk/isci/scil/scif_domain.h>
+#include <dev/disk/isci/scil/scif_user_callback.h>
+
+#include <dev/disk/isci/scil/scic_port.h>
+#include <dev/disk/isci/scil/scic_phy.h>
+
+static void
+isci_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb)
+{
+    kfree(ccb, M_TEMP);
+}
+
+/**
+ * @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->has_been_scanned) {
+			/* The sim object has been scanned at least once
+			 *  already.  In that case, create a CCB to instruct
+			 *  CAM to rescan this device.
+			 * If the sim object has not been scanned, this device
+			 *  will get scanned as part of the initial scan.
+			 */
+			union ccb *ccb = xpt_alloc_ccb();
+
+			xpt_create_path(&ccb->ccb_h.path, xpt_periph,
+			    cam_sim_path(isci_controller->sim),
+			    isci_remote_device->index, CAM_LUN_WILDCARD);
+
+			xpt_setup_ccb(&ccb->ccb_h, ccb->ccb_h.path,
+			    5/*priority (low)*/);
+			ccb->ccb_h.func_code = XPT_SCAN_LUN;
+			ccb->ccb_h.cbfcnp = isci_cam_rescan_callback;
+			ccb->crcn.flags = CAM_FLAG_NONE;
+			xpt_action(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,
+		    (SCI_TASK_STATUS)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,
+		    (SCI_TASK_STATUS)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 *device)
+{
+	if (TAILQ_EMPTY(&device->queued_ccbs)) {
+		lun_id_t lun;
+
+		for (lun = 0; lun < ISCI_MAX_LUN; lun++)
+			isci_remote_device_release_lun_queue(device, lun);
+	} else {
+		struct ccb_hdr *ccb_h;
+
+		ccb_h = TAILQ_FIRST(&device->queued_ccbs);
+		TAILQ_REMOVE(&device->queued_ccbs, ccb_h, sim_links.tqe);
+		ccb_h->status &= ~CAM_SIM_QUEUED;
+		isci_log_message(1, "ISCI", "release %p %x\n", ccb_h,
+		    ((union ccb*)ccb_h)->csio.cdb_io.cdb_bytes[0]);
+		isci_io_request_execute_scsi_io((union ccb *)ccb_h,
+		    device->domain->controller);
+	}
+}
diff --git a/sys/dev/disk/isci/isci_sysctl.c b/sys/dev/disk/isci/isci_sysctl.c
new file mode 100644
index 0000000..76fd5c2
--- /dev/null
+++ b/sys/dev/disk/isci/isci_sysctl.c
@@ -0,0 +1,233 @@
+/*-
+ * 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: src/sys/dev/isci/isci_sysctl.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+#include <dev/disk/isci/isci.h>
+
+#include <sys/sysctl.h>
+
+#include <dev/disk/isci/scil/scif_controller.h>
+#include <dev/disk/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) {
+				lockmgr(&controller->lock, LK_EXCLUSIVE);
+				isci_remote_device_reset(remote_device, NULL);
+				lockmgr(&controller->lock, LK_RELEASE);
+			}
+		}
+		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;
+	struct sysctl_oid *sysctl_tree;
+
+	sysctl_ctx_init(&isci->sysctl_ctx);
+	sysctl_ctx = &isci->sysctl_ctx;
+	isci->sysctl_tree = sysctl_tree = SYSCTL_ADD_NODE(&isci->sysctl_ctx,
+	    SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO,
+	    device_get_nameunit(isci->device), CTLFLAG_RD, 0, "");
+
+	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 --git a/sys/dev/disk/isci/isci_task_request.c b/sys/dev/disk/isci/isci_task_request.c
new file mode 100644
index 0000000..fee41f0
--- /dev/null
+++ b/sys/dev/disk/isci/isci_task_request.c
@@ -0,0 +1,256 @@
+/*-
+ * 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: src/sys/dev/isci/isci_task_request.c,v 1.2 2012/03/30 22:52:08 dim Exp $
+ */
+
+#include <dev/disk/isci/isci.h>
+
+#include <dev/disk/isci/scil/scif_controller.h>
+#include <dev/disk/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 ((int)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 --git a/sys/dev/disk/isci/isci_timer.c b/sys/dev/disk/isci/isci_timer.c
new file mode 100644
index 0000000..c600b26
--- /dev/null
+++ b/sys/dev/disk/isci/isci_timer.c
@@ -0,0 +1,169 @@
+/*-
+ * 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: src/sys/dev/isci/isci_timer.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+#include <dev/disk/isci/isci.h>
+
+#include <dev/disk/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) {
+		lockmgr(timer->lock, LK_EXCLUSIVE);
+		timer->callback(timer->cookie);
+		lockmgr(timer->lock, LK_RELEASE);
+	}
+}
+
+/**
+ * @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_mp(&timer->callout);
+
+	timer->lock = &isci_controller->lock;
+	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 --git a/sys/dev/disk/isci/sci_environment.h b/sys/dev/disk/isci/sci_environment.h
new file mode 100644
index 0000000..bae1ee5
--- /dev/null
+++ b/sys/dev/disk/isci/sci_environment.h
@@ -0,0 +1 @@
+/* empty file for now. compiler needs it */
diff --git a/sys/dev/disk/isci/scil/intel_ata.h b/sys/dev/disk/isci/scil/intel_ata.h
new file mode 100644
index 0000000..5bc10f7
--- /dev/null
+++ b/sys/dev/disk/isci/scil/intel_ata.h
@@ -0,0 +1,653 @@
+/*-
+ * 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: src/sys/dev/isci/scil/intel_ata.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+/**
+ * @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/disk/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 --git a/sys/dev/disk/isci/scil/intel_pci.h b/sys/dev/disk/isci/scil/intel_pci.h
new file mode 100644
index 0000000..b92a8dc
--- /dev/null
+++ b/sys/dev/disk/isci/scil/intel_pci.h
@@ -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: src/sys/dev/isci/scil/intel_pci.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#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/disk/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 --git a/sys/dev/disk/isci/scil/intel_sas.h b/sys/dev/disk/isci/scil/intel_sas.h
new file mode 100644
index 0000000..653d5ad
--- /dev/null
+++ b/sys/dev/disk/isci/scil/intel_sas.h
@@ -0,0 +1,976 @@
+/*-
+ * 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: src/sys/dev/isci/scil/intel_sas.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#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/disk/isci/types.h>
+#include <dev/disk/isci/scil/intel_sata.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/intel_sat.h b/sys/dev/disk/isci/scil/intel_sat.h
new file mode 100644
index 0000000..968a5d0
--- /dev/null
+++ b/sys/dev/disk/isci/scil/intel_sat.h
@@ -0,0 +1,93 @@
+/*-
+ * 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: src/sys/dev/isci/scil/intel_sat.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#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 --git a/sys/dev/disk/isci/scil/intel_sata.h b/sys/dev/disk/isci/scil/intel_sata.h
new file mode 100644
index 0000000..23df470
--- /dev/null
+++ b/sys/dev/disk/isci/scil/intel_sata.h
@@ -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: src/sys/dev/isci/scil/intel_sata.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SATA_H_
+#define _SATA_H_
+
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/intel_scsi.h b/sys/dev/disk/isci/scil/intel_scsi.h
new file mode 100644
index 0000000..516b60e
--- /dev/null
+++ b/sys/dev/disk/isci/scil/intel_scsi.h
@@ -0,0 +1,539 @@
+/*-
+ * 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: src/sys/dev/isci/scil/intel_scsi.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+/**
+ * @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 --git a/sys/dev/disk/isci/scil/sati.c b/sys/dev/disk/isci/scil/sati.c
new file mode 100644
index 0000000..d29387e
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati.c
@@ -0,0 +1,1249 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sati.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @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/disk/isci/scil/sati.h>
+#include <dev/disk/isci/scil/sati_callbacks.h>
+#include <dev/disk/isci/scil/sati_util.h>
+#include <dev/disk/isci/scil/sati_report_luns.h>
+#include <dev/disk/isci/scil/sati_inquiry.h>
+#include <dev/disk/isci/scil/sati_mode_sense_6.h>
+#include <dev/disk/isci/scil/sati_mode_sense_10.h>
+#include <dev/disk/isci/scil/sati_mode_select.h>
+#include <dev/disk/isci/scil/sati_test_unit_ready.h>
+#include <dev/disk/isci/scil/sati_read_capacity.h>
+#include <dev/disk/isci/scil/sati_read.h>
+#include <dev/disk/isci/scil/sati_write.h>
+#include <dev/disk/isci/scil/sati_verify.h>
+#include <dev/disk/isci/scil/sati_synchronize_cache.h>
+#include <dev/disk/isci/scil/sati_lun_reset.h>
+#include <dev/disk/isci/scil/sati_start_stop_unit.h>
+#include <dev/disk/isci/scil/sati_request_sense.h>
+#include <dev/disk/isci/scil/sati_write_long.h>
+#include <dev/disk/isci/scil/sati_reassign_blocks.h>
+#include <dev/disk/isci/scil/sati_log_sense.h>
+#include <dev/disk/isci/scil/sati_abort_task_set.h>
+#include <dev/disk/isci/scil/sati_unmap.h>
+#include <dev/disk/isci/scil/sati_passthrough.h>
+#include <dev/disk/isci/scil/sati_write_and_verify.h>
+#include <dev/disk/isci/scil/sati_read_buffer.h>
+#include <dev/disk/isci/scil/sati_write_buffer.h>
+#include <dev/disk/isci/scil/intel_ata.h>
+#include <dev/disk/isci/scil/intel_scsi.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati.h b/sys/dev/disk/isci/scil/sati.h
new file mode 100644
index 0000000..e1bbf16
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati.h
@@ -0,0 +1,270 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sati.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#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/disk/isci/scil/sati_types.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_abort_task_set.c b/sys/dev/disk/isci/scil/sati_abort_task_set.c
new file mode 100644
index 0000000..7209984
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_abort_task_set.c
@@ -0,0 +1,175 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sati_abort_task_set.c,v 1.2 2012/02/09 17:50:24 jimharris Exp $
+ */
+
+/**
+ * @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/disk/isci/scil/sati_abort_task_set.h>
+#include <dev/disk/isci/scil/sati_callbacks.h>
+#include <dev/disk/isci/scil/sati_util.h>
+#include <dev/disk/isci/scil/sati.h>
+#include <dev/disk/isci/scil/intel_ata.h>
+#include <dev/disk/isci/scil/intel_scsi.h>
+#include <dev/disk/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_IO_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_IO_FAILURE_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_IO_FAILURE_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 --git a/sys/dev/disk/isci/scil/sati_abort_task_set.h b/sys/dev/disk/isci/scil/sati_abort_task_set.h
new file mode 100644
index 0000000..09d79c2
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_abort_task_set.h
@@ -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: src/sys/dev/isci/scil/sati_abort_task_set.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#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/disk/isci/scil/sati_types.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_atapi.c b/sys/dev/disk/isci/scil/sati_atapi.c
new file mode 100644
index 0000000..860e8de
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_atapi.c
@@ -0,0 +1,256 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sati_atapi.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @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/disk/isci/scil/sati.h>
+#include <dev/disk/isci/scil/sati_util.h>
+#include <dev/disk/isci/scil/sati_atapi.h>
+#include <dev/disk/isci/scil/sati_callbacks.h>
+#include <dev/disk/isci/scil/intel_ata.h>
+#include <dev/disk/isci/scil/intel_scsi.h>
+#include <dev/disk/isci/scil/intel_sat.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_atapi.h b/sys/dev/disk/isci/scil/sati_atapi.h
new file mode 100644
index 0000000..82271bb
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_atapi.h
@@ -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: src/sys/dev/isci/scil/sati_atapi.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#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/disk/isci/scil/sati_types.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_callbacks.h b/sys/dev/disk/isci/scil/sati_callbacks.h
new file mode 100644
index 0000000..053cc08
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_callbacks.h
@@ -0,0 +1,480 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sati_callbacks.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#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/disk/isci/scil/sati_types.h>
+#include <dev/disk/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/disk/isci/scil/sati_callbacks_implementation.h>
+
+#else // SATI_DEFAULT_DECLARATION
+
+#include <dev/disk/isci/scil/scif_sas_sati_binding.h>
+#endif // SATI_DEFAULT_DECLARATION
+
+#endif // _SATI_CALLBACKS_H_
diff --git a/sys/dev/disk/isci/scil/sati_design.h b/sys/dev/disk/isci/scil/sati_design.h
new file mode 100644
index 0000000..b14d827
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_design.h
@@ -0,0 +1,168 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sati_design.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SATI_DESIGN_H_
+#define _SATI_DESIGN_H_
+
+/**
+@page sati_design_page SATI High Level Design
+
+<b>Authors:</b>
+- Nathan Marushak
+
+@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.
+
+@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()
+
+@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.
+
+@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.
+
+@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.
+
+@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).
+
+@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.
+
+@image html Use_Case_Diagram__SATI__SATI_-_SAT_Specific.jpg "SCSI-to-ATA Translation Specific Use Cases"
+
+@section sati_class_hierarchy Class Hierarchy
+
+@image html Class_Diagram__SATI__Class_Diagram.jpg "SATI Class Diagram"
+
+@section sati_sequences Sequence Diagrams
+
+@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.
+
+@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.
+
+@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.
+
+@image html Sequence_Diagram__General_Data_Translation_Sequence__General_Data_Translation_Sequence.jpg "General Data Translation Sequence"
+
+*/
+
+#endif // _SATI_DESIGN_H_
diff --git a/sys/dev/disk/isci/scil/sati_device.c b/sys/dev/disk/isci/scil/sati_device.c
new file mode 100644
index 0000000..45dc1ee
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_device.c
@@ -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.
+ *
+ * $FreeBSD: src/sys/dev/isci/scil/sati_device.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @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/disk/isci/scil/sati_device.h>
+#include <dev/disk/isci/scil/sci_util.h>  // Move this file.
+#include <dev/disk/isci/scil/sati_unmap.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_device.h b/sys/dev/disk/isci/scil/sati_device.h
new file mode 100644
index 0000000..bc6cf17
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_device.h
@@ -0,0 +1,202 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sati_device.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#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/disk/isci/scil/sati_types.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_inquiry.c b/sys/dev/disk/isci/scil/sati_inquiry.c
new file mode 100644
index 0000000..72be5aa
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_inquiry.c
@@ -0,0 +1,797 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sati_inquiry.c,v 1.2 2012/05/04 23:45:34 jimharris Exp $
+ */
+
+/**
+ * @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/disk/isci/scil/sati_inquiry.h>
+#include <dev/disk/isci/scil/sati_callbacks.h>
+#include <dev/disk/isci/scil/sati_util.h>
+#include <dev/disk/isci/scil/intel_ata.h>
+#include <dev/disk/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 < 64; 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 --git a/sys/dev/disk/isci/scil/sati_inquiry.h b/sys/dev/disk/isci/scil/sati_inquiry.h
new file mode 100644
index 0000000..44ad3ce
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_inquiry.h
@@ -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: src/sys/dev/isci/scil/sati_inquiry.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#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/disk/isci/scil/sati_types.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_log_sense.c b/sys/dev/disk/isci/scil/sati_log_sense.c
new file mode 100644
index 0000000..7d8d296
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_log_sense.c
@@ -0,0 +1,805 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sati_log_sense.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+* @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/disk/isci/scil/sati_log_sense.h>
+#include <dev/disk/isci/scil/sati_callbacks.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_log_sense.h b/sys/dev/disk/isci/scil/sati_log_sense.h
new file mode 100644
index 0000000..b6ca6b6
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_log_sense.h
@@ -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: src/sys/dev/isci/scil/sati_log_sense.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+/**
+ * @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/disk/isci/scil/intel_scsi.h>
+#include <dev/disk/isci/scil/sati_types.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_lun_reset.c b/sys/dev/disk/isci/scil/sati_lun_reset.c
new file mode 100644
index 0000000..fa4d93d
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_lun_reset.c
@@ -0,0 +1,120 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sati_lun_reset.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains the method implementations required to
+ *        translate the SCSI lun reset command.
+ */
+
+#if !defined(DISABLE_SATI_TASK_MANAGEMENT)
+
+#include <dev/disk/isci/scil/sati_lun_reset.h>
+#include <dev/disk/isci/scil/sati_callbacks.h>
+#include <dev/disk/isci/scil/sati_util.h>
+#include <dev/disk/isci/scil/intel_ata.h>
+#include <dev/disk/isci/scil/intel_scsi.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_lun_reset.h b/sys/dev/disk/isci/scil/sati_lun_reset.h
new file mode 100644
index 0000000..a3d9d28
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_lun_reset.h
@@ -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: src/sys/dev/isci/scil/sati_lun_reset.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#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/disk/isci/scil/sati_types.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_mode_pages.c b/sys/dev/disk/isci/scil/sati_mode_pages.c
new file mode 100644
index 0000000..2a67373
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_mode_pages.c
@@ -0,0 +1,370 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sati_mode_pages.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @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/disk/isci/scil/sati_types.h>
+
+#if defined(ENABLE_SATI_MODE_PAGES)
+
+#include <dev/disk/isci/scil/sati_mode_pages.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_mode_pages.h b/sys/dev/disk/isci/scil/sati_mode_pages.h
new file mode 100644
index 0000000..37f8f5a
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_mode_pages.h
@@ -0,0 +1,143 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sati_mode_pages.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+/**
+ * @file
+ * @brief This file contains the mode page constants and members that are
+ *        supported by this translation implementation.
+ */
+
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_mode_select.c b/sys/dev/disk/isci/scil/sati_mode_select.c
new file mode 100644
index 0000000..22582eb
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_mode_select.c
@@ -0,0 +1,1114 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sati_mode_select.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @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/disk/isci/scil/sati_mode_select.h>
+#include <dev/disk/isci/scil/sati_mode_pages.h>
+#include <dev/disk/isci/scil/sati_callbacks.h>
+#include <dev/disk/isci/scil/sci_object.h>
+#include <dev/disk/isci/scil/sati_translator_sequence.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_mode_select.h b/sys/dev/disk/isci/scil/sati_mode_select.h
new file mode 100644
index 0000000..ba0519c
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_mode_select.h
@@ -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: src/sys/dev/isci/scil/sati_mode_select.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#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/disk/isci/scil/sati_types.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_mode_sense.c b/sys/dev/disk/isci/scil/sati_mode_sense.c
new file mode 100644
index 0000000..261f782
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_mode_sense.c
@@ -0,0 +1,835 @@
+ /*-
+ * 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: src/sys/dev/isci/scil/sati_mode_sense.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @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/disk/isci/scil/sati_mode_sense.h>
+#include <dev/disk/isci/scil/sati_mode_pages.h>
+#include <dev/disk/isci/scil/sati_callbacks.h>
+#include <dev/disk/isci/scil/sati_util.h>
+#include <dev/disk/isci/scil/intel_scsi.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_mode_sense.h b/sys/dev/disk/isci/scil/sati_mode_sense.h
new file mode 100644
index 0000000..f5affc0
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_mode_sense.h
@@ -0,0 +1,145 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sati_mode_sense.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#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/disk/isci/scil/sati_types.h>
+#include <dev/disk/isci/scil/sati_translator_sequence.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_mode_sense_10.c b/sys/dev/disk/isci/scil/sati_mode_sense_10.c
new file mode 100644
index 0000000..8ca5db2
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_mode_sense_10.c
@@ -0,0 +1,507 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sati_mode_sense_10.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @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/disk/isci/scil/sati_mode_sense.h>
+#include <dev/disk/isci/scil/sati_mode_sense_10.h>
+#include <dev/disk/isci/scil/sati_mode_pages.h>
+#include <dev/disk/isci/scil/sati_callbacks.h>
+#include <dev/disk/isci/scil/sati_util.h>
+#include <dev/disk/isci/scil/intel_scsi.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_mode_sense_10.h b/sys/dev/disk/isci/scil/sati_mode_sense_10.h
new file mode 100644
index 0000000..8c69d9f
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_mode_sense_10.h
@@ -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: src/sys/dev/isci/scil/sati_mode_sense_10.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#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/disk/isci/scil/sati_types.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_mode_sense_6.c b/sys/dev/disk/isci/scil/sati_mode_sense_6.c
new file mode 100644
index 0000000..e12ec63
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_mode_sense_6.c
@@ -0,0 +1,427 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sati_mode_sense_6.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @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/disk/isci/scil/sati_mode_sense.h>
+#include <dev/disk/isci/scil/sati_mode_sense_6.h>
+#include <dev/disk/isci/scil/sati_mode_pages.h>
+#include <dev/disk/isci/scil/sati_callbacks.h>
+#include <dev/disk/isci/scil/sati_util.h>
+#include <dev/disk/isci/scil/intel_scsi.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_mode_sense_6.h b/sys/dev/disk/isci/scil/sati_mode_sense_6.h
new file mode 100644
index 0000000..393595f
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_mode_sense_6.h
@@ -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: src/sys/dev/isci/scil/sati_mode_sense_6.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#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/disk/isci/scil/sati_types.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_move.c b/sys/dev/disk/isci/scil/sati_move.c
new file mode 100644
index 0000000..f233835
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_move.c
@@ -0,0 +1,614 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sati_move.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @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/disk/isci/scil/sati_move.h>
+#include <dev/disk/isci/scil/sati_callbacks.h>
+#include <dev/disk/isci/scil/sati_translator_sequence.h>
+#include <dev/disk/isci/scil/sati_util.h>
+#include <dev/disk/isci/scil/intel_ata.h>
+#include <dev/disk/isci/scil/intel_scsi.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_move.h b/sys/dev/disk/isci/scil/sati_move.h
new file mode 100644
index 0000000..7fe8755
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_move.h
@@ -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: src/sys/dev/isci/scil/sati_move.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#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/disk/isci/scil/sati_types.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_passthrough.c b/sys/dev/disk/isci/scil/sati_passthrough.c
new file mode 100644
index 0000000..663f2ff
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_passthrough.c
@@ -0,0 +1,464 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sati_passthrough.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ *        translate the SCSI passthru command.
+ */
+
+#if !defined(DISABLE_SATI_PASSTHROUGH)
+
+#include <dev/disk/isci/scil/sati.h>
+#include <dev/disk/isci/scil/sati_passthrough.h>
+#include <dev/disk/isci/scil/sati_util.h>
+#include <dev/disk/isci/scil/sati_callbacks.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_passthrough.h b/sys/dev/disk/isci/scil/sati_passthrough.h
new file mode 100644
index 0000000..14a6f13
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_passthrough.h
@@ -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: src/sys/dev/isci/scil/sati_passthrough.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#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/disk/isci/scil/sati_types.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_read.c b/sys/dev/disk/isci/scil/sati_read.c
new file mode 100644
index 0000000..63bb41f
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_read.c
@@ -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.
+ *
+ * $FreeBSD: src/sys/dev/isci/scil/sati_read.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ *        translate the SCSI read (6, 10, 12, or 16-byte) commands.
+ */
+
+#include <dev/disk/isci/scil/sati_move.h>
+#include <dev/disk/isci/scil/sati_read.h>
+#include <dev/disk/isci/scil/sati_callbacks.h>
+#include <dev/disk/isci/scil/sati_util.h>
+
+#include <dev/disk/isci/scil/intel_ata.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_read.h b/sys/dev/disk/isci/scil/sati_read.h
new file mode 100644
index 0000000..cef1094
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_read.h
@@ -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: src/sys/dev/isci/scil/sati_read.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#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/disk/isci/scil/sati_types.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_read_buffer.c b/sys/dev/disk/isci/scil/sati_read_buffer.c
new file mode 100644
index 0000000..6d9a39d
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_read_buffer.c
@@ -0,0 +1,234 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sati_read_buffer.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+* @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/disk/isci/scil/sati_read_buffer.h>
+#include <dev/disk/isci/scil/sati_callbacks.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_read_buffer.h b/sys/dev/disk/isci/scil/sati_read_buffer.h
new file mode 100644
index 0000000..d4d6023
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_read_buffer.h
@@ -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: src/sys/dev/isci/scil/sati_read_buffer.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+/**
+* @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/disk/isci/scil/sati_types.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_read_capacity.c b/sys/dev/disk/isci/scil/sati_read_capacity.c
new file mode 100644
index 0000000..f853fe3
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_read_capacity.c
@@ -0,0 +1,368 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sati_read_capacity.c,v 1.2 2012/03/29 15:43:07 jimharris Exp $
+ */
+
+/**
+ * @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/disk/isci/scil/sati_read_capacity.h>
+#include <dev/disk/isci/scil/sati_callbacks.h>
+#include <dev/disk/isci/scil/sati_util.h>
+#include <dev/disk/isci/scil/intel_ata.h>
+#include <dev/disk/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));
+
+   //Explicitly set byte 12 to 0.  SATI requires that all bytes in the data
+   //response be explicitly set to some value.
+   sati_set_data_byte(sequence, scsi_io, 12, 0);
+
+   //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 --git a/sys/dev/disk/isci/scil/sati_read_capacity.h b/sys/dev/disk/isci/scil/sati_read_capacity.h
new file mode 100644
index 0000000..c62ce78
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_read_capacity.h
@@ -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: src/sys/dev/isci/scil/sati_read_capacity.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#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/disk/isci/scil/sati_types.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_reassign_blocks.c b/sys/dev/disk/isci/scil/sati_reassign_blocks.c
new file mode 100644
index 0000000..750b378
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_reassign_blocks.c
@@ -0,0 +1,620 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sati_reassign_blocks.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ *        translate the SCSI reassign blocks command.
+ */
+
+#if !defined(DISABLE_SATI_REASSIGN_BLOCKS)
+
+#include <dev/disk/isci/scil/sati_reassign_blocks.h>
+#include <dev/disk/isci/scil/sati_callbacks.h>
+#include <dev/disk/isci/scil/sati_move.h>
+#include <dev/disk/isci/scil/sati_write.h>
+#include <dev/disk/isci/scil/sati_translator_sequence.h>
+#include <dev/disk/isci/scil/sati_util.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_reassign_blocks.h b/sys/dev/disk/isci/scil/sati_reassign_blocks.h
new file mode 100644
index 0000000..309f22f
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_reassign_blocks.h
@@ -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: src/sys/dev/isci/scil/sati_reassign_blocks.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#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/disk/isci/scil/sati_types.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_report_luns.c b/sys/dev/disk/isci/scil/sati_report_luns.c
new file mode 100644
index 0000000..65fe6ff
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_report_luns.c
@@ -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.
+ *
+ * $FreeBSD: src/sys/dev/isci/scil/sati_report_luns.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ *        translate the SCSI REPORT LUNS command.
+ */
+
+#if !defined(DISABLE_SATI_REPORT_LUNS)
+
+#include <dev/disk/isci/scil/sati_report_luns.h>
+#include <dev/disk/isci/scil/sati_callbacks.h>
+#include <dev/disk/isci/scil/sati_util.h>
+#include <dev/disk/isci/scil/intel_ata.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_report_luns.h b/sys/dev/disk/isci/scil/sati_report_luns.h
new file mode 100644
index 0000000..af6395f
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_report_luns.h
@@ -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: src/sys/dev/isci/scil/sati_report_luns.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#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/disk/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 --git a/sys/dev/disk/isci/scil/sati_request_sense.c b/sys/dev/disk/isci/scil/sati_request_sense.c
new file mode 100644
index 0000000..9b43a7b
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_request_sense.c
@@ -0,0 +1,351 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sati_request_sense.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @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/disk/isci/scil/sati_request_sense.h>
+#include <dev/disk/isci/scil/sati_device.h>
+#include <dev/disk/isci/scil/sati_util.h>
+#include <dev/disk/isci/scil/intel_scsi.h>
+#include <dev/disk/isci/scil/intel_ata.h>
+#include <dev/disk/isci/scil/intel_sat.h>
+#include <dev/disk/isci/scil/sati_callbacks.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_request_sense.h b/sys/dev/disk/isci/scil/sati_request_sense.h
new file mode 100644
index 0000000..c1419ef
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_request_sense.h
@@ -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: src/sys/dev/isci/scil/sati_request_sense.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+/**
+ * @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/disk/isci/scil/sati_types.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_start_stop_unit.c b/sys/dev/disk/isci/scil/sati_start_stop_unit.c
new file mode 100644
index 0000000..ea512c8
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_start_stop_unit.c
@@ -0,0 +1,402 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sati_start_stop_unit.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @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/disk/isci/scil/sati_start_stop_unit.h>
+#include <dev/disk/isci/scil/sati_util.h>
+#include <dev/disk/isci/scil/sati_callbacks.h>
+#include <dev/disk/isci/scil/intel_ata.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_start_stop_unit.h b/sys/dev/disk/isci/scil/sati_start_stop_unit.h
new file mode 100644
index 0000000..b86d937
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_start_stop_unit.h
@@ -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: src/sys/dev/isci/scil/sati_start_stop_unit.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#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/disk/isci/scil/intel_scsi.h>
+#include <dev/disk/isci/scil/sati_types.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_synchronize_cache.c b/sys/dev/disk/isci/scil/sati_synchronize_cache.c
new file mode 100644
index 0000000..0dbff78
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_synchronize_cache.c
@@ -0,0 +1,117 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sati_synchronize_cache.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @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/disk/isci/scil/sati_synchronize_cache.h>
+#include <dev/disk/isci/scil/sati_callbacks.h>
+#include <dev/disk/isci/scil/sati_util.h>
+#include <dev/disk/isci/scil/sati_translator_sequence.h>
+
+#include <dev/disk/isci/scil/intel_ata.h>
+#include <dev/disk/isci/scil/intel_scsi.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_synchronize_cache.h b/sys/dev/disk/isci/scil/sati_synchronize_cache.h
new file mode 100644
index 0000000..d239aab
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_synchronize_cache.h
@@ -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: src/sys/dev/isci/scil/sati_synchronize_cache.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#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/disk/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 --git a/sys/dev/disk/isci/scil/sati_test_unit_ready.c b/sys/dev/disk/isci/scil/sati_test_unit_ready.c
new file mode 100644
index 0000000..1f97e41
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_test_unit_ready.c
@@ -0,0 +1,184 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sati_test_unit_ready.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @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/disk/isci/scil/sati_test_unit_ready.h>
+#include <dev/disk/isci/scil/sati_util.h>
+#include <dev/disk/isci/scil/sati_callbacks.h>
+#include <dev/disk/isci/scil/intel_ata.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_test_unit_ready.h b/sys/dev/disk/isci/scil/sati_test_unit_ready.h
new file mode 100644
index 0000000..cf6c40f
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_test_unit_ready.h
@@ -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: src/sys/dev/isci/scil/sati_test_unit_ready.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#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/disk/isci/scil/sati_types.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_translator_sequence.h b/sys/dev/disk/isci/scil/sati_translator_sequence.h
new file mode 100644
index 0000000..98135ef
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_translator_sequence.h
@@ -0,0 +1,360 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sati_translator_sequence.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#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/disk/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 --git a/sys/dev/disk/isci/scil/sati_types.h b/sys/dev/disk/isci/scil/sati_types.h
new file mode 100644
index 0000000..51044d0
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_types.h
@@ -0,0 +1,151 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sati_types.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#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/disk/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 --git a/sys/dev/disk/isci/scil/sati_unmap.c b/sys/dev/disk/isci/scil/sati_unmap.c
new file mode 100644
index 0000000..a049812
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_unmap.c
@@ -0,0 +1,608 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sati_unmap.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ *        translate the SCSI unmap command.
+ */
+
+#if !defined(DISABLE_SATI_UNMAP)
+
+#include <dev/disk/isci/scil/sati_unmap.h>
+#include <dev/disk/isci/scil/sati_callbacks.h>
+#include <dev/disk/isci/scil/sati_translator_sequence.h>
+#include <dev/disk/isci/scil/sati_util.h>
+#include <dev/disk/isci/scil/intel_ata.h>
+#include <dev/disk/isci/scil/intel_scsi.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_unmap.h b/sys/dev/disk/isci/scil/sati_unmap.h
new file mode 100644
index 0000000..ea1128a
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_unmap.h
@@ -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: src/sys/dev/isci/scil/sati_unmap.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#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/disk/isci/scil/sati_types.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_util.c b/sys/dev/disk/isci/scil/sati_util.c
new file mode 100644
index 0000000..5fcb1ea
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_util.c
@@ -0,0 +1,2004 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sati_util.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @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/disk/isci/scil/sati_util.h>
+#include <dev/disk/isci/scil/sati_callbacks.h>
+#include <dev/disk/isci/scil/intel_scsi.h>
+#include <dev/disk/isci/scil/intel_ata.h>
+#include <dev/disk/isci/scil/intel_sat.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_util.h b/sys/dev/disk/isci/scil/sati_util.h
new file mode 100644
index 0000000..b6c0110
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_util.h
@@ -0,0 +1,392 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sati_util.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#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/disk/isci/scil/sati_types.h>
+#include <dev/disk/isci/scil/sati_translator_sequence.h>
+
+#include <dev/disk/isci/scil/intel_sata.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_verify.c b/sys/dev/disk/isci/scil/sati_verify.c
new file mode 100644
index 0000000..9a4ecfe
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_verify.c
@@ -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: src/sys/dev/isci/scil/sati_verify.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @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/disk/isci/scil/sati_verify.h>
+#include <dev/disk/isci/scil/sati_callbacks.h>
+#include <dev/disk/isci/scil/sati_util.h>
+#include <dev/disk/isci/scil/sati_move.h>
+
+#include <dev/disk/isci/scil/intel_ata.h>
+#include <dev/disk/isci/scil/intel_scsi.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_verify.h b/sys/dev/disk/isci/scil/sati_verify.h
new file mode 100644
index 0000000..dbb55f8
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_verify.h
@@ -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: src/sys/dev/isci/scil/sati_verify.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#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/disk/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 --git a/sys/dev/disk/isci/scil/sati_write.c b/sys/dev/disk/isci/scil/sati_write.c
new file mode 100644
index 0000000..2d93153
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_write.c
@@ -0,0 +1,319 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sati_write.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ *        translate the SCSI write (6, 10, 12, or 16-byte) commands.
+ */
+
+#include <dev/disk/isci/scil/sati_move.h>
+#include <dev/disk/isci/scil/sati_write.h>
+#include <dev/disk/isci/scil/sati_callbacks.h>
+#include <dev/disk/isci/scil/sati_util.h>
+
+#include <dev/disk/isci/scil/intel_ata.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_write.h b/sys/dev/disk/isci/scil/sati_write.h
new file mode 100644
index 0000000..53aae28
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_write.h
@@ -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: src/sys/dev/isci/scil/sati_write.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#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/disk/isci/scil/sati_types.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_write_and_verify.c b/sys/dev/disk/isci/scil/sati_write_and_verify.c
new file mode 100644
index 0000000..4aebd83
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_write_and_verify.c
@@ -0,0 +1,242 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sati_write_and_verify.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+* @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/disk/isci/scil/sati_write_and_verify.h>
+#include <dev/disk/isci/scil/sati_write.h>
+#include <dev/disk/isci/scil/sati_verify.h>
+#include <dev/disk/isci/scil/sati_callbacks.h>
+#include <dev/disk/isci/scil/sati_util.h>
+
+#include <dev/disk/isci/scil/intel_ata.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_write_and_verify.h b/sys/dev/disk/isci/scil/sati_write_and_verify.h
new file mode 100644
index 0000000..78b1209
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_write_and_verify.h
@@ -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: src/sys/dev/isci/scil/sati_write_and_verify.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+/**
+* @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/disk/isci/scil/sati_types.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_write_buffer.c b/sys/dev/disk/isci/scil/sati_write_buffer.c
new file mode 100644
index 0000000..ca6a579
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_write_buffer.c
@@ -0,0 +1,253 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sati_write_buffer.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+* @file
+* @brief This file contains the method implementations to translate
+*        SCSI Write Buffer command based of the SAT2v07 spec.
+*/
+
+#include <dev/disk/isci/scil/sati_write_buffer.h>
+#include <dev/disk/isci/scil/sati_callbacks.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_write_buffer.h b/sys/dev/disk/isci/scil/sati_write_buffer.h
new file mode 100644
index 0000000..0df2e0a
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_write_buffer.h
@@ -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: src/sys/dev/isci/scil/sati_write_buffer.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+/**
+* @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/disk/isci/scil/sati_types.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_write_long.c b/sys/dev/disk/isci/scil/sati_write_long.c
new file mode 100644
index 0000000..f05ce0e
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_write_long.c
@@ -0,0 +1,258 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sati_write_long.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @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/disk/isci/scil/sati_write_long.h>
+#include <dev/disk/isci/scil/sati_device.h>
+#include <dev/disk/isci/scil/sati_util.h>
+#include <dev/disk/isci/scil/intel_scsi.h>
+#include <dev/disk/isci/scil/intel_ata.h>
+#include <dev/disk/isci/scil/intel_sat.h>
+#include <dev/disk/isci/scil/sati_callbacks.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sati_write_long.h b/sys/dev/disk/isci/scil/sati_write_long.h
new file mode 100644
index 0000000..6356f5c
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sati_write_long.h
@@ -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: src/sys/dev/isci/scil/sati_write_long.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+/**
+ * @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/disk/isci/scil/sati_types.h>
+#include <dev/disk/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 --git a/sys/dev/disk/isci/scil/sci_abstract_list.c b/sys/dev/disk/isci/scil/sci_abstract_list.c
new file mode 100644
index 0000000..3c5a603
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_abstract_list.c
@@ -0,0 +1,598 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_abstract_list.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @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/disk/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 --git a/sys/dev/disk/isci/scil/sci_abstract_list.h b/sys/dev/disk/isci/scil/sci_abstract_list.h
new file mode 100644
index 0000000..a8b2ded
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_abstract_list.h
@@ -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: src/sys/dev/isci/scil/sci_abstract_list.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+/**
+ * @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/disk/isci/scil/sci_types.h>
+
+//******************************************************************************
+//*
+//*     C O N S T A N T S
+//*
+//******************************************************************************
+
+//******************************************************************************
+//*
+//*     T Y P E S
+//*
+//******************************************************************************
+
+/**
+ * @struct SCI_ABSTRACT_ELEMENT
+ *
+ * @brief This object represents an element of a abstract list.
+ *        NOTE: This structure does not evenly align on a cache line
+ *              boundary.  If SSP specific code ends up using this list,
+ *              then it may be a good idea to force the alignment.  Now
+ *              it is more important to save the space.
+ */
+typedef struct SCI_ABSTRACT_ELEMENT
+{
+   /**
+    * This field points to the next item in the abstract_list.
+    */
+   struct SCI_ABSTRACT_ELEMENT * next_p;
+
+   /**
+    * This field points to the previous item in the abstract_list.
+    */
+   struct SCI_ABSTRACT_ELEMENT * previous_p;
+
+   /**
+    * This field points to the object the list is managing (i.e. the thing
+    * being listed).
+    */
+   void * object_p;
+
+} SCI_ABSTRACT_ELEMENT_T;
+
+/**
+ * @struct SCI_ABSTRACT_ELEMENT_LIST
+ *
+ * @brief This object represents an element list object.  It can have
+ *        elements added and removed from it.
+ */
+typedef struct SCI_ABSTRACT_ELEMENT_LIST
+{
+   /**
+    * Pointer to the front (head) of the list.
+    */
+   SCI_ABSTRACT_ELEMENT_T * front_p;
+
+   /**
+    * Pointer to the back (tail) of the list.
+    */
+   SCI_ABSTRACT_ELEMENT_T * back_p;
+
+   /**
+    * This field depicts the number of elements in this list.
+    * NOTE: It is possible to remove this field and replace it with a
+    *       linear walking of the list to determine the size, but since
+    *       there aren't many lists in the system we don't utilize much
+    *       space.
+    */
+   U32 size;
+
+} SCI_ABSTRACT_ELEMENT_LIST_T;
+
+/**
+ * @struct SCI_ABSTRACT_ELEMENT_POOL
+ *
+ * @brief This structure provides the pool of free abstract elements to be
+ *        utilized by an SCI_ABSTRACT_LIST.
+ */
+typedef struct SCI_ABSTRACT_ELEMENT_POOL
+{
+   /**
+    * Pointer to an array of elements to be managed by this pool.  This
+    * array acts as the memory store for the elements in the free pool or
+    * allocated out of the pool into an SCI_ABSTRACT_LIST.
+    */
+   SCI_ABSTRACT_ELEMENT_T * elements;
+
+   /**
+    * This field contains the maximum number of free elements for the pool.
+    * It is set at creation of the pool and should not be changed afterward.
+    */
+   U32 max_elements;
+
+   /**
+    * Pointer to the list of free elements that can be allocated from
+    * the pool.
+    */
+   struct SCI_ABSTRACT_ELEMENT_LIST  free_list;
+
+} SCI_ABSTRACT_ELEMENT_POOL_T;
+
+/**
+ * @struct SCI_ABSTRACT_LIST
+ *
+ * @brief This object provides the ability to queue any type of object or
+ *        even the same object multiple times.  The object must be provided
+ *        an element pool from which to draw free elements.
+ */
+typedef struct SCI_ABSTRACT_LIST
+{
+   /**
+    * This represents the elements currently managed by the list.
+    */
+   SCI_ABSTRACT_ELEMENT_LIST_T  elements;
+
+   /**
+    * This field contains elements that are currently available for
+    * allocation into the list of elements;
+    */
+   SCI_ABSTRACT_ELEMENT_POOL_T * free_pool;
+
+} SCI_ABSTRACT_LIST_T;
+
+//******************************************************************************
+//*
+//*     P R O T E C T E D   M E T H O D S
+//*
+//******************************************************************************
+
+void sci_abstract_element_pool_construct(
+   SCI_ABSTRACT_ELEMENT_POOL_T * pool,
+   SCI_ABSTRACT_ELEMENT_T      * list_elements,
+   int                           element_count
+);
+
+void sci_abstract_list_construct(
+   SCI_ABSTRACT_LIST_T         * list,
+   SCI_ABSTRACT_ELEMENT_POOL_T * free_pool
+);
+
+
+
+#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
+);
+
+
+/**
+ * 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
+);
+
+
+/**
+ * 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
+);
+
+
+/**
+ * This method will return FALSE if the list is not empty.
+ */
+BOOL sci_abstract_list_is_empty(
+   SCI_ABSTRACT_LIST_T * list_p
+);
+
+
+/**
+ * This method will return the number of elements queued in the list.
+ */
+U32 sci_abstract_list_size(
+   SCI_ABSTRACT_LIST_T * list_p
+);
+
+
+/**
+ * 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
+);
+
+
+/**
+ * This method simply prints the contents of the list.
+ */
+void  sci_abstract_list_print(
+   SCI_ABSTRACT_LIST_T * list_p
+);
+
+
+/**
+ * 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
+);
+
+
+/**
+ * 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
+);
+
+
+/**
+ * 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
+);
+
+
+
+/**
+ * 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
+);
+
+
+/**
+ * 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
+);
+
+
+
+/**
+ * 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
+);
+
+
+/**
+ * This method will add the objToAdd_p object to the list before the obj_p.
+ * NOTE: UNIMPLEMENTED
+ */
+void sci_abstract_list_insert(
+   SCI_ABSTRACT_LIST_T * list_p,
+   void * obj_p,
+   void * objToAdd_p
+);
+
+
+/**
+ * This method simply frees all the items from the list.
+ */
+void sci_abstract_list_clear(
+   SCI_ABSTRACT_LIST_T * 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
+);
+
+
+/**
+ * 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
+);
+
+
+//******************************************************************************
+//*
+//*     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
+);
+
+
+/**
+ * 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
+);
+
+
+/**
+ * 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
+);
+
+
+/**
+ * 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
+);
+
+
+/**
+ * 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
+);
+
+
+#else
+
+//******************************************************************************
+//*
+//*     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.
+ */
+#define sci_abstract_list_get_front(                                           \
+   list_p                                                                      \
+)                                                                              \
+((list_p)->elements.front_p)
+
+/**
+ * This method simply returns the object pointed to by the head (front) of
+ * the list.
+ */
+#define sci_abstract_list_front(                                               \
+   list_p                                                                      \
+)                                                                              \
+( ( (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.
+ */
+#define sci_abstract_list_back(                                                \
+   list_p                                                                      \
+)                                                                              \
+( ( (list_p)->elements.back_p ) ? ((list_p)->elements.back_p->object_p) : NULL )
+
+/**
+ * This method will return FALSE if the list is not empty.
+ */
+#define sci_abstract_list_is_empty(                                            \
+   list_p                                                                      \
+)                                                                              \
+( (list_p)->elements.front_p == NULL )
+
+/**
+ * This method will return the number of elements queued in the list.
+ */
+#define sci_abstract_list_size(                                                \
+   list_p                                                                      \
+)                                                                              \
+( (list_p)->elements.size )
+
+/**
+ * This method simply returns the next list element in the list.
+ */
+#define sci_abstract_list_get_next(                                            \
+   alElement_p                                                                 \
+)                                                                              \
+( (alElement_p)->next_p )
+
+/**
+ * This method simply prints the contents of the list.
+ */
+#define sci_abstract_list_print(                                               \
+   list_p                                                                      \
+)                                                                              \
+{                                                                              \
+   SCI_ABSTRACT_ELEMENT_T * alElement_p = list_p->elements.front_p;            \
+                                                                               \
+   while (alElement_p != NULL)                                                 \
+   {                                                                           \
+      /* 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));                                  \
+                                                                               \
+      alElement_p = alElement_p->next_p;                                       \
+   }                                                                           \
+}
+
+/**
+ * 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.
+ */
+#define sci_abstract_list_find(                                                \
+   list_p,                                                                     \
+   obj_p                                                                       \
+)                                                                              \
+({                                                                             \
+   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.
+ */
+#define sci_abstract_list_popback(                                             \
+   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);                     \
+   }                                                                           \
+                                                                               \
+   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.
+ */
+#define sci_abstract_list_popfront(                                            \
+   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);                     \
+   }                                                                           \
+                                                                               \
+   obj_p;                                                                      \
+})
+
+/**
+ * This method will erase (remove) all instances of the supplied object from
+ * anywhere in the list.
+ */
+#define sci_abstract_list_erase(                                               \
+   list_p,                                                                     \
+   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);                  \
+      }                                                                        \
+   }                                                                           \
+}
+
+/**
+ * This method simply adds a LIST_ELEMENT for the supplied object to the back
+ * (tail) of the supplied list.
+ */
+#define sci_abstract_list_pushback(                                            \
+   list_p,                                                                     \
+   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.
+ */
+#define sci_abstract_list_pushfront(                                           \
+   list_p,                                                                     \
+   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.
+ * NOTE: UNIMPLEMENTED
+ */
+#define sci_abstract_list_insert(                                              \
+   list_p,                                                                     \
+   obj_p,                                                                      \
+   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.
+ */
+#define sci_abstract_list_clear(                                               \
+   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).
+ */
+#define sci_abstract_list_get_object(                                          \
+   alElement_p                                                                 \
+)                                                                              \
+({                                                                             \
+   void * obj_p = NULL;                                                        \
+   if ((alElement_p) != NULL)                                                  \
+      obj_p = (alElement_p)->object_p;                                         \
+                                                                               \
+   obj_p;                                                                      \
+})
+
+/**
+ * This method is simply a wrapper to provide the number of elements in
+ * the free list.
+ */
+#define sci_abstract_list_freeList_size(freeList) (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.
+ */
+#define private_push_front(                                                    \
+   privateList_p,                                                              \
+   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.
+ */
+#define private_pop_front(                                                     \
+   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--;                                                 \
+   }                                                                           \
+                                                                               \
+   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.
+ */
+#define private_find(                                                          \
+   list_p,                                                                     \
+   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;                                       \
+   }                                                                           \
+                                                                               \
+   alElement_p;                                                                \
+})
+
+/**
+ * This private method will free the supplied list element back to the pool
+ * of free list elements.
+ */
+#define private_pool_free(                                                     \
+   free_pool,                                                                  \
+   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.
+ */
+#define private_pool_allocate(free_pool)                                       \
+({                                                                             \
+   SCI_ABSTRACT_ELEMENT_T * alElement_p;                                       \
+                                                                               \
+   alElement_p = private_pop_front(&(free_pool)->free_list);                   \
+                                                                               \
+   memset(alElement_p, 0, sizeof(SCI_ABSTRACT_ELEMENT_T));                     \
+   alElement_p;                                                                \
+})
+
+#endif
+#endif // _ABSTRACT_LIST_H_
diff --git a/sys/dev/disk/isci/scil/sci_base_controller.c b/sys/dev/disk/isci/scil/sci_base_controller.c
new file mode 100644
index 0000000..2b72d16
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_base_controller.c
@@ -0,0 +1,103 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_base_controller.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains the base controller method implementations and
+ *        any constants or structures private to the base controller object
+ *        or common to all controller derived objects.
+ */
+
+#include <dev/disk/isci/scil/sci_base_controller.h>
+#include <dev/disk/isci/scil/sci_controller.h>
+
+//******************************************************************************
+//* P U B L I C   M E T H O D S
+//******************************************************************************
+
+SCI_MEMORY_DESCRIPTOR_LIST_HANDLE_T sci_controller_get_memory_descriptor_list_handle(
+   SCI_CONTROLLER_HANDLE_T controller
+)
+{
+   SCI_BASE_CONTROLLER_T * this_controller = (SCI_BASE_CONTROLLER_T*)controller;
+   return (SCI_MEMORY_DESCRIPTOR_LIST_HANDLE_T) &this_controller->mdl;
+}
+
+//******************************************************************************
+//* P R O T E C T E D   M E T H O D S
+//******************************************************************************
+
+void sci_base_controller_construct(
+   SCI_BASE_CONTROLLER_T               * this_controller,
+   SCI_BASE_LOGGER_T                   * logger,
+   SCI_BASE_STATE_T                    * state_table,
+   SCI_PHYSICAL_MEMORY_DESCRIPTOR_T    * mdes,
+   U32                                   mde_count,
+   SCI_MEMORY_DESCRIPTOR_LIST_HANDLE_T   next_mdl
+)
+{
+   sci_base_object_construct((SCI_BASE_OBJECT_T *)this_controller, logger);
+
+   sci_base_state_machine_construct(
+      &this_controller->state_machine,
+      &this_controller->parent,
+      state_table,
+      SCI_BASE_CONTROLLER_STATE_INITIAL
+   );
+
+   sci_base_mdl_construct(&this_controller->mdl, mdes, mde_count, next_mdl);
+
+   sci_base_state_machine_start(&this_controller->state_machine);
+}
diff --git a/sys/dev/disk/isci/scil/sci_base_controller.h b/sys/dev/disk/isci/scil/sci_base_controller.h
new file mode 100644
index 0000000..52aaf59
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_base_controller.h
@@ -0,0 +1,347 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_base_controller.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCI_BASE_CONTROLLER_H_
+#define _SCI_BASE_CONTROLLER_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the structures, constants, and methods
+ *        common to all controller object definitions.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/intel_sas.h>
+#include <dev/disk/isci/scil/sci_controller_constants.h>
+
+#include <dev/disk/isci/scil/sci_base_object.h>
+#include <dev/disk/isci/scil/sci_base_state.h>
+#include <dev/disk/isci/scil/sci_base_logger.h>
+#include <dev/disk/isci/scil/sci_base_memory_descriptor_list.h>
+#include <dev/disk/isci/scil/sci_base_state_machine.h>
+#include <dev/disk/isci/scil/sci_base_state_machine_logger.h>
+
+/**
+ * @enum SCI_BASE_CONTROLLER_STATES
+ *
+ * @brief This enumeration depicts all the states for the common controller
+ *        state machine.
+ */
+typedef enum _SCI_BASE_CONTROLLER_STATES
+{
+   /**
+    * Simply the initial state for the base controller state machine.
+    */
+   SCI_BASE_CONTROLLER_STATE_INITIAL = 0,
+
+   /**
+    * This state indicates that the controller is reset.  The memory for
+    * the controller is in it's initial state, but the controller requires
+    * initialization.
+    * This state is entered from the INITIAL state.
+    * This state is entered from the RESETTING state.
+    */
+   SCI_BASE_CONTROLLER_STATE_RESET,
+
+   /**
+    * This state is typically an action state that indicates the controller
+    * is in the process of initialization.  In this state no new IO operations
+    * are permitted.
+    * This state is entered from the RESET state.
+    */
+   SCI_BASE_CONTROLLER_STATE_INITIALIZING,
+
+   /**
+    * This state indicates that the controller has been successfully
+    * initialized.  In this state no new IO operations are permitted.
+    * This state is entered from the INITIALIZING state.
+    */
+   SCI_BASE_CONTROLLER_STATE_INITIALIZED,
+
+   /**
+    * This state indicates the the controller is in the process of becoming
+    * ready (i.e. starting).  In this state no new IO operations are permitted.
+    * This state is entered from the INITIALIZED state.
+    */
+   SCI_BASE_CONTROLLER_STATE_STARTING,
+
+   /**
+    * This state indicates the controller is now ready.  Thus, the user
+    * is able to perform IO operations on the controller.
+    * This state is entered from the STARTING state.
+    */
+   SCI_BASE_CONTROLLER_STATE_READY,
+
+   /**
+    * This state is typically an action state that indicates the controller
+    * is in the process of resetting.  Thus, the user is unable to perform
+    * IO operations on the controller.  A reset is considered destructive in
+    * most cases.
+    * This state is entered from the READY state.
+    * This state is entered from the FAILED state.
+    * This state is entered from the STOPPED state.
+    */
+   SCI_BASE_CONTROLLER_STATE_RESETTING,
+
+   /**
+    * This state indicates that the controller is in the process of stopping.
+    * In this state no new IO operations are permitted, but existing IO
+    * operations are allowed to complete.
+    * This state is entered from the READY state.
+    */
+   SCI_BASE_CONTROLLER_STATE_STOPPING,
+
+   /**
+    * This state indicates that the controller has successfully been stopped.
+    * In this state no new IO operations are permitted.
+    * This state is entered from the STOPPING state.
+    */
+   SCI_BASE_CONTROLLER_STATE_STOPPED,
+
+   /**
+    * This state indicates that the controller could not successfully be
+    * initialized.  In this state no new IO operations are permitted.
+    * This state is entered from the INITIALIZING state.
+    * This state is entered from the STARTING state.
+    * This state is entered from the STOPPING state.
+    * This state is entered from the RESETTING state.
+    */
+   SCI_BASE_CONTROLLER_STATE_FAILED,
+
+   SCI_BASE_CONTROLLER_MAX_STATES
+
+} SCI_BASE_CONTROLLER_STATES;
+
+/**
+ * @struct SCI_BASE_CONTROLLER
+ *
+ * @brief The base controller object abstracts the fields common to all
+ *        SCI controller objects.
+ */
+typedef struct SCI_BASE_CONTROLLER
+{
+   /**
+    * The field specifies that the parent object for the base controller
+    * is the base object itself.
+    */
+   SCI_BASE_OBJECT_T parent;
+
+   /**
+    * This field points to the memory descriptor list associated with this
+    * controller.  The MDL indicates the memory requirements necessary for
+    * this controller object.
+    */
+   SCI_BASE_MEMORY_DESCRIPTOR_LIST_T  mdl;
+
+   /**
+    * This field records the fact that the controller has encountered a fatal memory
+    * error and controller must stay in failed state.
+    */
+   U8 error;
+
+   /**
+    * This field contains the information for the base controller state
+    * machine.
+    */
+   SCI_BASE_STATE_MACHINE_T state_machine;
+
+   #ifdef SCI_LOGGING
+   SCI_BASE_STATE_MACHINE_LOGGER_T state_machine_logger;
+   #endif // SCI_LOGGING
+
+} SCI_BASE_CONTROLLER_T;
+
+// Forward declarations
+struct SCI_BASE_REMOTE_DEVICE;
+struct SCI_BASE_REQUEST;
+
+typedef SCI_STATUS (*SCI_BASE_CONTROLLER_HANDLER_T)(
+   SCI_BASE_CONTROLLER_T *
+);
+
+typedef SCI_STATUS (*SCI_BASE_CONTROLLER_TIMED_HANDLER_T)(
+   SCI_BASE_CONTROLLER_T *,
+   U32
+);
+
+typedef SCI_STATUS (*SCI_BASE_CONTROLLER_REQUEST_HANDLER_T)(
+   SCI_BASE_CONTROLLER_T *,
+   struct SCI_BASE_REMOTE_DEVICE *,
+   struct SCI_BASE_REQUEST *
+);
+
+typedef SCI_STATUS (*SCI_BASE_CONTROLLER_START_REQUEST_HANDLER_T)(
+   SCI_BASE_CONTROLLER_T *,
+   struct SCI_BASE_REMOTE_DEVICE *,
+   struct SCI_BASE_REQUEST *,
+   U16
+);
+
+
+/**
+ * @struct SCI_BASE_CONTROLLER_STATE_HANDLER
+ *
+ * @brief This structure contains all of the state handler methods common to
+ *        base controller state machines.  Handler methods provide the ability
+ *        to change the behavior for user requests or transitions depending
+ *        on the state the machine is in.
+ */
+typedef struct SCI_BASE_CONTROLLER_STATE_HANDLER
+{
+   /**
+    * The start_handler specifies the method invoked when a user attempts to
+    * start a controller.
+    */
+   SCI_BASE_CONTROLLER_TIMED_HANDLER_T start_handler;
+
+   /**
+    * The stop_handler specifies the method invoked when a user attempts to
+    * stop a controller.
+    */
+   SCI_BASE_CONTROLLER_TIMED_HANDLER_T stop_handler;
+
+   /**
+    * The reset_handler specifies the method invoked when a user attempts to
+    * reset a controller.
+    */
+   SCI_BASE_CONTROLLER_HANDLER_T reset_handler;
+
+   /**
+    * The initialize_handler specifies the method invoked when a user
+    * attempts to initialize a controller.
+    */
+   SCI_BASE_CONTROLLER_HANDLER_T initialize_handler;
+
+   /**
+    * The start_io_handler specifies the method invoked when a user
+    * attempts to start an IO request for a controller.
+    */
+   SCI_BASE_CONTROLLER_START_REQUEST_HANDLER_T start_io_handler;
+
+   /**
+    * The start_internal_request_handler specifies the method invoked when a user
+    * attempts to start an internal request for a controller.
+    */
+   SCI_BASE_CONTROLLER_START_REQUEST_HANDLER_T start_high_priority_io_handler;
+
+   /**
+    * The complete_io_handler specifies the method invoked when a user
+    * attempts to complete an IO request for a controller.
+    */
+   SCI_BASE_CONTROLLER_REQUEST_HANDLER_T complete_io_handler;
+
+    /**
+    * The complete_high_priority_io_handler specifies the method invoked when a user
+    * attempts to complete a high priority IO request for a controller.
+    */
+   SCI_BASE_CONTROLLER_REQUEST_HANDLER_T complete_high_priority_io_handler;
+
+   /**
+    * The continue_io_handler specifies the method invoked when a user
+    * attempts to continue an IO request for a controller.
+    */
+   SCI_BASE_CONTROLLER_REQUEST_HANDLER_T continue_io_handler;
+
+   /**
+    * The start_task_handler specifies the method invoked when a user
+    * attempts to start a task management request for a controller.
+    */
+   SCI_BASE_CONTROLLER_START_REQUEST_HANDLER_T start_task_handler;
+
+   /**
+    * The complete_task_handler specifies the method invoked when a user
+    * attempts to complete a task management request for a controller.
+    */
+   SCI_BASE_CONTROLLER_REQUEST_HANDLER_T complete_task_handler;
+
+} SCI_BASE_CONTROLLER_STATE_HANDLER_T;
+
+/**
+ * @brief Construct the base controller
+ *
+ * @param[in] this_controller This parameter specifies the base controller
+ *            to be constructed.
+ * @param[in] logger This parameter specifies the logger associated with
+ *            this base controller object.
+ * @param[in] state_table This parameter specifies the table of state
+ *            definitions to be utilized for the controller state machine.
+ * @param[in] mde_array This parameter specifies the array of memory
+ *            descriptor entries to be managed by this list.
+ * @param[in] mde_array_length This parameter specifies the size of the
+ *            array of entries.
+ * @param[in] next_mdl This parameter specifies a subsequent MDL object
+ *            to be managed by this MDL object.
+ * @param[in] oem_parameters This parameter specifies the original
+ *            equipment manufacturer parameters to be utilized by this
+ *            controller object.
+ *
+ * @return none
+ */
+void sci_base_controller_construct(
+   SCI_BASE_CONTROLLER_T             * this_controller,
+   SCI_BASE_LOGGER_T                 * logger,
+   SCI_BASE_STATE_T                  * state_table,
+   SCI_PHYSICAL_MEMORY_DESCRIPTOR_T  * mdes,
+   U32                                 mde_count,
+   SCI_MEMORY_DESCRIPTOR_LIST_HANDLE_T next_mdl
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCI_BASE_CONTROLLER_H_
diff --git a/sys/dev/disk/isci/scil/sci_base_domain.c b/sys/dev/disk/isci/scil/sci_base_domain.c
new file mode 100644
index 0000000..27cd210
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_base_domain.c
@@ -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: src/sys/dev/isci/scil/sci_base_domain.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains the base domain method implementations and
+ *        any constants or structures private to the base domain object.
+ */
+
+#include <dev/disk/isci/scil/sci_base_domain.h>
+#include <dev/disk/isci/scil/sci_base_state_machine.h>
+
+//******************************************************************************
+//* P R O T E C T E D   M E T H O D S
+//******************************************************************************
+
+void sci_base_domain_construct(
+   SCI_BASE_DOMAIN_T * this_domain,
+   SCI_BASE_LOGGER_T * logger,
+   SCI_BASE_STATE_T  * state_table
+)
+{
+   sci_base_object_construct(&this_domain->parent, logger);
+
+   sci_base_state_machine_construct(
+      &this_domain->state_machine,
+      &this_domain->parent,
+      state_table,
+      SCI_BASE_DOMAIN_STATE_INITIAL
+   );
+
+   sci_base_state_machine_start(
+      &this_domain->state_machine
+   );
+}
diff --git a/sys/dev/disk/isci/scil/sci_base_domain.h b/sys/dev/disk/isci/scil/sci_base_domain.h
new file mode 100644
index 0000000..5c19840
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_base_domain.h
@@ -0,0 +1,309 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_base_domain.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCI_BASE_DOMAIN_H_
+#define _SCI_BASE_DOMAIN_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the structures, constants, and methods
+ *        common to all domain object definitions.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_base_object.h>
+#include <dev/disk/isci/scil/sci_base_logger.h>
+#include <dev/disk/isci/scil/sci_base_state_machine.h>
+#include <dev/disk/isci/scil/sci_base_state_machine_logger.h>
+
+/**
+ * @enum SCI_BASE_DOMAIN_STATES
+ *
+ * @brief This enumeration depicts the standard states common to all domain
+ *        state machine implementations.
+ */
+typedef enum _SCI_BASE_DOMAIN_STATES
+{
+   /**
+    * Simply the initial state for the base domain state machine.
+    */
+   SCI_BASE_DOMAIN_STATE_INITIAL,
+
+   /**
+    * This state indicates that the domain has successfully been stopped.
+    * In this state no new IO operations are permitted.
+    * This state is entered from the INITIAL state.
+    * This state is entered from the DISCOVERING state.
+    */
+   SCI_BASE_DOMAIN_STATE_STARTING,
+
+   /**
+    * This state indicates the the domain is now ready.  Thus, the user
+    * is able to perform IO operations to remote devices in this domain.
+    * This state is entered from the STOPPED state.
+    * This state is entered from the STOPPING state.
+    * This state is entered from the DISCOVERING state.
+    */
+   SCI_BASE_DOMAIN_STATE_READY,
+
+   /**
+    * This state indicates that the domain is in the process of stopping.
+    * In this state no new IO operations are permitted, but existing IO
+    * operations in the domain are allowed to complete.
+    * This state is entered from the READY state.
+    * This state is entered from the DISCOVERING state.
+    */
+   SCI_BASE_DOMAIN_STATE_STOPPING,
+
+   /**
+    * This state indicates that the domain has successfully been stopped.
+    * In this state no new IO operations are permitted.
+    * This state is entered from the INITIAL state.
+    * This state is entered from the STOPPING state.
+    */
+   SCI_BASE_DOMAIN_STATE_STOPPED,
+
+   /**
+    * This state indicates that the domain is actively attempting to
+    * discover what remote devices are contained in it.  In this state no
+    * new user IO requests are permitted.
+    * This state is entered from the READY state.
+    */
+   SCI_BASE_DOMAIN_STATE_DISCOVERING,
+
+   SCI_BASE_DOMAIN_MAX_STATES
+
+} SCI_BASE_DOMAIN_STATES;
+
+/**
+ * @struct SCI_BASE_DOMAIN
+ *
+ * @brief This structure defines all of the fields common to DOMAIN objects.
+ */
+typedef struct SCI_BASE_DOMAIN
+{
+   /**
+    * This field depicts the parent object (SCI_BASE_OBJECT) for the domain.
+    */
+   SCI_BASE_OBJECT_T parent;
+
+   /**
+    * This field contains the information for the base domain state machine.
+    */
+   SCI_BASE_STATE_MACHINE_T state_machine;
+
+   #ifdef SCI_LOGGING
+   SCI_BASE_STATE_MACHINE_LOGGER_T state_machine_logger;
+   #endif // SCI_LOGGING
+
+} SCI_BASE_DOMAIN_T;
+
+struct SCI_BASE_CONTROLLER;
+struct SCI_BASE_REMOTE_DEVICE;
+struct SCI_BASE_REQUEST;
+struct SCI_BASE_REQUEST;
+
+typedef SCI_STATUS (*SCI_BASE_DOMAIN_TIMED_HANDLER_T)(
+   SCI_BASE_DOMAIN_T *,
+   U32,
+   U32
+);
+
+typedef SCI_STATUS (*SCI_BASE_DOMAIN_HANDLER_T)(
+   SCI_BASE_DOMAIN_T *
+);
+
+typedef SCI_STATUS (*SCI_BASE_DOMAIN_PORT_NOT_READY_HANDLER_T)(
+   SCI_BASE_DOMAIN_T *,
+   U32
+);
+
+typedef SCI_STATUS (*SCI_BASE_DOMAIN_DEVICE_HANDLER_T)(
+   SCI_BASE_DOMAIN_T *,
+   struct SCI_BASE_REMOTE_DEVICE *
+);
+
+typedef SCI_STATUS (*SCI_BASE_DOMAIN_REQUEST_HANDLER_T)(
+   SCI_BASE_DOMAIN_T *,
+   struct SCI_BASE_REMOTE_DEVICE *,
+   struct SCI_BASE_REQUEST *
+);
+
+typedef SCI_STATUS (*SCI_BASE_DOMAIN_HIGH_PRIORITY_REQUEST_COMPLETE_HANDLER_T)(
+   SCI_BASE_DOMAIN_T *,
+   struct SCI_BASE_REMOTE_DEVICE *,
+   struct SCI_BASE_REQUEST *,
+   void *,
+   SCI_IO_STATUS
+);
+
+
+/**
+ * @struct SCI_BASE_DOMAIN_STATE_HANDLER
+ *
+ * @brief This structure contains all of the state handler methods common to
+ *        base domain state machines.  Handler methods provide the ability
+ *        to change the behavior for user requests or transitions depending
+ *        on the state the machine is in.
+ */
+typedef struct SCI_BASE_DOMAIN_STATE_HANDLER
+{
+   /**
+    * The discover_handler specifies the method invoked when a user attempts
+    * to discover a domain.
+    */
+   SCI_BASE_DOMAIN_TIMED_HANDLER_T discover_handler;
+
+   /**
+    * The port_ready_handler specifies the method invoked an SCI Core
+    * informs the domain object that it's associated port is now ready
+    * for IO operation.
+    */
+   SCI_BASE_DOMAIN_HANDLER_T port_ready_handler;
+
+   /**
+    * The port_not_ready_handler specifies the method invoked an SCI Core
+    * informs the domain object that it's associated port is no longer ready
+    * for IO operation.
+    */
+   SCI_BASE_DOMAIN_PORT_NOT_READY_HANDLER_T port_not_ready_handler;
+
+   /**
+    * The device_start_complete_handler specifies the method invoked when a
+    * remote device start operation in the domain completes.
+    */
+   SCI_BASE_DOMAIN_DEVICE_HANDLER_T device_start_complete_handler;
+
+   /**
+    * The device_stop_complete_handler specifies the method invoked when a
+    * remote device stop operation in the domain completes.
+    */
+   SCI_BASE_DOMAIN_DEVICE_HANDLER_T device_stop_complete_handler;
+
+   /**
+    * The device_destruct_handler specifies the method invoked when sci user
+    * destruct a remote device of this domain.
+    */
+   SCI_BASE_DOMAIN_DEVICE_HANDLER_T device_destruct_handler;
+
+   /**
+    * The start_io_handler specifies the method invoked when a user
+    * attempts to start an IO request for a domain.
+    */
+   SCI_BASE_DOMAIN_REQUEST_HANDLER_T start_io_handler;
+
+   /**
+    * The start_high_priority_io_handler specifies the method invoked when a user
+    * attempts to start an high priority request for a domain.
+    */
+   SCI_BASE_DOMAIN_REQUEST_HANDLER_T start_high_priority_io_handler;
+
+   /**
+    * The complete_io_handler specifies the method invoked when a user
+    * attempts to complete an IO request for a domain.
+    */
+   SCI_BASE_DOMAIN_REQUEST_HANDLER_T complete_io_handler;
+
+   /**
+    * The complete_high_priority_io_handler specifies the method invoked when a
+    * user attempts to complete an high priority IO request for a domain.
+    */
+   SCI_BASE_DOMAIN_HIGH_PRIORITY_REQUEST_COMPLETE_HANDLER_T complete_high_priority_io_handler;
+
+   /**
+    * The continue_io_handler specifies the method invoked when a user
+    * attempts to continue an IO request for a domain.
+    */
+   SCI_BASE_DOMAIN_REQUEST_HANDLER_T continue_io_handler;
+
+   /**
+    * The start_task_handler specifies the method invoked when a user
+    * attempts to start a task management request for a domain.
+    */
+   SCI_BASE_DOMAIN_REQUEST_HANDLER_T start_task_handler;
+
+   /**
+    * The complete_task_handler specifies the method invoked when a user
+    * attempts to complete a task management request for a domain.
+    */
+   SCI_BASE_DOMAIN_REQUEST_HANDLER_T complete_task_handler;
+
+} SCI_BASE_DOMAIN_STATE_HANDLER_T;
+
+/**
+ * @brief Construct the base domain
+ *
+ * @param[in] this_domain This parameter specifies the base domain to be
+ *            constructed.
+ * @param[in] logger This parameter specifies the logger associated with
+ *            this base domain object.
+ * @param[in] state_table This parameter specifies the table of state
+ *            definitions to be utilized for the domain state machine.
+ *
+ * @return none
+ */
+void sci_base_domain_construct(
+   SCI_BASE_DOMAIN_T * this_domain,
+   SCI_BASE_LOGGER_T * logger,
+   SCI_BASE_STATE_T  * state_table
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCI_BASE_DOMAIN_H_
diff --git a/sys/dev/disk/isci/scil/sci_base_iterator.c b/sys/dev/disk/isci/scil/sci_base_iterator.c
new file mode 100644
index 0000000..966230c
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_base_iterator.c
@@ -0,0 +1,180 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_base_iterator.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains the implementation of an iterator class.
+ *        This class will allow for iterating across the elements of a
+ *        container.
+ */
+
+#if !defined(DISABLE_SCI_ITERATORS)
+
+//******************************************************************************
+//*
+//*     I N C L U D E S
+//*
+//******************************************************************************
+
+#include <dev/disk/isci/scil/sci_base_iterator.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 Return the size of an iterator object.
+ *
+ * @return U32 : size of iterator object in bytes.
+ *
+ */
+U32 sci_iterator_get_object_size(
+   void
+)
+{
+    return sizeof(SCI_BASE_ITERATOR_T);
+}
+
+/**
+ * @brief Initialize the interator.
+ *
+ * @param[in] iterator This parameter specifies the iterator to be
+ *            constructed.
+ * @param[in] list This parameter specifies the abstract list that will be
+ *            iterated on by this iterator.  The iterator will by initialized
+ *            to point to the first element in this abstract list.
+ *
+ * @return none
+ */
+void sci_base_iterator_construct(
+   SCI_ITERATOR_HANDLE_T   iterator_handle,
+   SCI_ABSTRACT_LIST_T   * list
+)
+{
+    SCI_BASE_ITERATOR_T * iterator = (SCI_BASE_ITERATOR_T *) iterator_handle;
+
+    memset(iterator, 0, sizeof(SCI_BASE_ITERATOR_T));
+    iterator->list = list;
+    sci_iterator_first(iterator);
+}
+
+/**
+ * @brief Get the object currently pointed to by this iterator.
+ *
+ * @param[in] iterator_handle Handle to an iterator.
+ *
+ * @return void * : Object pointed to by this iterator.
+ * @retval NULL If iterator is not currently pointing to a valid element.
+ */
+void * sci_iterator_get_current(
+   SCI_ITERATOR_HANDLE_T iterator_handle
+)
+{
+   SCI_BASE_ITERATOR_T * iterator = (SCI_BASE_ITERATOR_T *)iterator_handle;
+
+   void *current_object = NULL;
+
+   if (iterator->current != NULL)
+   {
+      current_object = sci_abstract_list_get_object(iterator->current);
+   }
+
+   return current_object;
+}
+
+/**
+ * @brief Modify the iterator to point to the first element in the list.
+ *
+ * @param[in] iterator
+ *
+ * @return none
+ */
+void sci_iterator_first(
+   SCI_ITERATOR_HANDLE_T iterator_handle
+)
+{
+   SCI_BASE_ITERATOR_T * iterator = (SCI_BASE_ITERATOR_T *)iterator_handle;
+
+   iterator->current = sci_abstract_list_get_front(iterator->list);
+}
+
+/**
+ * @brief Modify the iterator to point to the next element in the list.
+ *
+ * @param[in] iterator
+ *
+ * @return none
+ */
+void sci_iterator_next(
+   SCI_ITERATOR_HANDLE_T iterator_handle
+)
+{
+   SCI_BASE_ITERATOR_T * iterator = (SCI_BASE_ITERATOR_T *)iterator_handle;
+
+   if (iterator->current != NULL)
+   {
+      iterator->current = sci_abstract_list_get_next(iterator->current);
+   }
+}
+
+#endif // !defined(DISABLE_SCI_ITERATORS)
diff --git a/sys/dev/disk/isci/scil/sci_base_iterator.h b/sys/dev/disk/isci/scil/sci_base_iterator.h
new file mode 100644
index 0000000..bc93135
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_base_iterator.h
@@ -0,0 +1,134 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_base_iterator.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+/**
+ * @file
+ *
+ * @brief This file contains the protected interface to the iterator class.
+ *        Methods Provided:
+ *        - sci_base_iterator_construct()
+ */
+
+#ifndef _SCI_BASE_ITERATOR_H_
+#define _SCI_BASE_ITERATOR_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+//******************************************************************************
+//*
+//*     I N C L U D E S
+//*
+//******************************************************************************
+
+#include <dev/disk/isci/scil/sci_iterator.h>
+#include <dev/disk/isci/scil/sci_abstract_list.h>
+
+//******************************************************************************
+//*
+//*     C O N S T A N T S
+//*
+//******************************************************************************
+
+//******************************************************************************
+//*
+//*     T Y P E S
+//*
+//******************************************************************************
+
+/**
+ * @struct SCI_BASE_ITERATOR
+ *
+ * @brief This object represents an iterator of an abstract list.
+ *
+ */
+typedef struct SCI_BASE_ITERATOR
+{
+   /**
+    * This field points to the list iterated by this iterator.
+    */
+   SCI_ABSTRACT_LIST_T * list;
+
+   /**
+    * This field points to the list element currently referenced by this
+    *  iterator.
+    */
+   SCI_ABSTRACT_ELEMENT_T * current;
+
+} SCI_BASE_ITERATOR_T;
+
+//******************************************************************************
+//*
+//*     P U B L I C       M E T H O D S
+//*
+//******************************************************************************
+
+#if !defined(DISABLE_SCI_ITERATORS)
+
+void sci_base_iterator_construct(
+   SCI_ITERATOR_HANDLE_T   iterator,
+   SCI_ABSTRACT_LIST_T   * list
+);
+
+#else // !defined(DISABLE_SCI_ITERATORS)
+
+#define sci_base_iterator_construct(the_iterator, the_list)
+
+#endif // !defined(DISABLE_SCI_ITERATORS)
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _BASE_ITERATOR_H_
diff --git a/sys/dev/disk/isci/scil/sci_base_library.c b/sys/dev/disk/isci/scil/sci_base_library.c
new file mode 100644
index 0000000..e729e8a
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_base_library.c
@@ -0,0 +1,101 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_base_library.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the method imlementations for the
+ *        SCI_BASE_LIBRARY object.
+ */
+
+#include <dev/disk/isci/scil/sci_base_library.h>
+
+//******************************************************************************
+//* P U B L I C   M E T H O D S
+//******************************************************************************
+
+U32 sci_library_get_major_version(
+   void
+)
+{
+   // Return the 32-bit value representing the major version for this SCI
+   // binary.
+   return __SCI_LIBRARY_MAJOR_VERSION__;
+}
+
+// ---------------------------------------------------------------------------
+
+U32 sci_library_get_minor_version(
+   void
+)
+{
+   // Return the 32-bit value representing the minor version for this SCI
+   // binary.
+   return __SCI_LIBRARY_MINOR_VERSION__;
+}
+
+// ---------------------------------------------------------------------------
+
+U32 sci_library_get_build_version(
+   void
+)
+{
+   // Return the 32-bit value representing the build version for this SCI
+   // binary.
+   return __SCI_LIBRARY_BUILD_VERSION__;
+}
+
+//******************************************************************************
+//* P R O T E C T E D   M E T H O D S
+//******************************************************************************
diff --git a/sys/dev/disk/isci/scil/sci_base_library.h b/sys/dev/disk/isci/scil/sci_base_library.h
new file mode 100644
index 0000000..33981a5
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_base_library.h
@@ -0,0 +1,197 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_base_library.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCI_BASE_LIBRARY_H_
+#define _SCI_BASE_LIBRARY_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains the protected interface structures, constants
+ *        and interface methods for the SCI_BASE_LIBRARY object.
+ *
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_library.h>
+#include <dev/disk/isci/scil/sci_pool.h>
+#include <dev/disk/isci/scil/sci_base_object.h>
+#include <dev/disk/isci/scil/sci_base_logger.h>
+#include <dev/disk/isci/scil/sci_controller_constants.h>
+
+/**
+ * @struct SCI_BASE_LIBRARY
+ *
+ * @brief This structure contains all of the objects common to all library
+ *        sub-objects.
+ */
+typedef struct SCI_BASE_LIBRARY
+{
+   /**
+    * This class derives directly from the base object class.  As a result,
+    * the field is named "parent" and is the first field contained in the
+    * structure.
+    */
+   SCI_BASE_OBJECT_T  parent;
+
+   /**
+    * This field provides the logger object to be utilized by all objects
+    * contained inside of a library.
+    */
+   SCI_BASE_LOGGER_T  logger;
+
+   // Create a pool structure to manage free controller indices.
+   SCI_POOL_CREATE(controller_id_pool, U16, SCI_MAX_CONTROLLERS);
+
+} SCI_BASE_LIBRARY_T;
+
+
+/**
+ * @brief This method will construct the base library object.
+ *
+ * @param[in] this_library This parameter specifies the library object
+ *            to be constructed.
+ * @param[in] max_controllers This parameter specifies the maximum number
+ *            of controllers to be supported by this library.
+ *
+ * @return none
+ */
+void sci_base_library_construct(
+   SCI_BASE_LIBRARY_T * this_library,
+   U32                  max_controllers
+);
+
+/**
+ * This macro provides common code for allocating a controller from a library.
+ * It will ensure that we successfully allocate an available controller index
+ * and return SCI_FAILURE_INSUFFICIENT_RESOURCES if unsuccessful.
+ */
+#define SCI_BASE_LIBRARY_ALLOCATE_CONTROLLER( \
+   library, \
+   controller_ptr, \
+   rc \
+) \
+{ \
+   U16 index; \
+   *rc = SCI_SUCCESS; \
+   if (! sci_pool_empty((library)->parent.controller_id_pool)) \
+   { \
+      sci_pool_get((library)->parent.controller_id_pool, index); \
+      *controller_ptr = (SCI_CONTROLLER_HANDLE_T) \
+                        & (library)->controllers[index]; \
+   } \
+   else \
+      *rc = SCI_FAILURE_INSUFFICIENT_RESOURCES; \
+}
+
+/**
+ * This macro provides common code for freeing a controller to a library.
+ * It calculates the index to the controller instance in the array by
+ * determining the offset.
+ */
+#define SCI_BASE_LIBRARY_FREE_CONTROLLER( \
+   library, \
+   controller, \
+   CONTROLLER_TYPE, \
+   rc \
+) \
+{ \
+   U16 index = (U16) \
+               ((((char *)(controller)) - ((char *)(library)->controllers))\
+                / sizeof(CONTROLLER_TYPE)); \
+   *rc = SCI_SUCCESS; \
+   if (  (index < SCI_MAX_CONTROLLERS) \
+      && (! sci_pool_full((library)->parent.controller_id_pool)) ) \
+   { \
+      sci_pool_put((library)->parent.controller_id_pool, index); \
+   } \
+   else \
+      *rc = SCI_FAILURE_CONTROLLER_NOT_FOUND; \
+}
+
+
+
+/**
+ * This macro provides common code for constructing library. It
+ * It initialize and fill the library's controller_id_pool.
+ */
+#define SCI_BASE_LIBRARY_CONSTRUCT( \
+   library, \
+   base_library, \
+   max_controllers, \
+   CONTROLLER_TYPE, \
+   status \
+) \
+{ \
+   U32 controller_index; \
+   sci_base_object_construct(&(base_library)->parent, &(base_library)->logger); \
+   sci_pool_initialize((base_library)->controller_id_pool); \
+   for (controller_index = 0; controller_index < max_controller_count; controller_index++) \
+   { \
+      SCI_BASE_LIBRARY_FREE_CONTROLLER( \
+         library, \
+         &library->controllers[controller_index], \
+         CONTROLLER_TYPE, \
+         &status \
+      ); \
+   } \
+}
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCI_BASE_LIBRARY_H_
diff --git a/sys/dev/disk/isci/scil/sci_base_logger.c b/sys/dev/disk/isci/scil/sci_base_logger.c
new file mode 100644
index 0000000..d2c43a3
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_base_logger.c
@@ -0,0 +1,290 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_base_logger.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains the implementation for the base logger object.
+ *        It provides the functionality necessary to enabling, disabling,
+ *        constructing, etc. logger objects.
+ */
+
+
+#include <dev/disk/isci/scil/sci_base_logger.h>
+
+
+#ifdef SCI_LOGGING
+
+//******************************************************************************
+//* P R I V A T E   M E T H O D S
+//******************************************************************************
+
+#define SCI_LOGGER_GET_OBJECT_MASK(logger, verbosity_level) \
+   (((SCI_BASE_LOGGER_T *)(logger))->object_mask[(verbosity_level)])
+
+/**
+ * @brief This method is private to this object.  It attempts to enable the
+ *        supplied log objects for the supplied verbosity levels.
+ *
+ * @param[in]  logger This parameter specifies the logger object for which
+ *             to attempt to enable log object and verbosity levels.
+ * @param[in]  log_object_mask This parameter specifies the log objects to
+ *             attempt to enable.
+ * @param[in]  verbosity_mask This parameter specifies the verbosity levels
+ *             that are allowed to be enabled.
+ * @param[in]  verbosity This parameter specifies the specific verbosity level
+ *             to attempt to enable.
+ *
+ * @return none
+ */
+static
+void sci_base_logger_enable_log_object(
+   SCI_LOGGER_HANDLE_T  logger,
+   U32                  log_object_mask,
+   U8                   verbosity_mask,
+   U8                   verbosity
+)
+{
+   // Enable the log objects for the error verbosity if errs are enabled.
+   if ( (1<<verbosity) & verbosity_mask)
+   {
+      SCI_LOGGER_GET_OBJECT_MASK(logger, verbosity) |= log_object_mask;
+      (((SCI_BASE_LOGGER_T *)(logger))->verbosity_mask |= (1<<verbosity) );
+   }
+}
+
+/**
+ * @brief This method is private to this object.  It attempts to disable the
+ *        supplied log objects for the supplied verbosity levels.
+ *
+ * @param[in]  logger This parameter specifies the logger object for which
+ *             to attempt to disable log object and verbosity levels.
+ * @param[in]  log_object_mask This parameter specifies the log objects to
+ *             attempt to disable.
+ * @param[in]  verbosity_mask This parameter specifies the verbosity levels
+ *             that are allowed to be disabled.
+ * @param[in]  verbosity This parameter specifies the specific verbosity level
+ *             to attempt to disable.
+ *
+ * @return none
+ */
+static
+void sci_base_logger_disable_log_object(
+   SCI_LOGGER_HANDLE_T  logger,
+   U32                  log_object_mask,
+   U8                   verbosity_mask,
+   U8                   verbosity
+)
+{
+   if ( (1<<verbosity) & verbosity_mask)
+   {
+      SCI_LOGGER_GET_OBJECT_MASK(logger, verbosity) &= ~log_object_mask;
+
+      // If all of the objects in the object mask are disabled for this
+      // verbosity, then disable the verbosity as well.
+      if (SCI_LOGGER_GET_OBJECT_MASK(logger, verbosity) == 0)
+         (((SCI_BASE_LOGGER_T *)(logger))->verbosity_mask &= ~(1<<verbosity) );
+   }
+}
+
+//******************************************************************************
+//* P U B L I C   M E T H O D S
+//******************************************************************************
+
+U8 sci_logger_get_verbosity_mask(
+   SCI_LOGGER_HANDLE_T  logger,
+   U32                  log_object
+)
+{
+   U8 verbosity_mask = 0;
+   SCI_BASE_LOGGER_T * base_logger = (SCI_BASE_LOGGER_T *)logger;
+
+   if ( base_logger->object_mask[SCI_LOG_VERBOSITY_ERROR] & log_object )
+      verbosity_mask |= 1<<SCI_LOG_VERBOSITY_ERROR;
+
+   if ( base_logger->object_mask[SCI_LOG_VERBOSITY_WARNING] & log_object )
+      verbosity_mask |= 1<<SCI_LOG_VERBOSITY_WARNING;
+
+   if ( base_logger->object_mask[SCI_LOG_VERBOSITY_INFO] & log_object )
+      verbosity_mask |= 1<<SCI_LOG_VERBOSITY_INFO;
+
+   if ( base_logger->object_mask[SCI_LOG_VERBOSITY_TRACE] & log_object )
+      verbosity_mask |= 1<<SCI_LOG_VERBOSITY_TRACE;
+
+   if ( base_logger->object_mask[SCI_LOG_VERBOSITY_STATES] & log_object )
+      verbosity_mask |= 1<<SCI_LOG_VERBOSITY_TRACE;
+
+   return verbosity_mask;
+}
+
+// ---------------------------------------------------------------------------
+
+U32 sci_logger_get_object_mask(
+   SCI_LOGGER_HANDLE_T  logger,
+   U8                   verbosity
+)
+{
+   // Ensure that a supported verbosity level was supplied.
+   if (  (SCI_LOG_VERBOSITY_ERROR == verbosity)
+      || (SCI_LOG_VERBOSITY_WARNING == verbosity)
+      || (SCI_LOG_VERBOSITY_INFO == verbosity)
+      || (SCI_LOG_VERBOSITY_TRACE == verbosity)
+      || (SCI_LOG_VERBOSITY_STATES == verbosity) )
+   {
+      return SCI_LOGGER_GET_OBJECT_MASK(logger, verbosity);
+   }
+
+   // An unsupported verbosity level was supplied.  Simply return an empty
+   // log object mask.
+   return 0;
+}
+
+// ---------------------------------------------------------------------------
+
+void sci_logger_enable(
+   SCI_LOGGER_HANDLE_T  logger,
+   U32                  log_object_mask,
+   U8                   verbosity_mask
+)
+{
+   sci_base_logger_enable_log_object(
+      logger, log_object_mask, verbosity_mask, SCI_LOG_VERBOSITY_ERROR
+   );
+
+   sci_base_logger_enable_log_object(
+      logger, log_object_mask, verbosity_mask, SCI_LOG_VERBOSITY_WARNING
+   );
+
+   sci_base_logger_enable_log_object(
+      logger, log_object_mask, verbosity_mask, SCI_LOG_VERBOSITY_INFO
+   );
+
+   sci_base_logger_enable_log_object(
+      logger, log_object_mask, verbosity_mask, SCI_LOG_VERBOSITY_TRACE
+   );
+
+   sci_base_logger_enable_log_object(
+      logger, log_object_mask, verbosity_mask, SCI_LOG_VERBOSITY_STATES
+   );
+}
+
+// ---------------------------------------------------------------------------
+
+void sci_logger_disable(
+   SCI_LOGGER_HANDLE_T  logger,
+   U32                  log_object_mask,
+   U8                   verbosity_mask
+)
+{
+   sci_base_logger_disable_log_object(
+      logger, log_object_mask, verbosity_mask, SCI_LOG_VERBOSITY_ERROR
+   );
+
+   sci_base_logger_disable_log_object(
+      logger, log_object_mask, verbosity_mask, SCI_LOG_VERBOSITY_WARNING
+   );
+
+   sci_base_logger_disable_log_object(
+      logger, log_object_mask, verbosity_mask, SCI_LOG_VERBOSITY_INFO
+   );
+
+   sci_base_logger_disable_log_object(
+      logger, log_object_mask, verbosity_mask, SCI_LOG_VERBOSITY_TRACE
+   );
+
+   sci_base_logger_disable_log_object(
+      logger, log_object_mask, verbosity_mask, SCI_LOG_VERBOSITY_STATES
+   );
+}
+
+// ---------------------------------------------------------------------------
+
+BOOL sci_logger_is_enabled(
+   SCI_LOGGER_HANDLE_T  logger,
+   U32                  log_object_mask,
+   U8                   verbosity_level
+)
+{
+   SCI_BASE_LOGGER_T * base_logger = (SCI_BASE_LOGGER_T*) logger;
+
+   if (  (base_logger->verbosity_mask & (1<<verbosity_level))
+      && (base_logger->object_mask[verbosity_level] & log_object_mask) )
+      return TRUE;
+
+   return FALSE;
+}
+
+//******************************************************************************
+//* P R O T E C T E D   M E T H O D S
+//******************************************************************************
+
+void sci_base_logger_construct(
+   SCI_BASE_LOGGER_T *this_logger
+)
+{
+   int index;
+
+   sci_base_object_construct(
+      &this_logger->parent, this_logger
+   );
+
+   this_logger->verbosity_mask = 0;
+
+   for (index = 0; index < SCI_BASE_LOGGER_MAX_VERBOSITY_LEVELS; index++)
+   {
+      this_logger->object_mask[index] = 0;
+   }
+}
+
+#endif // SCI_LOGGING
diff --git a/sys/dev/disk/isci/scil/sci_base_logger.h b/sys/dev/disk/isci/scil/sci_base_logger.h
new file mode 100644
index 0000000..ca73b39
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_base_logger.h
@@ -0,0 +1,131 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_base_logger.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCI_BASE_LOGGER_H_
+#define _SCI_BASE_LOGGER_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the constants, structures, and methods
+ *        common to all base logger objects.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_logger.h>
+#include <dev/disk/isci/scil/sci_base_object.h>
+
+
+#define SCI_BASE_LOGGER_MAX_VERBOSITY_LEVELS 5
+
+/**
+ * @struct SCI_BASE_LOGGER
+ *
+ * @brief This structure contains the set of log objects and verbosities that
+ *        are enabled for logging.  It's parent is the SCI_BASE_OBJECT_T.
+ */
+typedef struct SCI_BASE_LOGGER
+{
+#if defined(SCI_LOGGING)
+   /**
+    * The field specifies that the parent object for the base logger
+    * is the base object itself.
+    */
+   SCI_BASE_OBJECT_T parent;
+
+   /**
+    * This filed specifies an array of objects mask.  There is one object
+    * mask for each verbosity level (e.g. ERROR, WARNING, etc.).  This
+    * allows for more flexible logging.
+    */
+   U32  object_mask[SCI_BASE_LOGGER_MAX_VERBOSITY_LEVELS];
+
+   /**
+    * This filed specifies which verbosity levels are currently enabled
+    * for logging
+    */
+   U32  verbosity_mask;
+#else // defined(SCI_LOGGING)
+   U8  dummy;
+#endif // defined(SCI_LOGGING)
+
+} SCI_BASE_LOGGER_T;
+
+#if defined(SCI_LOGGING)
+
+/**
+ * @brief This method simply performs initialization of the base logger object.
+ *
+ * @param[in] this_logger This parameter specifies the logger that we are
+ *            going to construct
+ *
+ * @return none
+ */
+void sci_base_logger_construct(
+   SCI_BASE_LOGGER_T *this_logger
+);
+
+#else // SCI_LOGGING
+
+#define sci_base_logger_construct
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCI_BASE_LOGGER_H_
diff --git a/sys/dev/disk/isci/scil/sci_base_memory_descriptor_list.c b/sys/dev/disk/isci/scil/sci_base_memory_descriptor_list.c
new file mode 100644
index 0000000..eb4d24e
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_base_memory_descriptor_list.c
@@ -0,0 +1,166 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_base_memory_descriptor_list.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains the base implementation for the memory
+ *        descriptor list.  This is currently comprised of MDL iterator
+ *        methods.
+ */
+
+#include <dev/disk/isci/scil/sci_base_memory_descriptor_list.h>
+
+//******************************************************************************
+//* P U B L I C   M E T H O D S
+//******************************************************************************
+
+void sci_mdl_first_entry(
+   SCI_MEMORY_DESCRIPTOR_LIST_HANDLE_T mdl
+)
+{
+   SCI_BASE_MEMORY_DESCRIPTOR_LIST_T * base_mdl = (SCI_BASE_MEMORY_DESCRIPTOR_LIST_T*) mdl;
+
+   base_mdl->next_index = 0;
+
+   // If this MDL is managing another MDL, then recursively rewind that MDL
+   // object as well.
+   if (base_mdl->next_mdl != SCI_INVALID_HANDLE)
+      sci_mdl_first_entry(base_mdl->next_mdl);
+}
+
+// ---------------------------------------------------------------------------
+
+void sci_mdl_next_entry(
+   SCI_MEMORY_DESCRIPTOR_LIST_HANDLE_T mdl
+)
+{
+   SCI_BASE_MEMORY_DESCRIPTOR_LIST_T * base_mdl = (SCI_BASE_MEMORY_DESCRIPTOR_LIST_T*) mdl;
+
+   // If there is at least one more entry left in the array, then change
+   // the next pointer to it.
+   if (base_mdl->next_index < base_mdl->length)
+      base_mdl->next_index++;
+   else if (base_mdl->next_index == base_mdl->length)
+   {
+      // This MDL has exhausted it's set of entries.  If this MDL is managing
+      // another MDL, then start iterating through that MDL.
+      if (base_mdl->next_mdl != SCI_INVALID_HANDLE)
+         sci_mdl_next_entry(base_mdl->next_mdl);
+   }
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_PHYSICAL_MEMORY_DESCRIPTOR_T * sci_mdl_get_current_entry(
+   SCI_MEMORY_DESCRIPTOR_LIST_HANDLE_T mdl
+)
+{
+   SCI_BASE_MEMORY_DESCRIPTOR_LIST_T * base_mdl = (SCI_BASE_MEMORY_DESCRIPTOR_LIST_T*) mdl;
+
+   if (base_mdl->next_index < base_mdl->length)
+      return & base_mdl->mde_array[base_mdl->next_index];
+   else if (base_mdl->next_index == base_mdl->length)
+   {
+      // This MDL has exhausted it's set of entries.  If this MDL is managing
+      // another MDL, then return it's current entry.
+      if (base_mdl->next_mdl != SCI_INVALID_HANDLE)
+         return sci_mdl_get_current_entry(base_mdl->next_mdl);
+   }
+
+   return NULL;
+}
+
+//******************************************************************************
+//* P R O T E C T E D   M E T H O D S
+//******************************************************************************
+
+void sci_base_mdl_construct(
+   SCI_BASE_MEMORY_DESCRIPTOR_LIST_T * mdl,
+   SCI_PHYSICAL_MEMORY_DESCRIPTOR_T  * mde_array,
+   U32                                 mde_array_length,
+   SCI_MEMORY_DESCRIPTOR_LIST_HANDLE_T next_mdl
+)
+{
+   mdl->length     = mde_array_length;
+   mdl->mde_array  = mde_array;
+   mdl->next_index = 0;
+   mdl->next_mdl   = next_mdl;
+}
+
+// ---------------------------------------------------------------------------
+
+BOOL sci_base_mde_is_valid(
+   SCI_PHYSICAL_MEMORY_DESCRIPTOR_T * mde,
+   U32                                alignment,
+   U32                                size,
+   U16                                attributes
+)
+{
+   // Only need the lower 32 bits to ensure alignment is met.
+   U32 physical_address = sci_cb_physical_address_lower(mde->physical_address);
+
+   if (
+         ((physical_address & (alignment - 1)) != 0)
+      || (mde->constant_memory_alignment != alignment)
+      || (mde->constant_memory_size != size)
+      || (mde->virtual_address == NULL)
+      || (mde->constant_memory_attributes != attributes)
+      )
+   {
+      return FALSE;
+   }
+
+   return TRUE;
+}
diff --git a/sys/dev/disk/isci/scil/sci_base_memory_descriptor_list.h b/sys/dev/disk/isci/scil/sci_base_memory_descriptor_list.h
new file mode 100644
index 0000000..0f61983
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_base_memory_descriptor_list.h
@@ -0,0 +1,168 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_base_memory_descriptor_list.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCI_BASE_MEMORY_DESCRIPTOR_LIST_H_
+#define _SCI_BASE_MEMORY_DESCRIPTOR_LIST_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains the protected interface structures, constants
+ *        and interface methods for the SCI_BASE_MEMORY_DESCRIPTOR_LIST
+ *        object.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/sci_memory_descriptor_list.h>
+
+
+/**
+ * @struct SCI_BASE_MEMORY_DESCRIPTOR_LIST
+ *
+ * @brief This structure contains all of the fields necessary to implement
+ *        a simple stack for managing the list of available controller indices.
+ */
+typedef struct SCI_BASE_MEMORY_DESCRIPTOR_LIST
+{
+   /**
+    * This field indicates the length of the memory descriptor entry array.
+    */
+   U32  length;
+
+   /**
+    * This field is utilized to provide iterator pattern functionality.
+    * It indicates the index of the next memory descriptor in the iteration.
+    */
+   U32  next_index;
+
+   /**
+    * This field will point to the list of memory descriptors.
+    */
+   SCI_PHYSICAL_MEMORY_DESCRIPTOR_T * mde_array;
+
+   /**
+    * This field simply allows a user to chain memory descriptor lists
+    * together if desired.  This field will be initialized to
+    * SCI_INVALID_HANDLE.
+    */
+   SCI_MEMORY_DESCRIPTOR_LIST_HANDLE_T  next_mdl;
+
+} SCI_BASE_MEMORY_DESCRIPTOR_LIST_T;
+
+/**
+ * @brief This method is invoked to construct an memory descriptor list.
+ *        It initializes the fields of the MDL.
+ *
+ * @param[in]  mdl This parameter specifies the memory descriptor list
+ *             to be constructed.
+ * @param[in]  mde_array This parameter specifies the array of memory
+ *             descriptor entries to be managed by this list.
+ * @param[in]  mde_array_length This parameter specifies the size of the
+ *             array of entries.
+ * @param[in]  next_mdl This parameter specifies a subsequent MDL object
+ *             to be managed by this MDL object.
+ *
+ * @return none.
+ */
+void sci_base_mdl_construct(
+   SCI_BASE_MEMORY_DESCRIPTOR_LIST_T * mdl,
+   SCI_PHYSICAL_MEMORY_DESCRIPTOR_T  * mde_array,
+   U32                                 mde_array_length,
+   SCI_MEMORY_DESCRIPTOR_LIST_HANDLE_T next_mdl
+);
+
+/**
+ * This macro constructs an memory descriptor entry with the given
+ * alignment and size
+ */
+#define sci_base_mde_construct(mde, alignment, size, attributes) \
+{ \
+   (mde)->constant_memory_alignment  = (alignment); \
+   (mde)->constant_memory_size       = (size); \
+   (mde)->constant_memory_attributes = (attributes); \
+}
+
+/**
+ * @brief This method validates that the memory descriptor is correctly
+ *        filled out by the SCI User
+ *
+ * @param[in] mde This parameter is the mde entry to validate
+ * @param[in] alignment This parameter specifies the expected alignment of
+ *            the memory for the mde.
+ * @param[in] size This parameter specifies the memory size expected for
+ *            the mde its value should not have been changed by the SCI
+ *            User.
+ * @param[in] attributes This parameter specifies the attributes for the
+ *            memory descriptor provided.
+ *
+ * @return BOOL This method returns an indication as to whether the
+ *              supplied MDE is valid or not.
+ * @retval TRUE The MDE is valid.
+ * @retval FALSE The MDE is not valid.
+ */
+BOOL sci_base_mde_is_valid(
+   SCI_PHYSICAL_MEMORY_DESCRIPTOR_T *mde,
+   U32                               alignment,
+   U32                               size,
+   U16                               attributes
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCI_BASE_MEMORY_DESCRIPTOR_LIST_H_
diff --git a/sys/dev/disk/isci/scil/sci_base_memory_descriptor_list_decorator.c b/sys/dev/disk/isci/scil/sci_base_memory_descriptor_list_decorator.c
new file mode 100644
index 0000000..d9b7681
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_base_memory_descriptor_list_decorator.c
@@ -0,0 +1,147 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_base_memory_descriptor_list_decorator.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains the base implementation for the memory
+ *        descriptor list decorator.  The decorator adds additional
+ *        functionality that may be used by SCI users to help
+ *        offload MDE processing.
+ */
+
+#include <dev/disk/isci/scil/sci_memory_descriptor_list_decorator.h>
+
+U32 sci_mdl_decorator_get_memory_size(
+   SCI_MEMORY_DESCRIPTOR_LIST_HANDLE_T mdl,
+   U32                                 attributes
+)
+{
+   U32                                size = 0;
+   SCI_PHYSICAL_MEMORY_DESCRIPTOR_T * mde;
+
+   sci_mdl_first_entry(mdl);
+   mde = sci_mdl_get_current_entry(mdl);
+   while (mde != NULL)
+   {
+      if (  (mde->constant_memory_attributes == attributes)
+         || (attributes == 0) )
+         size += (mde->constant_memory_size + mde->constant_memory_alignment);
+
+      sci_mdl_next_entry(mdl);
+      mde = sci_mdl_get_current_entry(mdl);
+   }
+
+   return size;
+}
+
+// ---------------------------------------------------------------------------
+
+void sci_mdl_decorator_assign_memory(
+   SCI_MEMORY_DESCRIPTOR_LIST_HANDLE_T mdl,
+   U32                                 attributes,
+   POINTER_UINT                        virtual_address,
+   SCI_PHYSICAL_ADDRESS                sci_physical_address
+)
+{
+   SCI_PHYSICAL_MEMORY_DESCRIPTOR_T * mde;
+   U64  physical_address;
+
+   physical_address
+      =   ((U64) sci_cb_physical_address_lower(sci_physical_address))
+        | (((U64) sci_cb_physical_address_upper(sci_physical_address)) << 32);
+
+   sci_mdl_first_entry(mdl);
+   mde = sci_mdl_get_current_entry(mdl);
+   while (mde != NULL)
+   {
+      // As long as the memory attribute for this MDE is equivalent to
+      // those supplied by the caller, then fill out the appropriate
+      // MDE fields.
+      if (  (mde->constant_memory_attributes == attributes)
+         || (attributes == 0) )
+      {
+         // Ensure the virtual address alignment rules are met.
+         if ((virtual_address % mde->constant_memory_alignment) != 0)
+         {
+            virtual_address
+               += (mde->constant_memory_alignment -
+                   (virtual_address % mde->constant_memory_alignment));
+         }
+
+         // Ensure the physical address alignment rules are met.
+         if ((physical_address % mde->constant_memory_alignment) != 0)
+         {
+            physical_address
+               += (mde->constant_memory_alignment -
+                   (physical_address % mde->constant_memory_alignment));
+         }
+
+         // Update the MDE with properly aligned address values.
+         mde->virtual_address  = (void *)virtual_address;
+         sci_cb_make_physical_address(
+            mde->physical_address,
+            (U32) (physical_address >> 32),
+            (U32) (physical_address & 0xFFFFFFFF)
+         );
+
+         virtual_address  += mde->constant_memory_size;
+         physical_address += mde->constant_memory_size;
+      }
+
+      // Move on to the next MDE
+      sci_mdl_next_entry(mdl);
+      mde = sci_mdl_get_current_entry (mdl);
+   }
+}
diff --git a/sys/dev/disk/isci/scil/sci_base_object.c b/sys/dev/disk/isci/scil/sci_base_object.c
new file mode 100644
index 0000000..f4c2d52
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_base_object.c
@@ -0,0 +1,116 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_base_object.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the method implementations for the
+ *        SCI_BASE_OBJECT object.
+ */
+
+#include <dev/disk/isci/scil/sci_status.h>
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/sci_base_object.h>
+
+//******************************************************************************
+//* P U B L I C   M E T H O D S
+//******************************************************************************
+
+#if defined(SCI_OBJECT_USE_ASSOCIATION_FUNCTIONS)
+void * sci_object_get_association(
+   SCI_OBJECT_HANDLE_T object
+)
+{
+   return ((SCI_BASE_OBJECT_T *) object)->associated_object;
+}
+#endif
+
+// ---------------------------------------------------------------------------
+
+#if defined(SCI_OBJECT_USE_ASSOCIATION_FUNCTIONS)
+SCI_STATUS sci_object_set_association(
+   SCI_OBJECT_HANDLE_T   object,
+   void                * associated_object
+)
+{
+   ((SCI_BASE_OBJECT_T *)object)->associated_object = associated_object;
+   return SCI_SUCCESS;
+}
+#endif
+
+// ---------------------------------------------------------------------------
+
+void sci_base_object_construct(
+   SCI_BASE_OBJECT_T      * base_object,
+   struct SCI_BASE_LOGGER * logger
+)
+{
+#if defined(SCI_LOGGING)
+   base_object->logger = logger;
+#endif // defined(SCI_LOGGING)
+   base_object->associated_object = NULL;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_LOGGER_HANDLE_T sci_object_get_logger(
+   SCI_OBJECT_HANDLE_T object
+)
+{
+#if defined(SCI_LOGGING)
+   return sci_base_object_get_logger(object);
+#else // defined(SCI_LOGGING)
+   return NULL;
+#endif // defined(SCI_LOGGING)
+}
diff --git a/sys/dev/disk/isci/scil/sci_base_object.h b/sys/dev/disk/isci/scil/sci_base_object.h
new file mode 100644
index 0000000..a5da314
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_base_object.h
@@ -0,0 +1,141 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_base_object.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCI_BASE_OBJECT_H_
+#define _SCI_BASE_OBJECT_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the method and constants associated with
+ *        the SCI base object.  The SCI base object is the class from which
+ *        all other objects derive in the Storage Controller Interface.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_object.h>
+
+// Forward declare the logger object
+struct SCI_BASE_LOGGER;
+
+/**
+ * @struct SCI_BASE_OBJECT
+ *
+ * @brief The SCI_BASE_OBJECT object represents the data and functionality
+ *        that is common to all SCI objects.  It is the base class.
+ */
+typedef struct SCI_BASE_OBJECT
+{
+   /**
+    * This field represents an association created by the user for this
+    * object.  The association can be whatever the user wishes.  Think of
+    * it as a cookie.
+    */
+   void * associated_object;
+
+   /**
+    * This field simply contains a handle to the logger object to be
+    * utilized when utilizing the logger interface.
+    */
+   struct SCI_BASE_LOGGER * logger;
+
+} SCI_BASE_OBJECT_T;
+
+
+/**
+ * @brief This method constructs the sci base object.
+ *
+ * @param[in]  base_object This parameter specifies the SCI base
+ *              object which we whish to construct.
+ * @param[in]  logger This parameter specifies the logger object to be
+ *             saved and utilized for this base object.
+ *
+ * @return none
+ */
+void sci_base_object_construct(
+   SCI_BASE_OBJECT_T      * base_object,
+   struct SCI_BASE_LOGGER * logger
+);
+
+#if defined(SCI_LOGGING)
+/**
+ * @brief This method returns the logger to which a previous
+ *         association was created.
+ *
+ * @param[in]  base_object This parameter specifies the SCI base object for
+ *             which to retrieve the logger.
+ *
+ * @return This method returns a pointer to the logger that was
+ *          previously associated to the supplied base_object
+ *          parameter.
+ * @retval NULL This value is returned when there is no logger
+ *         association for the supplied base_object instance.
+ */
+#define sci_base_object_get_logger(this_object) \
+   (((SCI_BASE_OBJECT_T *)(this_object))->logger)
+
+#else // defined(SCI_LOGGING)
+
+#define sci_base_object_get_logger(this_object) NULL
+
+#endif // defined(SCI_LOGGING)
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+
+#endif // _SCI_BASE_OBJECT_H_
diff --git a/sys/dev/disk/isci/scil/sci_base_observer.c b/sys/dev/disk/isci/scil/sci_base_observer.c
new file mode 100644
index 0000000..4d13d99
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_base_observer.c
@@ -0,0 +1,106 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_base_observer.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file implements the functionality common to all observer
+ *        objects.
+ */
+
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/sci_base_subject.h>
+#include <dev/disk/isci/scil/sci_base_observer.h>
+
+#if defined(SCI_LOGGING)
+
+//******************************************************************************
+//* P U B L I C   M E T H O D S
+//******************************************************************************
+
+void sci_base_observer_construct(
+   struct SCI_BASE_OBSERVER *this_observer,
+   SCI_BASE_OBSERVER_UPDATE_T update
+)
+{
+   this_observer->next = NULL;
+   this_observer->update = update;
+}
+
+// ---------------------------------------------------------------------------
+
+void sci_base_observer_initialize(
+   SCI_BASE_OBSERVER_T        * the_observer,
+   SCI_BASE_OBSERVER_UPDATE_T   update,
+   SCI_BASE_SUBJECT_T         * the_subject
+)
+{
+   sci_base_observer_construct(the_observer, update);
+   sci_base_subject_attach_observer(the_subject, the_observer);
+}
+
+// ---------------------------------------------------------------------------
+
+void sci_base_observer_update(
+   SCI_BASE_OBSERVER_T *this_observer,
+   SCI_BASE_SUBJECT_T  *the_subject
+)
+{
+   if (this_observer->update != NULL)
+   {
+      this_observer->update(this_observer, the_subject);
+   }
+}
+
+#endif // defined(SCI_LOGGING)
diff --git a/sys/dev/disk/isci/scil/sci_base_observer.h b/sys/dev/disk/isci/scil/sci_base_observer.h
new file mode 100644
index 0000000..0eb9e36
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_base_observer.h
@@ -0,0 +1,167 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_base_observer.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCI_BASE_OBSERVER_H_
+#define _SCI_BASE_OBSERVER_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the structures, constants, and methods
+ *        common to all base observer object definitions.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#if defined(SCI_LOGGING)
+
+struct SCI_BASE_OBSERVER;
+struct SCI_BASE_SUBJECT;
+
+/**
+ * @typedef SCI_BASE_OBSERVER_UPDATE_T
+ *
+ * @brief This type definition defines the format for the update method
+ *        that is invoked for all observers participating in the observer
+ *        design pattern.
+ */
+typedef void (*SCI_BASE_OBSERVER_UPDATE_T)(
+   struct SCI_BASE_OBSERVER *this_observer,
+   struct SCI_BASE_SUBJECT  *the_subject
+);
+
+/**
+ * @struct SCI_BASE_OBSERVER
+ *
+ * @brief This structure defines the fields necessary for an object that
+ *        intends to participate as an observer.
+ */
+typedef struct SCI_BASE_OBSERVER
+{
+   /**
+    * This filed points to the next observer if there is one
+    */
+    struct SCI_BASE_OBSERVER *next;
+
+   /**
+    * This field defines the function pointer that is invoked in order to
+    * notify the observer of a change in the subject (i.e. observed object).
+    */
+   SCI_BASE_OBSERVER_UPDATE_T update;
+
+} SCI_BASE_OBSERVER_T;
+
+/**
+ * @brief This method is the basic constructor for the observer
+ *
+ * @param[in] this_observer This parameter specifies the observer to
+ *            be constructed.
+ * @param[in] update This parameter specifies the update method to be
+ *            invoked for this observer.
+ *
+ * @return none
+ */
+void sci_base_observer_construct(
+   struct SCI_BASE_OBSERVER   *this_observer,
+   SCI_BASE_OBSERVER_UPDATE_T  update
+);
+
+/**
+ * @brief This method performs the actions of construction and attaches to the
+ *        subject.
+ *
+ * @pre The the_subject to be observed must be constructed before this call.
+ *
+ * @param[in] this_observer This parameter specifies the observer to construct
+ *       an attach to the subject.
+ * @param[in] update This parameter is the update function that is passed to
+ *       the constructor.
+ * @param[in] the_subject This parameter specifies the subject to observe.
+ */
+void sci_base_observer_initialize(
+   struct SCI_BASE_OBSERVER   *this_observer,
+   SCI_BASE_OBSERVER_UPDATE_T  update,
+   struct SCI_BASE_SUBJECT    *the_subject
+);
+
+/**
+ * @brief This method will call the observers update function
+ *
+ * @param[in] this_observer This parameter specifies the observer to be
+ *            notified.
+ * @param[in] the_subject This parameter indicates the subject for which
+ *            the update call is occurring.
+ *
+ * @return none
+ */
+void sci_base_observer_update(
+   struct SCI_BASE_OBSERVER *this_observer,
+   struct SCI_BASE_SUBJECT  *the_subject
+);
+
+#else // defined(SCI_LOGGING)
+
+typedef U8 SCI_BASE_OBSERVER_T;
+#define sci_base_observer_construct
+#define sci_base_observer_initialize
+#define sci_base_observer_update
+
+#endif // defined(SCI_LOGGING)
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCI_BASE_OBSERVER_H_
diff --git a/sys/dev/disk/isci/scil/sci_base_phy.c b/sys/dev/disk/isci/scil/sci_base_phy.c
new file mode 100644
index 0000000..f2a936f
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_base_phy.c
@@ -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: src/sys/dev/isci/scil/sci_base_phy.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains the base phy method implementations and
+ *        any constants or structures private to the base phy object.
+ */
+
+#include <dev/disk/isci/scil/sci_base_phy.h>
+#include <dev/disk/isci/scil/sci_base_state_machine.h>
+
+//******************************************************************************
+//* P R O T E C T E D   M E T H O D S
+//******************************************************************************
+
+void sci_base_phy_construct(
+   SCI_BASE_PHY_T    *this_phy,
+   SCI_BASE_LOGGER_T *logger,
+   SCI_BASE_STATE_T  *state_table
+)
+{
+   sci_base_object_construct(&this_phy->parent, logger);
+
+   sci_base_state_machine_construct(
+      &this_phy->state_machine,
+      &this_phy->parent,
+      state_table,
+      SCI_BASE_PHY_STATE_INITIAL
+   );
+
+   sci_base_state_machine_start(
+      &this_phy->state_machine
+   );
+}
diff --git a/sys/dev/disk/isci/scil/sci_base_phy.h b/sys/dev/disk/isci/scil/sci_base_phy.h
new file mode 100644
index 0000000..7c6a270
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_base_phy.h
@@ -0,0 +1,213 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_base_phy.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCI_BASE_PHY_H_
+#define _SCI_BASE_PHY_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the structures, constants, and methods
+ *        common to all phy object definitions.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_base_logger.h>
+#include <dev/disk/isci/scil/sci_base_state_machine.h>
+#include <dev/disk/isci/scil/sci_base_state_machine_logger.h>
+
+/**
+ * @enum SCI_BASE_PHY_STATES
+ *
+ * @brief This enumeration depicts the standard states common to all phy
+ *        state machine implementations.
+ */
+typedef enum _SCI_BASE_PHY_STATES
+{
+   /**
+    * Simply the initial state for the base domain state machine.
+    */
+   SCI_BASE_PHY_STATE_INITIAL,
+
+   /**
+    * This state indicates that the phy has successfully been stopped.
+    * In this state no new IO operations are permitted on this phy.
+    * This state is entered from the INITIAL state.
+    * This state is entered from the STARTING state.
+    * This state is entered from the READY state.
+    * This state is entered from the RESETTING state.
+    */
+   SCI_BASE_PHY_STATE_STOPPED,
+
+   /**
+    * This state indicates that the phy is in the process of becomming
+    * ready.  In this state no new IO operations are permitted on this phy.
+    * This state is entered from the STOPPED state.
+    * This state is entered from the READY state.
+    * This state is entered from the RESETTING state.
+    */
+   SCI_BASE_PHY_STATE_STARTING,
+
+   /**
+    * This state indicates the the phy is now ready.  Thus, the user
+    * is able to perform IO operations utilizing this phy as long as it
+    * is currently part of a valid port.
+    * This state is entered from the STARTING state.
+    */
+   SCI_BASE_PHY_STATE_READY,
+
+   /**
+    * This state indicates that the phy is in the process of being reset.
+    * In this state no new IO operations are permitted on this phy.
+    * This state is entered from the READY state.
+    */
+   SCI_BASE_PHY_STATE_RESETTING,
+
+   /**
+    * Simply the final state for the base phy state machine.
+    */
+   SCI_BASE_PHY_STATE_FINAL,
+
+   SCI_BASE_PHY_MAX_STATES
+
+} SCI_BASE_PHY_STATES;
+
+/**
+ * @struct SCI_BASE_PHY
+ *
+ * @brief This structure defines all of the fields common to PHY objects.
+ */
+typedef struct SCI_BASE_PHY
+{
+   /**
+    * This field depicts the parent object (SCI_BASE_OBJECT) for the phy.
+    */
+   SCI_BASE_OBJECT_T parent;
+
+   /**
+    * This field contains the information for the base phy state machine.
+    */
+   SCI_BASE_STATE_MACHINE_T state_machine;
+
+   #ifdef SCI_LOGGING
+   SCI_BASE_STATE_MACHINE_LOGGER_T state_machine_logger;
+   #endif // SCI_LOGGING
+
+} SCI_BASE_PHY_T;
+
+typedef SCI_STATUS (*SCI_BASE_PHY_HANDLER_T)(
+   SCI_BASE_PHY_T *
+);
+
+/**
+ * @struct SCI_BASE_PHY_STATE_HANDLER
+ *
+ * @brief This structure contains all of the state handler methods common to
+ *        base phy state machines.  Handler methods provide the ability
+ *        to change the behavior for user requests or transitions depending
+ *        on the state the machine is in.
+ */
+typedef struct SCI_BASE_PHY_STATE_HANDLER
+{
+   /**
+    * The start_handler specifies the method invoked when there is an
+    * attempt to start a phy.
+    */
+   SCI_BASE_PHY_HANDLER_T start_handler;
+
+   /**
+    * The stop_handler specifies the method invoked when there is an
+    * attempt to stop a phy.
+    */
+   SCI_BASE_PHY_HANDLER_T stop_handler;
+
+   /**
+    * The reset_handler specifies the method invoked when there is an
+    * attempt to reset a phy.
+    */
+   SCI_BASE_PHY_HANDLER_T reset_handler;
+
+   /**
+    * The destruct_handler specifies the method invoked when attempting to
+    * destruct a phy.
+    */
+   SCI_BASE_PHY_HANDLER_T destruct_handler;
+
+} SCI_BASE_PHY_STATE_HANDLER_T;
+
+/**
+ * @brief Construct the base phy
+ *
+ * @param[in] this_phy This parameter specifies the base phy to be
+ *            constructed.
+ * @param[in] logger This parameter specifies the logger associated with
+ *            this base phy object.
+ * @param[in] state_table This parameter specifies the table of state
+ *            definitions to be utilized for the phy state machine.
+ *
+ * @return none
+ */
+void sci_base_phy_construct(
+   SCI_BASE_PHY_T    * this_phy,
+   SCI_BASE_LOGGER_T * logger,
+   SCI_BASE_STATE_T  * state_table
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCI_BASE_PHY_H_
diff --git a/sys/dev/disk/isci/scil/sci_base_port.c b/sys/dev/disk/isci/scil/sci_base_port.c
new file mode 100644
index 0000000..510347e
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_base_port.c
@@ -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: src/sys/dev/isci/scil/sci_base_port.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains the base port method implementations and
+ *        any constants or structures private to the base port object.
+ */
+
+#include <dev/disk/isci/scil/sci_base_port.h>
+
+//******************************************************************************
+//* P R O T E C T E D   M E T H O D S
+//******************************************************************************
+
+void sci_base_port_construct(
+   SCI_BASE_PORT_T   *this_port,
+   SCI_BASE_LOGGER_T *logger,
+   SCI_BASE_STATE_T  *state_table
+)
+{
+   sci_base_object_construct(&this_port->parent, logger);
+
+   sci_base_state_machine_construct(
+      &this_port->state_machine,
+      &this_port->parent,
+      state_table,
+      SCI_BASE_PORT_STATE_STOPPED
+   );
+
+   sci_base_state_machine_start(
+      &this_port->state_machine
+   );
+}
diff --git a/sys/dev/disk/isci/scil/sci_base_port.h b/sys/dev/disk/isci/scil/sci_base_port.h
new file mode 100644
index 0000000..e52b4a5
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_base_port.h
@@ -0,0 +1,233 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_base_port.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCI_BASE_PORT_H_
+#define _SCI_BASE_PORT_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the structures, constants, and methods
+ *        common to all port object definitions.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_base_object.h>
+#include <dev/disk/isci/scil/sci_base_logger.h>
+#include <dev/disk/isci/scil/sci_base_state_machine.h>
+#include <dev/disk/isci/scil/sci_base_state_machine_logger.h>
+
+/**
+ * @enum SCI_BASE_PORT_STATES
+ *
+ * @brief This enumeration depicts all the states for the common port
+ *        state machine.
+ */
+typedef enum _SCI_BASE_PORT_STATES
+{
+   /**
+    * This state indicates that the port has successfully been stopped.
+    * In this state no new IO operations are permitted.
+    * This state is entered from the STOPPING state.
+    */
+   SCI_BASE_PORT_STATE_STOPPED,
+
+   /**
+    * This state indicates that the port is in the process of stopping.
+    * In this state no new IO operations are permitted, but existing IO
+    * operations are allowed to complete.
+    * This state is entered from the READY state.
+    */
+   SCI_BASE_PORT_STATE_STOPPING,
+
+   /**
+    * This state indicates the port is now ready.  Thus, the user is
+    * able to perform IO operations on this port.
+    * This state is entered from the STARTING state.
+    */
+   SCI_BASE_PORT_STATE_READY,
+
+   /**
+    * This state indicates the port is in the process of performing a hard
+    * reset.  Thus, the user is unable to perform IO operations on this
+    * port.
+    * This state is entered from the READY state.
+    */
+   SCI_BASE_PORT_STATE_RESETTING,
+
+   /**
+    * This state indicates the port has failed a reset request.  This state
+    * is entered when a port reset request times out.
+    * This state is entered from the RESETTING state.
+    */
+   SCI_BASE_PORT_STATE_FAILED,
+
+   SCI_BASE_PORT_MAX_STATES
+
+} SCI_BASE_PORT_STATES;
+
+/**
+ * @struct SCI_BASE_PORT
+ *
+ * @brief The base port object abstracts the fields common to all SCI
+ *        port objects.
+ */
+typedef struct SCI_BASE_PORT
+{
+   /**
+    * The field specifies that the parent object for the base controller
+    * is the base object itself.
+    */
+   SCI_BASE_OBJECT_T parent;
+
+   /**
+    * This field contains the information for the base port state machine.
+    */
+   SCI_BASE_STATE_MACHINE_T state_machine;
+
+   #ifdef SCI_LOGGING
+   SCI_BASE_STATE_MACHINE_LOGGER_T state_machine_logger;
+   #endif // SCI_LOGGING
+
+} SCI_BASE_PORT_T;
+
+struct SCI_BASE_PHY;
+
+typedef SCI_STATUS (*SCI_BASE_PORT_HANDLER_T)(
+   SCI_BASE_PORT_T *
+);
+
+typedef SCI_STATUS (*SCI_BASE_PORT_PHY_HANDLER_T)(
+   SCI_BASE_PORT_T *,
+   struct SCI_BASE_PHY *
+);
+
+typedef SCI_STATUS (*SCI_BASE_PORT_RESET_HANDLER_T)(
+   SCI_BASE_PORT_T *,
+   U32 timeout
+);
+
+/**
+ * @struct SCI_BASE_PORT_STATE_HANDLER
+ *
+ * @brief This structure contains all of the state handler methods common to
+ *        base port state machines.  Handler methods provide the ability
+ *        to change the behavior for user requests or transitions depending
+ *        on the state the machine is in.
+ */
+typedef struct SCI_BASE_PORT_STATE_HANDLER
+{
+   /**
+    * The start_handler specifies the method invoked when a user attempts to
+    * start a port.
+    */
+   SCI_BASE_PORT_HANDLER_T start_handler;
+
+   /**
+    * The stop_handler specifies the method invoked when a user attempts to
+    * stop a port.
+    */
+   SCI_BASE_PORT_HANDLER_T stop_handler;
+
+   /**
+    * The destruct_handler specifies the method invoked when attempting to
+    * destruct a port.
+    */
+   SCI_BASE_PORT_HANDLER_T destruct_handler;
+
+   /**
+    * The reset_handler specifies the method invoked when a user attempts to
+    * hard reset a port.
+    */
+   SCI_BASE_PORT_RESET_HANDLER_T reset_handler;
+
+   /**
+    * The add_phy_handler specifies the method invoked when a user attempts to
+    * add another phy into the port.
+    */
+   SCI_BASE_PORT_PHY_HANDLER_T add_phy_handler;
+
+   /**
+    * The remove_phy_handler specifies the method invoked when a user
+    * attempts to remove a phy from the port.
+    */
+   SCI_BASE_PORT_PHY_HANDLER_T remove_phy_handler;
+
+} SCI_BASE_PORT_STATE_HANDLER_T;
+
+/**
+ * @brief Construct the base port object
+ *
+ * @param[in] this_port This parameter specifies the base port to be
+ *            constructed.
+ * @param[in] logger This parameter specifies the logger to be associated
+ *            with this base port object.
+ * @param[in] state_table This parameter specifies the table of state
+ *            definitions to be utilized for the domain state machine.
+ *
+ * @return none
+ */
+void sci_base_port_construct(
+   SCI_BASE_PORT_T   * this_port,
+   SCI_BASE_LOGGER_T * logger,
+   SCI_BASE_STATE_T  * state_table
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCI_BASE_PORT_H_
diff --git a/sys/dev/disk/isci/scil/sci_base_remote_device.c b/sys/dev/disk/isci/scil/sci_base_remote_device.c
new file mode 100644
index 0000000..1ec73d0
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_base_remote_device.c
@@ -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: src/sys/dev/isci/scil/sci_base_remote_device.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+#include <dev/disk/isci/scil/sci_base_remote_device.h>
+
+void sci_base_remote_device_construct(
+   SCI_BASE_REMOTE_DEVICE_T *this_device,
+   SCI_BASE_LOGGER_T        *logger,
+   SCI_BASE_STATE_T         *state_table
+)
+{
+   sci_base_object_construct(
+      &this_device->parent,
+      logger
+   );
+
+   sci_base_state_machine_construct(
+      &this_device->state_machine,
+      &this_device->parent,
+      state_table,
+      SCI_BASE_REMOTE_DEVICE_STATE_INITIAL
+   );
+
+   sci_base_state_machine_start(
+      &this_device->state_machine
+   );
+}
diff --git a/sys/dev/disk/isci/scil/sci_base_remote_device.h b/sys/dev/disk/isci/scil/sci_base_remote_device.h
new file mode 100644
index 0000000..2158861
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_base_remote_device.h
@@ -0,0 +1,298 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_base_remote_device.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCI_BASE_REMOTE_DEVICE_H_
+#define _SCI_BASE_REMOTE_DEVICE_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the structures, constants, and methods
+ *        common to all remote device object definitions.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_base_state_machine.h>
+#include <dev/disk/isci/scil/sci_base_logger.h>
+#include <dev/disk/isci/scil/sci_base_state_machine_logger.h>
+
+struct SCI_BASE_REQUEST;
+
+/**
+ * @enum SCI_BASE_REMOTE_DEVICE_STATES
+ *
+ * @brief This enumeration depicts all the states for the common remote device
+ *        state machine.
+ */
+typedef enum _SCI_BASE_REMOTE_DEVICE_STATES
+{
+   /**
+    * Simply the initial state for the base remote device state machine.
+    */
+   SCI_BASE_REMOTE_DEVICE_STATE_INITIAL,
+
+   /**
+    * This state indicates that the remote device has successfully been
+    * stopped.  In this state no new IO operations are permitted.
+    * This state is entered from the INITIAL state.
+    * This state is entered from the STOPPING state.
+    */
+   SCI_BASE_REMOTE_DEVICE_STATE_STOPPED,
+
+   /**
+    * This state indicates the the remote device is in the process of
+    * becoming ready (i.e. starting).  In this state no new IO operations
+    * are permitted.
+    * This state is entered from the STOPPED state.
+    */
+   SCI_BASE_REMOTE_DEVICE_STATE_STARTING,
+
+   /**
+    * This state indicates the remote device is now ready.  Thus, the user
+    * is able to perform IO operations on the remote device.
+    * This state is entered from the STARTING state.
+    */
+   SCI_BASE_REMOTE_DEVICE_STATE_READY,
+
+   /**
+    * This state indicates that the remote device is in the process of
+    * stopping.  In this state no new IO operations are permitted, but
+    * existing IO operations are allowed to complete.
+    * This state is entered from the READY state.
+    * This state is entered from the FAILED state.
+    */
+   SCI_BASE_REMOTE_DEVICE_STATE_STOPPING,
+
+   /**
+    * This state indicates that the remote device has failed.
+    * In this state no new IO operations are permitted.
+    * This state is entered from the INITIALIZING state.
+    * This state is entered from the READY state.
+    */
+   SCI_BASE_REMOTE_DEVICE_STATE_FAILED,
+
+   /**
+    * This state indicates the device is being reset.
+    * In this state no new IO operations are permitted.
+    * This state is entered from the READY state.
+    */
+   SCI_BASE_REMOTE_DEVICE_STATE_RESETTING,
+
+#if !defined(DISABLE_WIDE_PORTED_TARGETS)
+   /**
+    * This state indicates the device is in the middle of updating
+    * its port width. All the IOs sent to this device will be Quiesced.
+    */
+   SCI_BASE_REMOTE_DEVICE_STATE_UPDATING_PORT_WIDTH,
+#endif
+
+   /**
+    * Simply the final state for the base remote device state machine.
+    */
+   SCI_BASE_REMOTE_DEVICE_STATE_FINAL,
+
+   SCI_BASE_REMOTE_DEVICE_MAX_STATES
+
+} SCI_BASE_REMOTE_DEVICE_STATES;
+
+/**
+ * @struct SCI_BASE_REMOTE_DEVICE
+ *
+ * @brief The base remote device object abstracts the fields common to all
+ *        SCI remote device objects.
+ */
+typedef struct SCI_BASE_REMOTE_DEVICE
+{
+   /**
+    * The field specifies that the parent object for the base remote
+    * device is the base object itself.
+    */
+   SCI_BASE_OBJECT_T parent;
+
+   /**
+    * This field contains the information for the base remote device state
+    * machine.
+    */
+   SCI_BASE_STATE_MACHINE_T state_machine;
+
+   #ifdef SCI_LOGGING
+   /**
+    * This field contains the state machine observer for the state machine.
+    */
+   SCI_BASE_STATE_MACHINE_LOGGER_T state_machine_logger;
+   #endif // SCI_LOGGING
+
+} SCI_BASE_REMOTE_DEVICE_T;
+
+
+typedef SCI_STATUS (*SCI_BASE_REMOTE_DEVICE_HANDLER_T)(
+   SCI_BASE_REMOTE_DEVICE_T *
+);
+
+typedef SCI_STATUS (*SCI_BASE_REMOTE_DEVICE_REQUEST_HANDLER_T)(
+   SCI_BASE_REMOTE_DEVICE_T *,
+   struct SCI_BASE_REQUEST *
+);
+
+typedef SCI_STATUS (*SCI_BASE_REMOTE_DEVICE_HIGH_PRIORITY_REQUEST_COMPLETE_HANDLER_T)(
+   SCI_BASE_REMOTE_DEVICE_T *,
+   struct SCI_BASE_REQUEST *,
+   void *,
+   SCI_IO_STATUS
+);
+
+/**
+ * @struct SCI_BASE_CONTROLLER_STATE_HANDLER
+ *
+ * @brief This structure contains all of the state handler methods common to
+ *        base remote device state machines.  Handler methods provide the ability
+ *        to change the behavior for user requests or transitions depending
+ *        on the state the machine is in.
+ */
+typedef struct SCI_BASE_REMOTE_DEVICE_STATE_HANDLER
+{
+   /**
+    * The start_handler specifies the method invoked when a user attempts to
+    * start a remote device.
+    */
+   SCI_BASE_REMOTE_DEVICE_HANDLER_T start_handler;
+
+   /**
+    * The stop_handler specifies the method invoked when a user attempts to
+    * stop a remote device.
+    */
+   SCI_BASE_REMOTE_DEVICE_HANDLER_T stop_handler;
+
+   /**
+    * The fail_handler specifies the method invoked when a remote device
+    * failure has occurred.  A failure may be due to an inability to
+    * initialize/configure the device.
+    */
+   SCI_BASE_REMOTE_DEVICE_HANDLER_T fail_handler;
+
+   /**
+    * The destruct_handler specifies the method invoked when attempting to
+    * destruct a remote device.
+    */
+   SCI_BASE_REMOTE_DEVICE_HANDLER_T destruct_handler;
+
+   /**
+    * The reset handler specifies the method invloked when requesting to reset a
+    * remote device.
+    */
+   SCI_BASE_REMOTE_DEVICE_HANDLER_T reset_handler;
+
+   /**
+    * The reset complete handler specifies the method invloked when reporting
+    * that a reset has completed to the remote device.
+    */
+   SCI_BASE_REMOTE_DEVICE_HANDLER_T reset_complete_handler;
+
+   /**
+    * The start_io_handler specifies the method invoked when a user
+    * attempts to start an IO request for a remote device.
+    */
+   SCI_BASE_REMOTE_DEVICE_REQUEST_HANDLER_T start_io_handler;
+
+   /**
+    * The complete_io_handler specifies the method invoked when a user
+    * attempts to complete an IO request for a remote device.
+    */
+   SCI_BASE_REMOTE_DEVICE_REQUEST_HANDLER_T complete_io_handler;
+
+   /**
+    * The continue_io_handler specifies the method invoked when a user
+    * attempts to continue an IO request for a remote device.
+    */
+   SCI_BASE_REMOTE_DEVICE_REQUEST_HANDLER_T continue_io_handler;
+
+   /**
+    * The start_task_handler specifies the method invoked when a user
+    * attempts to start a task management request for a remote device.
+    */
+   SCI_BASE_REMOTE_DEVICE_REQUEST_HANDLER_T start_task_handler;
+
+   /**
+    * The complete_task_handler specifies the method invoked when a user
+    * attempts to complete a task management request for a remote device.
+    */
+   SCI_BASE_REMOTE_DEVICE_REQUEST_HANDLER_T complete_task_handler;
+
+} SCI_BASE_REMOTE_DEVICE_STATE_HANDLER_T;
+
+/**
+ * @brief Construct the base remote device
+ *
+ * @param[in] this_remote_device This parameter specifies the base remote
+ *            device to be constructed.
+ * @param[in] logger This parameter specifies the logger associated with
+ *            this base remote device object.
+ * @param[in] state_table This parameter specifies the table of state
+ *            definitions to be utilized for the remote device state machine.
+ *
+ * @return none
+ */
+void sci_base_remote_device_construct(
+   SCI_BASE_REMOTE_DEVICE_T * this_device,
+   SCI_BASE_LOGGER_T        * logger,
+   SCI_BASE_STATE_T         * state_table
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCI_BASE_REMOTE_DEVICE_H_
diff --git a/sys/dev/disk/isci/scil/sci_base_request.c b/sys/dev/disk/isci/scil/sci_base_request.c
new file mode 100644
index 0000000..74230d8
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_base_request.c
@@ -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: src/sys/dev/isci/scil/sci_base_request.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+#include <dev/disk/isci/scil/sci_base_request.h>
+
+void sci_base_request_construct(
+   SCI_BASE_REQUEST_T *this_request,
+   SCI_BASE_LOGGER_T  *my_logger,
+   SCI_BASE_STATE_T   *my_state_table
+)
+{
+   sci_base_object_construct(
+      &this_request->parent,
+      my_logger
+   );
+
+   sci_base_state_machine_construct(
+      &this_request->state_machine,
+      &this_request->parent,
+      my_state_table,
+      SCI_BASE_REQUEST_STATE_INITIAL
+   );
+
+   sci_base_state_machine_start(
+      &this_request->state_machine
+   );
+}
diff --git a/sys/dev/disk/isci/scil/sci_base_request.h b/sys/dev/disk/isci/scil/sci_base_request.h
new file mode 100644
index 0000000..25c9320
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_base_request.h
@@ -0,0 +1,209 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_base_request.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCI_BASE_REQUST_H_
+#define _SCI_BASE_REQUST_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the constants, types, and method
+ *        declarations for the SCI base IO and task request objects.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_base_logger.h>
+#include <dev/disk/isci/scil/sci_base_state_machine.h>
+#include <dev/disk/isci/scil/sci_base_state_machine_logger.h>
+
+/**
+ * @enum SCI_BASE_REQUEST_STATES
+ *
+ * @brief This enumeration depicts all the states for the common request
+ *        state machine.
+ */
+typedef enum _SCI_BASE_REQUEST_STATES
+{
+   /**
+    * Simply the initial state for the base request state machine.
+    */
+   SCI_BASE_REQUEST_STATE_INITIAL,
+
+   /**
+    * This state indicates that the request has been constructed. This state
+    * is entered from the INITIAL state.
+    */
+   SCI_BASE_REQUEST_STATE_CONSTRUCTED,
+
+   /**
+    * This state indicates that the request has been started. This state is
+    * entered from the CONSTRUCTED state.
+    */
+   SCI_BASE_REQUEST_STATE_STARTED,
+
+   /**
+    * This state indicates that the request has completed.
+    * This state is entered from the STARTED state. This state is entered from
+    * the ABORTING state.
+    */
+   SCI_BASE_REQUEST_STATE_COMPLETED,
+
+   /**
+    * This state indicates that the request is in the process of being
+    * terminated/aborted.
+    * This state is entered from the CONSTRUCTED state.
+    * This state is entered from the STARTED state.
+    */
+   SCI_BASE_REQUEST_STATE_ABORTING,
+
+   /**
+    * Simply the final state for the base request state machine.
+    */
+   SCI_BASE_REQUEST_STATE_FINAL,
+
+   SCI_BASE_REQUEST_MAX_STATES
+
+} SCI_BASE_REQUEST_STATES;
+
+/**
+ * @struct SCI_BASE_REQUEST
+ *
+ * @brief The base request object abstracts the fields common to all SCI IO
+ *        and task request objects.
+ */
+typedef struct SCI_BASE_REQUEST
+{
+   /**
+    * The field specifies that the parent object for the base request is the
+    * base object itself.
+    */
+   SCI_BASE_OBJECT_T parent;
+
+   /**
+    * This field contains the information for the base request state machine.
+    */
+   SCI_BASE_STATE_MACHINE_T state_machine;
+
+   #ifdef SCI_LOGGING
+   SCI_BASE_STATE_MACHINE_LOGGER_T state_machine_logger;
+   #endif // SCI_LOGGING
+
+} SCI_BASE_REQUEST_T;
+
+typedef SCI_STATUS (*SCI_BASE_REQUEST_HANDLER_T)(
+   SCI_BASE_REQUEST_T * this_request
+);
+
+/**
+ * @struct SCI_BASE_REQUEST_STATE_HANDLER
+ *
+ * @brief This structure contains all of the state handler methods common to
+ *        base IO and task request state machines.  Handler methods provide
+ *        the ability to change the behavior for user requests or
+ *        transitions depending on the state the machine is in.
+ *
+ */
+typedef struct SCI_BASE_REQUEST_STATE_HANDLER
+{
+   /**
+    * The start_handler specifies the method invoked when a user attempts to
+    * start a request.
+    */
+   SCI_BASE_REQUEST_HANDLER_T start_handler;
+
+   /**
+    * The abort_handler specifies the method invoked when a user attempts to
+    * abort a request.
+    */
+   SCI_BASE_REQUEST_HANDLER_T abort_handler;
+
+   /**
+    * The complete_handler specifies the method invoked when a user attempts to
+    * complete a request.
+    */
+   SCI_BASE_REQUEST_HANDLER_T complete_handler;
+
+   /**
+    * The destruct_handler specifies the method invoked when a user attempts to
+    * destruct a request.
+    */
+   SCI_BASE_REQUEST_HANDLER_T destruct_handler;
+
+} SCI_BASE_REQUEST_STATE_HANDLER_T;
+
+/**
+ * @brief Construct the base request.
+ *
+ * @param[in] this_request This parameter specifies the base request
+ *            to be constructed.
+ * @param[in] logger This parameter specifies the logger associated with
+ *            this base request object.
+ * @param[in] state_table This parameter specifies the table of state
+ *            definitions to be utilized for the request state machine.
+ *
+ * @return none
+ */
+void sci_base_request_construct(
+   SCI_BASE_REQUEST_T    * this_request,
+   SCI_BASE_LOGGER_T     * logger,
+   SCI_BASE_STATE_T      * state_table
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCI_BASE_REQUST_H_
diff --git a/sys/dev/disk/isci/scil/sci_base_state.h b/sys/dev/disk/isci/scil/sci_base_state.h
new file mode 100644
index 0000000..58184cd
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_base_state.h
@@ -0,0 +1,110 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_base_state.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCI_BASE_STATE_H_
+#define _SCI_BASE_STATE_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the structures, constants, and methods
+ *        common to all base object definitions.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_base_object.h>
+
+typedef void (*SCI_BASE_STATE_HANDLER_T)(
+   void
+);
+
+typedef void (*SCI_STATE_TRANSITION_T)(
+   SCI_BASE_OBJECT_T *base_object
+);
+
+/**
+ * @struct SCI_BASE_STATE
+ *
+ * @brief The base state object abstracts the fields common to all state
+ *        objects defined in SCI.
+ */
+typedef struct SCI_BASE_STATE
+{
+   /**
+    * This field indicates the defined value for this state.  After
+    * initialization this field should not change.
+    */
+   U32  value;
+
+   /**
+    * This field is a function pointer that defines the method to be
+    * invoked when the state is entered.
+    */
+   SCI_STATE_TRANSITION_T  enter_state;
+
+   /**
+    * This field is a function pointer that defines the method to be
+    * invoked when the state is exited.
+    */
+   SCI_STATE_TRANSITION_T  exit_state;
+
+} SCI_BASE_STATE_T;
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCI_BASE_STATE_H_
diff --git a/sys/dev/disk/isci/scil/sci_base_state_machine.c b/sys/dev/disk/isci/scil/sci_base_state_machine.c
new file mode 100644
index 0000000..2fe0fcb
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_base_state_machine.c
@@ -0,0 +1,210 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_base_state_machine.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the functionality common to all state
+ *        machine object implementations.
+ */
+
+#include <dev/disk/isci/scil/sci_base_state_machine.h>
+
+#define SCI_STATE_MACHINE_EXIT_STATE(state_machine) \
+   if ( \
+       ((state_machine)->state_table[(state_machine)->current_state_id].\
+          exit_state != NULL) \
+      ) \
+   { \
+      ((state_machine)->state_table[(state_machine)->current_state_id].\
+      exit_state((state_machine)->state_machine_owner)); \
+   }
+
+#define SCI_STATE_MACHINE_ENTER_STATE(state_machine) \
+      ((state_machine)->state_table[(state_machine)->current_state_id].\
+      enter_state((state_machine)->state_machine_owner))
+
+#define SCI_STATE_MACHINE_SET_STATE(state_machine, id) \
+   ((state_machine)->current_state_id = (id))
+
+//******************************************************************************
+//* P R O T E C T E D    M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method will set the initial state and state table
+ *        for the state machine. The caller should follow this
+ *        request with the initialize request to cause the state
+ *        machine to start.
+ *
+ * @param[in] this_state_machine This parameter provides the state machine
+ *            object to be constructed.
+ * @param[in] state_machine_owner This parameter indicates the object that
+ *            is owns the state machine being constructed.
+ * @param[in] state_table This parameter specifies the table of state objects
+ *            that is managed by this state machine.
+ * @param[in] initial_state This parameter specifies the value of the initial
+ *            state for this state machine.
+ *
+ * @return none
+ */
+void sci_base_state_machine_construct(
+   SCI_BASE_STATE_MACHINE_T * this_state_machine,
+   SCI_BASE_OBJECT_T        * my_state_machine_owner,
+   SCI_BASE_STATE_T         * state_table,
+   U32                        initial_state
+)
+{
+#if defined(SCI_LOGGING)
+   sci_base_subject_construct(&this_state_machine->parent);
+#endif // defined(SCI_LOGGING)
+
+   this_state_machine->state_machine_owner = my_state_machine_owner;
+   this_state_machine->initial_state_id  = initial_state;
+   this_state_machine->previous_state_id = initial_state;
+   this_state_machine->current_state_id  = initial_state;
+   this_state_machine->state_table       = state_table;
+}
+
+/**
+ * @brief This method will cause the state machine to enter the
+ *        initial state.
+ *
+ * @see sci_base_state_machine_construct() for how to set the initial state
+ *
+ * @param[in] this_state_machine This parameter specifies the state machine
+ *            that is to be started.
+ *
+ * @return none
+ */
+void sci_base_state_machine_start(
+   SCI_BASE_STATE_MACHINE_T *this_state_machine
+)
+{
+   SCI_STATE_MACHINE_SET_STATE(
+      this_state_machine, this_state_machine->initial_state_id
+   );
+
+#if defined(SCI_BASE_ENABLE_SUBJECT_NOTIFICATION)
+   sci_base_subject_notify(&this_state_machine->parent);
+#endif
+
+   SCI_STATE_MACHINE_ENTER_STATE(this_state_machine);
+}
+
+/**
+ * @brief This method will cause the state machine to exit it's current
+ *        state only.
+ *
+ * @param[in] this_state_machine This parameter specifies the state machine
+ *            that is to be stopped.
+ *
+ * @return none
+ */
+void sci_base_state_machine_stop(
+   SCI_BASE_STATE_MACHINE_T *this_state_machine
+)
+{
+   SCI_STATE_MACHINE_EXIT_STATE(this_state_machine);
+
+#if defined(SCI_BASE_ENABLE_SUBJECT_NOTIFICATION)
+   sci_base_subject_notify(&this_state_machine->parent);
+#endif
+}
+
+/**
+ * @brief This method performs an update to the current state of
+ *        the state machine.
+ *
+ * @param[in] this_state_machine This parameter specifies the state machine
+ *            for which the caller wishes to perform a state change.
+ * @param[in] next_state This parameter specifies the new state for the
+ *            state machine.
+ *
+ * @return none
+ */
+void sci_base_state_machine_change_state(
+   SCI_BASE_STATE_MACHINE_T *this_state_machine,
+   U32   next_state
+)
+{
+   SCI_STATE_MACHINE_EXIT_STATE(this_state_machine);
+
+   this_state_machine->previous_state_id = this_state_machine->current_state_id;
+   SCI_STATE_MACHINE_SET_STATE(this_state_machine, next_state);
+
+#if defined(SCI_BASE_ENABLE_SUBJECT_NOTIFICATION)
+   // Notify of the state change prior to entering the state.
+   sci_base_subject_notify(&this_state_machine->parent);
+#endif
+
+   SCI_STATE_MACHINE_ENTER_STATE(this_state_machine);
+}
+
+/**
+ * @brief This method simply returns the current state of the
+ *         state machine to the caller.
+ *
+ * @param[in] this_state_machine  This parameter specifies the state
+ *            machine for which to retrieve the current state.
+ *
+ * @return This method returns a U32 value indicating the current state for
+ *         the supplied state machine.
+ */
+U32 sci_base_state_machine_get_state(
+   SCI_BASE_STATE_MACHINE_T *this_state_machine
+)
+{
+   return this_state_machine->current_state_id;
+}
diff --git a/sys/dev/disk/isci/scil/sci_base_state_machine.h b/sys/dev/disk/isci/scil/sci_base_state_machine.h
new file mode 100644
index 0000000..9a8a5ec
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_base_state_machine.h
@@ -0,0 +1,157 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_base_state_machine.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCI_BASE_STATE_MACHINE_H_
+#define _SCI_BASE_STATE_MACHINE_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all structures, constants, or method declarations
+ *        common to all state machines defined in SCI.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_base_subject.h>
+#include <dev/disk/isci/scil/sci_base_state.h>
+
+
+/**
+ * This macro simply provides simplified retrieval of an objects state
+ * handler.
+ */
+#define SET_STATE_HANDLER(object, table, state) \
+   (object)->state_handlers = &(table)[(state)]
+
+/**
+ * @struct SCI_BASE_STATE_MACHINE
+ *
+ * @brief This structure defines the fields common to all state machines.
+ */
+typedef struct SCI_BASE_STATE_MACHINE
+{
+#if defined(SCI_LOGGING)
+   /**
+    * The state machine object participates in the observer design pattern.
+    * Thus, the SCI_BASE_SUBJECT is the parent object, which allows a
+    * state machine to be easily monitored by a user.
+    */
+   SCI_BASE_SUBJECT_T parent;
+#endif // defined(SCI_LOGGING)
+
+   /**
+    * This field points to the start of the state machine's state table.
+    */
+   SCI_BASE_STATE_T * state_table;
+
+   /**
+    * This field points to the object to which this state machine is
+    * associated.  It serves as a cookie to be provided to the state
+    * enter/exit methods.
+    */
+   SCI_BASE_OBJECT_T * state_machine_owner;
+
+   /**
+    * This field simply indicates the state value for the state machine's
+    * initial state.
+    */
+   U32  initial_state_id;
+
+   /**
+    * This field indicates the current state of the state machine.
+    */
+   U32  current_state_id;
+
+   /**
+    * This field indicates the previous state of the state machine.
+    */
+   U32  previous_state_id;
+
+} SCI_BASE_STATE_MACHINE_T;
+
+//******************************************************************************
+//* P R O T E C T E D    M E T H O D S
+//******************************************************************************
+
+void sci_base_state_machine_construct(
+   SCI_BASE_STATE_MACHINE_T *this_state_machine,
+   SCI_BASE_OBJECT_T        *state_machine_owner,
+   SCI_BASE_STATE_T         *state_table,
+   U32                       initial_state
+);
+
+void sci_base_state_machine_start(
+   SCI_BASE_STATE_MACHINE_T *this_state_machine
+);
+
+void sci_base_state_machine_stop(
+   SCI_BASE_STATE_MACHINE_T *this_state_machine
+);
+
+void sci_base_state_machine_change_state(
+   SCI_BASE_STATE_MACHINE_T *this_state_machine,
+   U32                       next_state
+);
+
+U32 sci_base_state_machine_get_state(
+   SCI_BASE_STATE_MACHINE_T *this_state_machine
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCI_BASE_STATE_MACHINE_H_
diff --git a/sys/dev/disk/isci/scil/sci_base_state_machine_logger.c b/sys/dev/disk/isci/scil/sci_base_state_machine_logger.c
new file mode 100644
index 0000000..e3c6367
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_base_state_machine_logger.c
@@ -0,0 +1,215 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_base_state_machine_logger.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file provides the public and protected implementations for the
+ *        state machine logger.  The state machine logger will provide debug
+ *        log information on a state machine for each state transition.
+ */
+
+#include <dev/disk/isci/scil/sci_base_state_machine_logger.h>
+
+#if defined(SCI_LOGGING)
+
+//******************************************************************************
+//* P R O T E C T E D    M E T H O D S
+//******************************************************************************
+
+/**
+ * This is the function that is called when the state machine wants to notify
+ * this observer that there has been a state change.
+ *
+ * @param[in] observer The state machine logger that is observing the state
+ *       machine.
+ * @param[in] subject The state machine that is being observed.
+ */
+static
+void sci_base_state_machine_logger_update(
+   SCI_BASE_OBSERVER_T *observer,
+   SCI_BASE_SUBJECT_T  *subject
+)
+{
+   SCI_BASE_STATE_MACHINE_LOGGER_T *this_observer;
+   this_observer = (SCI_BASE_STATE_MACHINE_LOGGER_T *)observer;
+
+   this_observer->log_function(
+      sci_base_object_get_logger(this_observer->log_object),
+      this_observer->log_mask,
+      "%s 0x%08x %s has transitioned from %d to %d\n",
+      this_observer->log_object_name,
+      this_observer->log_object,
+      this_observer->log_state_machine_name,
+      this_observer->parent.subject_state,
+      sci_base_state_machine_get_state((SCI_BASE_STATE_MACHINE_T *)subject)
+   );
+
+   sci_base_state_machine_observer_default_update(
+      &this_observer->parent.parent, subject
+   );
+}
+
+//******************************************************************************
+//* P U B L I C   M E T H O D S
+//******************************************************************************
+
+/**
+ * This function will construct the state machine logger and attach it to the
+ * state machine that is to be observed.
+ *
+ * @param[in] this_observer This is the state machine logger object that is
+ *       going to observe the subject state machine.
+ * @param[in] the_object This is the object that contains the state machine
+ *       being observed it is used to report the address of the object for
+ *       which a state transition has occurred.
+ * @param[in] the_log_function This is the logging function to be used when a
+ *       state machine transition occurs.  Since this is a base object type it
+ *       does not actually know if the logging function is for the core or
+ *       framework.
+ * @param[in] the_object_name This is the name of the object that contains the
+ *       state machine being observed.
+ * @param[in] the_state_machine_name This is the name that will be displayed
+ *       in the log string for the state machine being observed.
+ * @param[in] the_object_mask This is the log object mask used when calling
+ *       the logging function.
+ *
+ * @return Nothing
+ */
+void sci_base_state_machine_logger_construct(
+   SCI_BASE_STATE_MACHINE_LOGGER_T             * this_observer,
+   SCI_BASE_OBJECT_T                           * the_object,
+   SCI_BASE_STATE_MACHINE_LOGGER_LOG_HANDLER_T   the_log_function,
+   char                                        * log_object_name,
+   char                                        * log_state_machine_name,
+   U32                                           log_object_mask
+)
+{
+   sci_base_state_machine_observer_construct(&this_observer->parent);
+
+   this_observer->log_object             = the_object;
+   this_observer->log_function           = the_log_function;
+   this_observer->log_object_name        = log_object_name;
+   this_observer->log_state_machine_name = log_state_machine_name;
+   this_observer->log_mask               = log_object_mask;
+
+   this_observer->parent.parent.update = sci_base_state_machine_logger_update;
+}
+
+/**
+ * This is a helper function that will construct the state machine logger and
+ * attach it to the state machine that is to be observed.
+ *
+ * @param[in] this_observer This is the state machine logger object that is
+ *       going to observe the subject state machine.
+ * @param[in] the_state_machine This is the state machine that is under
+ *       observation.
+ * @param[in] the_object This is the object that contains the state machine
+ *       being observed it is used to report the address of the object for
+ *       which a state transition has occurred.
+ * @param[in] the_log_function This is the logging function to be used when a
+ *       state machine transition occurs.  Since this is a base object type it
+ *       does not actually know if the logging function is for the core or
+ *       framework.
+ * @param[in] the_object_name This is the name of the object that contains the
+ *       state machine being observed.
+ * @param[in] the_state_machine_name This is the name that will be displayed
+ *       in the log string for the state machine being observed.
+ * @param[in] the_object_mask This is the log object mask used when calling
+ *       the logging function.
+ *
+ * @return Nothing
+ */
+void sci_base_state_machine_logger_initialize(
+   SCI_BASE_STATE_MACHINE_LOGGER_T             * this_observer,
+   SCI_BASE_STATE_MACHINE_T                    * the_state_machine,
+   SCI_BASE_OBJECT_T                           * the_object,
+   SCI_BASE_STATE_MACHINE_LOGGER_LOG_HANDLER_T   the_log_function,
+   char                                        * log_object_name,
+   char                                        * log_state_machine_name,
+   U32                                           log_object_mask
+)
+{
+   sci_base_state_machine_logger_construct(
+      this_observer, the_object,
+      the_log_function, log_object_name, log_state_machine_name, log_object_mask
+   );
+
+   sci_base_subject_attach_observer(
+      &the_state_machine->parent, &this_observer->parent.parent
+   );
+}
+
+/**
+ * This is a helper function that will detach this observer from the state
+ * machine that is being observerd.
+ *
+ * @param[in] this_observer This is the observer to detach from the state
+ *       machine.
+ * @parame[in] the_state_machine This is the state machine that is no longer
+ *       going to be observed.
+ *
+ * @return Nothing
+ */
+void sci_base_state_machine_logger_deinitialize(
+   SCI_BASE_STATE_MACHINE_LOGGER_T * this_observer,
+   SCI_BASE_STATE_MACHINE_T        * the_state_machine
+)
+{
+   sci_base_subject_detach_observer(
+      &the_state_machine->parent, &this_observer->parent.parent
+   );
+}
+
+#endif // defined(SCI_LOGGING)
diff --git a/sys/dev/disk/isci/scil/sci_base_state_machine_logger.h b/sys/dev/disk/isci/scil/sci_base_state_machine_logger.h
new file mode 100644
index 0000000..9d09a9c
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_base_state_machine_logger.h
@@ -0,0 +1,137 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_base_state_machine_logger.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCI_BASE_STATE_MACHINE_LOGGER_H_
+#define _SCI_BASE_STATE_MACHINE_LOGGER_H_
+
+/**
+ * @file
+ *
+ * @brief This file provides the structures and function prototypes for the
+ *        state machine logger.  The functions provided are only implemented
+ *        if the SCI_LOGGING flag is enabled.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/sci_base_object.h>
+#include <dev/disk/isci/scil/sci_base_state_machine.h>
+#include <dev/disk/isci/scil/sci_base_state_machine_observer.h>
+
+/**
+ * This type is defined so we can pass either a core or framework logging
+ * function to the state machine logger since both have the same prototypes
+ * and this base state machine logger does not actually know which component
+ * will be doing the logging.
+ */
+typedef void (*SCI_BASE_STATE_MACHINE_LOGGER_LOG_HANDLER_T)(
+   SCI_LOGGER_HANDLE_T, U32, char *, ...
+);
+
+#if defined(SCI_LOGGING)
+
+typedef struct SCI_BASE_STATE_MACHINE_LOGGER
+{
+   SCI_BASE_STATE_MACHINE_OBSERVER_T parent;
+
+   SCI_BASE_OBJECT_T                           * log_object;
+   SCI_BASE_STATE_MACHINE_LOGGER_LOG_HANDLER_T   log_function;
+   char                                        * log_object_name;
+   char                                        * log_state_machine_name;
+   U32                                           log_mask;
+
+} SCI_BASE_STATE_MACHINE_LOGGER_T;
+
+
+void sci_base_state_machine_logger_construct(
+   SCI_BASE_STATE_MACHINE_LOGGER_T             * this_observer,
+   SCI_BASE_OBJECT_T                           * the_object,
+   SCI_BASE_STATE_MACHINE_LOGGER_LOG_HANDLER_T   the_log_function,
+   char                                        * log_object_name,
+   char                                        * log_state_machine_name,
+   U32                                           log_object_mask
+);
+
+void sci_base_state_machine_logger_initialize(
+   SCI_BASE_STATE_MACHINE_LOGGER_T             * this_observer,
+   SCI_BASE_STATE_MACHINE_T                    * the_state_machine,
+   SCI_BASE_OBJECT_T                           * the_object,
+   SCI_BASE_STATE_MACHINE_LOGGER_LOG_HANDLER_T   the_log_function,
+   char                                        * log_object_name,
+   char                                        * log_state_machine_name,
+   U32                                           log_object_mask
+);
+
+void sci_base_state_machine_logger_deinitialize(
+   SCI_BASE_STATE_MACHINE_LOGGER_T * this_observer,
+   SCI_BASE_STATE_MACHINE_T        * the_state_machine
+);
+
+#else // SCI_LOGGING
+
+typedef U8 SCI_BASE_STATE_MACHINE_LOGGER_T;
+
+#define sci_base_state_machine_logger_construct(this_observer,the_object,the_log_function,log_object_name,log_state_machine_name,log_object_mask)
+#define sci_base_state_machine_logger_initialize(this_observer,the_state_machine,the_object,the_log_function,log_object_name,log_state_machine_name,log_object_mask)
+#define sci_base_state_machine_logger_deinitialize(this_observer, the_state_machine)
+
+#endif // SCI_LOGGING
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCI_BASE_STATE_MACHINE_LOGGER_H_
diff --git a/sys/dev/disk/isci/scil/sci_base_state_machine_observer.c b/sys/dev/disk/isci/scil/sci_base_state_machine_observer.c
new file mode 100644
index 0000000..866588b
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_base_state_machine_observer.c
@@ -0,0 +1,98 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_base_state_machine_observer.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file provides the implementation for the observer role
+ *        for a state machine.  A state machine observer is notified when
+ *        the state machine changes states.
+ */
+
+#include <dev/disk/isci/scil/sci_base_state_machine.h>
+#include <dev/disk/isci/scil/sci_base_state_machine_observer.h>
+
+#if defined(SCI_LOGGING)
+
+#define SCI_BASE_INVALID_SUBJECT_STATE 0xFFFF
+
+//******************************************************************************
+//* P R O T E C T E D    M E T H O D S
+//******************************************************************************
+
+void sci_base_state_machine_observer_default_update(
+   SCI_BASE_OBSERVER_T *this_observer,
+   SCI_BASE_SUBJECT_T  *the_subject
+)
+{
+   SCI_BASE_STATE_MACHINE_OBSERVER_T *state_machine_observer;
+
+   state_machine_observer = (SCI_BASE_STATE_MACHINE_OBSERVER_T *)this_observer;
+
+   state_machine_observer->subject_state =
+      sci_base_state_machine_get_state((SCI_BASE_STATE_MACHINE_T *)the_subject);
+}
+
+// ---------------------------------------------------------------------------
+
+void sci_base_state_machine_observer_construct(
+   SCI_BASE_STATE_MACHINE_OBSERVER_T *this_observer
+)
+{
+   this_observer->parent.update = sci_base_state_machine_observer_default_update;
+
+   this_observer->subject_state = SCI_BASE_INVALID_SUBJECT_STATE;
+}
+
+#endif // defined(SCI_LOGGING)
diff --git a/sys/dev/disk/isci/scil/sci_base_state_machine_observer.h b/sys/dev/disk/isci/scil/sci_base_state_machine_observer.h
new file mode 100644
index 0000000..f9698bf
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_base_state_machine_observer.h
@@ -0,0 +1,138 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_base_state_machine_observer.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCI_BASE_STATE_MACHINE_OBSERVER_H_
+#define _SCI_BASE_STATE_MACHINE_OBSERVER_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the structures, constants, and methods
+ *        common to all state machine observer object definitions.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_base_observer.h>
+#include <dev/disk/isci/scil/sci_base_subject.h>
+
+#if defined(SCI_LOGGING)
+
+/**
+ * @struct SCI_BASE_STATE_MACHINE_OBSERVER
+ *
+ * @brief The base state machine observer structure defines the fields
+ *        necessary for a user that wishes to observe the behavior (i.e.
+ *        state changes) of a state machine.
+ */
+typedef struct SCI_BASE_STATE_MACHINE_OBSERVER
+{
+   /**
+    * The field specifies that the parent object for the base state
+    * machine observer is the base observer itself.
+    */
+   SCI_BASE_OBSERVER_T parent;
+
+   /**
+    * This field contains the state recorded during the last state machine
+    * update.
+    */
+   U32  subject_state;
+
+} SCI_BASE_STATE_MACHINE_OBSERVER_T;
+
+/**
+ * @brief This method provides default behavior for a state machine observer.
+ *        This method records the state of the subject (i.e. the state
+ *        machine) and returns.
+ *
+ * @param[in]  this_observer This parameter specifes the state machine
+ *             observer in which to record the state change from the subject.
+ * @param[in]  the_subject This parameter evaluates to the state machine
+ *             object under observation.
+ *
+ * @return none
+ */
+void sci_base_state_machine_observer_default_update(
+   SCI_BASE_OBSERVER_T *this_observer,
+   SCI_BASE_SUBJECT_T  *the_subject
+);
+
+/**
+ * @brief This method constructs the supplied state machine observer.
+ *
+ * @param[in]  this_observer This parameter specifes the state machine
+ *             observer to be constructed.
+ *
+ * @return none
+ */
+void sci_base_state_machine_observer_construct(
+   SCI_BASE_STATE_MACHINE_OBSERVER_T *this_observer
+);
+
+#else // defined(SCI_LOGGING)
+
+typedef U8 SCI_BASE_STATE_MACHINE_OBSERVER_T;
+
+#define sci_base_state_machine_observer_default_update
+#define sci_base_state_machine_observer_construct
+
+#endif // defined(SCI_LOGGING)
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCI_BASE_STATE_MACHINE_OBSERVER_H_
diff --git a/sys/dev/disk/isci/scil/sci_base_subject.c b/sys/dev/disk/isci/scil/sci_base_subject.c
new file mode 100644
index 0000000..54c1486
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_base_subject.c
@@ -0,0 +1,148 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_base_subject.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains the base subject method implementations and
+ *        any constants or structures private to the base subject object.
+ *        A subject is a participant in the observer design pattern.  A
+ *        subject represents the object being observed.
+ */
+
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/sci_base_subject.h>
+#include <dev/disk/isci/scil/sci_base_observer.h>
+
+#if defined(SCI_LOGGING)
+
+//******************************************************************************
+//* P R O T E C T E D    M E T H O D S
+//******************************************************************************
+
+void sci_base_subject_construct(
+   SCI_BASE_SUBJECT_T *this_subject
+)
+{
+   this_subject->observer_list = NULL;
+}
+
+// ---------------------------------------------------------------------------
+
+void sci_base_subject_notify(
+   SCI_BASE_SUBJECT_T *this_subject
+)
+{
+   SCI_BASE_OBSERVER_T *this_observer = this_subject->observer_list;
+
+   while (this_observer != NULL)
+   {
+      sci_base_observer_update(this_observer, this_subject);
+
+      this_observer = this_observer->next;
+   }
+}
+
+// ---------------------------------------------------------------------------
+
+void sci_base_subject_attach_observer(
+   SCI_BASE_SUBJECT_T   *this_subject,
+   SCI_BASE_OBSERVER_T  *observer
+)
+{
+   observer->next = this_subject->observer_list;
+
+   this_subject->observer_list = observer;
+}
+
+// ---------------------------------------------------------------------------
+
+void sci_base_subject_detach_observer(
+   SCI_BASE_SUBJECT_T   *this_subject,
+   SCI_BASE_OBSERVER_T  *observer
+)
+{
+   SCI_BASE_OBSERVER_T *current_observer = this_subject->observer_list;
+   SCI_BASE_OBSERVER_T *previous_observer = NULL;
+
+   // Search list for the item to remove
+   while (
+              current_observer != NULL
+           && current_observer != observer
+         )
+   {
+      previous_observer = current_observer;
+      current_observer = current_observer->next;
+   }
+
+   // Was this observer in the list?
+   if (current_observer == observer)
+   {
+      if (previous_observer != NULL)
+      {
+         // Remove from middle or end of list
+         previous_observer->next = observer->next;
+      }
+      else
+      {
+         // Remove from the front of the list
+         this_subject->observer_list = observer->next;
+      }
+
+      // protect the list so people dont follow bad pointers
+      observer->next = NULL;
+   }
+}
+
+#endif // defined(SCI_LOGGING)
diff --git a/sys/dev/disk/isci/scil/sci_base_subject.h b/sys/dev/disk/isci/scil/sci_base_subject.h
new file mode 100644
index 0000000..cb21971
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_base_subject.h
@@ -0,0 +1,157 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_base_subject.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCI_BASE_SUBJECT_H_
+#define _SCI_BASE_SUBJECT_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the structures, constants, and methods
+ *        common to all subjects object definitions.  A subject is a
+ *        participant in the observer pattern.  A subject represents the
+ *        object being observed.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_types.h>
+
+#if defined(SCI_LOGGING)
+
+struct SCI_BASE_OBSERVER;
+
+/**
+ * @struct SCI_BASE_SUBJECT
+ *
+ * @brief This structure defines the fields common to all subjects that
+ *        participate in the observer design pattern
+ */
+typedef struct SCI_BASE_SUBJECT
+{
+   struct SCI_BASE_OBSERVER *observer_list;
+
+} SCI_BASE_SUBJECT_T;
+
+
+/**
+ * @brief This method acts as the basic constructor for the subject.
+ *
+ * @param[in] this_subject This fields specifies the subject being
+ *            constructed.
+ *
+ * @return none
+ */
+void sci_base_subject_construct(
+   SCI_BASE_SUBJECT_T  *this_subject
+);
+
+/**
+ * @brief This method will call the update method for all
+ *        observers attached to this subject.
+ *
+ * @param[in] this_subject This parameter specifies the subject for
+ *            which to notify participating observers.
+ *
+ * @return none
+ */
+void sci_base_subject_notify(
+   SCI_BASE_SUBJECT_T  *this_subject
+);
+
+/**
+ * @brief This method will add an observer to the subject.
+ *
+ * @param[in] this_subject This parameter specifies the subject for which
+ *            an observer is being added.
+ * @param[in] observer This parameter specifies the observer that wishes
+ *            it listen for notifications for the supplied subject.
+ *
+ * @return none
+ */
+void sci_base_subject_attach_observer(
+   SCI_BASE_SUBJECT_T        *this_subject,
+   struct SCI_BASE_OBSERVER  *observer
+);
+
+/**
+ * @brief This method will remove the observer from the subject.
+ *
+ * @param[in] this_subject
+ * @param[in] my_observer
+ *
+ * @return none
+ */
+void sci_base_subject_detach_observer(
+   SCI_BASE_SUBJECT_T        *this_subject,
+   struct SCI_BASE_OBSERVER  *my_observer
+);
+
+#else // defined(SCI_LOGGING)
+
+typedef U8 SCI_BASE_SUBJECT_T;
+
+#define sci_base_subject_construct
+#define sci_base_subject_notify
+#define sci_base_subject_attach_observer
+#define sci_base_subject_detach_observer
+
+#endif // defined(SCI_LOGGING)
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCI_BASE_SUBJECT_H_
diff --git a/sys/dev/disk/isci/scil/sci_controller.h b/sys/dev/disk/isci/scil/sci_controller.h
new file mode 100644
index 0000000..fc37de5
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_controller.h
@@ -0,0 +1,112 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_controller.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCI_CONTROLLER_H_
+#define _SCI_CONTROLLER_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the interface methods that can be called
+ *        by an SCI user on all SCI controller objects.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_types.h>
+
+
+#define SCI_CONTROLLER_INVALID_IO_TAG 0xFFFF
+
+typedef enum _SCI_CONTROLLER_ERROR {
+    SCI_CONTROLLER_FATAL_ERROR = 1,
+    SCI_CONTROLLER_REMOTE_DEVICE_ERROR,
+    SCI_CONTROLLER_FATAL_MEMORY_ERROR
+} SCI_CONTROLLER_ERROR;
+
+/**
+ * @brief This method simply returns a handle for the memory descriptor
+ *        list associated with the supplied controller.  The descriptor list
+ *        provides DMA safe/capable memory requirements for this controller.
+ *
+ * @warning The user must adhere to the alignment requirements specified in
+ *          memory descriptor.  In situations where the operating environment
+ *          does not offer memory allocation utilities supporting alignment,
+ *          then it is the responsibility of the user to manually align the
+ *          memory buffer for SCI.  Thus, the user may have to allocate a
+ *          larger buffer to meet the alignment.  Additionally, the user will
+ *          need to remember the actual memory allocation addresses in order
+ *          to ensure the memory can be properly freed when necessary to do
+ *          so.
+ *
+ * @pre This method will return a valid handle, but the MDL may not be
+ *      accurate until after the user has invoked the associated
+ *      sci_controller_initialize() routine.
+ *
+ * @param[in]  controller This parameter specifies the controller for which
+ *             to retrieve the DMA safe memory descriptor list.
+ *
+ * @return A pointer to a physical memory descriptor array.
+ */
+SCI_MEMORY_DESCRIPTOR_LIST_HANDLE_T
+sci_controller_get_memory_descriptor_list_handle(
+   SCI_CONTROLLER_HANDLE_T  controller
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCI_CONTROLLER_H_
diff --git a/sys/dev/disk/isci/scil/sci_controller_constants.h b/sys/dev/disk/isci/scil/sci_controller_constants.h
new file mode 100644
index 0000000..50a0954
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_controller_constants.h
@@ -0,0 +1,216 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_controller_constants.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCI_CONTROLLER_CONSTANTS_H_
+#define _SCI_CONTROLLER_CONSTANTS_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains constant values that change based on the type
+ *        of core or framework being managed.  These constants are exported
+ *        in order to provide the user with information as to the bounds
+ *        (i.e. how many) of specific objects.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#ifdef SCIC_SDS_4_ENABLED
+
+#ifndef SCI_MAX_PHYS
+/**
+ * This constant defines the maximum number of phy objects that can be
+ * supported for the SCU Driver Standard (SDS) library.  This is tied
+ * directly to silicon capabilities.
+ */
+#define SCI_MAX_PHYS  (4)
+#endif
+
+#ifndef SCI_MAX_PORTS
+/**
+ * This constant defines the maximum number of port objects that can be
+ * supported for the SCU Driver Standard (SDS) library.  This is tied
+ * directly to silicon capabilities.
+ */
+#define SCI_MAX_PORTS SCI_MAX_PHYS
+#endif
+
+#ifndef SCI_MIN_SMP_PHYS
+/**
+ * This constant defines the minimum number of SMP phy objects that
+ * can be supported for a single expander level.
+ * This was determined by using 36 physical phys and room for 2 virtual
+ * phys.
+ */
+#define SCI_MIN_SMP_PHYS  (38)
+#endif
+
+#ifndef SCI_MAX_SMP_PHYS
+/**
+ * This constant defines the maximum number of SMP phy objects that
+ * can be supported for the SCU Driver Standard (SDS) library.
+ * This number can be increased if required.
+ */
+#define SCI_MAX_SMP_PHYS  (384)
+#endif
+
+#ifndef SCI_MAX_REMOTE_DEVICES
+/**
+ * This constant defines the maximum number of remote device objects that
+ * can be supported for the SCU Driver Standard (SDS) library.  This is tied
+ * directly to silicon capabilities.
+ */
+#define SCI_MAX_REMOTE_DEVICES (256)
+#endif
+
+#ifndef SCI_MIN_REMOTE_DEVICES
+/**
+ * This constant defines the minimum number of remote device objects that
+ * can be supported for the SCU Driver Standard (SDS) library.  This # can
+ * be configured for minimum memory environments to any value less than
+ * SCI_MAX_REMOTE_DEVICES
+ */
+#define SCI_MIN_REMOTE_DEVICES (16)
+#endif
+
+#ifndef SCI_MAX_IO_REQUESTS
+/**
+ * This constant defines the maximum number of IO request objects that
+ * can be supported for the SCU Driver Standard (SDS) library.  This is tied
+ * directly to silicon capabilities.
+ */
+#define SCI_MAX_IO_REQUESTS (256)
+#endif
+
+#ifndef SCI_MIN_IO_REQUESTS
+/**
+ * This constant defines the minimum number of IO request objects that
+ * can be supported for the SCU Driver Standard (SDS) library.  This #
+ * can be configured for minimum memory environments to any value less
+ * than SCI_MAX_IO_REQUESTS.
+ */
+#define SCI_MIN_IO_REQUESTS (1)
+#endif
+
+#ifndef SCI_MAX_SCATTER_GATHER_ELEMENTS
+/**
+ * This constant defines the maximum number of Scatter-Gather Elements
+ * to be used by any SCI component.
+ */
+#define SCI_MAX_SCATTER_GATHER_ELEMENTS 130
+#endif
+
+#ifndef SCI_MIN_SCATTER_GATHER_ELEMENTS
+/**
+ * This constant defines the minimum number of Scatter-Gather Elements
+ * to be used by any SCI component.
+ */
+#define SCI_MIN_SCATTER_GATHER_ELEMENTS 1
+#endif
+
+#else // SCIC_SDS_4_ENABLED
+
+#error "SCI Core configuration left unspecified (e.g. SCIC_SDS_4_ENABLED)"
+
+#endif // SCIC_SDS_4_ENABLED
+
+/**
+ * This constant defines the maximum number of PCI devices that can be supported
+ * by the driver.
+ */
+#define SCI_MAX_PCI_DEVICES (2)
+
+/**
+ * This constant defines the maximum number of controllers that can
+ * occur in a single silicon package.
+ */
+#define SCI_MAX_CONTROLLERS_PER_PCI_DEVICE  (2)
+
+/**
+ * This constant defines the maximum number of controllers that can
+ * be supported by a library object.  The user specified maximum controller
+ * count must be less than or equal to this number.  This is a driver
+ * specific constant that is not tied to silicon capabilities.
+ */
+#if !defined(SCI_MAX_CONTROLLERS)
+#define SCI_MAX_CONTROLLERS  (2)
+#endif
+
+#ifndef SCI_MAX_MSIX_MESSAGES_PER_CONTROLLER
+/**
+ * This constant defines the maximum number of MSI-X interrupt vectors/messages
+ * supported for an SCU hardware controller instance.
+ */
+#define SCI_MAX_MSIX_MESSAGES_PER_CONTROLLER  (2)
+#endif
+
+/**
+ * This constant defines the maximum number of MSI-X interrupt vectors/messages
+ * supported for an SCU device.
+ */
+#define SCI_MAX_MSIX_MESSAGES \
+    (SCI_MAX_MSIX_MESSAGES_PER_CONTROLLER * SCI_MAX_CONTROLLERS)
+
+/**
+ * The maximum number of supported domain objects is currently tied to the
+ * maximum number of support port objects.
+ */
+#define SCI_MAX_DOMAINS  SCI_MAX_PORTS
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCI_CONTROLLER_CONSTANTS_H_
diff --git a/sys/dev/disk/isci/scil/sci_fast_list.h b/sys/dev/disk/isci/scil/sci_fast_list.h
new file mode 100644
index 0000000..64af8b1
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_fast_list.h
@@ -0,0 +1,339 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_fast_list.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCI_FAST_LIST_HEADER_
+#define _SCI_FAST_LIST_HEADER_
+
+/**
+ * @file
+ *
+ * @brief Header file that contains basic Linked List manipulation macros.
+ *        These macros implement a double linked list (SCI_FAST_LIST_T) that is
+ *        circular in nature.  This means that the next and prev pointers for
+ *        an empty queue head always the address of the queue head
+ *        SCI_FAST_LIST_T.  Likewise an element that has been removed from
+ *        a queue will have its next and prev pointer set to the address of
+ *        the SCI_FAST_LIST_T found in the structure just removed from the
+ *        queue.   Pointers in this implementation never == NULL.
+ *
+ *        Definitions:
+ *        - anchor : This is ths list container and has a
+ *                   pointer to both the head and tail of the
+ *                   list elements
+ *        - element: This is the list element not the actual
+ *                   object but the list element which has a
+ *                   pointer to the object.
+ */
+
+//******************************************************************************
+//*
+//*     P U B L I C   M E T H O D S
+//*
+//******************************************************************************
+
+/**
+ * Initialize the double linked list anchor.  The other macros require the list
+ * anchor to be set up using this macro.
+ */
+#define sci_fast_list_init(anchor)                                            \
+{                                                                             \
+   (anchor)->list_head = NULL;                                                \
+   (anchor)->list_tail = NULL;                                                \
+   (anchor)->element_count = 0;                                               \
+}
+
+/**
+ * Initialize the sci_fast_list_element to point to its owning object
+ */
+#define sci_fast_list_element_init(list_object, element)                      \
+{                                                                             \
+   (element)->object = (list_object);                                         \
+   (element)->next = (element)->prev = NULL;                                  \
+   (element)->owning_list = NULL;                                             \
+}
+
+/**
+ * See if there is anything on the list by checking the list anchor.
+ */
+#define sci_fast_list_is_empty(anchor) ((anchor)->list_head == NULL)
+
+/**
+ * Return a pointer to the element at the head of the sci_fast_list.  The
+ * item is NOT removed from the list.
+ *
+ * NOTE: This macro will always return a value, even if the list is empty.
+ *       You must insure the list is not empty or use Dlist_safeGetHead.
+ *
+ * element - A pointer into which to save the address of the structure
+ *           containing the SCI_FAST_LIST at the list head.
+ */
+#define sci_fast_list_get_head(anchor)                                        \
+   ((anchor)->list_head == NULL ? NULL: (anchor)->list_head->object)
+
+/**
+ * Return a pointer to the element at the tail of the sci_fast_list.  The item
+ * is NOT removed from the list.
+ *
+ * NOTE: This macro will always return a value, even if the list is empty.
+ *       You must insure the list is not empty or use Dlist_safeGetHead.
+ *
+ * element - A pointer into which to save the address of the structure
+ *           containing the SCI_FAST_LIST at the list head.
+ */
+#define sci_fast_list_get_tail(anchor)                                        \
+   ((anchor)->list_tail == NULL ? NULL: (anchor)->list_head->object)
+
+/**
+ * This method will get the next dListField in the SCI_FAST_LIST.  This method
+ * returns a pointer to a SCI_FAST_LIST object.
+ */
+#define sci_fast_list_get_next(element) ((element)->next)
+
+/**
+ * This method will get the prev dListField in the SCI_FAST_LIST.  This method
+ * returns a pointer to a SCI_FAST_LIST object.
+ */
+#define sci_fast_list_get_prev(element) ((element)->prev)
+
+
+/**
+ * This method returns the object that is represented by this
+ * sci_fast_list_element
+ */
+#define sci_fast_list_get_object(element) ((element)->object)
+
+/**
+ * This method will determine if the supplied dListField is on a SCI_FAST_LIST.
+ * If the element has only one dListField but can be on more than one list,
+ * this will only tell you that it is on one of them.  If the element has
+ * multiple dListFields and can exist on multiple lists at the same time, this
+ * macro can tell you exactly which list it is on.
+ */
+#define sci_fast_list_is_on_a_list(element) ((element)->owning_list != NULL)
+
+/**
+ * This method will determine if the supplied dListFieldName is on the given
+ * specified list?  If the element can be on more than one list, this
+ * allows you to determine exactly which list it is on.  Performs a linear
+ * search through the list.
+ * result - BOOL_T that will contain the result of the search.
+ *          TRUE - item is on the list described by head.
+ *          FALSE - item is not on the list.
+ */
+#define sci_fast_list_is_on_this_list(anchor, element) \
+   ((element)->owning_list == (anchor))
+
+//******************************************************************************
+//*
+//*     T Y P E S
+//*
+//******************************************************************************
+
+/**
+ * @struct SCI_FAST_LIST
+ *
+ * @brief the list owner or list anchor for a set of SCI_FAST_LIST
+ *        elements.
+ */
+typedef struct SCI_FAST_LIST
+{
+   struct SCI_FAST_LIST_ELEMENT *list_head;
+   struct SCI_FAST_LIST_ELEMENT *list_tail;
+   int                           element_count;
+} SCI_FAST_LIST_T;
+
+/**
+ * @struct SCI_FAST_LIST_ELEMENT
+ *
+ * @brief This structure defines what a doubly linked list element contains.
+ */
+typedef struct SCI_FAST_LIST_ELEMENT
+{
+   struct SCI_FAST_LIST_ELEMENT *next;
+   struct SCI_FAST_LIST_ELEMENT *prev;
+   struct SCI_FAST_LIST         *owning_list;
+   void                         *object;
+} SCI_FAST_LIST_ELEMENT_T;
+
+
+/**
+ * Insert an element to be the new head of the list hanging off of the list
+ * anchor.  An empty list has the list anchor pointing to itself.
+ * dListAnchor - The name of the SCI_FAST_LIST_T element that is the anchor
+ *               of the queue.
+ * dListFieldBeingInserted - The SCI_FAST_LIST_T field in the data structure
+ *                           being queued.  This SCI_FAST_LIST will become
+ *                           the new list head.
+ */
+INLINE
+static void sci_fast_list_insert_head(
+    SCI_FAST_LIST_T *anchor,
+    SCI_FAST_LIST_ELEMENT_T *element
+)
+{
+    element->owning_list = anchor;
+    element->prev = NULL;
+    if ( anchor->list_head == NULL )
+        anchor->list_tail = element;
+    else
+        anchor->list_head->prev = element;
+    element->next = anchor->list_head;
+    anchor->list_head = element;
+    anchor->element_count++;
+}
+
+/**
+ * Insert an element at the tail of the list.  Since the list is circular we
+ * can add the element at the tail through use the list anchors previous
+ * pointer.
+ * dListAnchor - The name of the SCI_FAST_LIST_T element that is the anchor
+ *               of the queue.
+ * dListFieldBeingInserted - The SCI_FAST_LIST_T field in the data structure
+ *                           being queued.  This SCI_FAST_LIST will become
+ *                           the new list head.
+ */
+INLINE
+static void sci_fast_list_insert_tail(
+    SCI_FAST_LIST_T *anchor,
+    SCI_FAST_LIST_ELEMENT_T *element
+)
+{
+    element->owning_list = anchor;
+    element->next = NULL;
+    if ( anchor->list_tail == NULL ) {
+        anchor->list_head = element;
+    } else {
+        anchor->list_tail->next = element;
+    }
+    element->prev = anchor->list_tail;
+    anchor->list_tail = element;
+    anchor->element_count++;
+}
+
+/**
+ * This method will remove a dListFieldName from the head of the list.
+ *
+ * NOTE: This macro will always return a value, even if the list is empty.
+ *       You must insure the list is not empty or use Dlist_safeRemoveHead.
+ *
+ * element - A pointer into which to save the address of the structure
+ *           containing the SCI_FAST_LIST at the list head.
+ */
+INLINE
+static void *sci_fast_list_remove_head(
+    SCI_FAST_LIST_T *anchor
+)
+{
+    void *object = NULL;
+    SCI_FAST_LIST_ELEMENT_T *element;
+    if ( anchor->list_head != NULL )
+    {
+        element = anchor->list_head;
+        object = anchor->list_head->object;
+        anchor->list_head = anchor->list_head->next;
+        if ( anchor->list_head == NULL )
+        {
+            anchor->list_tail = NULL;
+        }
+        anchor->element_count--;
+        element->next = element->prev = NULL;
+        element->owning_list = NULL;
+    }
+    return object;
+}
+
+INLINE
+static void *sci_fast_list_remove_tail(
+    SCI_FAST_LIST_T *anchor
+)
+{
+    void *object = NULL;
+    SCI_FAST_LIST_ELEMENT_T *element;
+    if ( anchor->list_tail != NULL )
+    {
+        element = anchor->list_tail;
+        object = element->object;
+        anchor->list_tail = element->prev;
+        if ( anchor->list_tail == NULL )
+            anchor->list_head = NULL;
+        anchor->element_count--;
+        element->next = element->prev = NULL;
+        element->owning_list = NULL;
+    }
+    return object;
+}
+
+/**
+ * Remove an element from anywhere in the list referenced by name.
+ */
+INLINE
+static void sci_fast_list_remove_element(
+    SCI_FAST_LIST_ELEMENT_T *element
+)
+{
+    if ( element->next == NULL )
+        element->owning_list->list_tail = element->prev;
+    else
+        element->next->prev = element->prev;
+
+    if ( element->prev == NULL )
+        element->owning_list->list_head = element->next;
+    else
+        element->prev->next = element->next;
+
+    element->owning_list->element_count--;
+    element->next = element->prev = NULL;
+    element->owning_list = NULL;
+}
+
+#endif // _SCI_FAST_LIST_HEADER_
diff --git a/sys/dev/disk/isci/scil/sci_iterator.h b/sys/dev/disk/isci/scil/sci_iterator.h
new file mode 100644
index 0000000..9e27903
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_iterator.h
@@ -0,0 +1,129 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_iterator.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+/**
+ * @file
+ *
+ * @brief This file contains the interface to the iterator class.
+ *        Methods Provided:
+ *        - sci_iterator_get_object_size()
+ *        - sci_iterator_get_current()
+ *        - sci_iterator_first()
+ *        - sci_iterator_next()
+ */
+
+#ifndef _SCI_ITERATOR_H_
+#define _SCI_ITERATOR_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#if !defined(DISABLE_SCI_ITERATORS)
+
+//******************************************************************************
+//*
+//*     I N C L U D E S
+//*
+//******************************************************************************
+
+#include <dev/disk/isci/scil/sci_types.h>
+
+//******************************************************************************
+//*
+//*     C O N S T A N T S
+//*
+//******************************************************************************
+
+//******************************************************************************
+//*
+//*     T Y P E S
+//*
+//******************************************************************************
+
+//******************************************************************************
+//*
+//*     P U B L I C       M E T H O D S
+//*
+//******************************************************************************
+
+U32 sci_iterator_get_object_size(
+   void
+);
+
+void * sci_iterator_get_current(
+   SCI_ITERATOR_HANDLE_T iterator_handle
+);
+
+void sci_iterator_first(
+   SCI_ITERATOR_HANDLE_T iterator_handle
+);
+
+void sci_iterator_next(
+   SCI_ITERATOR_HANDLE_T iterator_handle
+);
+
+#else // !defined(DISABLE_SCI_ITERATORS)
+
+#define sci_iterator_get_object_size() 0
+#define sci_iterator_get_current(the_iterator) NULL
+#define sci_iterator_first(the_iterator)
+#define sci_iterator_next(the_iterator)
+
+#endif // !defined(DISABLE_SCI_ITERATORS)
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _ITERATOR_H_
diff --git a/sys/dev/disk/isci/scil/sci_library.h b/sys/dev/disk/isci/scil/sci_library.h
new file mode 100644
index 0000000..33ef7e7
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_library.h
@@ -0,0 +1,110 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_library.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCI_LIBRARY_H_
+#define _SCI_LIBRARY_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the interface methods that can be called
+ *        by an SCI user on a library object.  The library is the container
+ *        of all other objects being managed (i.e. controllers, target devices,
+ *        sas ports, etc.).
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_types.h>
+
+
+/**
+ * @brief This method will return the major revision level for the entire
+ *        SCI library.
+ * @note  Format: Major.Minor.Build.
+ *
+ * @return Return an integer value indicating the major revision level.
+ */
+U32 sci_library_get_major_version(
+   void
+);
+
+/**
+ * @brief This method will return the minor revision level for the entire
+ *        SCI library.
+ * @note  Format: Major.Minor.Build.
+ *
+ * @return Return an integer value indicating the minor revision level.
+ */
+U32 sci_library_get_minor_version(
+   void
+);
+
+/**
+ * @brief This method will return the build revision level for the entire
+ *        SCI library.
+ * @note  Format: Major.Minor.Build.
+ *
+ * @return Return an integer value indicating the build revision level.
+ */
+U32 sci_library_get_build_version(
+   void
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCI_LIBRARY_H_
diff --git a/sys/dev/disk/isci/scil/sci_logger.h b/sys/dev/disk/isci/scil/sci_logger.h
new file mode 100644
index 0000000..c0f2edd
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_logger.h
@@ -0,0 +1,249 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_logger.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCI_LOGGER_H_
+#define _SCI_LOGGER_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the interface methods that can be called
+ *        by an SCI user on the logger object.  These methods should be
+ *        utilized to control the amount of information being logged by the
+ *        SCI implementation.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_types.h>
+
+
+/* The following is a list of verbosity levels that can be used to enable */
+/* logging for specific log objects.                                      */
+
+/** Enable/disable error level logging for the associated logger object(s). */
+#define SCI_LOG_VERBOSITY_ERROR      0x00
+
+/** Enable/disable warning level logging for the associated logger object(s). */
+#define SCI_LOG_VERBOSITY_WARNING    0x01
+
+/**
+ * Enable/disable informative level logging for the associated logger object(s).
+ */
+#define SCI_LOG_VERBOSITY_INFO       0x02
+
+/**
+ * This constant is used to enable function trace (enter/exit) level
+ * logging for the associated log object(s).
+ */
+#define SCI_LOG_VERBOSITY_TRACE      0x03
+
+/**
+ * This constant is used to enable state tracing information it will emit a
+ * log message each time a state is entered for the associated log object(s).
+ */
+#define SCI_LOG_VERBOSITY_STATES     0x04
+
+#ifdef SCI_LOGGING
+
+/**
+ * @brief This method will return the verbosity levels enabled for the object
+ *        listed in the log_object parameter.
+ * @note  Logging must be enabled at compile time in the driver, otherwise
+ *        calling this method has no affect.
+ *
+ * @param[in]  logger This parameter specifies the logger for which to
+ *             disable the supplied objects/verbosities.  For example,
+ *             the framework and core components have different loggers.
+ * @param[in]  log_object This parameter specifies the log object for which
+ *             to retrieve the associated verbosity levels.
+ *             @note This parameter is not a mask, but rather a discrete
+ *             value.
+ *
+ * @return This method will return the verbosity levels enabled for the
+ *         supplied log object.
+ * @retval SCI_LOGGER_VERBOSITY_ERROR This value indicates that the error
+ *         verbosity level was set for the supplied log_object.
+ * @retval SCI_LOGGER_VERBOSITY_WARNING This value indicates that the warning
+ *         verbosity level was set for the supplied log_object.
+ * @retval SCI_LOGGER_VERBOSITY_INFO This value indicates that the
+ *         informational verbosity level was set for the supplied log_object.
+ * @retval SCI_LOGGER_VERBOSITY_TRACE This value indicates that the trace
+ *         verbosity level was set for the supplied log_object.
+ * @retval SCI_LOGGER_VERBOSITY_STATES This value indicates that the states
+ *         transition verbosity level was set for the supplied log_object
+ */
+U8 sci_logger_get_verbosity_mask(
+   SCI_LOGGER_HANDLE_T  logger,
+   U32                  log_object
+);
+
+/**
+ * @brief This method simply returns the log object mask.  This mask
+ *        is essentially a list of log objects for which the specified
+ *        level (verbosity) is enabled.
+ * @note  Logging must be enabled at compile time in the driver, otherwise
+ *        calling this method has no affect.
+ * @note  Reserved bits in both the supplied masks shall be ignored.
+ *
+ * @param[in]  logger This parameter specifies the logger for which to
+ *             disable the supplied objects/verbosities.  For example,
+ *             the framework and core components have different loggers.
+ * @param[in]  verbosity This parameter specifies the verbosity for which
+ *             to retrieve the set of enabled log objects.  Valid values for
+ *             this parameter are:
+ *                -# SCI_LOGGER_VERBOSITY_ERROR
+ *                -# SCI_LOGGER_VERBOSITY_WARNING
+ *                -# SCI_LOGGER_VERBOSITY_INFO
+ *                -# SCI_LOGGER_VERBOSITY_TRACE
+ *                -# SCI_LOGGER_VERBOSITY_STATES
+ *             @note This parameter is not a mask, but rather a discrete
+ *             value.
+ *
+ * @return This method will return the log object mask indicating each of
+ *         the log objects for which logging is enabled at the supplied level.
+ */
+U32 sci_logger_get_object_mask(
+   SCI_LOGGER_HANDLE_T  logger,
+   U8                   verbosity
+);
+
+/**
+ * @brief This method will enable each of the supplied log objects in
+ *        log_object_mask for each of the supplied verbosities in
+ *        verbosity_mask.  To enable all logging, simply set all bits in
+ *        both the log_object_mask and verbosity_mask.
+ * @note  Logging must be enabled at compile time in the driver, otherwise
+ *        calling this method has no affect.
+ * @note  Reserved bits in both the supplied masks shall be ignored.
+ *
+ * @param[in]  logger This parameter specifies the logger for which to
+ *             disable the supplied objects/verbosities.  For example,
+ *             the framework and core components have different loggers.
+ * @param[in]  log_object_mask This parameter specifies the log objects for
+ *             which to enable logging.
+ * @param[in]  verbosity_mask This parameter specifies the verbosity levels
+ *             at which to enable each log_object.
+ *
+ * @return none
+ */
+void sci_logger_enable(
+   SCI_LOGGER_HANDLE_T  logger,
+   U32                  log_object_mask,
+   U8                   verbosity_mask
+);
+
+/**
+ * @brief This method will disable each of the supplied log objects in
+ *        log_object_mask for each of the supplied verbosities in
+ *        verbosity_mask.  To disable all logging, simply set all bits in
+ *        both the log_object_mask and verbosity_mask.
+ * @note  Logging must be enabled at compile time in the driver, otherwise
+ *        calling this method has no affect.
+ * @note  Reserved bits in both the supplied masks shall be ignored.
+ *
+ * @param[in]  logger This parameter specifies the logger for which to
+ *             disable the supplied objects/verbosities.  For example,
+ *             the framework and core components have different loggers.
+ * @param[in]  log_object_mask This parameter specifies the log objects for
+ *             which to disable logging.
+ * @param[in]  verbosity_mask This parameter specifies the verbosity levels
+ *             at which to disable each log_object.
+ *
+ * @return none
+ */
+void sci_logger_disable(
+   SCI_LOGGER_HANDLE_T  logger,
+   U32                  log_object_mask,
+   U8                   verbosity_mask
+);
+
+
+/**
+ * @brief this macro checks whether it is ok to log.
+ *
+ * @param[in]  logger This parameter specifies the logger for
+ *             which to disable the supplied
+ *             objects/verbosities.  For example, the framework
+ *             and core components have different loggers.
+ * @param[in]  log_object_mask This parameter specifies the log objects for
+ *             which to disable logging.
+ * @param[in]  verbosity_mask This parameter specifies the verbosity levels
+ *             at which to disable each log_object.
+ *
+ * @return TRUE or FALSE
+ */
+BOOL sci_logger_is_enabled(
+   SCI_LOGGER_HANDLE_T  logger,
+   U32                  log_object_mask,
+   U8                   verbosity_mask
+);
+
+
+#else // SCI_LOGGING
+
+#define sci_logger_get_verbosity_mask(logger, log_object)
+#define sci_logger_get_object_mask(logger, verbosity)
+#define sci_logger_enable(logger, log_object_mask, verbosity_mask)
+#define sci_logger_disable(logger, log_object_mask, verbosity_mask)
+#define sci_logger_is_enabled(logger, log_object_mask, verbosity_level)
+
+#endif // SCI_LOGGING
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCI_LOGGER_H_
diff --git a/sys/dev/disk/isci/scil/sci_memory_descriptor_list.h b/sys/dev/disk/isci/scil/sci_memory_descriptor_list.h
new file mode 100644
index 0000000..4fe3e72
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_memory_descriptor_list.h
@@ -0,0 +1,180 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_memory_descriptor_list.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCI_MEMORY_DESCRIPTOR_LIST_H_
+#define _SCI_MEMORY_DESCRIPTOR_LIST_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the basic data types utilized by an
+ *        SCI user or implementor.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_types.h>
+
+/**
+ * @name SCI_MDE_ATTRIBUTES
+ *
+ * These constants depict memory attributes for the Memory
+ * Descriptor Entries (MDEs) contained in the MDL.
+ */
+/*@{*/
+#define SCI_MDE_ATTRIBUTE_CACHEABLE              0x0001
+#define SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS  0x0002
+/*@}*/
+
+/**
+ * @struct SCI_PHYSICAL_MEMORY_DESCRIPTOR
+ * @brief  This structure defines a description of a memory location for
+ *         the SCI implementation.
+ */
+typedef struct SCI_PHYSICAL_MEMORY_DESCRIPTOR
+{
+   /**
+    * This field contains the virtual address associated with this descriptor
+    * element. This field shall be zero when the descriptor is retrieved from
+    * the SCI implementation.  The user shall set this field prior
+    * sci_controller_start()
+    */
+   void * virtual_address;
+
+   /**
+    * This field contains the physical address associated with this desciptor
+    * element. This field shall be zero when the descriptor is retrieved from
+    * the SCI implementation.  The user shall set this field prior
+    * sci_controller_start()
+    */
+   SCI_PHYSICAL_ADDRESS  physical_address;
+
+   /**
+    * This field contains the size requirement for this memory descriptor.
+    * A value of zero for this field indicates the end of the descriptor
+    * list.  The value should be treated as read only for an SCI user.
+    */
+   U32 constant_memory_size;
+
+   /**
+    * This field contains the alignment requirement for this memory
+    * descriptor.  A value of zero for this field indicates the end of the
+    * descriptor list.  All other values indicate the number of bytes to
+    * achieve the necessary alignment.  The value should be treated as
+    * read only for an SCI user.
+    */
+   U32 constant_memory_alignment;
+
+   /**
+    * This field contains an indication regarding the desired memory
+    * attributes for this memory descriptor entry.
+    * Notes:
+    * - If the cacheable attribute is set, the user can allocate
+    *   memory that is backed by cache for better performance. It
+    *   is not required that the memory be backed by cache.
+    * - If the physically contiguous attribute is set, then the
+    *   entire memory must be physically contiguous across all
+    *   page boundaries.
+    */
+   U16 constant_memory_attributes;
+
+} SCI_PHYSICAL_MEMORY_DESCRIPTOR_T;
+
+/**
+ * @brief This method simply rewinds the MDL iterator back to the first memory
+ *        descriptor entry in the list.
+ *
+ * @param[in] mdl This parameter specifies the memory descriptor list that
+ *            is to be rewound.
+ *
+ * @return none
+ */
+void sci_mdl_first_entry(
+   SCI_MEMORY_DESCRIPTOR_LIST_HANDLE_T mdl
+);
+
+/**
+ * @brief This method simply updates the "current" pointer to the next
+ *        sequential memory descriptor.
+ *
+ * @param[in] mdl This parameter specifies the memory descriptor list for
+ *            which to return the next memory descriptor entry in the list.
+ *
+ * @return none.
+ */
+void sci_mdl_next_entry(
+   SCI_MEMORY_DESCRIPTOR_LIST_HANDLE_T mdl
+);
+
+/**
+ * @brief This method simply returns the current memory descriptor entry.
+ *
+ * @param[in] mdl This parameter specifies the memory descriptor list for
+ *            which to return the current memory descriptor entry.
+ *
+ * @return This method returns a pointer to the current physical memory
+ *         descriptor in the MDL.
+ * @retval NULL This value is returned if there are no descriptors in the
+ *         list.
+ */
+SCI_PHYSICAL_MEMORY_DESCRIPTOR_T * sci_mdl_get_current_entry(
+   SCI_MEMORY_DESCRIPTOR_LIST_HANDLE_T mdl
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCI_MEMORY_DESCRIPTOR_LIST_H_
diff --git a/sys/dev/disk/isci/scil/sci_memory_descriptor_list_decorator.h b/sys/dev/disk/isci/scil/sci_memory_descriptor_list_decorator.h
new file mode 100644
index 0000000..ae5f7b8
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_memory_descriptor_list_decorator.h
@@ -0,0 +1,128 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_memory_descriptor_list_decorator.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCI_MEMORY_DESCRIPTOR_LIST_DECORATOR_H_
+#define _SCI_MEMORY_DESCRIPTOR_LIST_DECORATOR_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains methods utilized to provide additional
+ *        functionality above normal MDL processing.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_memory_descriptor_list.h>
+
+/**
+ * @brief This method will determine the amount of memory needed for
+ *        memory descriptors with exact matching memory attributes.
+ *        If the supplied attributes value is 0, then all MDEs are
+ *        included in the calculation.
+ *
+ * @param[in] mdl This parameter specifies the MDL to search through
+ *            for MDEs with matching memory attributes.
+ * @param[in] attributes This parameter specifies the attributes to
+ *            match.  If this parameter is set to 0, then each MDE
+ *            is included in the calculation.
+ *
+ * @return This method returns the number of bytes, including offsets
+ *         to achieve proper alignment, for memory descriptors that
+ *         exactly match the supplied memory attributes.
+ */
+U32 sci_mdl_decorator_get_memory_size(
+   SCI_MEMORY_DESCRIPTOR_LIST_HANDLE_T mdl,
+   U32                                 attributes
+);
+
+/**
+ * @brief This method will assign the supplied memory address values
+ *        to all of the MDEs in the memory descriptor list with
+ *        exact matching attributes as those supplied by parameter.
+ *        If the supplied attributes value is 0, then all MDEs will
+ *        have their values assigned.
+ *
+ * @warning It is suggested the user invoke the
+ *          sci_mdl_decorator_get_memory_size() method prior to invoking
+ *          this method.  This ensures that the user supplies pointers
+ *          that refer to memory locations with sufficient space.
+ *
+ * @param[in,out] mdl This parameter specifies the MDL to iterate through
+ *                for MDEs with matching memory attributes.
+ * @param[in]     attributes This parameter specifies the attributes to
+ *                match.  If this parameter is set to 0, then each
+ *                memory descriptor will be filled out.
+ * @param[in]     virtual_address This parameter specifies the starting
+ *                virtual address to be used when filling out the MDE
+ *                virtual address field.
+ * @param[in]     sci_physical_address This parameter specifies the starting
+ *                physical address to be used when filling out the MDE
+ *                physical address field.
+ *
+ * @return none
+ */
+void sci_mdl_decorator_assign_memory(
+   SCI_MEMORY_DESCRIPTOR_LIST_HANDLE_T mdl,
+   U32                                 attributes,
+   POINTER_UINT                        virtual_address,
+   SCI_PHYSICAL_ADDRESS                sci_physical_address
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCI_MEMORY_DESCRIPTOR_LIST_DECORATOR_H_
diff --git a/sys/dev/disk/isci/scil/sci_object.h b/sys/dev/disk/isci/scil/sci_object.h
new file mode 100644
index 0000000..a28c332
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_object.h
@@ -0,0 +1,138 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_object.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCI_OBJECT_H_
+#define _SCI_OBJECT_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the method and constants associated with
+ *        the SCI base object.  The SCI base object is the class from which
+ *        all other objects derive in the Storage Controller Interface.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/sci_status.h>
+
+/**
+ * @brief This method returns the object to which a previous association was
+ *        created.  This association represents a link between an SCI object
+ *        and another SCI object or potentially a user object.  The
+ *        association essentially acts as a cookie for the user of an object.
+ *        The user of an SCI object is now able to retrieve a handle to their
+ *        own object that is managing, or related in someway, to said SCI
+ *        object.
+ *
+ * @param[in]  base_object This parameter specifies the SCI object for
+ *             which to retrieve the association reference.
+ *
+ * @return This method returns a pointer to the object that was previously
+ *         associated to the supplied base_object parameter.
+ * @retval SCI_INVALID_HANDLE This value is returned when there is no known
+ *         association for the supplied base_object instance.
+ */
+#if defined(SCI_OBJECT_USE_ASSOCIATION_FUNCTIONS)
+void * sci_object_get_association(
+   SCI_OBJECT_HANDLE_T  base_object
+);
+#else
+#define sci_object_get_association(object) (*((void **)object))
+#endif
+
+/**
+ * @brief This method will associate to SCI objects.
+ *
+ * @see   For more information about associations please reference the
+ *        sci_object_get_association() method.
+ *
+ * @param[in]  base_object This parameter specifies the SCI object for
+ *             which to set the association reference.
+ * @param[in]  associated_object This parameter specifies a pointer to the
+ *             object being associated.
+ *
+ * @return This method will return an indication as to whether the
+ *         association was set successfully.
+ * @retval SCI_SUCCESS This value is currently always returned.
+ */
+#if defined(SCI_OBJECT_USE_ASSOCIATION_FUNCTIONS)
+SCI_STATUS sci_object_set_association(
+   SCI_OBJECT_HANDLE_T   base_object,
+   void                * associated_object
+);
+#else
+#define sci_object_set_association(base_object, associated_object) \
+   ((*((void **)base_object)) = (associated_object))
+#endif
+
+/**
+ * @brief This method will get the logger for an object.
+ *
+ * @param[in] object This parameter specifies SCI object for
+ *       which to retrieve its logger.
+ *
+ * @return This method returns a SCI_LOGGER_HANDLE to SCI user.
+ */
+SCI_LOGGER_HANDLE_T sci_object_get_logger(
+   SCI_OBJECT_HANDLE_T object
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCI_OBJECT_H_
diff --git a/sys/dev/disk/isci/scil/sci_overview.h b/sys/dev/disk/isci/scil/sci_overview.h
new file mode 100644
index 0000000..090ef73
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_overview.h
@@ -0,0 +1,250 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_overview.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCI_OVERVIEW_H_
+#define _SCI_OVERVIEW_H_
+
+/**
+@mainpage The Intel Storage Controller Interface (SCI)
+
+SCI provides a common interface across intel storage controller hardware.
+This includes abstracting differences between Physical PCI functions and
+Virtual PCI functions.  The SCI is comprised of four primary components:
+-# SCI Base classes
+-# SCI Core
+-# SCI Framework
+
+It is important to recognize that no component, object, or functionality in
+SCI directly allocates memory from the operating system.  It is expected that
+the SCI User (OS specific driver code) allocates and frees all memory from
+and to the operating system itself.
+
+The C language is utilized to implement SCI.  Although C is not an object
+oriented language the SCI driver components, methods, and structures are
+modeled and organized following object oriented principles.
+
+The Unified Modeling Language is utilized to present graphical depictions
+of the SCI classes and their relationships.
+
+The following figure denotes the meanings of the colors utilized in UML
+diagrams throughout this document.
+@image latex object_color_key.eps "Object Color Legend" width=8cm
+
+The following figure denotes the meanings for input and output arrows that
+are utilized to define parameters for methods defined in this specification.
+@image latex arrow_image.eps "Method Parameter Symbol Definition"
+
+@page abbreviations_section Abbreviations
+
+- ATA: Advanced Technology Attachment
+- IAF: Identify Address Frame
+- SAS: Serial Attached SCSI
+- SAT: SCSI to ATA Translation
+- SATA: Serial ATA
+- SCI: Storage Controller Interface
+- SCIC: SCI Core
+- SCIF: SCI Framework
+- SCU: Storage Controller Unit
+- SDS: SCU Driver Standard (i.e. non-virtualization)
+- SDV: SCU Driver Virtualized
+- SDVP: SDV Physical (PCI function)
+- SDVV: SDV Virtual (PCI function)
+- SGE: Scatter-Gather Element
+- SGL: Scatter-Gather List
+- SGPIO: Serial General Purpose Input/Output
+- SSC: Spread Spectrum Clocking
+
+@page definitions_section Definitions
+
+- <b>construct</b> - The term "construct" is utilized throughout the
+  interface to indicate when an object is being created.  Typically construct
+  methods perform pure memory initialization.  No "construct" method ever
+  performs memory allocation.  It is incumbent upon the SCI user to provide
+  the necessary memory.
+- <b>initialize</b> - The term "initialize" is utilized throughout the
+  interface to indicate when an object is performing actions on other objects
+  or on physical resources in an attempt to allow these resources to become
+  operational.
+- <b>protected</b> - The term "protected" is utilized to denote a method
+  defined in this standard that MUST NOT be invoked directly by operating
+  system specific driver code.
+- <b>SCI Component</b> - An SCI component is one of: SCI base classes, Core,
+  or Framework.
+- <b>SCI User</b> - The user callbacks for each SCI Component represent the
+  dependencies that the SCI component implementation has upon the operating
+  system/environment specific portion of the driver.  It is essentially a
+  set of functions or macro definitions that are specific to a particular
+  operating system.
+- <b>THIN</b> - A term utilized to describe an SCI Component implementation
+  that is built to conserve memory.
+
+@page inheritance SCI Inheritance Hierarchy
+
+This section describes the inheritance (i.e. "is-a") relationships between
+the various objects in SCI.  Due to various operating environment requirements
+the programming language employed for the SCI driver is C.  As a result, one
+might be curious how inheritance shall be applied in such an environment.
+The SCI driver source shall maintain generalization relationships by ensuring
+that child object structures shall contain an instance of their parent's
+structure as the very first member of their structure.  As a result, parent
+object methods can be invoked with a child structure parameter.  This works
+since casting of the child structure to the parent structure inside the parent
+method will yield correct access to the parent structure fields.
+
+Consider the following example:
+<pre>
+typedef struct SCI_OBJECT
+{
+   U32 object_type;
+};
+
+typedef struct SCI_CONTROLLER
+{
+   U32 state;
+
+} SCI_CONTROLLER_T;
+
+typedef struct SCIC_CONTROLLER
+{
+   SCI_CONTROLLER_T parent;
+   U32 type;
+
+} SCIC_CONTROLLER_T;
+</pre>
+
+With the above structure orientation, a user would be allowed to perform
+method invocations in a manner similar to the following:
+<pre>
+SCIC_CONTROLLER_T scic_controller;
+scic_controller_initialize((SCIC_CONTROLLER_T*) &scic_controller);
+
+// OR
+
+sci_object_get_association(&scic_controller);
+</pre>
+@note The actual interface will not require type casting.
+
+The following diagram graphically depicts the inheritance relationships
+between the various objects defined in the Storage Controller Interface.
+@image latex inheritance.eps "SCI Inheritance Hierarchy" width=16cm
+
+@page sci_classes SCI Classes
+
+This section depicts the common classes and utility functions across the
+entire set of SCI Components.  Descriptions about each of the specific
+objects will be found in the header file definition in the File Documentation
+section.
+
+The following is a list of features that can be found in the SCI base classes:
+-# Logging utility methods, constants, and type definitions
+-# Memory Descriptor object methods common to the core and framework.
+-# Controller object methods common to SCI derived controller objects.
+-# Library object methods common to SCI derived library objects.
+-# Storage standard (e.g. SAS, SATA) defined constants, structures, etc.
+-# Standard types utilized by SCI sub-components.
+-# The ability to associate/link SCI objects together or to user objects.
+
+SCI class methods can be overridden by sub-classes in the SCI Core,
+SCI Framework, etc.  SCI class methods that MUST NOT be invoked directly
+by operating system specific driver code shall be adorned with a
+<code>[protected]</code> keyword.  These <code>[protected]</code> API are still
+defined as part of the specification in order to demonstrate commonality across
+components as well as provide a common description of related methods.  If
+these methods are invoked directly by operating system specific code, the
+operation of the driver as a whole is not specified or supported.
+
+The following UML diagram graphically depicts the SCI base classes and their
+relationships to one another.
+@image latex sci_base_classes.eps "SCI Classes" width=4cm
+
+@page associations_section Associations
+The sci_object class provides functionality common to all SCI objects.
+An important feature provided by this base class is the means by which to
+associate one object to another.  An SCI object can be made to have an
+association to another SCI object.  Additionally, an SCI object can be
+made to have an association to a non-SCI based object.  For example, an SCI
+Framework library can have it's association set to an operating system
+specific adapter/device driver structre.
+
+Simply put, the association that an object has is a handle (i.e. a void pointer)
+to a user structure.  This enables the user of the SCI object to
+easily determine it's own associated structure. This association is useful
+because the user is now enabled to easily determine their pertinent information
+inside of their SCI user callback methods.
+
+Setting an association within an SCI object is generally optional.  The
+primary case in which an association is not optional is in the case of IO
+request objects.  These associations are necessary in order  to fill
+to fill in appropriate information for an IO request (i.e. CDB address, size,
+SGL information, etc.) in an efficient manner.
+
+In the case of other objects, the user is free to not create associations.
+When the user chooses not to create an association, the user is responsible for
+being able to determine their data structures based on the SCI object handles.
+Additionally, the user may be forced to invoke additional functionality in
+situations where the SCI Framework is employed.  If the user does not
+establish proper associations between objects (i.e. SCIC Library to SCIF Library), then the framework is unable to automate interactions.  Users should
+strongly consider establishing associations between SCI Framework objects and
+OS Driver related structures.
+
+Example Associations:
+- The user might set the scif_controller association to their adapter or
+controller object.
+- The user might set the scif_domain association to their SCSI bus object.
+
+If SCIF is being utilized, then the framework will set the associations
+in the core.  In this situation, the user should only set the associations
+in the framework objects, unless otherwise directed.
+*/
+
+#endif // _SCI_OVERVIEW_H_
diff --git a/sys/dev/disk/isci/scil/sci_pool.h b/sys/dev/disk/isci/scil/sci_pool.h
new file mode 100644
index 0000000..52100ad
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_pool.h
@@ -0,0 +1,188 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_pool.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+/**
+ * @file
+ *
+ * @brief This file contains the interface to the pool class.
+ *        This class allows two different two different priority tasks to
+ *        insert and remove items from the free pool. The user of the pool
+ *        is expected to evaluate the pool condition empty before a get
+ *        operation and pool condition full before a put operation.
+ *        Methods Provided:
+ *        - sci_pool_create()
+ *        - sci_pool_initialize()
+ *        - sci_pool_empty()
+ *        - sci_pool_full()
+ *        - sci_pool_get()
+ *        - sci_pool_put()
+ */
+
+#ifndef _SCI_POOL_H_
+#define _SCI_POOL_H_
+
+#include <dev/disk/isci/types.h>
+
+/**
+ * Private operation for the pool
+ */
+#define SCI_POOL_INCREMENT(this_pool, index) \
+  (((index) + 1) == (this_pool).size ? 0 : (index) + 1)
+
+/**
+ * This creates a pool structure of pool_name. The members in the pool are
+ * of type with number of elements equal to size.
+ */
+#define SCI_POOL_CREATE(pool_name, type, pool_size) \
+struct \
+{ \
+   U32 size; \
+   U32 get; \
+   U32 put; \
+   type array[(pool_size) + 1]; \
+} pool_name
+
+
+/**
+ * This macro evaluates the pool and returns TRUE if the pool is empty.
+ * If the pool is empty the user should not perform any get operation on
+ * the pool.
+ */
+#define sci_pool_empty(this_pool) \
+   ((this_pool).get == (this_pool).put)
+
+/**
+ * This macro evaluates the pool and returns TRUE if the pool is full.  If
+ * the pool is full the user should not perform any put operation.
+ */
+#define sci_pool_full(this_pool) \
+   (SCI_POOL_INCREMENT(this_pool, (this_pool).put) == (this_pool).get)
+
+/**
+ * This macro returns the size of the pool created.  The internal size
+ * of the pool is actually 1 larger then necessary in order to ensure
+ * get and put pointers can be written simultaneously by different
+ * users.  As a result, this macro subtracts 1 from the internal size
+ */
+#define sci_pool_size(this_pool) \
+   ((this_pool).size - 1)
+
+/**
+ * This macro indicates the number of elements currently contained in the
+ * pool.
+ */
+#define sci_pool_count(this_pool) \
+   ( \
+      sci_pool_empty((this_pool)) \
+      ? 0 \
+      : ( \
+           sci_pool_full((this_pool)) \
+           ? sci_pool_size((this_pool)) \
+           : ( \
+                (this_pool).get > (this_pool).put \
+                ? ((this_pool).size - (this_pool).get + (this_pool).put) \
+                : ((this_pool).put - (this_pool).get) \
+             ) \
+        ) \
+   )
+
+/**
+ * This macro initializes the pool to an empty condition.
+ */
+#define sci_pool_initialize(this_pool) \
+{ \
+   (this_pool).size = (sizeof((this_pool).array) / sizeof((this_pool).array[0])); \
+   (this_pool).get = 0; \
+   (this_pool).put = 0; \
+}
+
+/**
+ * This macro will get the next free element from the pool.
+ * This should only be called if the pool is not empty.
+ */
+#define sci_pool_get(this_pool, my_value) \
+{ \
+   (my_value) = (this_pool).array[(this_pool).get]; \
+   (this_pool).get = SCI_POOL_INCREMENT((this_pool), (this_pool).get); \
+}
+
+/**
+ * This macro will put the value into the pool.
+ * This should only be called if the pool is not full.
+ */
+#define sci_pool_put(this_pool, the_value) \
+{ \
+   (this_pool).array[(this_pool).put] = (the_value); \
+   (this_pool).put = SCI_POOL_INCREMENT((this_pool), (this_pool).put); \
+}
+
+/**
+ * This macro will search the pool and remove any elements in the pool
+ * matching the supplied value.
+ * @note This method can only be utilized on pools
+ */
+#define sci_pool_erase(this_pool, type, the_value) \
+{ \
+   type tmp_value; \
+   U32 index; \
+   U32 element_count = sci_pool_count((this_pool)); \
+ \
+   for (index = 0; index < element_count; index++) \
+   { \
+      sci_pool_get((this_pool), tmp_value); \
+      if (tmp_value != (the_value)) \
+         sci_pool_put((this_pool), tmp_value); \
+   } \
+}
+
+#endif // _SCI_POOL_H_
diff --git a/sys/dev/disk/isci/scil/sci_simple_list.h b/sys/dev/disk/isci/scil/sci_simple_list.h
new file mode 100644
index 0000000..6344cb5
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_simple_list.h
@@ -0,0 +1,350 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_simple_list.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCI_SIMPLE_LIST_HEADER_
+#define _SCI_SIMPLE_LIST_HEADER_
+
+/**
+ * @file
+ *
+ * @brief This header file contains simple linked list manipulation macros.
+ *        These macros differ from the SCI_FAST_LIST in that deletion of
+ *        an element from the list is O(n).
+ *        The reason for using this implementation over the SCI_FAST_LIST
+ *        is
+ *           1) space savings as there is only a single link element instead
+ *              of the 2 link elements used in the SCI_FAST_LIST and
+ *           2) it is possible to detach the entire list from its anchor
+ *              element for processing.
+ *
+ * @note Do not use the SCI_SIMPLE_LIST if you need to remove elements from
+ *       random locations within the list use instead the SCI_FAST_LIST.
+ */
+
+
+//******************************************************************************
+//*
+//*     P U B L I C    M E T H O D S
+//*
+//******************************************************************************
+
+/**
+ * Initialize the singely linked list anchor.  The other macros require the
+ * list anchor to be properly initialized.
+ */
+#define sci_simple_list_init(anchor) \
+{ \
+   (anchor)->list_head = NULL; \
+   (anchor)->list_tail = NULL; \
+   (anchor)->list_count = 0; \
+}
+
+/**
+ * Initialze the singely linked list element. The other macros require the
+ * list element to be properly initialized.
+ */
+#define sci_simple_list_element_init(list_object, element) \
+{ \
+   (element)->next = NULL; \
+   (element)->object = (list_object); \
+}
+
+/**
+ * See if there are any list elements on this list.
+ */
+#define sci_simple_list_is_empty(anchor)  ((anchor)->list_head == NULL)
+
+/**
+ * Return a pointer to the list element at the head of the list.  The list
+ * element is not removed from the list.
+ */
+#define sci_simple_list_get_head(anchor) ((anchor)->list_head)
+
+/**
+ * Retuen a pointer to the lsit element at the tail of the list.  The list
+ * element is not removed from the list.
+ */
+#define sci_simple_list_get_tail(anchor) ((anchor)->list_tail)
+
+/**
+ * Return the count of the number of elements in this list.
+ */
+#define sci_simple_list_get_count(anchor) ((anchor)->list_count)
+
+/**
+ * Return a pointer to the list element following this list element.
+ * If this is the last element in the list then NULL is returned.
+ */
+#define sci_simple_list_get_next(element) ((element)->next)
+
+/**
+ * Return the object represented by the list element.
+ */
+#define sci_simple_list_get_object(element) ((element)->object)
+
+
+//******************************************************************************
+//*
+//*     T Y P E S
+//*
+//******************************************************************************
+
+/**
+ * @struct
+ *
+ * @brief This structure defines the list owner for singely linked list.
+ */
+typedef struct SCI_SIMPLE_LIST
+{
+   struct SCI_SIMPLE_LIST_ELEMENT *list_head;
+   struct SCI_SIMPLE_LIST_ELEMENT *list_tail;
+   U32                             list_count;
+} SCI_SIMPLE_LIST_T;
+
+/**
+ * @struct SCI_SIMPLE_LIST_ELEMENT
+ *
+ * @brief This structure defines what a singely linked list element contains.
+ */
+typedef struct SCI_SIMPLE_LIST_ELEMENT
+{
+   struct SCI_SIMPLE_LIST_ELEMENT *next;
+   void                           *object;
+} SCI_SIMPLE_LIST_ELEMENT_T;
+
+/**
+ * This method will insert the list element to the head of the list contained
+ * by the anchor.
+ *
+ * @note Pushing new elements onto a list is more efficient than inserting
+ *       them to the tail of the list though both are O(1) operations.
+ */
+INLINE
+static void sci_simple_list_insert_head(
+   SCI_SIMPLE_LIST_T * anchor,
+   SCI_SIMPLE_LIST_ELEMENT_T *element
+)
+{
+   if (anchor->list_tail == NULL)
+   {
+      anchor->list_tail = element;
+   }
+
+   element->next = anchor->list_head;
+   anchor->list_head = element;
+   anchor->list_count++;
+}
+
+/**
+ * This methos will insert the list element to the tail of the list contained
+ * by the anchor.
+ *
+ * @param[in, out] anchor this is the list into which the element is to be
+ *                 inserted
+ * @param[in] element this is the element which to insert into the list.
+ *
+ * @note Pushing new elements onto a list is more efficient than inserting
+ *       them to the tail of the list though both are O(1) operations.
+ */
+INLINE
+static void sci_simple_list_insert_tail(
+   SCI_SIMPLE_LIST_T * anchor,
+   SCI_SIMPLE_LIST_ELEMENT_T *element
+)
+{
+   if (anchor->list_tail == NULL)
+   {
+      anchor->list_head = element;
+   }
+   else
+   {
+      anchor->list_tail->next = element;
+   }
+
+   anchor->list_tail = element;
+   anchor->list_count++;
+}
+
+/**
+ * This method will remove the list element from the anchor and return the
+ * object pointed to by that list element.
+ *
+ * @param[in, out] anchor this is the list into which the element is to be
+ *                 inserted
+ *
+ * @return the list element at the head of the list.
+ */
+INLINE
+static void * sci_simple_list_remove_head(
+   SCI_SIMPLE_LIST_T * anchor
+)
+{
+   void * object = NULL;
+
+   if (anchor->list_head != NULL)
+   {
+      object = anchor->list_head->object;
+
+      anchor->list_head = anchor->list_head->next;
+
+      if (anchor->list_head == NULL)
+      {
+         anchor->list_tail = NULL;
+      }
+
+      anchor->list_count--;
+   }
+
+   return object;
+}
+
+/**
+ * Move all the list elements from source anchor to the dest anchor.
+ * The source anchor will have all of its elements removed making it
+ * an empty list and the dest anchor will contain all of the source
+ * and dest list elements.
+ *
+ * @param[in, out] dest_anchor this is the list into which all elements from
+ *                 the source list are to be moved.
+ * @param[in, out] source_anchor this is the list which is to be moved to the
+ *                 destination list.  This list will be empty on return.
+ *
+ * @return the list element at the head of the list.
+ * @note If the destination has list elements use the insert at head
+ *       or tail routines instead.
+ */
+INLINE
+static void sci_simple_list_move_list(
+   SCI_SIMPLE_LIST_T * dest_anchor,
+   SCI_SIMPLE_LIST_T * source_anchor
+)
+{
+   *dest_anchor = *source_anchor;
+
+   sci_simple_list_init(source_anchor);
+}
+
+/**
+ * This method will insert the list elements from the source anchor to the
+ * destination list before all previous elements on the destination list.
+ *
+ * @param[in, out] dest_anchor this is the list into which all elements from
+ *                 the source list are to be moved. The destination list will
+ *                 now contain both sets of list elements.
+ * @param[in, out] source_anchor this is the list which is to be moved to the
+ *                 destination list.  This list will be empty on return.
+ */
+INLINE
+static void sci_simple_list_insert_list_at_head(
+   SCI_SIMPLE_LIST_T * dest_anchor,
+   SCI_SIMPLE_LIST_T * source_anchor
+)
+{
+   if (!sci_simple_list_is_empty(source_anchor))
+   {
+      if (sci_simple_list_is_empty(dest_anchor))
+      {
+         // Destination is empty just copy the source on over
+         *dest_anchor = *source_anchor;
+      }
+      else
+      {
+         source_anchor->list_tail->next = dest_anchor->list_head;
+         dest_anchor->list_head = source_anchor->list_head;
+         dest_anchor->list_count += source_anchor->list_count;
+      }
+
+      // Wipe the source list to make sure the list elements can not be accessed
+      // from two seperate lists at the same time.
+      sci_simple_list_init(source_anchor);
+   }
+}
+
+/**
+ * This method will insert the list elements from the source anchor to the
+ * destination anchor after all list elements on the destination anchor.
+ *
+ * @param[in, out] dest_anchor this is the list into which all elements from
+ *                 the source list are to be moved. The destination list will
+ *                 contain both the source and destination list elements.
+ * @param[in, out] source_anchor this is the list which is to be moved to the
+ *                 destination list.  This list will be empty on return.
+ */
+INLINE
+static void sci_simple_list_insert_list_at_tail(
+   SCI_SIMPLE_LIST_T * dest_anchor,
+   SCI_SIMPLE_LIST_T * source_anchor
+)
+{
+   if (!sci_simple_list_is_empty(source_anchor))
+   {
+      if (sci_simple_list_is_empty(dest_anchor))
+      {
+         // Destination is empty just copy the source on over
+         *dest_anchor = *source_anchor;
+      }
+      else
+      {
+         // If the source list is empty the desination list is the result.
+         dest_anchor->list_tail->next = source_anchor->list_head;
+         dest_anchor->list_tail = source_anchor->list_tail;
+         dest_anchor->list_count += source_anchor->list_count;
+      }
+
+      // Wipe the source list to make sure the list elements can not be accessed
+      // from two seperate lists at the same time.
+      sci_simple_list_init(source_anchor);
+   }
+}
+
+#endif // _SCI_SIMPLE_LIST_HEADER_
diff --git a/sys/dev/disk/isci/scil/sci_status.h b/sys/dev/disk/isci/scil/sci_status.h
new file mode 100644
index 0000000..009d580
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_status.h
@@ -0,0 +1,417 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_status.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCI_STATUS_H_
+#define _SCI_STATUS_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the return status codes utilized across
+ *        the various sub-components in SCI.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+/**
+ * @enum  _SCI_STATUS
+ * @brief This is the general return status enumeration for non-IO, non-task
+ *        management related SCI interface methods.
+ */
+typedef enum _SCI_STATUS
+{
+   /**
+    * This member indicates successful completion.
+    */
+   SCI_SUCCESS = 0,
+
+   /**
+    * This value indicates that the calling method completed successfully,
+    * but that the IO may have completed before having it's start method
+    * invoked.  This occurs during SAT translation for requests that do
+    * not require an IO to the target or for any other requests that may
+    * be completed without having to submit IO.
+    */
+   SCI_SUCCESS_IO_COMPLETE_BEFORE_START,
+
+   /**
+    *  This Value indicates that the SCU hardware returned an early response
+    *  because the io request specified more data than is returned by the
+    *  target device (mode pages, inquiry data, etc.). The completion routine
+    *  will handle this case to get the actual number of bytes transferred.
+    */
+   SCI_SUCCESS_IO_DONE_EARLY,
+
+   /**
+    * This member indicates that the object for which a state change is
+    * being requested is already in said state.
+    */
+   SCI_WARNING_ALREADY_IN_STATE,
+
+   /**
+    * This member indicates interrupt coalescence timer may cause SAS
+    * specification compliance issues (i.e. SMP target mode response
+    * frames must be returned within 1.9 milliseconds).
+    */
+   SCI_WARNING_TIMER_CONFLICT,
+
+   /**
+    * This field indicates a sequence of action is not completed yet. Mostly,
+    * this status is used when multiple ATA commands are needed in a SATI translation.
+    */
+   SCI_WARNING_SEQUENCE_INCOMPLETE,
+
+   /**
+    * This member indicates that there was a general failure.
+    */
+   SCI_FAILURE,
+
+   /**
+    * This member indicates that the SCI implementation is unable to complete
+    * an operation due to a critical flaw the prevents any further operation
+    * (i.e. an invalid pointer).
+    */
+   SCI_FATAL_ERROR,
+
+   /**
+    * This member indicates the calling function failed, because the state
+    * of the controller is in a state that prevents successful completion.
+    */
+   SCI_FAILURE_INVALID_STATE,
+
+   /**
+    * This member indicates the calling function failed, because there is
+    * insufficient resources/memory to complete the request.
+    */
+   SCI_FAILURE_INSUFFICIENT_RESOURCES,
+
+   /**
+    * This member indicates the calling function failed, because the
+    * controller object required for the operation can't be located.
+    */
+   SCI_FAILURE_CONTROLLER_NOT_FOUND,
+
+   /**
+    * This member indicates the calling function failed, because the
+    * discovered controller type is not supported by the library.
+    */
+   SCI_FAILURE_UNSUPPORTED_CONTROLLER_TYPE,
+
+   /**
+    * This member indicates the calling function failed, because the
+    * requested initialization data version isn't supported.
+    */
+   SCI_FAILURE_UNSUPPORTED_INIT_DATA_VERSION,
+
+   /**
+    * This member indicates the calling function failed, because the
+    * requested configuration of SAS Phys into SAS Ports is not supported.
+    */
+   SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION,
+
+   /**
+    * This member indicates the calling function failed, because the
+    * requested protocol is not supported by the remote device, port,
+    * or controller.
+    */
+   SCI_FAILURE_UNSUPPORTED_PROTOCOL,
+
+   /**
+    * This member indicates the calling function failed, because the
+    * requested information type is not supported by the SCI implementation.
+    */
+   SCI_FAILURE_UNSUPPORTED_INFORMATION_TYPE,
+
+   /**
+    * This member indicates the calling function failed, because the
+    * device already exists.
+    */
+   SCI_FAILURE_DEVICE_EXISTS,
+
+   /**
+    * This member indicates the calling function failed, because adding
+    * a phy to the object is not possible.
+    */
+   SCI_FAILURE_ADDING_PHY_UNSUPPORTED,
+
+   /**
+    * This member indicates the calling function failed, because the
+    * requested information type is not supported by the SCI implementation.
+    */
+   SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD,
+
+   /**
+    * This member indicates the calling function failed, because the SCI
+    * implementation does not support the supplied time limit.
+    */
+   SCI_FAILURE_UNSUPPORTED_TIME_LIMIT,
+
+   /**
+    * This member indicates the calling method failed, because the SCI
+    * implementation does not contain the specified Phy.
+    */
+   SCI_FAILURE_INVALID_PHY,
+
+   /**
+    * This member indicates the calling method failed, because the SCI
+    * implementation does not contain the specified Port.
+    */
+   SCI_FAILURE_INVALID_PORT,
+
+    /**
+     * This member indicates the calling method was partly successful
+     * The port was reset but not all phys in port are operational
+     */
+    SCI_FAILURE_RESET_PORT_PARTIAL_SUCCESS,
+
+    /**
+     * This member indicates that calling method failed
+     * The port reset did not complete because none of the phys are operational
+     */
+    SCI_FAILURE_RESET_PORT_FAILURE,
+
+   /**
+    * This member indicates the calling method failed, because the SCI
+    * implementation does not contain the specified remote device.
+    */
+   SCI_FAILURE_INVALID_REMOTE_DEVICE,
+
+   /**
+    * This member indicates the calling method failed, because the remote
+    * device is in a bad state and requires a reset.
+    */
+   SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED,
+
+   /**
+    * This member indicates the calling method failed, because the SCI
+    * implementation does not contain or support the specified IO tag.
+    */
+   SCI_FAILURE_INVALID_IO_TAG,
+
+   /**
+    * This member indicates that the operation failed and the user should
+    * check the response data associated with the IO.
+    */
+   SCI_FAILURE_IO_RESPONSE_VALID,
+
+   /**
+    * This member indicates that the operation failed, the failure is
+    * controller implementation specific, and the response data associated
+    * with the request is not valid.  You can query for the controller
+    * specific error information via scic_request_get_controller_status()
+    */
+   SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR,
+
+   /**
+    * This member indicated that the operation failed because the
+    * user requested this IO to be terminated.
+    */
+   SCI_FAILURE_IO_TERMINATED,
+
+   /**
+    * This member indicates that the operation failed and the associated
+    * request requires a SCSI abort task to be sent to the target.
+    */
+   SCI_FAILURE_IO_REQUIRES_SCSI_ABORT,
+
+   /**
+    * This member indicates that the operation failed because the supplied
+    * device could not be located.
+    */
+   SCI_FAILURE_DEVICE_NOT_FOUND,
+
+   /**
+    * This member indicates that the operation failed because the
+    * objects association is required and is not correctly set.
+    */
+   SCI_FAILURE_INVALID_ASSOCIATION,
+
+   /**
+    * This member indicates that the operation failed, because a timeout
+    * occurred.
+    */
+   SCI_FAILURE_TIMEOUT,
+
+   /**
+    * This member indicates that the operation failed, because the user
+    * specified a value that is either invalid or not supported.
+    */
+   SCI_FAILURE_INVALID_PARAMETER_VALUE,
+
+   /**
+    * This value indicates that the operation failed, because the number
+    * of messages (MSI-X) is not supported.
+    */
+   SCI_FAILURE_UNSUPPORTED_MESSAGE_COUNT,
+
+   /**
+    * This value indicates that the method failed due to a lack of
+    * available NCQ tags.
+    */
+   SCI_FAILURE_NO_NCQ_TAG_AVAILABLE,
+
+   /**
+    * This value indicates that a protocol violation has occurred on the
+    * link.
+    */
+   SCI_FAILURE_PROTOCOL_VIOLATION,
+
+   /**
+    * This value indicates a failure condition that retry may help to clear.
+    */
+   SCI_FAILURE_RETRY_REQUIRED,
+
+   /**
+    * This field indicates the retry limit was reached when a retry is attempted
+    */
+   SCI_FAILURE_RETRY_LIMIT_REACHED,
+
+   /**
+    * This member indicates the calling method was partly successful.
+    * Mostly, this status is used when a LUN_RESET issued to an expander attached
+    * STP device in READY NCQ substate needs to have RNC suspended/resumed
+    * before posting TC.
+    */
+   SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS,
+
+   /**
+    * This field indicates an illegal phy connection based on the routing attribute
+    * of both expander phy attached to each other.
+    */
+   SCI_FAILURE_ILLEGAL_ROUTING_ATTRIBUTE_CONFIGURATION,
+
+   /**
+    * This field indicates a CONFIG ROUTE INFO command has a response with function result
+    * INDEX DOES NOT EXIST, usually means exceeding max route index.
+    */
+   SCI_FAILURE_EXCEED_MAX_ROUTE_INDEX,
+
+   /**
+    * This value indicates that an unsupported PCI device ID has been
+    * specified.  This indicates that attempts to invoke
+    * scic_library_allocate_controller() will fail.
+    */
+   SCI_FAILURE_UNSUPPORTED_PCI_DEVICE_ID
+
+} SCI_STATUS;
+
+/**
+ * @enum  _SCI_IO_STATUS
+ * @brief This enumeration depicts all of the possible IO completion
+ *        status values.  Each value in this enumeration maps directly to
+ *        a value in the SCI_STATUS enumeration.  Please refer to that
+ *        enumeration for detailed comments concerning what the status
+ *        represents.
+ * @todo Add the API to retrieve the SCU status from the core.
+ * @todo Check to see that the following status are properly handled:
+ *       - SCI_IO_FAILURE_UNSUPPORTED_PROTOCOL
+ *       - SCI_IO_FAILURE_INVALID_IO_TAG
+ */
+typedef enum _SCI_IO_STATUS
+{
+   SCI_IO_SUCCESS                         = SCI_SUCCESS,
+   SCI_IO_FAILURE                         = SCI_FAILURE,
+   SCI_IO_SUCCESS_COMPLETE_BEFORE_START   = SCI_SUCCESS_IO_COMPLETE_BEFORE_START,
+   SCI_IO_SUCCESS_IO_DONE_EARLY           = SCI_SUCCESS_IO_DONE_EARLY,
+   SCI_IO_FAILURE_INVALID_STATE           = SCI_FAILURE_INVALID_STATE,
+   SCI_IO_FAILURE_INSUFFICIENT_RESOURCES  = SCI_FAILURE_INSUFFICIENT_RESOURCES,
+   SCI_IO_FAILURE_UNSUPPORTED_PROTOCOL    = SCI_FAILURE_UNSUPPORTED_PROTOCOL,
+   SCI_IO_FAILURE_RESPONSE_VALID          = SCI_FAILURE_IO_RESPONSE_VALID,
+   SCI_IO_FAILURE_CONTROLLER_SPECIFIC_ERR = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR,
+   SCI_IO_FAILURE_TERMINATED              = SCI_FAILURE_IO_TERMINATED,
+   SCI_IO_FAILURE_REQUIRES_SCSI_ABORT     = SCI_FAILURE_IO_REQUIRES_SCSI_ABORT,
+   SCI_IO_FAILURE_INVALID_PARAMETER_VALUE = SCI_FAILURE_INVALID_PARAMETER_VALUE,
+   SCI_IO_FAILURE_NO_NCQ_TAG_AVAILABLE    = SCI_FAILURE_NO_NCQ_TAG_AVAILABLE,
+   SCI_IO_FAILURE_PROTOCOL_VIOLATION      = SCI_FAILURE_PROTOCOL_VIOLATION,
+
+   SCI_IO_FAILURE_REMOTE_DEVICE_RESET_REQUIRED = SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED,
+
+   SCI_IO_FAILURE_RETRY_REQUIRED      = SCI_FAILURE_RETRY_REQUIRED,
+   SCI_IO_FAILURE_RETRY_LIMIT_REACHED = SCI_FAILURE_RETRY_LIMIT_REACHED,
+   SCI_IO_FAILURE_INVALID_REMOTE_DEVICE = SCI_FAILURE_INVALID_REMOTE_DEVICE
+} SCI_IO_STATUS;
+
+/**
+ * @enum  _SCI_TASK_STATUS
+ * @brief This enumeration depicts all of the possible task completion
+ *        status values.  Each value in this enumeration maps directly to
+ *        a value in the SCI_STATUS enumeration.  Please refer to that
+ *        enumeration for detailed comments concerning what the status
+ *        represents.
+ * @todo Check to see that the following status are properly handled:
+ */
+typedef enum _SCI_TASK_STATUS
+{
+   SCI_TASK_SUCCESS                         = SCI_SUCCESS,
+   SCI_TASK_FAILURE                         = SCI_FAILURE,
+   SCI_TASK_FAILURE_INVALID_STATE           = SCI_FAILURE_INVALID_STATE,
+   SCI_TASK_FAILURE_INSUFFICIENT_RESOURCES  = SCI_FAILURE_INSUFFICIENT_RESOURCES,
+   SCI_TASK_FAILURE_UNSUPPORTED_PROTOCOL    = SCI_FAILURE_UNSUPPORTED_PROTOCOL,
+   SCI_TASK_FAILURE_INVALID_TAG             = SCI_FAILURE_INVALID_IO_TAG,
+   SCI_TASK_FAILURE_RESPONSE_VALID          = SCI_FAILURE_IO_RESPONSE_VALID,
+   SCI_TASK_FAILURE_CONTROLLER_SPECIFIC_ERR = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR,
+   SCI_TASK_FAILURE_TERMINATED              = SCI_FAILURE_IO_TERMINATED,
+   SCI_TASK_FAILURE_INVALID_PARAMETER_VALUE = SCI_FAILURE_INVALID_PARAMETER_VALUE,
+
+   SCI_TASK_FAILURE_REMOTE_DEVICE_RESET_REQUIRED = SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED,
+   SCI_TASK_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS = SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS
+
+} SCI_TASK_STATUS;
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCI_STATUS_H_
diff --git a/sys/dev/disk/isci/scil/sci_types.h b/sys/dev/disk/isci/scil/sci_types.h
new file mode 100644
index 0000000..5139c13
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_types.h
@@ -0,0 +1,279 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_types.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCI_TYPES_H_
+#define _SCI_TYPES_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the basic data types utilized by an
+ *        SCI user or implementor.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/types.h>
+
+#ifndef sci_cb_physical_address_upper
+#error "sci_cb_physical_address_upper needs to be defined in appropriate environment.h"
+#endif
+
+#ifndef sci_cb_physical_address_lower
+#error "sci_cb_physical_address_lower needs to be defined in appropriate environment.h"
+#endif
+
+#ifndef sci_cb_make_physical_address
+#error "sci_cb_make_physical_address needs to be defined in appropriate environment.h"
+#endif
+
+#ifndef ASSERT
+#error "ASSERT needs to be defined in appropriate environment.h or system"
+#endif
+
+
+/**
+ * This constant defines the value utilized by SCI Components to indicate
+ * an invalid handle.
+ */
+#define SCI_INVALID_HANDLE 0x0
+
+/**
+ * @typedef SCI_OBJECT_HANDLE_T
+ * @brief   This typedef just provides an opaque handle for all SCI
+ *          objects.
+ */
+typedef void* SCI_OBJECT_HANDLE_T;
+
+/**
+ * @typedef SCI_LOGGER_HANDLE_T
+ * @brief   This typedef just provides an opaque handle for all SCI
+ *          Logger objects.
+ */
+typedef void* SCI_LOGGER_HANDLE_T;
+
+/**
+ * @typedef SCI_IO_REQUEST_HANDLE_T
+ * @brief   The SCI_IO_REQUEST_HANDLE_T will be utilized by SCI users as an
+ *          opaque handle for the various SCI IO Request objects.
+ */
+typedef void * SCI_IO_REQUEST_HANDLE_T;
+
+/**
+ * @typedef SCI_TASK_REQUEST_HANDLE_T
+ * @brief   The SCI_TASK_REQUEST_HANDLE_T will be utilized by SCI users as an
+ *          opaque handle for the various SCI Task Management Request objects.
+ */
+typedef void * SCI_TASK_REQUEST_HANDLE_T;
+
+/**
+ * @typedef SCI_PHY_HANDLE_T
+ * @brief   This typedef just provides an opaque handle for all SCI
+ *          Phy objects.
+ */
+typedef void * SCI_PHY_HANDLE_T;
+
+/**
+ * @typedef SCI_REMOTE_DEVICE_HANDLE_T
+ * @brief   The SCI_REMOTE_DEVICE_HANDLE_T will be utilized by SCI users as
+ *          an opaque handle for the SCI remote device object.
+ */
+typedef void * SCI_REMOTE_DEVICE_HANDLE_T;
+
+/**
+ * @typedef SCI_DOMAIN_HANDLE_T
+ * @brief   This typedef just provides an opaque handle for all SCI
+ *          Domain objects.
+ */
+typedef void* SCI_DOMAIN_HANDLE_T;
+
+/**
+ * @typedef SCI_PORT_HANDLE_T
+ * @brief   This typedef just provides an opaque handle for all SCI
+ *          SAS or SATA Port objects.
+ */
+typedef void * SCI_PORT_HANDLE_T;
+
+/**
+ * @typedef SCI_MEMORY_DESCRIPTOR_LIST_HANDLE_T
+ * @brief   The SCI_MEMORY_DESCRIPTOR_LIST_HANDLE_T will be utilized by SCI
+ *          users as an opaque handle for the SCI MEMORY DESCRIPTOR LIST object.
+ */
+typedef void * SCI_MEMORY_DESCRIPTOR_LIST_HANDLE_T;
+
+/**
+ * @typedef SCI_LOCK_HANDLE_T
+ * @brief   The SCI_LOCK_HANDLE_T will be utilized by SCI users as an
+ *          opaque handle for the SCI LOCK object.  A lock denotes a
+ *          critical code section of some form.
+ */
+typedef void * SCI_LOCK_HANDLE_T;
+
+/**
+ * @typedef SCI_CONTROLLER_HANDLE_T
+ * @brief   The SCI_CONTROLLER_HANDLE_T will be utilized by SCI users as an
+ *          opaque handle for all SCI Controller objects.
+ */
+typedef void * SCI_CONTROLLER_HANDLE_T;
+
+/**
+ * @typedef SCI_LIBRARY_HANDLE_T
+ * @brief   The SCI_LIBRARY_HANDLE_T will be utilized by SCI users as an
+ *          opaque handle for the SCI Library object.
+ */
+typedef void * SCI_LIBRARY_HANDLE_T;
+
+/**
+ * @typedef SCI_ITERATOR_HANDLE_T
+ * @brief   The SCI_ITERATOR_T will be utilized by SCI users as an
+ *          opaque handle for the SCI Iterator object.
+ */
+typedef void * SCI_ITERATOR_HANDLE_T;
+
+/**
+ * @typedef SCI_TIMER_CALLBACK_T
+ * @brief   This callback defines the format of all other timer callback
+ *          methods that are to be implemented by an SCI user, including
+ *          the method that will be invoked as a result of timer expiration.
+ *
+ *          Parameters:
+ *          - The void* value passed into the callback represents the cookie
+ *            supplied by the SCI component when the timer was created.
+ *
+ *          Return:
+ *          - None
+ */
+typedef void (*SCI_TIMER_CALLBACK_T)(void*);
+
+/**
+ * @brief This enumeration is provided so the SCI User can communicate the
+ *        data direction for an IO request.
+ */
+typedef enum
+{
+   /**
+    * The data direction for the request is in (a read operation)
+    * This is also the value to use for an io request that has no specific
+    * data direction.
+    */
+   SCI_IO_REQUEST_DATA_IN = 0,
+
+   /**
+    * The data direction for the request is out (a write operation)
+    */
+   SCI_IO_REQUEST_DATA_OUT,
+
+   /**
+    * There is no data transfer for the associated request.
+    */
+   SCI_IO_REQUEST_NO_DATA
+
+} SCI_IO_REQUEST_DATA_DIRECTION;
+
+/**
+ * @enum  SCI_LOCK_LEVEL
+ * @brief This enumeration defines the various lock levels utilized by
+ *        the SCI component.  These lock levels help inform users, of the
+ *        library, about what APIs must be protected from other APIs.
+ *        The higher the lock level the more restricted the access.  For
+ *        example, APIs specifying lock level 5 are allowed to be executed
+ *        while an API of lock level 4 is on-going, but the converse is
+ *        not true.
+ */
+typedef enum
+{
+   /**
+    * This value indicates there is no lock level required.  This is
+    * primarily utilized for situations in which there is a true critical
+    * code section that merely needs to protect against access to a
+    * region of memory.
+    */
+   SCI_LOCK_LEVEL_NONE,
+
+   SCI_LOCK_LEVEL_1,
+   SCI_LOCK_LEVEL_2,
+   SCI_LOCK_LEVEL_3,
+   SCI_LOCK_LEVEL_4,
+   SCI_LOCK_LEVEL_5
+
+} SCI_LOCK_LEVEL;
+
+/**
+ * @enum _SCI_CONTROLLER_MODE
+ * @brief This enumeration is utilized to indicate the operating mode
+ *        in which the SCI component should function.
+ */
+typedef enum _SCI_CONTROLLER_MODE
+{
+   /**
+    * This enumerant specifies that the SCI component be optimized to
+    * perform as fast as possible without concern for the amount of
+    * memory being utilized.
+    */
+   SCI_MODE_SPEED,
+
+   /**
+    * This enumerant specifies that the SCI component be optimized to
+    * save memory space without concern for performance of the system.
+    */
+   SCI_MODE_SIZE
+
+} SCI_CONTROLLER_MODE;
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCI_TYPES_H_
diff --git a/sys/dev/disk/isci/scil/sci_util.c b/sys/dev/disk/isci/scil/sci_util.c
new file mode 100644
index 0000000..c0b84d5
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_util.c
@@ -0,0 +1,70 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_util.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+#include <dev/disk/isci/scil/sci_util.h>
+
+void scic_word_copy_with_swap(
+   U32 *destination,
+   U32 *source,
+   U32 word_count
+)
+{
+   while (word_count--)
+   {
+      *destination = SCIC_SWAP_DWORD(*source);
+
+      source++;
+      destination++;
+   }
+}
diff --git a/sys/dev/disk/isci/scil/sci_util.h b/sys/dev/disk/isci/scil/sci_util.h
new file mode 100644
index 0000000..56a3d35
--- /dev/null
+++ b/sys/dev/disk/isci/scil/sci_util.h
@@ -0,0 +1,164 @@
+/*-
+ * 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: src/sys/dev/isci/scil/sci_util.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCI_UTIL_H_
+#define _SCI_UTIL_H_
+
+#include <dev/disk/isci/scil/sci_types.h>
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#endif
+
+#ifndef MIN
+#define MIN(x,y) ((x) < (y) ? (x) : (y))
+#endif
+
+#ifndef MAX
+#define MAX(x,y) ((x) > (y) ? (x) : (y))
+#endif
+
+/**
+ * Normal byte swap macro
+ */
+#define SCIC_SWAP_DWORD(x) \
+   ( \
+       (((x) >> 24) & 0x000000FF) \
+     | (((x) >>  8) & 0x0000FF00) \
+     | (((x) <<  8) & 0x00FF0000) \
+     | (((x) << 24) & 0xFF000000) \
+   )
+
+#define SCIC_BUILD_DWORD(char_buffer) \
+   ( \
+     ((char_buffer)[0] << 24) \
+   | ((char_buffer)[1] << 16) \
+   | ((char_buffer)[2] <<  8) \
+   | ((char_buffer)[3]) \
+   )
+
+#define SCI_FIELD_OFFSET(type, field)   ((POINTER_UINT)&(((type *)0)->field))
+
+//This macro counts how many bits being set in a mask.
+#define SCI_GET_BITS_SET_COUNT(mask, set_bit_count)     \
+{                                                  \
+   U8 index;                                       \
+   set_bit_count = 0;                              \
+   for (index = 0; index < sizeof(mask)*8; index++)            \
+   {                                               \
+      if( mask & (1<<index) )                      \
+         set_bit_count++;                          \
+   }                                               \
+}
+
+/**
+ * This macro simply performs addition on an SCI_PHYSICAL_ADDRESS
+ * type.  The lower U32 value is "clipped" or "wrapped" back through
+ * 0.  When this occurs the upper 32-bits are incremented by 1.
+ */
+#define sci_physical_address_add(physical_address, value) \
+{ \
+   U32 lower = sci_cb_physical_address_lower((physical_address)); \
+   U32 upper = sci_cb_physical_address_upper((physical_address)); \
+ \
+   if (lower + (value) < lower) \
+      upper += 1; \
+ \
+   lower += (value); \
+   sci_cb_make_physical_address(physical_address, upper, lower); \
+}
+
+/**
+ * This macro simply performs subtraction on an SCI_PHYSICAL_ADDRESS
+ * type.  The lower U32 value is "clipped" or "wrapped" back through
+ * 0.  When this occurs the upper 32-bits are decremented by 1.
+ */
+#define sci_physical_address_subtract(physical_address, value) \
+{ \
+   U32 lower = sci_cb_physical_address_lower((physical_address)); \
+   U32 upper = sci_cb_physical_address_upper((physical_address)); \
+ \
+   if (lower - (value) > lower) \
+      upper -= 1; \
+ \
+   lower -= (value); \
+   sci_cb_make_physical_address(physical_address, upper, lower); \
+}
+
+/**
+ * @brief Copy the data from source to destination and swap the
+ *        bytes during the copy.
+ *
+ * @param[in] destination This parameter specifies the destination address
+ *            to which the data is to be copied.
+ * @param[in] source This parameter specifies the source address from
+ *            which data is to be copied.
+ * @param[in] word_count This parameter specifies the number of 32-bit words
+ *            to copy and byte swap.
+ *
+ * @return none
+ */
+void scic_word_copy_with_swap(
+   U32 *destination,
+   U32 *source,
+   U32 word_count
+);
+
+
+#define sci_ssp_get_sense_data_length(sense_data_length_buffer) \
+   SCIC_BUILD_DWORD(sense_data_length_buffer)
+
+#define sci_ssp_get_response_data_length(response_data_length_buffer) \
+   SCIC_BUILD_DWORD(response_data_length_buffer)
+
+#endif // _SCI_UTIL_H_
diff --git a/sys/dev/disk/isci/scil/scic_config_parameters.h b/sys/dev/disk/isci/scil/scic_config_parameters.h
new file mode 100644
index 0000000..d98751e
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_config_parameters.h
@@ -0,0 +1,345 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_config_parameters.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIC_SDS_USER_PARAMETERS_H_
+#define _SCIC_SDS_USER_PARAMETERS_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the structure definitions and interface
+ *        methods that can be called by a SCIC user on the SCU Driver
+ *        Standard (SCIC_SDS_USER_PARAMETERS_T) user parameter block.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/sci_status.h>
+#include <dev/disk/isci/scil/intel_sas.h>
+#include <dev/disk/isci/scil/sci_controller_constants.h>
+#include <dev/disk/isci/scil/scu_bios_definitions.h>
+
+/**
+ * @name SCIC_SDS_PARM_PHY_SPEED
+ *
+ * These constants define the speeds utilized for a phy/port.
+ */
+/*@{*/
+#define SCIC_SDS_PARM_NO_SPEED   0
+
+/**
+ * This value of 1 indicates generation 1 (i.e. 1.5 Gb/s).
+ */
+#define SCIC_SDS_PARM_GEN1_SPEED 1
+
+/**
+ * This value of 2 indicates generation 2 (i.e. 3.0 Gb/s).
+ */
+#define SCIC_SDS_PARM_GEN2_SPEED 2
+
+/**
+ * This value of 3 indicates generation 3 (i.e. 6.0 Gb/s).
+ */
+#define SCIC_SDS_PARM_GEN3_SPEED 3
+
+/**
+ * For range checks, the max speed generation
+ */
+#define SCIC_SDS_PARM_MAX_SPEED SCIC_SDS_PARM_GEN3_SPEED
+/*@}*/
+
+/**
+ * @struct SCIC_SDS_USER_PARAMETERS
+ *
+ * @brief This structure delineates the various user parameters that can be
+ *        changed by the core user.
+ */
+typedef struct SCIC_SDS_USER_PARAMETERS
+{
+   struct
+   {
+      /**
+       * This field specifies the NOTIFY (ENABLE SPIN UP) primitive
+       * insertion frequency for this phy index.
+       */
+      U32  notify_enable_spin_up_insertion_frequency;
+
+      /**
+       * This method specifies the number of transmitted DWORDs within which
+       * to transmit a single ALIGN primitive.  This value applies regardless
+       * of what type of device is attached or connection state.  A value of
+       * 0 indicates that no ALIGN primitives will be inserted.
+       */
+      U16  align_insertion_frequency;
+
+      /**
+       * This method specifies the number of transmitted DWORDs within which
+       * to transmit 2 ALIGN primitives.  This applies for SAS connections
+       * only.  A minimum value of 3 is required for this field.
+       */
+      U16  in_connection_align_insertion_frequency;
+
+      /**
+       * This field indicates the maximum speed generation to be utilized
+       * by phys in the supplied port.
+       * - A value of 1 indicates generation 1 (i.e. 1.5 Gb/s).
+       * - A value of 2 indicates generation 2 (i.e. 3.0 Gb/s).
+       * - A value of 3 indicates generation 3 (i.e. 6.0 Gb/s).
+       */
+      U8 max_speed_generation;
+
+   } phys[SCI_MAX_PHYS];
+
+
+   /**
+    * This field specifies the number of seconds to allow a phy to consume
+    * power before yielding to another phy.
+    *
+    */
+   U8  phy_spin_up_delay_interval;
+
+   /**
+   * These timer values specifies how long a link will remain open with no
+   * activity in increments of a microsecond, it can be in increments of
+   * 100 microseconds if the upper most bit is set.
+   *
+   */
+   U16 stp_inactivity_timeout;
+   U16 ssp_inactivity_timeout;
+
+   /**
+   * These timer values specifies how long a link will remain open in increments
+   * of 100 microseconds.
+   *
+   */
+   U16 stp_max_occupancy_timeout;
+   U16 ssp_max_occupancy_timeout;
+
+   /**
+   * This timer value specifies how long a link will remain open with no
+   * outbound traffic in increments of a microsecond.
+   *
+   */
+   U8 no_outbound_task_timeout;
+
+} SCIC_SDS_USER_PARAMETERS_T;
+
+/**
+ * @union SCIC_USER_PARAMETERS
+ * @brief This structure/union specifies the various different user
+ *        parameter sets available.  Each type is specific to a hardware
+ *        controller version.
+ */
+typedef union SCIC_USER_PARAMETERS
+{
+   /**
+    * This field specifies the user parameters specific to the
+    * Storage Controller Unit (SCU) Driver Standard (SDS) version
+    * 1.
+    */
+   SCIC_SDS_USER_PARAMETERS_T sds1;
+
+} SCIC_USER_PARAMETERS_T;
+
+
+/**
+ * @name SCIC_SDS_OEM_PHY_MASK
+ *
+ * These constants define the valid values for phy_mask
+ */
+/*@{*/
+
+/**
+ * This is the min value assignable to a port's phy mask
+ */
+#define SCIC_SDS_PARM_PHY_MASK_MIN 0x0
+
+/**
+ * This is the max value assignable to a port's phy mask
+ */
+#define SCIC_SDS_PARM_PHY_MASK_MAX 0xF
+/*@}*/
+
+#define MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT 4
+
+typedef SCI_BIOS_OEM_PARAM_ELEMENT_v_1_3_T SCIC_SDS_OEM_PARAMETERS_T;
+
+/**
+ * @union SCIC_OEM_PARAMETERS
+ *
+ * @brief This structure/union specifies the various different OEM
+ *        parameter sets available.  Each type is specific to a hardware
+ *        controller version.
+ */
+typedef union SCIC_OEM_PARAMETERS
+{
+   /**
+    * This field specifies the OEM parameters specific to the
+    * Storage Controller Unit (SCU) Driver Standard (SDS) version
+    * 1.
+    */
+   SCIC_SDS_OEM_PARAMETERS_T sds1;
+
+} SCIC_OEM_PARAMETERS_T;
+
+/**
+ * @union OEM_SSC_DATA
+ *
+ * @brief This typedef provides a means to convert from the original
+ *        1.0 version of the OEM PARAMETER do_enable_ssc to the more
+ *        comprehensive 1.1 version of enabling SSC parameters.
+ *        For the definition of the field members see scu_bios_definitions.h
+ *        header file or refer to the SCU BIOS Writers Guide.
+ */
+typedef union OEM_SSC_PARAMETERS
+{
+   struct
+   {
+      U8 ssc_sata_tx_spread_level : 4;
+      U8 ssc_sas_tx_spread_level : 3;
+      U8 ssc_sas_tx_type : 1;
+   } bf;
+
+   U8 do_enable_ssc;
+
+} OEM_SSC_PARAMETERS_T;
+
+/**
+ * @brief This method allows the user to attempt to change the user
+ *        parameters utilized by the controller.
+ *
+ * @param[in] controller This parameter specifies the controller on which
+ *            to set the user parameters.
+ * @param[in] user_parameters This parameter specifies the USER_PARAMETERS
+ *            object containing the potential new values.
+ *
+ * @return Indicate if the update of the user parameters was successful.
+ * @retval SCI_SUCCESS This value is returned if the operation succeeded.
+ * @retval SCI_FAILURE_INVALID_STATE This value is returned if the attempt
+ *         to change the user parameter failed, because changing one of
+ *         the parameters is not currently allowed.
+ * @retval SCI_FAILURE_INVALID_PARAMETER_VALUE This value is returned if the
+ *         user supplied an invalid interrupt coalescence time, spin up
+ *         delay interval, etc.
+ */
+SCI_STATUS scic_user_parameters_set(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   SCIC_USER_PARAMETERS_T  * user_parameters
+);
+
+/**
+ * @brief This method allows the user to retrieve the user parameters
+ *        utilized by the controller.
+ *
+ * @param[in] controller This parameter specifies the controller on which
+ *            to set the user parameters.
+ * @param[in] user_parameters This parameter specifies the USER_PARAMETERS
+ *            object into which the framework shall save it's parameters.
+ *
+ * @return none
+ */
+void scic_user_parameters_get(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   SCIC_USER_PARAMETERS_T  * user_parameters
+);
+
+/**
+ * @brief This method allows the user to attempt to change the OEM
+ *        parameters utilized by the controller.
+ *
+ * @param[in] controller This parameter specifies the controller on which
+ *            to set the user parameters.
+ * @param[in] oem_parameters This parameter specifies the OEM parameters
+ *            object containing the potential new values.
+ * @param[in] oem_parameters_version This parameter is the OEM block version
+ *            value indicating the format of the data associated with
+ *            oem_parameters.
+ *
+ * @return Indicate if the update of the user parameters was successful.
+ * @retval SCI_SUCCESS This value is returned if the operation succeeded.
+ * @retval SCI_FAILURE_INVALID_STATE This value is returned if the attempt
+ *         to change the user parameter failed, because changing one of
+ *         the parameters is not currently allowed.
+ * @retval SCI_FAILURE_INVALID_PARAMETER_VALUE This value is returned if the
+ *         user supplied an unsupported value for one of the OEM parameters.
+ */
+SCI_STATUS scic_oem_parameters_set(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   SCIC_OEM_PARAMETERS_T   * oem_parameters,
+   U8 oem_parameters_version
+);
+
+/**
+ * @brief This method allows the user to retreive the OEM
+ *        parameters utilized by the controller.
+ *
+ * @param[in]  controller This parameter specifies the controller on which
+ *             to set the user parameters.
+ * @param[out] oem_parameters This parameter specifies the OEM parameters
+ *             object in which to write the core's OEM parameters.
+ *
+ * @return none
+ */
+void scic_oem_parameters_get(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   SCIC_OEM_PARAMETERS_T   * oem_parameters
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIC_SDS_USER_PARAMETERS_H_
diff --git a/sys/dev/disk/isci/scil/scic_controller.h b/sys/dev/disk/isci/scil/scic_controller.h
new file mode 100644
index 0000000..564b177
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_controller.h
@@ -0,0 +1,855 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_controller.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIC_CONTROLLER_H_
+#define _SCIC_CONTROLLER_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the interface methods that can be called
+ *        by an SCIC user on a controller object.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/sci_status.h>
+#include <dev/disk/isci/scil/sci_controller.h>
+#include <dev/disk/isci/scil/scic_config_parameters.h>
+
+/**
+ * @enum
+ *
+ * Allowed PORT configuration modes
+ *
+ * APC Automatic PORT configuration mode is defined by the OEM configuration
+ * parameters providing no PHY_MASK parameters for any PORT. i.e. There are
+ * no phys assigned to any of the ports at start.
+ *
+ * MPC Manual PORT configuration mode is defined by the OEM configuration
+ * parameters providing a PHY_MASK value for any PORT.  It is assumed that
+ * any PORT with no PHY_MASK is an invalid port and not all PHYs must be
+ * assigned. A PORT_PHY mask that assigns just a single PHY to a port and no
+ * other PHYs being assigned is sufficient to declare manual PORT configuration.
+ */
+enum SCIC_PORT_CONFIGURATION_MODE
+{
+   SCIC_PORT_MANUAL_CONFIGURATION_MODE,
+   SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE
+};
+
+/**
+ * @enum _SCIC_INTERRUPT_TYPE
+ *
+ * @brief This enumeration depicts the various types of interrupts that
+ *        are potentially supported by a SCI Core implementation.
+ */
+typedef enum _SCIC_INTERRUPT_TYPE
+{
+   SCIC_LEGACY_LINE_INTERRUPT_TYPE,
+   SCIC_MSIX_INTERRUPT_TYPE,
+
+   /**
+    * This enumeration value indicates the use of polling.
+    */
+   SCIC_NO_INTERRUPTS
+
+} SCIC_INTERRUPT_TYPE;
+
+/**
+ * @typedef SCIC_CONTROLLER_INTERRUPT_HANDLER
+ *
+ * @brief This method is called by the SCI user in order to have the SCI
+ *        implementation handle the interrupt.  This method performs
+ *        minimal processing to allow for streamlined interrupt time usage.
+ * @note
+ *        TRUE: returned if there is an interrupt to process and it was
+ *              processed.
+ *        FALSE: returned if no interrupt was processed.
+ *
+ */
+typedef BOOL (*SCIC_CONTROLLER_INTERRUPT_HANDLER)(
+   SCI_CONTROLLER_HANDLE_T  controller
+);
+
+/**
+ * @brief This method is called by the SCI user to process completions
+ *        generated as a result of a previously handled interrupt.  This
+ *        method will result in the completion of IO requests and handling
+ *        of other controller generated events.  This method should be
+ *        called some time after the interrupt handler.
+ *
+ * @note  Most, if not all, of the user callback APIs are invoked from within
+ *        this API.  As a result, the user should be cognizent of the operating
+ *        level at which they invoke this API.
+ *
+ */
+typedef void (*SCIC_CONTROLLER_COMPLETION_HANDLER)(
+   SCI_CONTROLLER_HANDLE_T  controller
+);
+
+/**
+ * @struct SCIC_CONTROLLER_HANDLER_METHODS
+ *
+ * @brief This structure contains an interrupt handler and completion
+ *        handler function pointers.
+ */
+typedef struct SCIC_CONTROLLER_HANDLER_METHODS
+{
+   SCIC_CONTROLLER_INTERRUPT_HANDLER  interrupt_handler;
+   SCIC_CONTROLLER_COMPLETION_HANDLER completion_handler;
+
+} SCIC_CONTROLLER_HANDLER_METHODS_T;
+
+/**
+ * @brief This method will attempt to construct a controller object
+ *        utilizing the supplied parameter information.
+ *
+ * @param[in]  library This parameter specifies the handle to the library
+ *             object associated with the controller being constructed.
+ * @param[in]  controller This parameter specifies the controller to be
+ *             constructed.
+ * @param[in]  user_object This parameter is a reference to the SCIL users
+ *             controller object and will be used to associate with the core
+ *             controller.
+ *
+ * @return Indicate if the controller was successfully constructed or if
+ *         it failed in some way.
+ * @retval SCI_SUCCESS This value is returned if the controller was
+ *         successfully constructed.
+ * @retval SCI_WARNING_TIMER_CONFLICT This value is returned if the
+ *         interrupt coalescence timer may cause SAS compliance issues
+ *         for SMP Target mode response processing.
+ * @retval SCI_FAILURE_UNSUPPORTED_CONTROLLER_TYPE This value is returned if
+ *         the controller does not support the supplied type.
+ * @retval SCI_FAILURE_UNSUPPORTED_INIT_DATA_VERSION This value is returned
+ *         if the controller does not support the supplied initialization
+ *         data version.
+ */
+SCI_STATUS scic_controller_construct(
+   SCI_LIBRARY_HANDLE_T      library,
+   SCI_CONTROLLER_HANDLE_T   controller,
+   void *                    user_object
+);
+
+/**
+ * @brief This method will enable all controller interrupts.
+ *
+ * @param[in]  controller This parameter specifies the controller for which
+ *             to enable interrupts.
+ *
+ * @return none
+ */
+void scic_controller_enable_interrupts(
+   SCI_CONTROLLER_HANDLE_T      controller
+);
+
+/**
+ * @brief This method will disable all controller interrupts.
+ *
+ * @param[in]  controller This parameter specifies the controller for which
+ *             to disable interrupts.
+ *
+ * @return none
+ */
+void scic_controller_disable_interrupts(
+   SCI_CONTROLLER_HANDLE_T      controller
+);
+
+/**
+ * @brief This method will return provide function pointers for the
+ *        interrupt handler and completion handler.  The interrupt handler
+ *        is expected to be invoked at interrupt time.  The completion
+ *        handler is scheduled to run as a result of the interrupt handler.
+ *        The completion handler performs the bulk work for processing
+ *        silicon events.
+ *
+ * @param[in]  interrupt_type This parameter informs the core which type
+ *             of interrupt/completion methods are being requested. These
+ *             are the types: SCIC_LEGACY_LINE_INTERRUPT_TYPE,
+ *             SCIC_MSIX_INTERRUPT_TYPE, SCIC_NO_INTERRUPTS (POLLING)
+ * @param[in]  message_count This parameter informs the core the
+ *             number of MSI-X messages to be utilized.  This parameter must
+ *             be 0 when requesting legacy line based handlers.
+ * @param[in]  handler_methods The caller provides a pointer to a buffer of
+ *             type SCIC_CONTROLLER_HANDLER_METHODS_T. The size depends on
+ *             the combination of the interrupt_type and message_count input
+ *             parameters:
+ *             SCIC_LEGACY_LINE_INTERRUPT_TYPE:
+ *             - size = sizeof(SCIC_CONTROLLER_HANDLER_METHODS_T)
+ *             SCIC_MSIX_INTERRUPT_TYPE:
+ *             - size = message_count*sizeof(SCIC_CONTROLLER_HANDLER_METHODS_T)
+ * @param[out] handler_methods SCIC fills out the caller's buffer with the
+ *             appropriate interrupt and completion handlers based on the info
+ *             provided in the interrupt_type and message_count input
+ *             parameters. For SCIC_LEGACY_LINE_INTERRUPT_TYPE, the buffer
+ *             receives a single SCIC_CONTROLLER_HANDLER_METHODS_T element
+ *             regardless that the message_count parameter is zero.
+ *             For SCIC_MSIX_INTERRUPT_TYPE, the buffer receives an array of
+ *             elements of type SCIC_CONTROLLER_HANDLER_METHODS_T where the
+ *             array size is equivalent to the message_count parameter. The
+ *             array is zero-relative where entry zero corresponds to
+ *             message-vector zero, entry one corresponds to message-vector one,
+ *             and so forth.
+ *
+ * @return Indicate if the handler retrieval operation was successful.
+ * @retval SCI_SUCCESS This value is returned if retrieval succeeded.
+ * @retval SCI_FAILURE_UNSUPPORTED_MESSAGE_COUNT This value is returned
+ *         if the user supplied an unsupported number of MSI-X messages.
+ *         For legacy line interrupts the only valid value is 0.
+ */
+SCI_STATUS scic_controller_get_handler_methods(
+   SCIC_INTERRUPT_TYPE                  interrupt_type,
+   U16                                  message_count,
+   SCIC_CONTROLLER_HANDLER_METHODS_T *  handler_methods
+);
+
+/**
+ * @brief This method will initialize the controller hardware managed by
+ *        the supplied core controller object.  This method will bring the
+ *        physical controller hardware out of reset and enable the core to
+ *        determine the capabilities of the hardware being managed.  Thus,
+ *        the core controller can determine it's exact physical (DMA capable)
+ *        memory requirements.
+ *
+ * @pre   The SCI Core user must have called scic_controller_construct()
+ *        on the supplied controller object previously.
+ *
+ * @param[in]  controller This parameter specifies the controller to be
+ *             initialized.
+ *
+ * @return Indicate if the controller was successfully initialized or if
+ *         it failed in some way.
+ * @retval SCI_SUCCESS This value is returned if the controller hardware
+ *         was successfully initialized.
+ */
+SCI_STATUS scic_controller_initialize(
+   SCI_CONTROLLER_HANDLE_T   controller
+);
+
+/**
+ * @brief This method returns the suggested scic_controller_start()
+ *        timeout amount.  The user is free to use any timeout value,
+ *        but this method provides the suggested minimum start timeout
+ *        value.  The returned value is based upon empirical information
+ *        determined as a result of interoperability testing.
+ *
+ * @param[in]  controller the handle to the controller object for which
+ *             to return the suggested start timeout.
+ *
+ * @return  This method returns the number of milliseconds for the
+ *          suggested start operation timeout.
+ */
+U32 scic_controller_get_suggested_start_timeout(
+   SCI_CONTROLLER_HANDLE_T  controller
+);
+
+/**
+ * @brief This method will start the supplied core controller.  This method
+ *        will start the staggered spin up operation.  The SCI User completion
+ *        callback is called when the following conditions are met:
+ *        -# the return status of this method is SCI_SUCCESS.
+ *        -# after all of the phys have successfully started or been given
+ *           the opportunity to start.
+ *
+ * @pre   The SCI Core user must have filled in the physical memory
+ *        descriptor structure via the
+ *        sci_controller_get_memory_descriptor_list() method.
+ * @pre   The SCI Core user must have invoked the scic_controller_initialize()
+ *        method prior to invoking this method.
+ *
+ * @pre   The controller must be in the INITIALIZED or STARTED state.
+ *
+ * @param[in]  controller the handle to the controller object to start.
+ * @param[in]  timeout This parameter specifies the number of milliseconds
+ *             in which the start operation should complete.
+ *
+ * @return Indicate if the controller start method succeeded or failed in
+ *         some way.
+ * @retval SCI_SUCCESS if the start operation succeeded.
+ * @retval SCI_WARNING_ALREADY_IN_STATE if the controller is already in
+ *         the STARTED state.
+ * @retval SCI_FAILURE_INVALID_STATE if the controller is not either in
+ *         the INITIALIZED or STARTED states.
+ * @retval SCI_FAILURE_INVALID_MEMORY_DESCRIPTOR if there are
+ *         inconsistent or invalid values in the supplied
+ *         SCI_PHYSICAL_MEMORY_DESCRIPTOR array.
+ */
+SCI_STATUS scic_controller_start(
+   SCI_CONTROLLER_HANDLE_T  controller,
+   U32                      timeout
+);
+
+/**
+ * @brief This method will stop an individual controller object.This method
+ *        will invoke the associated user callback upon completion.  The
+ *        completion callback is called when the following conditions are met:
+ *           -# the method return status is SCI_SUCCESS.
+ *           -# the controller has been quiesced.
+ *        This method will ensure that all IO requests are quiesced, phys
+ *        are stopped, and all additional operation by the hardware is halted.
+ *
+ * @pre   The controller must be in the STARTED or STOPPED state.
+ *
+ * @param[in]  controller the handle to the controller object to stop.
+ * @param[in]  timeout This parameter specifies the number of milliseconds
+ *             in which the stop operation should complete.
+ *
+ * @return Indicate if the controller stop method succeeded or failed in
+ *         some way.
+ * @retval SCI_SUCCESS if the stop operation successfully began.
+ * @retval SCI_WARNING_ALREADY_IN_STATE if the controller is already in
+ *         the STOPPED state.
+ * @retval SCI_FAILURE_INVALID_STATE if the controller is not either in
+ *         the STARTED or STOPPED states.
+ */
+SCI_STATUS scic_controller_stop(
+   SCI_CONTROLLER_HANDLE_T  controller,
+   U32                      timeout
+);
+
+/**
+ * @brief This method will reset the supplied core controller regardless of
+ *        the state of said controller.  This operation is considered
+ *        destructive.  In other words, all current operations are wiped
+ *        out.  No IO completions for outstanding devices occur.  Outstanding
+ *        IO requests are not aborted or completed at the actual remote
+ *        device.
+ *
+ * @param[in]  controller the handle to the controller object to reset.
+ *
+ * @return Indicate if the controller reset method succeeded or failed in
+ *         some way.
+ * @retval SCI_SUCCESS if the reset operation successfully started.
+ * @retval SCI_FATAL_ERROR if the controller reset operation is unable to
+ *         complete.
+ */
+SCI_STATUS scic_controller_reset(
+   SCI_CONTROLLER_HANDLE_T  controller
+);
+
+/**
+ * @brief This method is called by the SCI user to send/start an IO request.
+ *        If the method invocation is successful, then the IO request has
+ *        been queued to the hardware for processing.
+ *
+ * @warning
+ *         - IO tags are a protected resource.  It is incumbent upon the
+ *           SCI Core user to ensure that each of the methods that may
+ *           allocate or free available IO tags are handled in a mutually
+ *           exclusive manner.  This method is one of said methods requiring
+ *           proper critical code section protection (e.g. semaphore,
+ *           spin-lock, etc.).
+ *         - For SATA, the user is required to manage NCQ tags.  As a
+ *           result, it is expected the user will have set the NCQ tag
+ *           field in the host to device register FIS prior to calling
+ *           this method.  There is also a requirement for the user
+ *           to call scic_stp_io_set_ncq_tag() prior to invoking the
+ *           scic_controller_start_io() method.
+ *
+ * @param[in]  controller the handle to the controller object for which
+ *             to start an IO request.
+ * @param[in]  remote_device the handle to the remote device object for which
+ *             to start an IO request.
+ * @param[in]  io_request the handle to the io request object to start.
+ * @param[in]  io_tag This parameter specifies a previously allocated IO tag
+ *             that the user desires to be utilized for this request.
+ *             This parameter is optional.  The user is allowed to supply
+ *             SCI_CONTROLLER_INVALID_IO_TAG as the value for this parameter.
+ *             @see scic_controller_allocate_tag() for more information
+ *             on allocating a tag.
+ *
+ * @return Indicate if the controller successfully started the IO request.
+ * @retval SCI_IO_SUCCESS if the IO request was successfully started.
+ *
+ * @todo Determine the failure situations and return values.
+ */
+SCI_IO_STATUS scic_controller_start_io(
+   SCI_CONTROLLER_HANDLE_T     controller,
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
+   SCI_IO_REQUEST_HANDLE_T     io_request,
+   U16                         io_tag
+);
+
+#if !defined(DISABLE_TASK_MANAGEMENT)
+
+/**
+ * @brief This method is called by the SCIC user to send/start a framework
+ *        task management request.
+ *
+ * @warning
+ *         - IO tags are a protected resource.  It is incumbent upon the
+ *           SCI Core user to ensure that each of the methods that may
+ *           allocate or free available IO tags are handled in a mutually
+ *           exclusive manner.  This method is one of said methods requiring
+ *           proper critical code section protection (e.g. semaphore,
+ *           spin-lock, etc.).
+ *         - The user must synchronize this task with completion queue
+ *           processing.  If they are not synchronized then it is possible
+ *           for the io requests that are being managed by the task request
+ *           can complete before starting the task request.
+ *
+ * @param[in]  controller the handle to the controller object for which
+ *             to start the task management request.
+ * @param[in]  remote_device the handle to the remote device object for which
+ *             to start the task management request.
+ * @param[in]  task_request the handle to the task request object to start.
+ * @param[in]  io_tag This parameter specifies a previously allocated IO tag
+ *             that the user desires to be utilized for this request.  Note
+ *             this not the io_tag of the request being managed.  It is to
+ *             be utilized for the task request itself.
+ *             This parameter is optional.  The user is allowed to supply
+ *             SCI_CONTROLLER_INVALID_IO_TAG as the value for this parameter.
+ *             @see scic_controller_allocate_tag() for more information
+ *             on allocating a tag.
+ *
+ * @return Indicate if the controller successfully started the IO request.
+ * @retval SCI_TASK_SUCCESS if the task request was successfully started.
+ * @retval SCI_TASK_FAILURE_REQUIRES_SCSI_ABORT This value is returned if
+ *         there is/are task(s) outstanding that require termination or
+ *         completion before this request can succeed.
+ */
+SCI_TASK_STATUS scic_controller_start_task(
+   SCI_CONTROLLER_HANDLE_T     controller,
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
+   SCI_TASK_REQUEST_HANDLE_T   task_request,
+   U16                         io_tag
+);
+
+/**
+ * @brief This method will perform core specific completion operations for
+ *        task management request. After this method is invoked, the user should
+ *        consider the task request as invalid until it is properly reused
+ *        (i.e. re-constructed).
+ *
+ * @param[in]  controller The handle to the controller object for which
+ *             to complete the task management request.
+ * @param[in]  remote_device The handle to the remote device object for which
+ *             to complete the task management request.
+ * @param[in]  task_request the handle to the task management request object
+ *             to complete.
+ *
+ * @return Indicate if the controller successfully completed the task
+ *         management request.
+ * @retval SCI_SUCCESS if the completion process was successful.
+ */
+SCI_STATUS scic_controller_complete_task(
+   SCI_CONTROLLER_HANDLE_T     controller,
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
+   SCI_TASK_REQUEST_HANDLE_T   task_request
+);
+
+#else // !defined(DISABLE_TASK_MANAGEMENT)
+
+#define scic_controller_start_task(controller, dev, task, tag) SCI_TASK_FAILURE
+#define scic_controller_complete_task(controller, dev, task) SCI_FAILURE
+
+#endif // !defined(DISABLE_TASK_MANAGEMENT)
+
+/**
+ * @brief This method is called by the SCI Core user to terminate an ongoing
+ *        (i.e. started) core IO request.  This does not abort the IO request
+ *        at the target, but rather removes the IO request from the host
+ *        controller.
+ *
+ * @param[in]  controller the handle to the controller object for which
+ *             to terminate a request.
+ * @param[in]  remote_device the handle to the remote device object for which
+ *             to terminate a request.
+ * @param[in]  request the handle to the io or task management request
+ *             object to terminate.
+ *
+ * @return Indicate if the controller successfully began the terminate process
+ *         for the IO request.
+ * @retval SCI_SUCCESS if the terminate process was successfully started for
+ *         the request.
+ *
+ * @todo Determine the failure situations and return values.
+ */
+SCI_STATUS scic_controller_terminate_request(
+   SCI_CONTROLLER_HANDLE_T     controller,
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
+   SCI_IO_REQUEST_HANDLE_T     request
+);
+
+/**
+ * @brief This method will perform core specific completion operations for
+ *        an IO request.  After this method is invoked, the user should
+ *        consider the IO request as invalid until it is properly reused
+ *        (i.e. re-constructed).
+ *
+ * @warning
+ *        - IO tags are a protected resource.  It is incumbent upon the
+ *          SCI Core user to ensure that each of the methods that may
+ *          allocate or free available IO tags are handled in a mutually
+ *          exclusive manner.  This method is one of said methods requiring
+ *          proper critical code section protection (e.g. semaphore,
+ *          spin-lock, etc.).
+ *        - If the IO tag for a request was allocated, by the SCI Core user,
+ *          using the scic_controller_allocate_io_tag() method, then it is
+ *          the responsibility of the caller to invoke the
+ *          scic_controller_free_io_tag() method to free the tag (i.e. this
+ *          method will not free the IO tag).
+ *
+ * @param[in]  controller The handle to the controller object for which
+ *             to complete the IO request.
+ * @param[in]  remote_device The handle to the remote device object for which
+ *             to complete the IO request.
+ * @param[in]  io_request the handle to the io request object to complete.
+ *
+ * @return Indicate if the controller successfully completed the IO request.
+ * @retval SCI_SUCCESS if the completion process was successful.
+ */
+SCI_STATUS scic_controller_complete_io(
+   SCI_CONTROLLER_HANDLE_T     controller,
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
+   SCI_IO_REQUEST_HANDLE_T     io_request
+);
+
+
+/**
+ * @brief This method simply provides the user with a unique handle for a
+ *        given SAS/SATA core port index.
+ *
+ * @param[in]  controller This parameter represents the handle to the
+ *             controller object from which to retrieve a port (SAS or
+ *             SATA) handle.
+ * @param[in]  port_index This parameter specifies the port index in
+ *             the controller for which to retrieve the port handle.
+ *             0 <= port_index < maximum number of phys.
+ * @param[out] port_handle This parameter specifies the retrieved port handle
+ *             to be provided to the caller.
+ *
+ * @return Indicate if the retrieval of the port handle was successful.
+ * @retval SCI_SUCCESS This value is returned if the retrieval was successful.
+ * @retval SCI_FAILURE_INVALID_PORT This value is returned if the supplied
+ *         port id is not in the supported range.
+ */
+SCI_STATUS scic_controller_get_port_handle(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   U8                        port_index,
+   SCI_PORT_HANDLE_T       * port_handle
+);
+
+/**
+ * @brief This method simply provides the user with a unique handle for a
+ *        given SAS/SATA phy index/identifier.
+ *
+ * @param[in]  controller This parameter represents the handle to the
+ *             controller object from which to retrieve a phy (SAS or
+ *             SATA) handle.
+ * @param[in]  phy_index This parameter specifies the phy index in
+ *             the controller for which to retrieve the phy handle.
+ *             0 <= phy_index < maximum number of phys.
+ * @param[out] phy_handle This parameter specifies the retrieved phy handle
+ *             to be provided to the caller.
+ *
+ * @return Indicate if the retrieval of the phy handle was successful.
+ * @retval SCI_SUCCESS This value is returned if the retrieval was successful.
+ * @retval SCI_FAILURE_INVALID_PHY This value is returned if the supplied phy
+ *         id is not in the supported range.
+ */
+SCI_STATUS scic_controller_get_phy_handle(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   U8                        phy_index,
+   SCI_PHY_HANDLE_T        * phy_handle
+);
+
+/**
+ * @brief This method will allocate a tag from the pool of free IO tags.
+ *        Direct allocation of IO tags by the SCI Core user is optional.
+ *        The scic_controller_start_io() method will allocate an IO
+ *        tag if this method is not utilized and the tag is not
+ *        supplied to the IO construct routine.  Direct allocation of IO tags
+ *        may provide additional performance improvements in environments
+ *        capable of supporting this usage model.  Additionally, direct
+ *        allocation of IO tags also provides additional flexibility to the
+ *        SCI Core user.  Specifically, the user may retain IO tags across
+ *        the lives of multiple IO requests.
+ *
+ * @warning IO tags are a protected resource.  It is incumbent upon the
+ *          SCI Core user to ensure that each of the methods that may
+ *          allocate or free available IO tags are handled in a mutually
+ *          exclusive manner.  This method is one of said methods requiring
+ *          proper critical code section protection (e.g. semaphore,
+ *          spin-lock, etc.).
+ *
+ * @param[in]  controller the handle to the controller object for which to
+ *             allocate the tag.
+ *
+ * @return An unsigned integer representing an available IO tag.
+ * @retval SCI_CONTROLLER_INVALID_IO_TAG This value is returned if there
+ *         are no currently available tags to be allocated.
+ * @retval All return other values indicate a legitimate tag.
+ */
+U16 scic_controller_allocate_io_tag(
+   SCI_CONTROLLER_HANDLE_T  controller
+);
+
+/**
+ * @brief This method will free an IO tag to the pool of free IO tags.
+ *        This method provides the SCI Core user more flexibility with
+ *        regards to IO tags.  The user may desire to keep an IO tag after
+ *        an IO request has completed, because they plan on re-using the
+ *        tag for a subsequent IO request.  This method is only legal if
+ *        the tag was allocated via scic_controller_allocate_io_tag().
+ *
+ * @warning
+ *        - IO tags are a protected resource.  It is incumbent upon the
+ *          SCI Core user to ensure that each of the methods that may
+ *          allocate or free available IO tags are handled in a mutually
+ *          exclusive manner.  This method is one of said methods requiring
+ *          proper critical code section protection (e.g. semaphore,
+ *          spin-lock, etc.).
+ *        - If the IO tag for a request was allocated, by the SCI Core user,
+ *          using the scic_controller_allocate_io_tag() method, then it is
+ *          the responsibility of the caller to invoke this method to free
+ *          the tag.
+ *
+ * @param[in]  controller This parameter specifies the handle to the
+ *             controller object for which to free/return the tag.
+ * @param[in]  io_tag This parameter represents the tag to be freed to the
+ *             pool of available tags.
+ *
+ * @return This method returns an indication of whether the tag was
+ *         successfully put back (freed) to the pool of available tags.
+ * @retval SCI_SUCCESS This return value indicates the tag was successfully
+ *         placed into the pool of available IO tags.
+ * @retval SCI_FAILURE_INVALID_IO_TAG This value is returned if the supplied
+ *         tag is not a valid IO tag value.
+ */
+SCI_STATUS scic_controller_free_io_tag(
+   SCI_CONTROLLER_HANDLE_T  controller,
+   U16                      io_tag
+);
+
+/**
+ * @brief This method returns the size of the core's scratch RAM.
+ *
+ * @return Size of the scratch RAM in dwords.
+ */
+U32 scic_controller_get_scratch_ram_size(
+   SCI_CONTROLLER_HANDLE_T   controller
+);
+
+/**
+ * @brief This method allows the user to read a U32 from the core's
+ *        scratch RAM.
+ *
+ * @param[in]  controller This parameter represents the handle to the
+ *             controller object for which to read scratch RAM.
+ * @param[in]  offset The offset (in dwords) into the scratch RAM.
+ * @param[out] value The location where the read value should be stored.
+ *
+ * @return Indicate if the user specified a valid offset into the
+ *         scratch RAM.
+ * @retval SCI_SUCCESS The scratch RAM was successfully read.
+ * @retval SCI_FAILURE_INVALID_PARAMETER_VALUE The user specified an
+ *          invalid offset.
+ */
+SCI_STATUS scic_controller_read_scratch_ram_dword(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   U32                       offset,
+   U32                     * value
+);
+
+/**
+ * @brief This method allows the user to write a U32 to the core's
+ *        scratch RAM.
+ *
+ * @param[in]  controller This parameter represents the handle to the
+ *             controller object for which to write scratch RAM.
+ * @param[in]  offset The offset (in dwords) into the scratch RAM.
+ * @param[out] value The value to be written to scratch RAM.
+ *
+ * @return Indicate if the user specified a valid offset into the
+ *         scratch RAM.
+ * @retval SCI_SUCCESS The scratch RAM was successfully written.
+ * @retval SCI_FAILURE_INVALID_PARAMETER_VALUE The user specified an
+ *          invalid offset.
+ */
+SCI_STATUS scic_controller_write_scratch_ram_dword(
+    SCI_CONTROLLER_HANDLE_T   controller,
+    U32                       offset,
+    U32                       value
+);
+
+/**
+ * @brief This method allows the user to configure the SCI core into
+ *        either a performance mode or a memory savings mode.
+ *
+ * @param[in]  controller This parameter represents the handle to the
+ *             controller object for which to update the operating
+ *             mode.
+ * @param[in]  mode This parameter specifies the new mode for the
+ *             controller.
+ *
+ * @return Indicate if the user successfully change the operating mode
+ *         of the controller.
+ * @retval SCI_SUCCESS The user successfully updated the mode.
+ */
+SCI_STATUS scic_controller_set_mode(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   SCI_CONTROLLER_MODE       mode
+);
+
+
+#if !defined(DISABLE_INTERRUPTS)
+/**
+ * @brief This method allows the user to configure the interrupt coalescence.
+ *
+ * @param[in]  controller This parameter represents the handle to the
+ *                controller object for which its interrupt coalesce register
+ *                is overridden.
+ *
+ * @param[in]  coalesce_number Used to control the number of entries in the
+ *                Completion Queue before an interrupt is generated. If the
+ *                number of entries exceed this number, an interrupt will be
+ *                generated. The valid range of the input is [0, 256].
+ *                A setting of 0 results in coalescing being disabled.
+ * @param[in]  coalesce_timeout Timeout value in microseconds. The valid range
+ *                of the input is [0, 2700000] . A setting of 0 is allowed and
+ *                results in no interrupt coalescing timeout.
+ *
+ * @return Indicate if the user successfully set the interrupt coalesce parameters.
+ * @retval SCI_SUCCESS The user successfully updated the interrutp coalescence.
+ * @retval SCI_FAILURE_INVALID_PARAMETER_VALUE The user input value is out of range.
+ */
+SCI_STATUS scic_controller_set_interrupt_coalescence(
+   SCI_CONTROLLER_HANDLE_T controller,
+   U32                     coalesce_number,
+   U32                     coalesce_timeout
+);
+
+/**
+ * @brief This method retrieves the interrupt coalescing values
+ *
+ * @param[in] controller This parameter specifies the controller for
+ *            which its interrupt coalescing number is read.
+ *
+ * @param[out] coalesce_number, interrupt coalescing number read from controller.
+ *
+ * @param[out] coalesce_timeout, timeout value in microseconds.
+ *
+ * @return None
+ */
+void scic_controller_get_interrupt_coalescence(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   U32                     * coalesce_number,
+   U32                     * coalesce_timeout
+);
+#else // !defined(DISABLE_INTERRUPTS)
+#define scic_controller_set_interrupt_coalescence(controller, num, timeout) \
+        SCI_FAILURE
+#define scic_controller_get_interrupt_coalescence(controller, num, timeout)
+#endif // !defined(DISABLE_INTERRUPTS)
+
+
+/**
+ * @brief This method suspend the controller, reinitialize RAMs, then resume
+ *           the controller.
+ *
+ * @param[in] controller This parameter specifies the controller which is transitioning.
+ *
+ * @param[in] restrict_completions This parameter specifies whether the controller should
+ *               ignore completion processing for non-fastpath events.  This will cause
+ *               the completions to be thrown away.
+ *
+ * @return SCI_STATUS The status of controller transition.
+ */
+SCI_STATUS scic_controller_transition(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   BOOL                      restrict_completions
+);
+
+
+/**
+ * @brief This method suspends the controller.
+ *
+ * @param[in] controller This parameter specifies the controller which is to be suspended.
+ *
+ * @return SCI_STATUS The status of controller suspend.
+ */
+SCI_STATUS scic_controller_suspend(
+   SCI_CONTROLLER_HANDLE_T   controller
+);
+
+/**
+ * @brief This method resumes the controller.
+ *
+ * @param[in] controller This parameter specifies the controller which is to be resumed.
+ *
+ * @return SCI_STATUS The status of controller resume.
+ */
+SCI_STATUS scic_controller_resume(
+   SCI_CONTROLLER_HANDLE_T   controller
+);
+
+SCI_STATUS scic_controller_get_max_ports(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   U8                      * count
+);
+
+SCI_STATUS scic_controller_get_max_phys(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   U8                      * count
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIC_CONTROLLER_H_
diff --git a/sys/dev/disk/isci/scil/scic_io_request.h b/sys/dev/disk/isci/scil/scic_io_request.h
new file mode 100644
index 0000000..eeaec25
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_io_request.h
@@ -0,0 +1,760 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_io_request.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIC_IO_REQUEST_H_
+#define _SCIC_IO_REQUEST_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains the structures and interface methods that
+ *        can be referenced and used by the SCI user for the SCI IO request
+ *        object.
+ *
+ * @todo Determine the failure situations and return values.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/sci_status.h>
+#include <dev/disk/isci/scil/intel_sas.h>
+
+/**
+ * @struct SCIC_IO_SSP_PARAMETERS
+ * @brief  This structure contains additional optional parameters for SSP
+ *         IO requests.  These parameters are utilized with the
+ *         scic_io_request_construct_advanced_ssp() method.
+ *
+ * @todo Add Block-guard/DIF, TLR
+ */
+typedef struct SCIC_IO_SSP_PARAMETERS
+{
+   /**
+    * Data Integrity Format (DIF) is also known as protection information
+    * or block-guard.  This sub-structure contains DIF specific feature
+    * information for SSP IO requests.
+    */
+   struct
+   {
+      void * placeholder;
+   } dif;
+
+   /**
+    * Transport Layer Retries (TLR) is an SSP protocol specific feature.
+    * This sub-structure contains Transport Layer Retries (TLR) specific
+    * feature information for SSP IO requests.
+    */
+   struct
+   {
+      void * placeholder;
+   } tlr;
+
+} SCIC_IO_SSP_PARAMETERS_T;
+
+/**
+ * @struct SCIC_IO_PARAMETERS
+ * @brief  This structure contains additional optional parameters for
+ *         STP/SATA IO requests.  These parameters are utilized with the
+ *         scic_io_request_construct_advanced_sata() method.
+ */
+typedef struct SCIC_IO_SATA_PARAMETERS
+{
+   /**
+    * This field indicates whether or not to construct the Scatter-Gather
+    * List elements for the SATA request.  This is used in scenarios
+    * where Scatter-gather-list processing/translation is done by the
+    * user.
+    */
+   BOOL do_translate_sgl;
+
+} SCIC_IO_SATA_PARAMETERS_T;
+
+/**
+ * @struct SCIC_PASSTHRU_REQUEST_CALLBACKS
+ * @brief  This structure contains the pointer to the callback functions
+ *         for constructing the passthrough request common to SSP, SMP and STP.
+ *         This structure must be set by the win sci layer before the passthrough
+ *         build is called
+ *
+ */
+typedef struct SCIC_PASSTHRU_REQUEST_CALLBACKS
+{
+   /**
+   * Function pointer to get the phy identifier for passthrough request.
+   */
+   U32 (*scic_cb_passthru_get_phy_identifier) ( void * , U8 *);
+   /**
+   * Function pointer to get the port identifier for passthrough request.
+   */
+   U32 (*scic_cb_passthru_get_port_identifier) ( void * , U8 *);
+   /**
+   * Function pointer to get the connection rate for passthrough request.
+   */
+   U32 (*scic_cb_passthru_get_connection_rate) ( void * , void *);
+   /**
+   * Function pointer to get the destination sas address for passthrough request.
+   */
+   void (*scic_cb_passthru_get_destination_sas_address) (void *, U8 **);
+   /**
+   * Function pointer to get the transfer length for passthrough request.
+   */
+   U32 (*scic_cb_passthru_get_transfer_length) (void *);
+   /**
+   * Function pointer to get the data direction for passthrough request.
+   */
+   U32 (*scic_cb_passthru_get_data_direction) (void *);
+
+} SCIC_PASSTHRU_REQUEST_CALLBACKS_T;
+
+/**
+ * @struct SCIC_SSP_PASSTHRU_REQUEST_CALLBACKS
+ * @brief  This structure contains the pointer to the callback functions
+ *         for constructing the passthrough request specific to SSP.
+ *         This structure must be set by the win sci layer before the passthrough
+ *         build is called
+ *
+ */
+typedef struct SCIC_SSP_PASSTHRU_REQUEST_CALLBACKS
+{
+   /**
+   * Common callbacks for all Passthru requests
+   */
+   SCIC_PASSTHRU_REQUEST_CALLBACKS_T common_callbacks;
+   /**
+   * Function pointer to get the lun for passthrough request.
+   */
+   void (* scic_cb_ssp_passthru_get_lun) (void *, U8 **);
+   /**
+   * Function pointer to get the cdb
+   */
+   void (* scic_cb_ssp_passthru_get_cdb) ( void *, U32 *, U8 **, U32 *, U8 ** );
+   /**
+   * Function pointer to get the task attribute for passthrough request.
+   */
+   U32 (*scic_cb_ssp_passthru_get_task_attribute) (void *);
+} SCIC_SSP_PASSTHRU_REQUEST_CALLBACKS_T;
+
+/**
+ * @struct SCIC_STP_PASSTHRU_REQUEST_CALLBACKS
+ * @brief  This structure contains the pointer to the callback functions
+ *         for constructing the passthrough request specific to STP.
+ *         This structure must be set by the win sci layer before the passthrough
+ *         build is called
+ *
+ */
+typedef struct SCIC_STP_PASSTHRU_REQUEST_CALLBACKS
+{
+   /**
+   * Common callbacks for all Passthru requests
+   */
+   SCIC_PASSTHRU_REQUEST_CALLBACKS_T common_callbacks;
+   /**
+   * Function pointer to get the protocol for passthrough request.
+   */
+   U8 (* scic_cb_stp_passthru_get_protocol) (void *);
+   /**
+   * Function pointer to get the resgister fis
+   */
+   void (* scic_cb_stp_passthru_get_register_fis) ( void *, U8 ** );
+   /**
+   * Function pointer to get the MULTIPLE_COUNT (bits 5,6,7 in Byte 1 in the SAT-specific SCSI extenstion in ATA Pass-through (0x85))
+   */
+   U8 (* scic_cb_stp_passthru_get_multiplecount) ( void *);
+   /**
+   * Function pointer to get the EXTEND (bit 0 in Byte 1 the SAT-specific SCSI extenstion in ATA Pass-through (0x85))
+   */
+   U8 (* scic_cb_stp_passthru_get_extend) ( void *);
+   /**
+   * Function pointer to get the CK_COND (bit 5 in Byte 2 the SAT-specific SCSI extenstion in ATA Pass-through (0x85))
+   */
+   U8 (* scic_cb_stp_passthru_get_ckcond) ( void *);
+   /**
+   * Function pointer to get the T_DIR (bit 3 in Byte 2 the SAT-specific SCSI extenstion in ATA Pass-through (0x85))
+   */
+   U8 (* scic_cb_stp_passthru_get_tdir) ( void *);
+   /**
+   * Function pointer to get the BYTE_BLOCK (bit 2 in Byte 2 the SAT-specific SCSI extenstion in ATA Pass-through (0x85))
+   */
+   U8 (* scic_cb_stp_passthru_get_byteblock) ( void *);
+   /**
+   * Function pointer to get the T_LENGTH (bits 0,1 in Byte 2 the SAT-specific SCSI extenstion in ATA Pass-through (0x85))
+   */
+   U8 (* scic_cb_stp_passthru_get_tlength) ( void *);
+
+} SCIC_STP_PASSTHRU_REQUEST_CALLBACKS_T;
+
+/**
+ * @struct SCIC_SMP_PASSTHRU_REQUEST_CALLBACKS
+ * @brief  This structure contains the pointer to the callback functions
+ *         for constructing the passthrough request specific to SMP.
+ *         This structure must be set by the win sci layer before the passthrough
+ *         build is called
+ *
+ */
+typedef struct SCIC_SMP_PASSTHRU_REQUEST_CALLBACKS
+{
+   /**
+   * Common callbacks for all Passthru requests
+   */
+   SCIC_PASSTHRU_REQUEST_CALLBACKS_T common_callbacks;
+
+   /**
+   * Function pointer to get the length of the smp request and its length
+   */
+   U32 (* scic_cb_smp_passthru_get_request) ( void *, U8 ** );
+   /**
+   * Function pointer to get the frame type of the smp request
+   */
+   U8 (* scic_cb_smp_passthru_get_frame_type) ( void *);
+   /**
+   * Function pointer to get the function in the the smp request
+   */
+   U8 (* scic_cb_smp_passthru_get_function) ( void * );
+
+   /**
+   * Function pointer to get the "allocated response length" in the the smp request
+   */
+   U8 (* scic_cb_smp_passthru_get_allocated_response_length) ( void * );
+
+} SCIC_SMP_PASSTHRU_REQUEST_CALLBACKS_T;
+
+/**
+ * @brief This enumeration specifies the transport protocol utilized
+ *        for the request.
+ */
+typedef enum
+{
+   /**
+    * This enumeration constant indicates that no protocol has yet been
+    * set.
+    */
+   SCIC_NO_PROTOCOL,
+
+   /**
+    * This enumeration constant indicates that the protocol utilized
+    * is the Serial Management Protocol.
+    */
+   SCIC_SMP_PROTOCOL,
+
+   /**
+    * This enumeration constant indicates that the protocol utilized
+    * is the Serial SCSI Protocol.
+    */
+   SCIC_SSP_PROTOCOL,
+
+   /**
+    * This enumeration constant indicates that the protocol utilized
+    * is the Serial-ATA Tunneling Protocol.
+    */
+   SCIC_STP_PROTOCOL
+
+} SCIC_TRANSPORT_PROTOCOL;
+
+
+/**
+ * @brief This method simply returns the size required to build an SCI
+ *        based IO request object.
+ *
+ * @return Return the size of the SCI IO request object.
+ */
+U32 scic_io_request_get_object_size(
+   void
+);
+
+/**
+ * @brief This method is called by the SCI user to construct all SCI Core
+ *        IO requests.  Memory initialization and functionality common to
+ *        all IO request types is performed in this method.
+ *
+ * @note  The SCI core implementation will create an association between
+ *        the user IO request object and the core IO request object.
+ *
+ * @param[in]  scic_controller the handle to the core controller object
+ *             for which to build an IO request.
+ * @param[in]  scic_remote_device the handle to the core remote device
+ *             object for which to build an IO request.
+ * @param[in]  io_tag This parameter specifies the IO tag to be associated
+ *             with this request.  If SCI_CONTROLLER_INVALID_IO_TAG is
+ *             passed, then a copy of the request is built internally.  The
+ *             request will be copied into the actual controller request
+ *             memory when the IO tag is allocated internally during the
+ *             scic_controller_start_io() method.
+ * @param[in]  user_io_request_object This parameter specifies the user
+ *             IO request to be utilized during IO construction.  This IO
+ *             pointer will become the associated object for the core
+ *             IO request object.
+ * @param[in]  scic_io_request_memory This parameter specifies the memory
+ *             location to be utilized when building the core request.
+ * @param[out] new_scic_io_request_handle This parameter specifies a
+ *             pointer to the handle the core will expect in further
+ *             interactions with the core IO request object.
+ *
+ * @return Indicate if the controller successfully built the IO request.
+ * @retval SCI_SUCCESS This value is returned if the IO request was
+ *         successfully built.
+ */
+SCI_STATUS scic_io_request_construct(
+   SCI_CONTROLLER_HANDLE_T      scic_controller,
+   SCI_REMOTE_DEVICE_HANDLE_T   scic_remote_device,
+   U16                          io_tag,
+   void                       * user_io_request_object,
+   void                       * scic_io_request_memory,
+   SCI_IO_REQUEST_HANDLE_T    * new_scic_io_request_handle
+);
+
+/**
+ * @brief This method is called by the SCI user to build an SSP
+ *        IO request.
+ *
+ * @pre
+ *        - The user must have previously called scic_io_request_construct()
+ *          on the supplied IO request.
+ *
+ * @param[in]  scic_io_request This parameter specifies the handle to the
+ *             io request object to be built.
+ *
+ * @return Indicate if the controller successfully built the IO request.
+ * @retval SCI_SUCCESS This value is returned if the IO request was
+ *         successfully built.
+ * @retval SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned if the
+ *         remote_device does not support the SSP protocol.
+ * @retval SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the
+ *         user did not properly set the association between the SCIC IO
+ *         request and the user's IO request.  Please refer to the
+ *         sci_object_set_association() routine for more
+ *         information.
+ */
+SCI_STATUS scic_io_request_construct_basic_ssp(
+   SCI_IO_REQUEST_HANDLE_T  scic_io_request
+);
+
+/**
+ * @brief This method is called by the SCI user to build an SSP
+ *        IO request with additional parameters that provide additional
+ *        flexibility from the standard scic_io_request_construct_basic_ssp()
+ *        method.
+ *
+ * @pre
+ *        - The user must have previously called scic_io_request_construct()
+ *          on the supplied IO request.
+ *
+ * @param[in]  scic_io_request This parameter specifies the handle to the
+ *             io request object to be built.
+ * @param[in]  io_parameters the additional parameter information to
+ *             be added to the outgoing IO request.
+ *
+ * @return Indicate if the controller successfully built the IO request.
+ * @retval SCI_SUCCESS This value is returned if the IO request was
+ *         successfully built.
+ * @retval SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned if the
+ *         remote_device does not support the SSP protocol.
+ * @retval SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the
+ *         user did not properly set the association between the SCIC IO
+ *         request and the user's IO request.  Please refer to the
+ *         sci_object_set_association() routine for more
+ *         information.
+ *
+ * @todo Determine the failure situations and return values.
+ */
+SCI_STATUS scic_io_request_construct_advanced_ssp(
+   SCI_IO_REQUEST_HANDLE_T    scic_io_request,
+   SCIC_IO_SSP_PARAMETERS_T * io_parameters
+);
+
+#if !defined(DISABLE_PASS_THROUGH)
+
+/**
+ * @brief This method will build an IO request based on the user information
+ *        supplied in the pass-through IO request object.
+ *
+ * @param[in]  scic_io_request This parameter specifies the handle to the
+ *             io request object to be built.
+ *
+ * @param[in]  ssp_passthru_cb This parameter specifies the pointer to
+ *             the structure containing the callback to the function
+ *             pointers to get the needed fields from the pass-through
+ *             reqiest instead of SRB
+ *
+ * @return Indicate if the controller successfully built the IO request.
+ * @retval SCI_SUCCESS This value is returned if the IO request was
+ *         successfully built.
+ * @retval SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the
+ *         user did not properly set the association between the SCIC IO
+ *         request and the user's IO request.  Please refer to the
+ *         sci_object_set_association() routine for more
+ *         information.
+ */
+SCI_STATUS scic_io_request_construct_ssp_pass_through(
+   void                       * scic_io_request_memory,
+   SCIC_SSP_PASSTHRU_REQUEST_CALLBACKS_T *ssp_passthru_cb
+);
+
+#else // !defined(DISABLE_PASS_THROUGH)
+
+#define scic_io_request_construct_ssp_pass_through(memory, cb) SCI_FAILURE
+
+#endif // !defined(DISABLE_PASS_THROUGH)
+
+/**
+ * @brief This method is called by the SCI Core user to build an STP
+ *        IO request.
+ *
+ * @pre
+ *        - The user must have previously called scic_io_request_construct()
+ *          on the supplied IO request.
+ *
+ * @param[in]  scic_io_request This parameter specifies the handle to the
+ *             io request object to be built.
+ *
+ * @return Indicate if the controller successfully built the IO request.
+ * @retval SCI_SUCCESS This value is returned if the IO request was
+ *         successfully built.
+ * @retval SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned if the
+ *         remote_device does not support the STP protocol.
+ * @retval SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the
+ *         user did not properly set the association between the SCIC IO
+ *         request and the user's IO request.  Please refer to the
+ *         sci_object_set_association() routine for more
+ *         information.
+ */
+SCI_STATUS scic_io_request_construct_basic_sata(
+   SCI_IO_REQUEST_HANDLE_T  scic_io_request
+);
+
+/**
+ * @brief This method is called by the SCI Core user to build an STP
+ *        IO request.
+ *
+ * @pre
+ *        - The user must have previously called scic_io_request_construct()
+ *          on the supplied IO request.
+ *
+ * @param[in]  scic_io_request This parameter specifies the handle to the
+ *             io request object to be built.
+ *
+ * @return Indicate if the controller successfully built the IO request.
+ * @retval SCI_SUCCESS This value is returned if the IO request was
+ *         successfully built.
+ * @retval SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned if the
+ *         remote_device does not support the STP protocol.
+ * @retval SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the
+ *         user did not properly set the association between the SCIC IO
+ *         request and the user's IO request.  Please refer to the
+ *         sci_object_set_association() routine for more
+ *         information.
+ */
+SCI_STATUS scic_io_request_construct_advanced_sata(
+   SCI_IO_REQUEST_HANDLE_T     scic_io_request,
+   SCIC_IO_SATA_PARAMETERS_T * io_parameters
+);
+
+#if !defined(DISABLE_PASS_THROUGH)
+
+/**
+ * @brief This method is called by the SCI user to build an STP pass-through
+ *        IO request.
+ *
+ * @pre
+ *        - The user must have previously called scic_io_request_construct()
+ *          on the supplied IO request.
+ *
+ * @param[in]  scic_io_request This parameter specifies the handle to the
+ *             io request object to be built.
+ *
+ * @param[in]  passthru_cb This parameter specifies the pointer to the callback
+ *             structure that contains the function pointers
+ *
+ * @return Indicate if the controller successfully built the IO request.
+ */
+SCI_STATUS scic_io_request_construct_sata_pass_through(
+   SCI_IO_REQUEST_HANDLE_T  scic_io_request,
+   SCIC_STP_PASSTHRU_REQUEST_CALLBACKS_T *passthru_cb
+
+);
+
+#else // !defined(DISABLE_PASS_THROUGH)
+
+#define scic_io_request_construct_sata_pass_through(io, cb) SCI_FAILURE
+
+#endif // !defined(DISABLE_PASS_THROUGH)
+
+/**
+ * @brief This method is called by the SCI user to build an SMP
+ *        IO request.
+ *
+ * @pre
+ *        - The user must have previously called scic_io_request_construct()
+ *          on the supplied IO request.
+ *
+ * @param[in]  scic_io_request This parameter specifies the handle to the
+ *             io request object to be built.
+ *
+ * @return Indicate if the controller successfully built the IO request.
+ * @retval SCI_SUCCESS This value is returned if the IO request was
+ *         successfully built.
+ * @retval SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned if the
+ *         remote_device does not support the SMP protocol.
+ * @retval SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the
+ *         user did not properly set the association between the SCIC IO
+ *         request and the user's IO request.  Please refer to the
+ *         sci_object_set_association() routine for more
+ *         information.
+ */
+SCI_STATUS scic_io_request_construct_smp(
+   SCI_IO_REQUEST_HANDLE_T  scic_io_request
+);
+
+
+/**
+ * @brief This method is called by the SCI user to build an SMP pass-through
+ *        IO request.
+ *
+ * @pre
+ *        - The user must have previously called scic_io_request_construct()
+ *          on the supplied IO request.
+ *
+ * @param[in]  scic_smp_request This parameter specifies the handle to the
+ *             io request object to be built.
+ *
+ * @param[in]  passthru_cb This parameter specifies the pointer to the callback
+ *             structure that contains the function pointers
+ *
+ * @return Indicate if the controller successfully built the IO request.
+ */
+SCI_STATUS scic_io_request_construct_smp_pass_through(
+   SCI_IO_REQUEST_HANDLE_T  scic_smp_request,
+   SCIC_SMP_PASSTHRU_REQUEST_CALLBACKS_T *passthru_cb
+);
+
+/**
+ * @brief This method returns the controller specific IO/Task request status.
+ *        These status values are unique to the specific controller being
+ *        managed by the SCIC.
+ *
+ * @param[in]  io_request the handle to the IO or task management request
+ *             object for which to retrieve the status.
+ *
+ * @return This method returns a value indicating the controller specific
+ *         request status.
+ */
+U32 scic_request_get_controller_status(
+   SCI_IO_REQUEST_HANDLE_T  io_request
+);
+
+/**
+ * @brief This method returns the user specific IO/Task request status.
+ *
+ * @param[in]  io_request the handle to the IO or task management request
+ *             object for which to retrieve the status.
+ *
+ * @return This method returns a value indicating the user specific
+ *         request status.
+ */
+U32 scic_request_get_sci_status(
+   SCI_IO_REQUEST_HANDLE_T  io_request
+);
+
+
+/**
+ * @brief This method will return the address to the command information
+ *        unit.
+ *
+ * @param[in]  scic_io_request This parameter specifies the handle to the
+ *             io request object to be built.
+ *
+ * @return The address of the SSP/SMP command information unit.
+ */
+void * scic_io_request_get_command_iu_address(
+   SCI_IO_REQUEST_HANDLE_T  scic_io_request
+);
+
+/**
+ * @brief This method will return the address to the response information
+ *        unit.  For an SSP request this buffer is only valid if the IO
+ *        request is completed with the status SCI_FAILURE_IO_RESPONSE_VALID.
+ *
+ * @param[in]  scic_io_request This parameter specifies the handle to the
+ *             io request object to be built.
+ *
+ * @return The address of the SSP/SMP response information unit.
+ */
+void * scic_io_request_get_response_iu_address(
+   SCI_IO_REQUEST_HANDLE_T  scic_io_request
+);
+
+/**
+ * @brief This method will return the IO tag utilized by the IO request.
+ *
+ * @param[in]  scic_io_request This parameter specifies the handle to the
+ *             io request object for which to return the IO tag.
+ *
+ * @return An unsigned integer representing the IO tag being utilized.
+ * @retval SCI_CONTROLLER_INVALID_IO_TAG This value is returned if the IO
+ *         does not currently have an IO tag allocated to it.
+ * @retval All return other values indicate a legitimate tag.
+ */
+U16 scic_io_request_get_io_tag(
+   SCI_IO_REQUEST_HANDLE_T  scic_io_request
+);
+
+/**
+ * @brief This method will inform the user of the protocol with which
+ *        the supplied IO request was created.
+ *
+ * @param[in]  scic_io_request This parameter specifies the IO request
+ *             for which to retrieve the protocol.
+ *
+ * @return This method returns the transport protocol utilized for the
+ *         the supplied request.  Please refer to SCIC_TRANSPORT_PROTOCOL
+ *         for more information.
+ */
+SCIC_TRANSPORT_PROTOCOL scic_io_request_get_protocol(
+   SCI_IO_REQUEST_HANDLE_T  scic_io_request
+);
+
+/**
+ * @brief This method will assign an NCQ tag to the io request object.  The
+ *        caller of this function must make sure that only valid NCQ tags are
+ *        assigned to the io request object.
+ *
+ * @param[in]  scic_io_request This parameter specifies the handle to the
+ *             io request object to which to assign the ncq tag.
+ * @param[in]  ncq_tag This parameter specifies the NCQ tag to be utilized
+ *             for the supplied core IO request.  It is up to the user to make
+ *             sure that this is a valid NCQ tag.
+ *
+ * @return none
+ *
+ * @note This function is only valid for SATA NCQ requests.
+ */
+void scic_stp_io_request_set_ncq_tag(
+   SCI_IO_REQUEST_HANDLE_T  scic_io_request,
+   U16                      ncq_tag
+);
+
+/**
+ * @brief This method will return the address of the host to device register
+ *        fis region for the io request object.
+ *
+ * @param[in] scic_io_request This parameter specifies the handle to the io
+ *       request object from which to get the host to device register fis
+ *       buffer.
+ *
+ * @return The address of the host to device register fis buffer in the io
+ *         request object.
+ *
+ * @note This function is only valid for SATA requests.
+ */
+void * scic_stp_io_request_get_h2d_reg_address(
+   SCI_IO_REQUEST_HANDLE_T  scic_io_request
+);
+
+/**
+ * @brief This method will return the address of the device to host register
+ *        fis region for the io request object.
+ *
+ * @param[in] scic_io_request This parameter specifies teh handle to the io
+ *       request object from which to get the device to host register fis
+ *       buffer.
+ *
+ * @return The address fo the device to host register fis ending the io
+ *         request.
+ *
+ * @note This function is only valid for SATA requests.
+ */
+void * scic_stp_io_request_get_d2h_reg_address(
+   SCI_IO_REQUEST_HANDLE_T  scic_io_request
+);
+
+/**
+ * @brief This method will return the rx frame for the io request object that
+ *        contains the given offset.
+ *
+ * @param[in] scic_io_request This parameter specifies the handle to the io
+ *       request object which has received the frame data.
+ * @param[in] offset This parameter specifies which frame is being requested.
+ *
+ * @return The return is a pointer to the frame buffer data.
+ *
+ * @note Frame buffers are only 1024 bytes in size.  Reading past the end of a
+ *       frame will have unexpected results.
+ */
+void * scic_io_request_get_rx_frame(
+   SCI_IO_REQUEST_HANDLE_T  scic_io_request,
+   U32                      offset
+);
+
+/**
+ * @brief This method will return the number of bytes transferred from the SCU
+ *
+ * @param[in] scic_io_request This parameter specifies the handle to the io request
+ *            whose data length was not eqaul to the data length specified in the request.
+ *            When the driver gets an early io completion status from the hardware,
+ *            this routine should be called to get the actual number of bytes transferred
+ *
+ * @return The return is the number of bytes transferred when the data legth is not equal to
+ *         the specified length in the io request
+ *
+ */
+U32 scic_io_request_get_number_of_bytes_transferred (
+   SCI_IO_REQUEST_HANDLE_T  scic_io_request
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIC_IO_REQUEST_H_
diff --git a/sys/dev/disk/isci/scil/scic_library.h b/sys/dev/disk/isci/scil/scic_library.h
new file mode 100644
index 0000000..e82754e
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_library.h
@@ -0,0 +1,274 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_library.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIC_LIBRARY_H_
+#define _SCIC_LIBRARY_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the interface methods that can be called
+ *        by an SCI Core user on the library object.  The library is the
+ *        container of all other objects being managed (i.e. controllers,
+ *        target devices, sas ports, etc.).
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/sci_status.h>
+
+
+/**
+ * @enum  _SCIC_LIBRARY_IO_MODE
+ * @brief This enumeration depicts the different IO modes in which the SCI
+ *        library and it's controllers can operate.
+ */
+typedef enum _SCIC_LIBRARY_IO_MODE
+{
+   /**
+    * In this mode the SCI library will operate in a polling mode for
+    * operations.  In other words, the library will not return from a
+    * send io method until the completion for the IO has been received.
+    */
+   SCIC_IO_MODE_POLLING,
+
+   /**
+    * In this mode the SCI library returns after committing the IO request
+    * to the controller hardware.  Completion of the request will occur
+    * asynchronously.
+    */
+   SCIC_IO_MODE_ASYNCHRONOUS
+
+} SCIC_LIBRARY_IO_MODE;
+
+
+struct sci_pci_common_header;
+
+/**
+ * @brief This method will contsruct the core library based on the supplied
+ *        parameter information.  By default, libraries are considered
+ *        "ready" as soon as they are constructed.
+ *
+ * @param[in]  library_memory a pointer to the memory at which the
+ *             library object is located.
+ * @param[in]  max_controller_count the maximum number of controllers that
+ *             this library can manage.
+ *
+ * @return An opaque library handle to be used by the SCI user for all
+ *         subsequent library operations.
+ */
+SCI_LIBRARY_HANDLE_T scic_library_construct(
+   void *                         library_memory,
+   U8                             max_controller_count
+);
+
+/**
+ * This method sets the PCI header information required for proper
+ * controller object creation/allocation.
+ *
+ * @param[in]  library the handle to the library object for which to allocate
+ *             a controller.
+ * @param[in]  pci_header a pointer to the pci header data for the pci
+ *             device for which this library is being created.
+ *
+ * @return none
+ */
+void scic_library_set_pci_info(
+   SCI_LIBRARY_HANDLE_T           library,
+   struct sci_pci_common_header * pci_header
+);
+
+/**
+ * @brief This method returns the size of the core library object.
+ *
+ * @param[in]  max_controller_count the maximum number of controllers that
+ *             this library can manage.
+ *
+ * @return a positive integer value indicating the size (in bytes) of the
+ *         library object.
+ */
+U32 scic_library_get_object_size(
+   U8  max_controller_count
+);
+
+/**
+ *
+ *
+ */
+U8 scic_library_get_pci_device_controller_count(
+   SCI_LIBRARY_HANDLE_T  library
+);
+
+/**
+ * @brief This method will allocate the next available core controller object
+ *        that can be managed by this core library.
+ *
+ * @param[in]  library the handle to the library object for which to allocate
+ *             a controller.
+ * @param[out] new_controller This parameter specifies a pointer to the
+ *             controller handle that was added to the library.
+
+ * @return Indicate if the controller was successfully allocated or if iti
+ *         failed in some way.
+ * @retval SCI_SUCCESS if the controller was successfully allocated.
+ * @retval SCI_FAILURE_INSUFFICIENT_RESOURCES if the library has no more
+ *         available controller objects to allocate.
+ */
+SCI_STATUS scic_library_allocate_controller(
+   SCI_LIBRARY_HANDLE_T      library,
+   SCI_CONTROLLER_HANDLE_T * new_controller
+);
+
+/**
+ * @brief This method will attempt to free the supplied controller to the
+ *        library.
+ *
+ * @param[in]  library the handle to the library object for which to free
+ *             a controller.
+ * @param[in]  controller the handle to the controller object to be freed
+ *             from the library.
+ *
+ * @return Indicate if the controller was successfully freed or if it failed
+ *         in some way.
+ * @retval SCI_SUCCESS if the controller was successfully freed.
+ * @retval SCI_FAILURE_CONTROLLER_NOT_FOUND if the supplied controller is
+ *         not managed by the supplied library.
+ */
+SCI_STATUS scic_library_free_controller(
+   SCI_LIBRARY_HANDLE_T     library,
+   SCI_CONTROLLER_HANDLE_T  controller
+);
+
+/**
+ * @brief This method returns the maximum size (in bytes) that an individual
+ *        SGL element can address using this library.
+ *
+ * @note  SGL size is restricted to the lowest common denominator across all
+ *        controllers managed by the library.
+ * @todo  Does the byte count have to be DWORD aligned?
+ *
+ * @param[in]  library the handle to the library object for which to
+ *             determine the maximum SGL size.
+ *
+ * @return Return the maximum size (in bytes) for an SGE for any controller
+ *         managed by this library.
+ */
+U32 scic_library_get_max_sge_size(
+   SCI_LIBRARY_HANDLE_T  library
+);
+
+/**
+ * @brief This method returns the maximum number of SGL elements for a
+ *        single IO request using this library.
+ *
+ * @note  SGE count is restricted to the lowest common denominator across all
+ *        controllers managed by the library.
+ *
+ * @param[in]  library the handle to the library object for which to
+ *             determine the maximum number of SGEs per IO request.
+ *
+ * @return Return the maximum number of SGEs for an IO request for any
+ *         controller in this library.
+ */
+U32 scic_library_get_max_sge_count(
+   SCI_LIBRARY_HANDLE_T  library
+);
+
+/**
+ * @brief This method returns the maximum length for any IO request that
+ *        can be handled by the underlying controllers
+ *
+ * @note  IO length is restricted to the lowest common denominator across all
+ *        controllers managed by the library.
+ *
+ * @param[in]  library the handle to the library object for which to
+ *             determine the maximum length for all IO requests.
+ *
+ * @return Return the maximum length for all IO requests for any
+ *         controller in this library.
+ */
+U32 scic_library_get_max_io_length(
+   SCI_LIBRARY_HANDLE_T  library
+);
+
+/**
+ * @brief This method returns the minimum number of timers needed.  If the
+ *        user supplies timers less then the number specified via this
+ *        call, then the user runs the risk of improper operation.
+ *
+ * @return This method returns a value representing the minimum number of
+ *         timers required by this framework implementation
+ */
+U16 scic_library_get_min_timer_count(
+   void
+);
+
+/**
+ * @brief This method returns the maximum number of timers that could
+ *        be ever be in use by this component at a given time.
+ *
+ * @return This method returns a value representing the minimum number of
+ *         timers required by this framework implementation
+ */
+U16 scic_library_get_max_timer_count(
+   void
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIC_LIBRARY_H_
diff --git a/sys/dev/disk/isci/scil/scic_logger.h b/sys/dev/disk/isci/scil/scic_logger.h
new file mode 100644
index 0000000..87660fa
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_logger.h
@@ -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: src/sys/dev/isci/scil/scic_logger.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIC_LOGGER_H_
+#define _SCIC_LOGGER_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the SCI Core specific logger object
+ *        constant definitions.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_logger.h>
+
+
+/* The following is a list of log objects for which log information can */
+/* be enabled or disabled.                                              */
+
+/** Enables/disables logging specific to the library. */
+#define SCIC_LOG_OBJECT_LIBRARY                 0x00000001
+
+/** Enables/disables logging specific to the controller. */
+#define SCIC_LOG_OBJECT_CONTROLLER              0x00000002
+
+/** Enables/disables logging specific to the sas port. */
+#define SCIC_LOG_OBJECT_PORT                    0x00000004
+
+/** Enables/disables logging specific to the SAS phy. */
+#define SCIC_LOG_OBJECT_PHY                     0x00000008
+
+/** Enables/disables logging specific to the SSP remote target. */
+#define SCIC_LOG_OBJECT_SSP_REMOTE_TARGET       0x00000010
+
+/** Enables/disables logging specific to the STP remote target. */
+#define SCIC_LOG_OBJECT_STP_REMOTE_TARGET       0x00000020
+
+/** Enables/disables logging specific to the SMP remote target. */
+#define SCIC_LOG_OBJECT_SMP_REMOTE_TARGET       0x00000040
+
+/** Enables/disables logging specific to the SMP remote initiator. */
+#define SCIC_LOG_OBJECT_SMP_REMOTE_INITIATOR    0x00000080
+
+/** Enables/disables logging specific to the SSP IO requests. */
+#define SCIC_LOG_OBJECT_SSP_IO_REQUEST          0x00000100
+
+/** Enables/disables logging specific to the STP IO requests. */
+#define SCIC_LOG_OBJECT_STP_IO_REQUEST          0x00000200
+
+/** Enables/disables logging specific to the SMP IO requests. */
+#define SCIC_LOG_OBJECT_SMP_IO_REQUEST          0x00000400
+
+/** Enables/disables logging specific to the SMP IO response. */
+#define SCIC_LOG_OBJECT_SMP_IO_RESPONSE         0x00000800
+
+/** Enables/disables logging specific to the initialization. */
+#define SCIC_LOG_OBJECT_INITIALIZATION          0x00001000
+
+/** Enables/disables logging specific to the SGPIO. */
+#define SCIC_LOG_OBJECT_SGPIO                   0x00002000
+
+/** Enables/disables logging specific to staggered spin up. */
+#define SCIC_LOG_OBJECT_STAGGERED_SPIN_UP       0x00004000
+
+/** Enables/disables logging specific to the controller unsolicited frames. */
+#define SCIC_LOG_OBJECT_UNSOLICITED_FRAMES      0x00008000
+
+/** Enables/disables logging specific to the received controller events. */
+#define SCIC_LOG_OBJECT_RECEIVED_EVENTS         0x00010000
+
+/** Enables/disables logging specific to the controller completion queue */
+#define SCIC_LOG_OBJECT_COMPLETION_QUEUE        0x00020000
+
+/** Enables/disables logging specific to the task management requests. */
+#define SCIC_LOG_OBJECT_TASK_MANAGEMENT         0x00040000
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIC_LOGGER_H_
diff --git a/sys/dev/disk/isci/scil/scic_overview.h b/sys/dev/disk/isci/scil/scic_overview.h
new file mode 100644
index 0000000..65e0416
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_overview.h
@@ -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: src/sys/dev/isci/scil/scic_overview.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIC_OVERVIEW_H_
+#define _SCIC_OVERVIEW_H_
+
+/**
+
+@page core_section SCI Core
+
+@section scic_introduction_section Introduction
+
+The Storage Controller Interface Core (SCIC) provides the underlying fundamental
+hardware abstractions required to implement a standard SAS/SATA storage driver.
+
+The following is a list of features that may be found in a core implementation:
+-# hardware interrupt handling
+-# hardware event handling
+-# hardware state machine handling
+-# IO and task management state machine handling
+-# Phy staggered spin up
+
+@image latex sci_core.eps "SCI Core Class Diagram" width=16cm
+
+@note
+For the SCU Driver Standard implementation of the SCI Core interface the
+following definitions should be used to augment the cardinalities described
+in the previous diagram:
+-# There are exactly 4 scic_phy objects in the scic_controller.
+-# There are exactly 4 scic_port objects in the scic_controller.
+-# There can be a maximum of 4 scic_phy objects managed in a single scic_port.
+-# The maximum number of supported controllers in a library is a truly flexible
+   value, but the likely maximum number is 4.
+
+*/
+
+#endif // _SCIC_OVERVIEW_H_
diff --git a/sys/dev/disk/isci/scil/scic_phy.h b/sys/dev/disk/isci/scil/scic_phy.h
new file mode 100644
index 0000000..e1d8c4d
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_phy.h
@@ -0,0 +1,461 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_phy.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIC_PHY_H_
+#define _SCIC_PHY_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the interface methods that can be called
+ *        by an SCIC user on a phy (SAS or SATA) object.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/sci_status.h>
+
+#include <dev/disk/isci/scil/intel_sata.h>
+#include <dev/disk/isci/scil/intel_sas.h>
+
+
+/**
+ * @struct SCIC_PHY_PROPERTIES
+ * @brief This structure defines the properties common to all phys
+ *        that can be retrieved.
+ */
+typedef struct SCIC_PHY_PROPERTIES
+{
+   /**
+    * This field specifies the port that currently contains the
+    * supplied phy.  This field may be set to SCI_INVALID_HANDLE
+    * if the phy is not currently contained in a port.
+    */
+   SCI_PORT_HANDLE_T  owning_port;
+
+   /**
+    * This field specifies the maximum link rate for which this phy
+    * will negotiate.
+    */
+   SCI_SAS_LINK_RATE max_link_rate;
+
+   /**
+    * This field specifies the link rate at which the phy is
+    * currently operating.
+    */
+   SCI_SAS_LINK_RATE  negotiated_link_rate;
+
+   /**
+    * This field indicates the identify address frame that will be
+    * transmitted to the connected phy.
+    */
+   SCI_SAS_IDENTIFY_ADDRESS_FRAME_T transmit_iaf;
+
+   /**
+    * This field specifies the index of the phy in relation to other
+    * phys within the controller.  This index is zero relative.
+    */
+   U8 index;
+
+} SCIC_PHY_PROPERTIES_T;
+
+/**
+ * @struct SCIC_SAS_PHY_PROPERTIES
+ * @brief This structure defines the properties, specific to a
+ *        SAS phy, that can be retrieved.
+ */
+typedef struct SCIC_SAS_PHY_PROPERTIES
+{
+   /**
+    * This field delineates the Identify Address Frame received
+    * from the remote end point.
+    */
+   SCI_SAS_IDENTIFY_ADDRESS_FRAME_T received_iaf;
+
+   /**
+    * This field delineates the Phy capabilities structure received
+    * from the remote end point.
+    */
+   SAS_CAPABILITIES_T received_capabilities;
+
+} SCIC_SAS_PHY_PROPERTIES_T;
+
+/**
+ * @struct SCIC_SATA_PHY_PROPERTIES
+ * @brief This structure defines the properties, specific to a
+ *        SATA phy, that can be retrieved.
+ */
+typedef struct SCIC_SATA_PHY_PROPERTIES
+{
+   /**
+    * This field delineates the signature FIS received from the
+    * attached target.
+    */
+   SATA_FIS_REG_D2H_T signature_fis;
+
+   /**
+    * This field specifies to the user if a port selector is connected
+    * on the specified phy.
+    */
+   BOOL is_port_selector_present;
+
+} SCIC_SATA_PHY_PROPERTIES_T;
+
+/**
+ * @enum  SCIC_PHY_COUNTER_ID
+ * @brief This enumeration depicts the various pieces of optional
+ *        information that can be retrieved for a specific phy.
+ */
+typedef enum SCIC_PHY_COUNTER_ID
+{
+   /**
+    * This PHY information field tracks the number of frames received.
+    */
+   SCIC_PHY_COUNTER_RECEIVED_FRAME,
+
+   /**
+    * This PHY information field tracks the number of frames transmitted.
+    */
+   SCIC_PHY_COUNTER_TRANSMITTED_FRAME,
+
+   /**
+    * This PHY information field tracks the number of DWORDs received.
+    */
+   SCIC_PHY_COUNTER_RECEIVED_FRAME_DWORD,
+
+   /**
+    * This PHY information field tracks the number of DWORDs transmitted.
+    */
+   SCIC_PHY_COUNTER_TRANSMITTED_FRAME_DWORD,
+
+   /**
+    * This PHY information field tracks the number of times DWORD
+    * synchronization was lost.
+    */
+   SCIC_PHY_COUNTER_LOSS_OF_SYNC_ERROR,
+
+   /**
+    * This PHY information field tracks the number of received DWORDs with
+    * running disparity errors.
+    */
+   SCIC_PHY_COUNTER_RECEIVED_DISPARITY_ERROR,
+
+   /**
+    * This PHY information field tracks the number of received frames with a
+    * CRC error (not including short or truncated frames).
+    */
+   SCIC_PHY_COUNTER_RECEIVED_FRAME_CRC_ERROR,
+
+   /**
+    * This PHY information field tracks the number of DONE (ACK/NAK TIMEOUT)
+    * primitives received.
+    */
+   SCIC_PHY_COUNTER_RECEIVED_DONE_ACK_NAK_TIMEOUT,
+
+   /**
+    * This PHY information field tracks the number of DONE (ACK/NAK TIMEOUT)
+    * primitives transmitted.
+    */
+   SCIC_PHY_COUNTER_TRANSMITTED_DONE_ACK_NAK_TIMEOUT,
+
+   /**
+    * This PHY information field tracks the number of times the inactivity
+    * timer for connections on the phy has been utilized.
+    */
+   SCIC_PHY_COUNTER_INACTIVITY_TIMER_EXPIRED,
+
+   /**
+    * This PHY information field tracks the number of DONE (CREDIT TIMEOUT)
+    * primitives received.
+    */
+   SCIC_PHY_COUNTER_RECEIVED_DONE_CREDIT_TIMEOUT,
+
+   /**
+    * This PHY information field tracks the number of DONE (CREDIT TIMEOUT)
+    * primitives transmitted.
+    */
+   SCIC_PHY_COUNTER_TRANSMITTED_DONE_CREDIT_TIMEOUT,
+
+   /**
+    * This PHY information field tracks the number of CREDIT BLOCKED
+    * primitives received.
+    * @note Depending on remote device implementation, credit blocks
+    *       may occur regularly.
+    */
+   SCIC_PHY_COUNTER_RECEIVED_CREDIT_BLOCKED,
+
+   /**
+    * This PHY information field contains the number of short frames
+    * received.  A short frame is simply a frame smaller then what is
+    * allowed by either the SAS or SATA specification.
+    */
+   SCIC_PHY_COUNTER_RECEIVED_SHORT_FRAME,
+
+   /**
+    * This PHY information field contains the number of frames received after
+    * credit has been exhausted.
+    */
+   SCIC_PHY_COUNTER_RECEIVED_FRAME_WITHOUT_CREDIT,
+
+   /**
+    * This PHY information field contains the number of frames received after
+    * a DONE has been received.
+    */
+   SCIC_PHY_COUNTER_RECEIVED_FRAME_AFTER_DONE,
+
+   /**
+    * This PHY information field contains the number of times the phy
+    * failed to achieve DWORD synchronization during speed negotiation.
+    */
+   SCIC_PHY_COUNTER_SN_DWORD_SYNC_ERROR
+} SCIC_PHY_COUNTER_ID_T;
+
+/**
+ * @brief This method will enable the user to retrieve information
+ *        common to all phys, such as: the negotiated link rate,
+ *        the phy id, etc.
+ *
+ * @param[in]  phy This parameter specifies the phy for which to retrieve
+ *             the properties.
+ * @param[out] properties This parameter specifies the properties
+ *             structure into which to copy the requested information.
+ *
+ * @return Indicate if the user specified a valid phy.
+ * @retval SCI_SUCCESS This value is returned if the specified phy was valid.
+ * @retval SCI_FAILURE_INVALID_PHY This value is returned if the specified phy
+ *         is not valid.  When this value is returned, no data is copied to the
+ *         properties output parameter.
+ */
+SCI_STATUS scic_phy_get_properties(
+   SCI_PHY_HANDLE_T        phy,
+   SCIC_PHY_PROPERTIES_T * properties
+);
+
+/**
+ * @brief This method will enable the user to retrieve information
+ *        specific to a SAS phy, such as: the received identify
+ *        address frame, received phy capabilities, etc.
+ *
+ * @param[in]  phy this parameter specifies the phy for which to
+ *             retrieve properties.
+ * @param[out] properties This parameter specifies the properties
+ *             structure into which to copy the requested information.
+ *
+ * @return This method returns an indication as to whether the SAS
+ *         phy properties were successfully retrieved.
+ * @retval SCI_SUCCESS This value is returned if the SAS properties
+ *         are successfully retrieved.
+ * @retval SCI_FAILURE This value is returned if the SAS properties
+ *         are not successfully retrieved (e.g. It's not a SAS Phy).
+ */
+SCI_STATUS scic_sas_phy_get_properties(
+   SCI_PHY_HANDLE_T            phy,
+   SCIC_SAS_PHY_PROPERTIES_T * properties
+);
+
+/**
+ * @brief This method will enable the user to retrieve information
+ *        specific to a SATA phy, such as: the recieved signature
+ *        FIS, if a port selector is present, etc.
+ *
+ * @param[in]  phy this parameter specifies the phy for which to
+ *             retrieve properties.
+ * @param[out] properties This parameter specifies the properties
+ *             structure into which to copy the requested information.
+ *
+ * @return This method returns an indication as to whether the SATA
+ *         phy properties were successfully retrieved.
+ * @retval SCI_SUCCESS This value is returned if the SATA properties
+ *         are successfully retrieved.
+ * @retval SCI_FAILURE This value is returned if the SATA properties
+ *         are not successfully retrieved (e.g. It's not a SATA Phy).
+ */
+SCI_STATUS scic_sata_phy_get_properties(
+   SCI_PHY_HANDLE_T             phy,
+   SCIC_SATA_PHY_PROPERTIES_T * properties
+);
+
+/**
+ * @brief This method allows the SCIC user to instruct the SCIC
+ *        implementation to send the SATA port selection signal.
+ *
+ * @param[in]  phy this parameter specifies the phy for which to send
+ *             the port selection signal.
+ *
+ * @return An indication of whether the port selection signal was
+ *         successfully executed.
+ * @retval SCI_SUCCESS This value is returned if the port selection signal
+ *         was successfully transmitted.
+ */
+SCI_STATUS scic_sata_phy_send_port_selection_signal(
+   SCI_PHY_HANDLE_T  phy
+);
+
+/**
+ * @brief This method requests the SCI implementation to begin tracking
+ *        information specified by the supplied parameters.
+ *
+ * @param[in]  phy this parameter specifies the phy for which to enable
+ *             the information type.
+ * @param[in]  counter_id this parameter specifies the information
+ *             type to be enabled.
+ *
+ * @return Indicate if enablement of the information type was successful.
+ * @retval SCI_SUCCESS This value is returned if the information type was
+ *         successfully enabled.
+ * @retval SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD This value is returned
+ *         if the supplied information type is not supported.
+ */
+SCI_STATUS scic_phy_enable_counter(
+   SCI_PHY_HANDLE_T       phy,
+   SCIC_PHY_COUNTER_ID_T  counter_id
+);
+
+/**
+ * @brief This method requests the SCI implementation to stop tracking
+ *        information specified by the supplied parameters.
+ *
+ * @param[in]  phy this parameter specifies the phy for which to disable
+ *             the information type.
+ * @param[in]  counter_id this parameter specifies the information
+ *             type to be disabled.
+ *
+ * @return Indicate if disablement of the information type was successful.
+ * @retval SCI_SUCCESS This value is returned if the information type was
+ *         successfully disabled.
+ * @retval SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD This value is returned
+ *         if the supplied information type is not supported.
+ */
+SCI_STATUS scic_phy_disable_counter(
+   SCI_PHY_HANDLE_T       phy,
+   SCIC_PHY_COUNTER_ID_T  counter_id
+);
+
+/**
+ * @brief This method requests the SCI implementation to retrieve
+ *        tracking information specified by the supplied parameters.
+ *
+ * @param[in]  phy this parameter specifies the phy for which to retrieve
+ *             the information type.
+ * @param[in]  counter_id this parameter specifies the information
+ *             type to be retrieved.
+ * @param[out] data this parameter is a 32-bit pointer to a location
+ *             where the data being retrieved is to be placed.
+ *
+ * @return Indicate if retrieval of the information type was successful.
+ * @retval SCI_SUCCESS This value is returned if the information type was
+ *         successfully retrieved.
+ * @retval SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD This value is returned
+ *         if the supplied information type is not supported.
+ */
+SCI_STATUS scic_phy_get_counter(
+   SCI_PHY_HANDLE_T        phy,
+   SCIC_PHY_COUNTER_ID_T   counter_id,
+   U32                   * data
+);
+
+/**
+ * @brief This method requests the SCI implementation to clear (reset)
+ *        tracking information specified by the supplied parameters.
+ *
+ * @param[in]  phy this parameter specifies the phy for which to clear
+ *             the information type.
+ * @param[in]  counter_id this parameter specifies the information
+ *             type to be cleared.
+ *
+ * @return Indicate if clearing of the information type was successful.
+ * @retval SCI_SUCCESS This value is returned if the information type was
+ *         successfully cleared.
+ * @retval SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD This value is returned
+ *         if the supplied information type is not supported.
+ */
+SCI_STATUS scic_phy_clear_counter(
+   SCI_PHY_HANDLE_T       phy,
+   SCIC_PHY_COUNTER_ID_T  counter_id
+);
+
+/**
+ * @brief This method will attempt to stop the phy object.
+ *
+ * @param[in] this_phy
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS if the phy is going to stop
+ *         SCI_INVALID_STATE if the phy is not in a valid state
+ *         to stop
+ */
+SCI_STATUS scic_phy_stop(
+   SCI_PHY_HANDLE_T       phy
+);
+
+/**
+ * @brief This method will attempt to start the phy object. This
+ *        request is only valid when the phy is in the stopped
+ *        state
+ *
+ * @param[in] this_phy
+ *
+ * @return SCI_STATUS
+ */
+SCI_STATUS scic_phy_start(
+   SCI_PHY_HANDLE_T       phy
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIC_PHY_H_
diff --git a/sys/dev/disk/isci/scil/scic_port.h b/sys/dev/disk/isci/scil/scic_port.h
new file mode 100644
index 0000000..1d251ac
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_port.h
@@ -0,0 +1,238 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_port.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIC_PORT_H_
+#define _SCIC_PORT_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the interface methods that can be called
+ *        by an SCI Core user on a SAS or SATA port.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/sci_status.h>
+#include <dev/disk/isci/scil/intel_sas.h>
+
+enum SCIC_PORT_NOT_READY_REASON_CODE
+{
+   SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS,
+   SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED,
+   SCIC_PORT_NOT_READY_INVALID_PORT_CONFIGURATION,
+   SCIC_PORT_NOT_READY_RECONFIGURING,
+
+   SCIC_PORT_NOT_READY_REASON_CODE_MAX
+};
+
+/**
+ * @struct SCIC_PORT_END_POINT_PROPERTIES
+ * @brief  This structure defines the properties that can be retrieved
+ *         for each end-point local or remote (attached) port in the
+ *         controller.
+ */
+typedef struct SCIC_PORT_END_POINT_PROPERTIES
+{
+   /**
+    * This field indicates the SAS address for the associated end
+    * point in the port.
+    */
+   SCI_SAS_ADDRESS_T  sas_address;
+
+   /**
+    * This field indicates the protocols supported by the associated
+    * end-point in the port.
+    */
+   SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T  protocols;
+
+} SCIC_PORT_END_POINT_PROPERTIES_T;
+
+/**
+ * @struct SCIC_PORT_PROPERTIES
+ * @brief  This structure defines the properties that can be retrieved
+ *         for each port in the controller.
+ */
+typedef struct SCIC_PORT_PROPERTIES
+{
+   /**
+    * This field specifies the logical index of the port (0 relative).
+    */
+   U32  index;
+
+   /**
+    * This field indicates the local end-point properties for port.
+    */
+   SCIC_PORT_END_POINT_PROPERTIES_T  local;
+
+   /**
+    * This field indicates the remote (attached) end-point properties
+    * for the port.
+    */
+   SCIC_PORT_END_POINT_PROPERTIES_T  remote;
+
+   /**
+    * This field specifies the phys contained inside the port.
+    */
+   U32  phy_mask;
+
+} SCIC_PORT_PROPERTIES_T;
+
+/**
+ * @brief This method simply returns the properties regarding the
+ *        port, such as: physical index, protocols, sas address, etc.
+ *
+ * @param[in]  port this parameter specifies the port for which to retrieve
+ *             the physical index.
+ * @param[out] properties This parameter specifies the properties
+ *             structure into which to copy the requested information.
+ *
+ * @return Indicate if the user specified a valid port.
+ * @retval SCI_SUCCESS This value is returned if the specified port was valid.
+ * @retval SCI_FAILURE_INVALID_PORT This value is returned if the specified port
+ *         is not valid.  When this value is returned, no data is copied to the
+ *         properties output parameter.
+ */
+SCI_STATUS scic_port_get_properties(
+   SCI_PORT_HANDLE_T        port,
+   SCIC_PORT_PROPERTIES_T * properties
+);
+
+/**
+ * @brief This method will add a phy to an existing port.
+ *
+ * @param[in]  port This parameter specifies the port in which to add a new
+ *             phy.
+ * @param[in]  phy This parameter specifies the phy to be added to the port.
+ *
+ * @return Indicate if the phy was successfully added to the port.
+ * @retval SCI_SUCCESS This value is returned if the phy was successfully
+ *         added to the port.
+ * @retval SCI_FAILURE_INVALID_PORT This value is returned if the supplied
+ *         port is not valid.
+ * @retval SCI_FAILURE_INVALID_PHY This value is returned if the supplied
+ *         phy is either invalid or already contained in another port.
+ */
+SCI_STATUS scic_port_add_phy(
+   SCI_PORT_HANDLE_T port,
+   SCI_PHY_HANDLE_T  phy
+);
+
+/**
+ * @brief This method will remove a phy from an existing port.
+ *
+ * @param[in]  port This parameter specifies the port in which to remove a
+ *             phy.
+ * @param[in]  phy This parameter specifies the phy to be removed from the
+ *             port.
+ *
+ * @return Indicate if the phy was successfully removed from the port.
+ * @retval SCI_SUCCESS This value is returned if the phy was successfully
+ *         removed from the port.
+ * @retval SCI_FAILURE_INVALID_PORT This value is returned if the supplied
+ *         port is not valid.
+ * @retval SCI_FAILURE_INVALID_PHY This value is returned if the supplied
+ *         phy is either invalid or
+ *         not contained in the port.
+ */
+SCI_STATUS scic_port_remove_phy(
+   SCI_PORT_HANDLE_T  port,
+   SCI_PHY_HANDLE_T   phy
+);
+
+/**
+ * @brief This method will request the SCI implementation to perform a
+ *        HARD RESET on the SAS Port.  If/When the HARD RESET completes
+ *        the SCI user will be notified via an SCI OS callback indicating
+ *        a direct attached device was found.
+ *
+ * @note The SCI User callback in SCIC_USER_CALLBACKS_T will only be called
+ *       once for each phy in the SAS Port at completion of the hard reset
+ *       sequence.
+ *
+ * @param[in]  port a handle corresponding to the SAS port to be
+ *             hard reset.
+ * @param[in]  reset_timeout This parameter specifies the number of
+ *             milliseconds in which the port reset operation should complete.
+ *
+ * @return Return a status indicating whether the hard reset started
+ *         successfully.
+ * @retval SCI_SUCCESS This value is returned if the hard reset operation
+ *         started successfully.
+ */
+SCI_STATUS scic_port_hard_reset(
+   SCI_PORT_HANDLE_T port,
+   U32               reset_timeout
+);
+
+/**
+ * @brief This API method enables the broadcast change notification from
+ *        underneath hardware.
+ *
+ * @param[in] port The port upon which broadcast change notifications
+ *            (BCN) are to be enabled.
+ *
+ * @return none
+ */
+void scic_port_enable_broadcast_change_notification(
+   SCI_PORT_HANDLE_T  port
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIC_PORT_H_
diff --git a/sys/dev/disk/isci/scil/scic_remote_device.h b/sys/dev/disk/isci/scil/scic_remote_device.h
new file mode 100644
index 0000000..41e9658
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_remote_device.h
@@ -0,0 +1,441 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_remote_device.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIC_REMOTE_DEVICE_H_
+#define _SCIC_REMOTE_DEVICE_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the interface methods that can be called
+ *        by an SCIC user on the device object.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/sci_status.h>
+#include <dev/disk/isci/scil/intel_sas.h>
+
+
+/**
+ * @brief
+ */
+typedef enum SCIC_REMOTE_DEVICE_NOT_READY_REASON_CODE
+{
+   SCIC_REMOTE_DEVICE_NOT_READY_START_REQUESTED,
+   SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED,
+   SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED,
+   SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED,
+   SCIC_REMOTE_DEVICE_NOT_READY_SMP_REQUEST_STARTED,
+
+   SCIC_REMOTE_DEVICE_NOT_READY_REASON_CODE_MAX
+
+} SCIC_REMOTE_DEVICE_NOT_READY_REASON_CODE_T;
+
+/**
+ * @brief This method simply returns the maximum memory space needed to
+ *        store a remote device object.
+ *
+ * @return a positive integer value indicating the size (in bytes) of the
+ *         remote device object.
+ */
+U32 scic_remote_device_get_object_size(
+   void
+);
+
+/**
+ * @brief This method will perform the construction common to all
+ *        remote device objects.
+ *
+ * @note  It isn't necessary to call scic_remote_device_destruct() for
+ *        device objects that have only called this method for construction.
+ *        Once subsequent construction methods have been invoked (e.g.
+ *        scic_remote_device_da_construct()), then destruction should occur.
+ * @note
+ *
+ * @param[in]  port This parameter specifies the SAS/SATA Port handle
+ *             corresponding to the port through which this device
+ *             is to be accessed.
+ * @param[in]  remote_device_memory This parameter specifies the memory
+ *             location to be used by the SCIC implementation to store the
+ *             SCIC REMOTE DEVICE.
+ * @param[out] new_remote_device_handle An opaque remote device handle to
+ *             be used by the SCIC user for all subsequent remote device
+ *             operations.
+ *
+ * @return none
+ */
+void scic_remote_device_construct(
+   SCI_PORT_HANDLE_T            port,
+   void                       * remote_device_memory,
+   SCI_REMOTE_DEVICE_HANDLE_T * new_remote_device_handle
+);
+
+/**
+ * @brief This method will construct a SCIC_REMOTE_DEVICE object for a
+ *        direct attached (da) device.  The information (e.g. IAF, Signature
+ *        FIS, etc.) necessary to build the device is known to the SCI Core
+ *        since it is contained in the scic_phy object.
+ *
+ * @pre The user must have previously called scic_remote_device_construct()
+ *
+ * @note  Remote device objects are a limited resource.  As such, they
+ *        must be protected.  Thus calls to construct and destruct are
+ *        mutually exclusive and non-reentrant.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device to be
+ *             destructed.
+ *
+ * @return Indicate if the remote device was successfully constructed.
+ * @retval SCI_SUCCESS Returned if the device was successfully constructed.
+ * @retval SCI_FAILURE_DEVICE_EXISTS Returned if the device has already
+ *         been constructed.  If it's an additional phy for the target, then
+ *         call scic_remote_device_da_add_phy().
+ * @retval SCI_FAILURE_UNSUPPORTED_PROTOCOL Returned if the supplied
+ *         parameters necessitate creation of a remote device for which
+ *         the protocol is not supported by the underlying controller
+ *         hardware.
+ * @retval SCI_FAILURE_INSUFFICIENT_RESOURCES This value is returned if
+ *         the core controller associated with the supplied parameters
+ *         is unable to support additional remote devices.
+ */
+SCI_STATUS scic_remote_device_da_construct(
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device
+);
+
+/**
+ * @brief This method will construct an SCIC_REMOTE_DEVICE object for an
+ *        expander attached (ea) device from an SMP Discover Response.
+ *
+ * @pre The user must have previously called scic_remote_device_construct()
+ *
+ * @note  Remote device objects are a limited resource.  As such, they
+ *        must be protected.  Thus calls to construct and destruct are
+ *        mutually exclusive and non-reentrant.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device to be
+ *             destructed.
+ * @param[in]  discover_response This parameter specifies the SMP
+ *             Discovery Response to be used in device creation.
+ *
+ * @return Indicate if the remote device was successfully constructed.
+ * @retval SCI_SUCCESS Returned if the device was successfully constructed.
+ * @retval SCI_FAILURE_DEVICE_EXISTS Returned if the device has already
+ *         been constructed.  If it's an additional phy for the target, then
+ *         call scic_ea_remote_device_add_phy().
+ * @retval SCI_FAILURE_UNSUPPORTED_PROTOCOL Returned if the supplied
+ *         parameters necessitate creation of a remote device for which
+ *         the protocol is not supported by the underlying controller
+ *         hardware.
+ * @retval SCI_FAILURE_INSUFFICIENT_RESOURCES This value is returned if
+ *         the core controller associated with the supplied parameters
+ *         is unable to support additional remote devices.
+ */
+SCI_STATUS scic_remote_device_ea_construct(
+   SCI_REMOTE_DEVICE_HANDLE_T   remote_device,
+   SMP_RESPONSE_DISCOVER_T    * discover_response
+);
+
+/**
+ * @brief This method is utilized to free up a core's remote device object.
+ *
+ * @note  Remote device objects are a limited resource.  As such, they
+ *        must be protected.  Thus calls to construct and destruct are
+ *        mutually exclusive and non-reentrant.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device to be
+ *             destructed.
+ *
+ * @return The return value shall indicate if the device was successfully
+ *         destructed or if some failure occurred.
+ * @retval SCI_STATUS This value is returned if the device is successfully
+ *         destructed.
+ * @retval SCI_FAILURE_INVALID_REMOTE_DEVICE This value is returned if the
+ *         supplied device isn't valid (e.g. it's already been destoryed,
+ *         the handle isn't valid, etc.).
+ */
+SCI_STATUS scic_remote_device_destruct(
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device
+);
+
+#if !defined(DISABLE_WIDE_PORTED_TARGETS)
+/**
+ * @brief This method will attempt to set port width for a remote device.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object for which to set new port width.
+ * @param[in]  new_port_width The new port width to update.
+ *
+ * @return Indicate if the device port width was successfully updated.
+ * @retval SCI_SUCCESS This value is returned when port width update was successful.
+ * @retval SCI_FAILURE The port width update failed.
+ */
+SCI_STATUS scic_remote_device_set_port_width(
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
+   U8                          new_port_width
+);
+
+/**
+ * @brief This method retrieve the SCIC's record of a remote device's port width.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object for which to retrieve the port width value.
+ *
+ * @return The SCIC's record of a remote device's port width
+ */
+U8 scic_remote_device_get_port_width(
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device
+);
+
+#define scic_remote_device_da_add_phy(device, phy) SCI_FAILURE
+#define scic_remote_device_ea_add_phy(device, response) SCI_FAILURE
+#define scic_remote_device_remove_phy(device) SCI_FAILURE
+
+#else // !defined(DISABLE_WIDE_PORTED_TARGETS)
+
+#define scic_remote_device_set_port_width(device, port_width) SCI_FAILURE
+#define scic_remote_device_get_port_width(device) (1)
+
+#define scic_remote_device_da_add_phy(device, phy) SCI_FAILURE
+#define scic_remote_device_ea_add_phy(device, response) SCI_FAILURE
+#define scic_remote_device_remove_phy(device) SCI_FAILURE
+
+#endif // !defined(DISABLE_WIDE_PORTED_TARGETS)
+
+/**
+ * @brief This method will start the supplied remote device.  This method
+ *        enables normal IO requests to flow through to the remote device.
+ *
+ * @param[in]  remote_device This parameter specifies the device to be
+ *             started.
+ * @param[in]  timeout This parameter specifies the number of milliseconds
+ *             in which the start operation should complete.
+ *
+ * @return An indication of whether the device was successfully started.
+ * @retval SCI_SUCCESS This value is returned if the device was successfully
+ *         started.
+ * @retval SCI_FAILURE_INVALID_PHY This value is returned if the user attempts
+ *         to start the device when there have been no phys added to it.
+ */
+SCI_STATUS scic_remote_device_start(
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
+   U32                         timeout
+);
+
+/**
+ * @brief This method will stop both transmission and reception of link
+ *        activity for the supplied remote device.  This method disables
+ *        normal IO requests from flowing through to the remote device.
+ *
+ * @param[in]  remote_device This parameter specifies the device to be
+ *             stopped.
+ * @param[in]  timeout This parameter specifies the number of milliseconds
+ *             in which the stop operation should complete.
+ *
+ * @return An indication of whether the device was successfully stopped.
+ * @retval SCI_SUCCESS This value is returned if the transmission and reception
+ *         for the device was successfully stopped.
+ */
+SCI_STATUS scic_remote_device_stop(
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
+   U32                         timeout
+);
+
+/**
+ * @brief This method will reset the device making it ready for operation.
+ *        This method must be called anytime the device is reset either
+ *        through a SMP phy control or a port hard reset request.
+ *
+ * @note This method does not actually cause the device hardware to be reset.
+ *       This method resets the software object so that it will be operational
+ *       after a device hardware reset completes.
+ *
+ * @param[in]  remote_device This parameter specifies the device to be
+ *             reset.
+ *
+ * @return An indication of whether the device reset was accepted.
+ * @retval SCI_SUCCESS This value is returned if the device reset is started.
+ */
+SCI_STATUS scic_remote_device_reset(
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device
+);
+
+/**
+ * @brief This method informs the device object that the reset operation is
+ *        complete and the device can resume operation again.
+ *
+ * @param[in]  remote_device This parameter specifies the device which is to
+ *             be informed of the reset complete operation.
+ *
+ * @return An indication that the device is resuming operation.
+ * @retval SCI_SUCCESS the device is resuming operation.
+ */
+SCI_STATUS scic_remote_device_reset_complete(
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device
+);
+
+/**
+ * @brief This method returns the suggested target reset timeout.  SAS and
+ *        SATA devices have different timeout values in milliseconds for
+ *        target reset operations.
+ *
+ * @param[in]  remote_device This parameter specifies the device which is to
+ *             be informed of the reset complete operation.
+ *
+ * @return The suggested reset timeout value for the specified target device
+ *         in milliseconds.
+ */
+U32 scic_remote_device_get_suggested_reset_timeout(
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device
+);
+
+/**
+ * @brief This method will set the maximum link speed to be utilized
+ *        when connections are established for the supplied remote device.
+ *
+ * @pre The remote device must previously have been stopped for this
+ *      call to succeed.
+ *
+ * @param[in]  remote_device This parameter specifies the device for which
+ *             to set the maximum connection rate.
+ * @param[in]  connection_rate This parameter specifies the maximum link rate
+ *             to be utilized for all connections to the supplied remote
+ *             device.
+ *
+ * @return An indication as to whether the connection rate was successfully
+ *         updated.
+ * @retval SCI_SUCCESS This value is returned if the connection rate was
+ *         successfully updated.
+ * @retval SCI_FAILURE_INVALID_STATE This value is returned if the remote
+ *         device is not in a stopped state or some other state that allows
+ *         for a maximum connection rate change.
+ */
+SCI_STATUS scic_remote_device_set_max_connection_rate(
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
+   SCI_SAS_LINK_RATE           connection_rate
+);
+
+/**
+ * @brief This method simply returns the link rate at which communications
+ *        to the remote device occur.
+ *
+ * @param[in]  remote_device This parameter specifies the device for which
+ *             to get the connection rate.
+ *
+ * @return Return the link rate at which we transfer for the supplied
+ *         remote device.
+ */
+SCI_SAS_LINK_RATE scic_remote_device_get_connection_rate(
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device
+);
+
+/**
+ * @brief This method will indicate which protocols are supported by this
+ *        remote device.
+ *
+ * @param[in]  remote_device This parameter specifies the device for which
+ *             to return the protocol.
+ * @param[out] protocols This parameter specifies the output values, from
+ *             the remote device object, which indicate the protocols
+ *             supported by the supplied remote_device.
+ *
+ * @return The type of protocols supported by this device.  The values are
+ *         returned as part of a bit mask in order to allow for multi-protocol
+ *         support.
+ */
+void scic_remote_device_get_protocols(
+   SCI_REMOTE_DEVICE_HANDLE_T          remote_device,
+   SMP_DISCOVER_RESPONSE_PROTOCOLS_T * protocols
+);
+
+/**
+ * @brief This method will indicate the SAS address for the remote device.
+ *
+ * @param[in]  remote_device This parameter specifies the device for which
+ *             to return the SAS address.
+ * @param[out] sas_address This parameter specifies a pointer to a SAS
+ *             address structure into which the core will copy the SAS
+ *             address for the remote device.
+ *
+ * @return none
+ */
+void scic_remote_device_get_sas_address(
+   SCI_REMOTE_DEVICE_HANDLE_T   remote_device,
+   SCI_SAS_ADDRESS_T          * sas_address
+);
+
+#if !defined(DISABLE_ATAPI)
+/**
+ * This method first decide whether a device is a stp target, then
+ *    decode the signature fis of a DA STP device to tell whether it
+ *    is a standard end disk or an ATAPI device.
+ *
+ * @param[in] this_device The device whose type is to be decided.
+ *
+ * @return BOOL Indicate a device is ATAPI device or not.
+ */
+BOOL scic_remote_device_is_atapi(
+   SCI_REMOTE_DEVICE_HANDLE_T device_handle
+);
+#else // !defined(DISABLE_ATAPI)
+#define scic_remote_device_is_atapi(device_handle) FALSE
+#endif // !defined(DISABLE_ATAPI)
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIC_REMOTE_DEVICE_H_
diff --git a/sys/dev/disk/isci/scil/scic_sds_controller.c b/sys/dev/disk/isci/scil/scic_sds_controller.c
new file mode 100644
index 0000000..7ea7ca3
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_sds_controller.c
@@ -0,0 +1,7040 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_sds_controller.c,v 1.2 2012/02/09 17:50:24 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains the implementation of the SCIC_SDS_CONTROLLER
+ *        public, protected, and private methods.
+ */
+
+#include <dev/disk/isci/types.h>
+#include <dev/disk/isci/scil/sci_util.h>
+#include <dev/disk/isci/scil/scic_controller.h>
+#include <dev/disk/isci/scil/scic_port.h>
+#include <dev/disk/isci/scil/scic_phy.h>
+#include <dev/disk/isci/scil/scic_remote_device.h>
+#include <dev/disk/isci/scil/scic_user_callback.h>
+#include <dev/disk/isci/scil/scic_sds_pci.h>
+#include <dev/disk/isci/scil/scic_sds_library.h>
+#include <dev/disk/isci/scil/scic_sds_controller.h>
+#include <dev/disk/isci/scil/scic_sds_controller_registers.h>
+#include <dev/disk/isci/scil/scic_sds_port.h>
+#include <dev/disk/isci/scil/scic_sds_phy.h>
+#include <dev/disk/isci/scil/scic_sds_remote_device.h>
+#include <dev/disk/isci/scil/scic_sds_request.h>
+#include <dev/disk/isci/scil/scic_sds_logger.h>
+#include <dev/disk/isci/scil/scic_sds_port_configuration_agent.h>
+#include <dev/disk/isci/scil/scu_constants.h>
+#include <dev/disk/isci/scil/scu_event_codes.h>
+#include <dev/disk/isci/scil/scu_completion_codes.h>
+#include <dev/disk/isci/scil/scu_task_context.h>
+#include <dev/disk/isci/scil/scu_remote_node_context.h>
+#include <dev/disk/isci/scil/scu_unsolicited_frame.h>
+#include <dev/disk/isci/scil/intel_pci.h>
+#include <dev/disk/isci/scil/scic_sgpio.h>
+#include <dev/disk/isci/scil/scic_sds_phy_registers.h>
+
+#define SCU_CONTEXT_RAM_INIT_STALL_TIME      200
+#define SCIC_SDS_CONTROLLER_MIN_TIMER_COUNT  3
+#define SCIC_SDS_CONTROLLER_MAX_TIMER_COUNT  3
+
+#define SCU_MAX_ZPT_DWORD_INDEX              131
+
+/**
+ * The number of milliseconds to wait for a phy to start.
+ */
+#define SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT      100
+
+/**
+ * The number of milliseconds to wait while a given phy is consuming
+ * power before allowing another set of phys to consume power.
+ * Ultimately, this will be specified by OEM parameter.
+ */
+#define SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL 500
+
+/**
+ * This macro will return the cycle bit of the completion queue entry
+ */
+#define COMPLETION_QUEUE_CYCLE_BIT(x) ((x) & 0x80000000)
+
+/**
+ * This macro will normalize the completion queue get pointer so its value
+ * can be used as an index into an array
+ */
+#define NORMALIZE_GET_POINTER(x) \
+   ((x) & SMU_COMPLETION_QUEUE_GET_POINTER_MASK)
+
+/**
+ *  This macro will normalize the completion queue put pointer so its value
+ *  can be used as an array inde
+ */
+#define NORMALIZE_PUT_POINTER(x) \
+   ((x) & SMU_COMPLETION_QUEUE_PUT_POINTER_MASK)
+
+
+/**
+ * This macro will normalize the completion queue cycle pointer so it
+ * matches the completion queue cycle bit
+ */
+#define NORMALIZE_GET_POINTER_CYCLE_BIT(x) \
+   (((U32)(SMU_CQGR_CYCLE_BIT & (x))) << (31 - SMU_COMPLETION_QUEUE_GET_CYCLE_BIT_SHIFT))
+
+/**
+ * This macro will normalize the completion queue event entry so its value
+ * can be used as an index.
+ */
+#define NORMALIZE_EVENT_POINTER(x) \
+   ( \
+        ((U32)((x) & SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_MASK)) \
+     >> SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_SHIFT \
+   )
+
+/**
+ * This macro will increment the controllers completion queue index value
+ * and possibly toggle the cycle bit if the completion queue index wraps
+ * back to 0.
+ */
+#define INCREMENT_COMPLETION_QUEUE_GET(controller, index, cycle) \
+   INCREMENT_QUEUE_GET( \
+      (index), \
+      (cycle), \
+      (controller)->completion_queue_entries, \
+      SMU_CQGR_CYCLE_BIT \
+   )
+
+/**
+ * This macro will increment the controllers event queue index value and
+ * possibly toggle the event cycle bit if the event queue index wraps back
+ * to 0.
+ */
+#define INCREMENT_EVENT_QUEUE_GET(controller, index, cycle) \
+   INCREMENT_QUEUE_GET( \
+      (index), \
+      (cycle), \
+      (controller)->completion_event_entries, \
+      SMU_CQGR_EVENT_CYCLE_BIT \
+   )
+
+//****************************************************************************-
+//* SCIC SDS Controller Initialization Methods
+//****************************************************************************-
+
+/**
+ * @brief This timer is used to start another phy after we have given up on
+ *        the previous phy to transition to the ready state.
+ *
+ * @param[in] controller
+ */
+static
+void scic_sds_controller_phy_startup_timeout_handler(
+   void *controller
+)
+{
+   SCI_STATUS status;
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+
+   this_controller->phy_startup_timer_pending = FALSE;
+
+   status = SCI_FAILURE;
+
+   while (status != SCI_SUCCESS)
+   {
+      status = scic_sds_controller_start_next_phy(this_controller);
+   }
+}
+
+/**
+ * This method initializes the phy startup operations for controller start.
+ *
+ * @param this_controller
+ */
+static
+SCI_STATUS scic_sds_controller_initialize_phy_startup(
+   SCIC_SDS_CONTROLLER_T *this_controller
+)
+{
+   this_controller->phy_startup_timer = scic_cb_timer_create(
+      this_controller,
+      scic_sds_controller_phy_startup_timeout_handler,
+      this_controller
+   );
+
+   if (this_controller->phy_startup_timer == NULL)
+   {
+      return SCI_FAILURE_INSUFFICIENT_RESOURCES;
+   }
+   else
+   {
+      this_controller->next_phy_to_start = 0;
+      this_controller->phy_startup_timer_pending = FALSE;
+   }
+
+   return SCI_SUCCESS;
+}
+
+/**
+ * This method initializes the power control operations for the controller
+ * object.
+ *
+ * @param this_controller
+ */
+void scic_sds_controller_initialize_power_control(
+   SCIC_SDS_CONTROLLER_T *this_controller
+)
+{
+   this_controller->power_control.timer = scic_cb_timer_create(
+      this_controller,
+      scic_sds_controller_power_control_timer_handler,
+      this_controller
+   );
+
+   memset(
+      this_controller->power_control.requesters,
+      0,
+      sizeof(this_controller->power_control.requesters)
+   );
+
+   this_controller->power_control.phys_waiting = 0;
+   this_controller->power_control.remote_devices_granted_power = 0;
+}
+
+// ---------------------------------------------------------------------------
+
+#define SCU_REMOTE_NODE_CONTEXT_ALIGNMENT       (32)
+#define SCU_TASK_CONTEXT_ALIGNMENT              (256)
+#define SCU_UNSOLICITED_FRAME_ADDRESS_ALIGNMENT (64)
+#define SCU_UNSOLICITED_FRAME_BUFFER_ALIGNMENT  (1024)
+#define SCU_UNSOLICITED_FRAME_HEADER_ALIGNMENT  (64)
+
+// ---------------------------------------------------------------------------
+
+/**
+ * @brief This method builds the memory descriptor table for this
+ *        controller.
+ *
+ * @param[in] this_controller This parameter specifies the controller
+ *            object for which to build the memory table.
+ *
+ * @return none
+ */
+void scic_sds_controller_build_memory_descriptor_table(
+   SCIC_SDS_CONTROLLER_T *this_controller
+)
+{
+   sci_base_mde_construct(
+      &this_controller->memory_descriptors[SCU_MDE_COMPLETION_QUEUE],
+      SCU_COMPLETION_RAM_ALIGNMENT,
+      (sizeof(U32) * this_controller->completion_queue_entries),
+      (SCI_MDE_ATTRIBUTE_CACHEABLE | SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS)
+   );
+
+   sci_base_mde_construct(
+      &this_controller->memory_descriptors[SCU_MDE_REMOTE_NODE_CONTEXT],
+      SCU_REMOTE_NODE_CONTEXT_ALIGNMENT,
+      this_controller->remote_node_entries * sizeof(SCU_REMOTE_NODE_CONTEXT_T),
+      SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
+   );
+
+   sci_base_mde_construct(
+      &this_controller->memory_descriptors[SCU_MDE_TASK_CONTEXT],
+      SCU_TASK_CONTEXT_ALIGNMENT,
+      this_controller->task_context_entries * sizeof(SCU_TASK_CONTEXT_T),
+      SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
+   );
+
+   // The UF buffer address table size must be programmed to a power
+   // of 2.  Find the first power of 2 that is equal to or greater then
+   // the number of unsolicited frame buffers to be utilized.
+   scic_sds_unsolicited_frame_control_set_address_table_count(
+      &this_controller->uf_control
+   );
+
+   sci_base_mde_construct(
+      &this_controller->memory_descriptors[SCU_MDE_UF_BUFFER],
+      SCU_UNSOLICITED_FRAME_BUFFER_ALIGNMENT,
+      scic_sds_unsolicited_frame_control_get_mde_size(this_controller->uf_control),
+      SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
+   );
+}
+
+/**
+ * @brief This method validates the driver supplied memory descriptor
+ *        table.
+ *
+ * @param[in] this_controller
+ *
+ * @return SCI_STATUS
+ */
+SCI_STATUS scic_sds_controller_validate_memory_descriptor_table(
+   SCIC_SDS_CONTROLLER_T *this_controller
+)
+{
+   BOOL mde_list_valid;
+
+   mde_list_valid = sci_base_mde_is_valid(
+      &this_controller->memory_descriptors[SCU_MDE_COMPLETION_QUEUE],
+      SCU_COMPLETION_RAM_ALIGNMENT,
+      (sizeof(U32) * this_controller->completion_queue_entries),
+      (SCI_MDE_ATTRIBUTE_CACHEABLE | SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS)
+   );
+
+   if (mde_list_valid == FALSE)
+      return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD;
+
+   mde_list_valid = sci_base_mde_is_valid(
+      &this_controller->memory_descriptors[SCU_MDE_REMOTE_NODE_CONTEXT],
+      SCU_REMOTE_NODE_CONTEXT_ALIGNMENT,
+      this_controller->remote_node_entries * sizeof(SCU_REMOTE_NODE_CONTEXT_T),
+      SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
+   );
+
+   if (mde_list_valid == FALSE)
+      return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD;
+
+   mde_list_valid = sci_base_mde_is_valid(
+      &this_controller->memory_descriptors[SCU_MDE_TASK_CONTEXT],
+      SCU_TASK_CONTEXT_ALIGNMENT,
+      this_controller->task_context_entries * sizeof(SCU_TASK_CONTEXT_T),
+      SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
+   );
+
+   if (mde_list_valid == FALSE)
+      return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD;
+
+   mde_list_valid = sci_base_mde_is_valid(
+      &this_controller->memory_descriptors[SCU_MDE_UF_BUFFER],
+      SCU_UNSOLICITED_FRAME_BUFFER_ALIGNMENT,
+      scic_sds_unsolicited_frame_control_get_mde_size(this_controller->uf_control),
+      SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
+   );
+
+   if (mde_list_valid == FALSE)
+      return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD;
+
+   return SCI_SUCCESS;
+}
+
+/**
+ * @brief This method initializes the controller with the physical memory
+ *        addresses that are used to communicate with the driver.
+ *
+ * @param[in] this_controller
+ *
+ * @return none
+ */
+void scic_sds_controller_ram_initialization(
+   SCIC_SDS_CONTROLLER_T *this_controller
+)
+{
+   SCI_PHYSICAL_MEMORY_DESCRIPTOR_T *mde;
+
+   // The completion queue is actually placed in cacheable memory
+   // Therefore it no longer comes out of memory in the MDL.
+   mde = &this_controller->memory_descriptors[SCU_MDE_COMPLETION_QUEUE];
+   this_controller->completion_queue = (U32*) mde->virtual_address;
+   SMU_CQBAR_WRITE(this_controller, mde->physical_address);
+
+   // Program the location of the Remote Node Context table
+   // into the SCU.
+   mde = &this_controller->memory_descriptors[SCU_MDE_REMOTE_NODE_CONTEXT];
+   this_controller->remote_node_context_table = (SCU_REMOTE_NODE_CONTEXT_T *)
+                                                mde->virtual_address;
+   SMU_RNCBAR_WRITE(this_controller, mde->physical_address);
+
+   // Program the location of the Task Context table into the SCU.
+   mde = &this_controller->memory_descriptors[SCU_MDE_TASK_CONTEXT];
+   this_controller->task_context_table = (SCU_TASK_CONTEXT_T *)
+                                         mde->virtual_address;
+   SMU_HTTBAR_WRITE(this_controller, mde->physical_address);
+
+   mde = &this_controller->memory_descriptors[SCU_MDE_UF_BUFFER];
+   scic_sds_unsolicited_frame_control_construct(
+      &this_controller->uf_control, mde, this_controller
+   );
+
+   // Inform the silicon as to the location of the UF headers and
+   // address table.
+   SCU_UFHBAR_WRITE(
+      this_controller,
+      this_controller->uf_control.headers.physical_address);
+   SCU_PUFATHAR_WRITE(
+      this_controller,
+      this_controller->uf_control.address_table.physical_address);
+
+   //enable the ECC correction and detection.
+   SCU_SECR0_WRITE(
+      this_controller,
+      (SIGNLE_BIT_ERROR_CORRECTION_ENABLE
+       | MULTI_BIT_ERROR_REPORTING_ENABLE
+       | SINGLE_BIT_ERROR_REPORTING_ENABLE) );
+   SCU_SECR1_WRITE(
+      this_controller,
+      (SIGNLE_BIT_ERROR_CORRECTION_ENABLE
+       | MULTI_BIT_ERROR_REPORTING_ENABLE
+       | SINGLE_BIT_ERROR_REPORTING_ENABLE) );
+}
+
+/**
+ * @brief This method initializes the task context data for the controller.
+ *
+ * @param[in] this_controller
+ *
+ * @return none
+ */
+void scic_sds_controller_assign_task_entries(
+   SCIC_SDS_CONTROLLER_T *this_controller
+)
+{
+   U32 task_assignment;
+
+   // Assign all the TCs to function 0
+   // TODO: Do we actually need to read this register to write it back?
+   task_assignment = SMU_TCA_READ(this_controller, 0);
+
+   task_assignment =
+      (
+          task_assignment
+        | (SMU_TCA_GEN_VAL(STARTING, 0))
+        | (SMU_TCA_GEN_VAL(ENDING,  this_controller->task_context_entries - 1))
+        | (SMU_TCA_GEN_BIT(RANGE_CHECK_ENABLE))
+      );
+
+   SMU_TCA_WRITE(this_controller, 0, task_assignment);
+}
+
+/**
+ * @brief This method initializes the hardware completion queue.
+ *
+ * @param[in] this_controller
+ */
+void scic_sds_controller_initialize_completion_queue(
+   SCIC_SDS_CONTROLLER_T *this_controller
+)
+{
+   U32 index;
+   U32 completion_queue_control_value;
+   U32 completion_queue_get_value;
+   U32 completion_queue_put_value;
+
+   this_controller->completion_queue_get = 0;
+
+   completion_queue_control_value = (
+        SMU_CQC_QUEUE_LIMIT_SET(this_controller->completion_queue_entries - 1)
+      | SMU_CQC_EVENT_LIMIT_SET(this_controller->completion_event_entries - 1)
+   );
+
+   SMU_CQC_WRITE(this_controller, completion_queue_control_value);
+
+   // Set the completion queue get pointer and enable the queue
+   completion_queue_get_value = (
+        (SMU_CQGR_GEN_VAL(POINTER, 0))
+      | (SMU_CQGR_GEN_VAL(EVENT_POINTER, 0))
+      | (SMU_CQGR_GEN_BIT(ENABLE))
+      | (SMU_CQGR_GEN_BIT(EVENT_ENABLE))
+   );
+
+   SMU_CQGR_WRITE(this_controller, completion_queue_get_value);
+
+   this_controller->completion_queue_get = completion_queue_get_value;
+
+   // Set the completion queue put pointer
+   completion_queue_put_value = (
+        (SMU_CQPR_GEN_VAL(POINTER, 0))
+      | (SMU_CQPR_GEN_VAL(EVENT_POINTER, 0))
+   );
+
+   SMU_CQPR_WRITE(this_controller, completion_queue_put_value);
+
+   // Initialize the cycle bit of the completion queue entries
+   for (index = 0; index < this_controller->completion_queue_entries; index++)
+   {
+      // If get.cycle_bit != completion_queue.cycle_bit
+      // its not a valid completion queue entry
+      // so at system start all entries are invalid
+      this_controller->completion_queue[index] = 0x80000000;
+   }
+}
+
+/**
+ * @brief This method initializes the hardware unsolicited frame queue.
+ *
+ * @param[in] this_controller
+ */
+void scic_sds_controller_initialize_unsolicited_frame_queue(
+   SCIC_SDS_CONTROLLER_T *this_controller
+)
+{
+   U32 frame_queue_control_value;
+   U32 frame_queue_get_value;
+   U32 frame_queue_put_value;
+
+   // Write the queue size
+   frame_queue_control_value =
+      SCU_UFQC_GEN_VAL(QUEUE_SIZE, this_controller->uf_control.address_table.count);
+
+   SCU_UFQC_WRITE(this_controller, frame_queue_control_value);
+
+   // Setup the get pointer for the unsolicited frame queue
+   frame_queue_get_value = (
+         SCU_UFQGP_GEN_VAL(POINTER, 0)
+      |  SCU_UFQGP_GEN_BIT(ENABLE_BIT)
+      );
+
+   SCU_UFQGP_WRITE(this_controller, frame_queue_get_value);
+
+   // Setup the put pointer for the unsolicited frame queue
+   frame_queue_put_value = SCU_UFQPP_GEN_VAL(POINTER, 0);
+
+   SCU_UFQPP_WRITE(this_controller, frame_queue_put_value);
+}
+
+/**
+ * @brief This method enables the hardware port task scheduler.
+ *
+ * @param[in] this_controller
+ */
+void scic_sds_controller_enable_port_task_scheduler(
+   SCIC_SDS_CONTROLLER_T *this_controller
+)
+{
+   U32 port_task_scheduler_value;
+
+   port_task_scheduler_value = SCU_PTSGCR_READ(this_controller);
+
+   port_task_scheduler_value |=
+      (SCU_PTSGCR_GEN_BIT(ETM_ENABLE) | SCU_PTSGCR_GEN_BIT(PTSG_ENABLE));
+
+   SCU_PTSGCR_WRITE(this_controller, port_task_scheduler_value);
+}
+
+// ---------------------------------------------------------------------------
+
+#ifdef ARLINGTON_BUILD
+/**
+ * This method will read from the lexington status register.  This is required
+ * as a read fence to the lexington register writes.
+ *
+ * @param this_controller
+ */
+void scic_sds_controller_lex_status_read_fence(
+   SCIC_SDS_CONTROLLER_T *this_controller
+)
+{
+   U32 lex_status;
+
+   // Read Fence
+   lex_status = lex_register_read(
+                  this_controller, this_controller->lex_registers + 0xC4);
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_controller),
+      SCIC_LOG_OBJECT_CONTROLLER,
+      "Controller 0x%x lex_status = 0x%08x\n",
+      this_controller, lex_status
+   ));
+}
+
+/**
+ * This method will initialize the arlington through the LEX_BAR.
+ *
+ * @param this_controller
+ */
+void scic_sds_controller_lex_atux_initialization(
+   SCIC_SDS_CONTROLLER_T *this_controller
+)
+{
+   // 1. Reset all SCU PHY
+   lex_register_write(
+      this_controller, this_controller->lex_registers + 0x28, 0x0020FFFF) ;
+
+   // 2. Write to LEX_CTRL
+   lex_register_write(
+      this_controller, this_controller->lex_registers + 0xC0, 0x00000700);
+
+   scic_sds_controller_lex_status_read_fence(this_controller);
+
+   // 3. Enable PCI Master
+   lex_register_write(
+      this_controller, this_controller->lex_registers + 0x70, 0x00000002);
+
+   // 4. Enable SCU Register Clock Domain
+   lex_register_write(
+      this_controller, this_controller->lex_registers + 0xC0, 0x00000300);
+
+   scic_sds_controller_lex_status_read_fence(this_controller);
+
+   // 5.1 Release PHY-A Reg Reset
+   lex_register_write(
+      this_controller, this_controller->lex_registers + 0x28, 0x0000FFFF);
+
+   // 5.2 Initialize the AFE for PHY-A
+   scic_sds_controller_afe_initialization(this_controller);
+
+   scic_sds_controller_lex_status_read_fence(this_controller);
+
+#if 0
+   // 5.3 Release PHY Reg Reset
+   lex_register_write(
+      this_controller, this_controller->lex_registers + 0x28, 0x0000FFFF);
+#endif
+
+   // 6.1 Release PHY-B Reg Reset
+   lex_register_write(
+      this_controller, this_controller->lex_registers + 0x28, 0x0040FFFF) ;
+
+   // 6.2 Initialize the AFE for PHY-B
+   scic_sds_controller_afe_initialization(this_controller);
+
+   scic_sds_controller_lex_status_read_fence(this_controller);
+
+#if 0
+   // 6.3 Release PHY-B Reg Reset
+   lex_register_write(
+      this_controller, this_controller->lex_registers + 0x28, 0x0040FFFF) ;
+#endif
+
+   // 7. Enable SCU clock domaion
+   lex_register_write(
+      this_controller, this_controller->lex_registers + 0xC0, 0x00000100);
+
+   scic_sds_controller_lex_status_read_fence(this_controller);
+
+   // 8. Release LEX SCU Reset
+   lex_register_write(
+      this_controller, this_controller->lex_registers + 0xC0, 0x00000000);
+
+   scic_sds_controller_lex_status_read_fence(this_controller);
+
+#if !defined(DISABLE_INTERRUPTS)
+   // 8a. Set legacy interrupts (SCU INTx to PCI-x INTA)
+   lex_register_write(
+      this_controller, this_controller->lex_registers + 0xC0, 0x00000800);
+
+   scic_sds_controller_lex_status_read_fence(this_controller);
+#endif
+
+#if 0
+   // 9. Override TXOLVL
+   //write to lex_ctrl
+   lex_register_write(
+      this_controller, this_controller->lex_registers + 0xC0, 0x27800000);
+#endif
+
+   // 10. Release PHY-A & PHY-B Resets
+   lex_register_write(
+      this_controller, this_controller->lex_registers + 0x28, 0x0000FF77);
+
+   lex_register_write(
+      this_controller, this_controller->lex_registers + 0x28, 0x0000FF55);
+
+   lex_register_write(
+      this_controller, this_controller->lex_registers + 0x28, 0x0000FF11);
+
+   lex_register_write(
+      this_controller, this_controller->lex_registers + 0x28, 0x0000FF00);
+
+   lex_register_write(
+      this_controller, this_controller->lex_registers + 0x28, 0x0003FF00);
+}
+#endif // ARLINGTON_BUILD
+
+// ---------------------------------------------------------------------------
+
+#ifdef ARLINGTON_BUILD
+/**
+ * This method enables chipwatch on the arlington board
+ *
+ * @param[in] this_controller
+ */
+void scic_sds_controller_enable_chipwatch(
+   SCIC_SDS_CONTROLLER_T *this_controller
+)
+{
+   lex_register_write(
+      this_controller, this_controller->lex_registers + 0x88, 0x09090909);
+
+   lex_register_write(
+      this_controller, this_controller->lex_registers + 0x8C, 0xcac9c862);
+}
+#endif
+
+/**
+ * This macro is used to delay between writes to the AFE registers
+ * during AFE initialization.
+ */
+#define AFE_REGISTER_WRITE_DELAY 10
+
+/**
+ * Initialize the AFE for this phy index.
+ *
+ * @todo We need to read the AFE setup from the OEM parameters
+ *
+ * @param[in] this_controller
+ *
+ * @return none
+ */
+#if defined(ARLINGTON_BUILD)
+void scic_sds_controller_afe_initialization(
+   SCIC_SDS_CONTROLLER_T *this_controller
+)
+{
+   // 1. Establish Power
+   //       Hold Bias, PLL, and RX TX in reset and powerdown
+   //       pe_afe0_rst_n = 0
+   //       pe_afe0_txpdn0,1,2,3 = 1
+   //       pe_afe0_rxpdn0,1,2,3 = 1
+   //       pe_afe0_txrst0,1,2,3_n = 0
+   //       pe_afe0_rxrst0,1,2,3_n = 0
+   //       wait 1us
+   //       pe_afe0_rst_n = 1
+   //       wait 1us
+   scu_afe_register_write(
+      this_controller, afe_pll_control, 0x00247506);
+
+   // 2. Write 0x00000000 to AFE XCVR Ctrl2
+   scu_afe_register_write(
+      this_controller, afe_dfx_transceiver_status_clear, 0x00000000);
+
+   // 3. afe0_override_en = 0
+   //    afe0_pll_dis_override = 0
+   //    afe0_tx_rst_override = 0
+   //    afe0_pll_dis = 1
+   //    pe_afe0_txrate = 01
+   //    pe_afe0_rxrate = 01
+   //    pe_afe0_txdis = 11
+   //    pe_afe0_txoob = 1
+   //    pe_afe0_txovlv = 9'b001110000
+   scu_afe_register_write(
+      this_controller, afe_transceiver_control0[0], 0x0700141e);
+
+   // 4. Configure PLL Unit
+   //    Write 0x00200506 to AFE PLL Ctrl Register 0
+   scu_afe_register_write(this_controller, afe_pll_control,     0x00200506);
+   scu_afe_register_write(this_controller, afe_pll_dfx_control, 0x10000080);
+
+   // 5. Configure Bias Unit
+   scu_afe_register_write(this_controller, afe_bias_control[0], 0x00124814);
+   scu_afe_register_write(this_controller, afe_bias_control[1], 0x24900000);
+
+   // 6. Configure Transceiver Units
+   scu_afe_register_write(
+      this_controller, afe_transceiver_control0[0], 0x0702941e);
+
+   scu_afe_register_write(
+      this_controller, afe_transceiver_control1[0], 0x0000000a);
+
+   // 7. Configure RX Units
+   scu_afe_register_write(
+      this_controller, afe_transceiver_equalization_control[0], 0x00ba2223);
+
+   scu_afe_register_write(
+      this_controller, reserved_0028_003c[2], 0x00000000);
+
+   // 8. Configure TX Units
+   scu_afe_register_write(
+      this_controller, afe_dfx_transmit_control_register[0], 0x03815428);
+
+   // 9. Transfer control to PE signals
+   scu_afe_register_write(
+      this_controller, afe_dfx_transceiver_status_clear, 0x00000010);
+
+   // 10. Release PLL Powerdown
+   scu_afe_register_write(this_controller, afe_pll_control, 0x00200504);
+
+   // 11. Release PLL Reset
+   scu_afe_register_write(this_controller, afe_pll_control, 0x00200505);
+
+   // 12. Wait for PLL to Lock
+   // (afe0_comm_sta [1:0] should go to 1'b11, and
+   //                [5:2] is 0x5, 0x6, 0x7, 0x8, or 0x9
+   scu_afe_register_write(this_controller, afe_pll_control, 0x00200501);
+
+   while ((scu_afe_register_read(this_controller, afe_common_status) & 0x03) != 0x03)
+   {
+      // Give time for the PLLs to lock
+      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+   }
+
+   // 13. pe_afe0_rxpdn0 = 0
+   //     pe_afe0_rxrst0 = 1
+   //     pe_afe0_txrst0_n = 1
+   //     pe_afe_txoob0_n = 0
+   scu_afe_register_write(
+      this_controller, afe_transceiver_control0[0], 0x07028c11);
+}
+
+#elif defined(PLEASANT_RIDGE_BUILD)
+
+void scic_sds_controller_afe_initialization(
+   SCIC_SDS_CONTROLLER_T *this_controller
+)
+{
+   U32 afe_status;
+   U32 phy_id;
+
+#if defined(SPREADSHEET_AFE_SETTINGS)
+   // Clear DFX Status registers
+   scu_afe_register_write(
+      this_controller, afe_dfx_master_control0, 0x0000000f);
+   // Configure bias currents to normal
+   scu_afe_register_write(
+      this_controller, afe_bias_control, 0x0000aa00);
+   // Enable PLL
+   scu_afe_register_write(
+      this_controller, afe_pll_control0, 0x80000908);
+
+   // Wait for the PLL to lock
+   do
+   {
+      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+      afe_status = scu_afe_register_read(
+                     this_controller, afe_common_block_status);
+   }
+   while((afe_status & 0x00001000) == 0);
+
+   for (phy_id = 0; phy_id < SCI_MAX_PHYS; phy_id++)
+   {
+      // Initialize transceiver channels
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_channel_control, 0x00000157);
+      // Configure transceiver modes
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x38016d1a);
+      // Configure receiver parameters
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control1, 0x01501014);
+      // Configure transmitter parameters
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_tx_control, 0x00000000);
+      // Configure transmitter equalization
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control0, 0x000bdd08);
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control1, 0x000ffc00);
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control2, 0x000b7c09);
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control3, 0x000afc6e);
+      // Configure transmitter SSC parameters
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_tx_ssc_control, 0x00000000);
+      // Configure receiver parameters
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_rx_ssc_control0, 0x3208903f);
+
+      // Start power on sequence
+      // Enable bias currents to transceivers and wait 200ns
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_channel_control, 0x00000154);
+      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+      // Take receiver out of power down and wait 200ns
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x3801611a);
+      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+      // Take receiver out of reset and wait 200ns
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x3801631a);
+      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+      // Take transmitter out of power down and wait 200ns
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x38016318);
+      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+      // Take transmitter out of reset and wait 200ns
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x38016319);
+      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+      // Take transmitter out of DC idle
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x38016319);
+      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+   }
+
+   // Transfer control to the PEs
+   scu_afe_register_write(
+      this_controller, afe_dfx_master_control0, 0x00010f00);
+#else // !defined(SPREADSHEET_AFE_SETTINGS)
+   // These are the AFEE settings used by the SV group
+   // Clear DFX Status registers
+   scu_afe_register_write(
+      this_controller, afe_dfx_master_control0, 0x0081000f);
+   // Configure bias currents to normal
+   scu_afe_register_write(
+      this_controller, afe_bias_control, 0x0000aa00);
+   // Enable PLL
+   scu_afe_register_write(
+      this_controller, afe_pll_control0, 0x80000908);
+
+   // Wait for the PLL to lock
+   // Note: this is done later in the SV shell script however this looks
+   //       like the location to do this since we have enabled the PLL.
+   do
+   {
+      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+      afe_status = scu_afe_register_read(
+                     this_controller, afe_common_block_status);
+   }
+   while((afe_status & 0x00001000) == 0);
+
+   // Make sure BIST is disabled
+   scu_afe_register_write(
+      this_controller, afe_dfx_master_control1, 0x00000000);
+   // Shorten SAS SNW lock time
+   scu_afe_register_write(
+      this_controller, afe_pmsn_master_control0, 0x7bd316ad);
+
+   for (phy_id = 0; phy_id < SCI_MAX_PHYS; phy_id++)
+   {
+      // Initialize transceiver channels
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_channel_control, 0x00000174);
+      // Configure SSC control
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_tx_ssc_control, 0x00030000);
+      // Configure transceiver modes
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x0000651a);
+      // Power up TX RX and RX OOB
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00006518);
+      // Enable RX OOB Detect
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00006518);
+      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+      #if 0
+      // Configure transmitter parameters
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_tx_control, 0x00000000);
+      // Configure transmitter equalization
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control0, 0x000bdd08);
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control1, 0x000ffc00);
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control2, 0x000b7c09);
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control3, 0x000afc6e);
+      // Configure transmitter SSC parameters
+      // Power up TX RX
+
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_channel_control, 0x00000154);
+      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+
+      // FFE = Max
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_dfx_rx_control1, 0x00000080);
+      // DFE1-5 = small
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_dfx_rx_control1, 0x01041042);
+      // Enable DFE/FFE and freeze
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_rx_ssc_control0, 0x320891bf);
+      #endif
+      // Take receiver out of power down and wait 200ns
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00006118);
+      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+      // TX Electrical Idle
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00006108);
+      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+
+      // Leave DFE/FFE on
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_rx_ssc_control0, 0x0317108f);
+
+      // Configure receiver parameters
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control1, 0x01e00021);
+
+      // Bring RX out of reset
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00006109);
+      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00006009);
+      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00006209);
+      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+   }
+
+   // Transfer control to the PEs
+   scu_afe_register_write(
+      this_controller, afe_dfx_master_control0, 0x00010f00);
+#endif
+}
+
+#elif defined(PBG_HBA_A0_BUILD) || defined(PBG_HBA_A2_BUILD) || defined(PBG_HBA_BETA_BUILD) || defined(PBG_BUILD)
+
+void scic_sds_controller_afe_initialization(
+   SCIC_SDS_CONTROLLER_T *this_controller
+)
+{
+   U32  afe_status;
+   U32  phy_id;
+   U8   cable_selection_mask;
+
+   if (
+         (this_controller->pci_revision != SCIC_SDS_PCI_REVISION_A0)
+      && (this_controller->pci_revision != SCIC_SDS_PCI_REVISION_A2)
+      && (this_controller->pci_revision != SCIC_SDS_PCI_REVISION_B0)
+      && (this_controller->pci_revision != SCIC_SDS_PCI_REVISION_C0)
+      && (this_controller->pci_revision != SCIC_SDS_PCI_REVISION_C1)
+      )
+   {
+      // A programming bug has occurred if we are attempting to
+      // support a PCI revision other than those listed.  Default
+      // to B0, and attempt to limp along if it isn't B0.
+      ASSERT(FALSE);
+      this_controller->pci_revision = SCIC_SDS_PCI_REVISION_C1;
+   }
+
+   cable_selection_mask =
+      this_controller->oem_parameters.sds1.controller.cable_selection_mask;
+
+   // These are the AFEE settings used by the SV group
+   // Clear DFX Status registers
+   scu_afe_register_write(
+      this_controller, afe_dfx_master_control0, 0x0081000f);
+   scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+
+   if (
+         (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0)
+      || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0)
+      || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1)
+      )
+   {
+      // PM Rx Equalization Save, PM SPhy Rx Acknowledgement Timer, PM Stagger Timer
+      scu_afe_register_write(
+         this_controller, afe_pmsn_master_control2, 0x0007FFFF);
+      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+   }
+
+   // Configure bias currents to normal
+   if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
+      scu_afe_register_write(this_controller, afe_bias_control, 0x00005500);
+   else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2)
+      scu_afe_register_write(this_controller, afe_bias_control, 0x00005A00);
+   else if (  (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0)
+           || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0) )
+      scu_afe_register_write(this_controller, afe_bias_control, 0x00005F00);
+   else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1)
+      scu_afe_register_write(this_controller, afe_bias_control, 0x00005500);
+   // For C0 the AFE BIAS Controll is unchanged
+
+   scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+
+      // Enable PLL
+   if (  (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
+      || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2) )
+   {
+      scu_afe_register_write(this_controller, afe_pll_control0, 0x80040908);
+   }
+   else if (  (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0)
+           || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0) )
+   {
+      scu_afe_register_write(this_controller, afe_pll_control0, 0x80040A08);
+   }
+   else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1)
+   {
+      scu_afe_register_write(this_controller, afe_pll_control0, 0x80000b08);
+      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+      scu_afe_register_write(this_controller, afe_pll_control0, 0x00000b08);
+      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+      scu_afe_register_write(this_controller, afe_pll_control0, 0x80000b08);
+   }
+
+   scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+
+   // Wait for the PLL to lock
+   // Note: this is done later in the SV shell script however this looks
+   //       like the location to do this since we have enabled the PLL.
+   do
+   {
+      afe_status = scu_afe_register_read(
+                      this_controller, afe_common_block_status);
+      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+   }
+   while((afe_status & 0x00001000) == 0);
+
+   if (  (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
+      || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2) )
+   {
+      // Shorten SAS SNW lock time (RxLock timer value from 76 us to 50 us)
+      scu_afe_register_write(
+         this_controller, afe_pmsn_master_control0, 0x7bcc96ad);
+      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+   }
+
+   for (phy_id = 0; phy_id < SCI_MAX_PHYS; phy_id++)
+   {
+      U8 cable_length_long   = (cable_selection_mask >> phy_id) & 1;
+      U8 cable_length_medium = (cable_selection_mask >> (phy_id + 4)) & 1;
+
+      if (  (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
+         || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2) )
+      {
+         // All defaults, except the Receive Word Alignament/Comma Detect
+         // Enable....(0xe800)
+         scu_afe_register_write(
+            this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00004512
+         );
+         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+
+         scu_afe_register_write(
+            this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control1, 0x0050100F
+         );
+         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+      }
+      else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0)
+      {
+         // Configure transmitter SSC parameters
+         scu_afe_register_write(
+            this_controller, scu_afe_xcvr[phy_id].afe_tx_ssc_control, 0x00030000
+         );
+         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+      }
+      else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0)
+      {
+         // Configure transmitter SSC parameters
+         scu_afe_register_write(
+            this_controller, scu_afe_xcvr[phy_id].afe_tx_ssc_control, 0x00010202
+         );
+         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+
+         // All defaults, except the Receive Word Alignament/Comma Detect
+         // Enable....(0xe800)
+         scu_afe_register_write(
+            this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00014500
+         );
+         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+      }
+      else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1)
+      {
+         // Configure transmitter SSC parameters
+         scu_afe_register_write(
+            this_controller, scu_afe_xcvr[phy_id].afe_tx_ssc_control, 0x00010202
+         );
+         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+
+         // All defaults, except the Receive Word Alignament/Comma Detect
+         // Enable....(0xe800)
+         scu_afe_register_write(
+            this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x0001C500
+         );
+         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+      }
+      // Power up TX and RX out from power down (PWRDNTX and PWRDNRX)
+      // & increase TX int & ext bias 20%....(0xe85c)
+      if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
+      {
+         scu_afe_register_write(
+            this_controller,
+            scu_afe_xcvr[phy_id].afe_channel_control,
+            0x000003D4
+         );
+      }
+      else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2)
+      {
+         scu_afe_register_write(
+            this_controller,
+            scu_afe_xcvr[phy_id].afe_channel_control,
+            0x000003F0
+         );
+      }
+      else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0)
+      {
+         // Power down TX and RX (PWRDNTX and PWRDNRX)
+         scu_afe_register_write(
+            this_controller,
+            scu_afe_xcvr[phy_id].afe_channel_control,
+            0x000003d7
+         );
+
+         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+
+         // Power up TX and RX out from power down (PWRDNTX and PWRDNRX)
+         // & increase TX int & ext bias 20%....(0xe85c)
+         scu_afe_register_write(
+            this_controller,
+            scu_afe_xcvr[phy_id].afe_channel_control,
+            0x000003d4
+         );
+      }
+      else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0)
+      {
+         scu_afe_register_write(
+            this_controller,
+            scu_afe_xcvr[phy_id].afe_channel_control,
+            0x000001e7
+         );
+
+         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+
+         // Power up TX and RX out from power down (PWRDNTX and PWRDNRX)
+         // & increase TX int & ext bias 20%....(0xe85c)
+         scu_afe_register_write(
+            this_controller,
+            scu_afe_xcvr[phy_id].afe_channel_control,
+            0x000001e4
+         );
+      }
+      else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1)
+      {
+         scu_afe_register_write(
+            this_controller,
+            scu_afe_xcvr[phy_id].afe_channel_control,
+            cable_length_long   ? 0x000002F7 :
+            cable_length_medium ? 0x000001F7 : 0x000001F7
+         );
+
+         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+
+         // Power up TX and RX out from power down (PWRDNTX and PWRDNRX)
+         // & increase TX int & ext bias 20%....(0xe85c)
+         scu_afe_register_write(
+            this_controller,
+            scu_afe_xcvr[phy_id].afe_channel_control,
+            cable_length_long   ? 0x000002F4 :
+            cable_length_medium ? 0x000001F4 : 0x000001F4
+         );
+      }
+
+      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+
+      if (  (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
+         || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2) )
+      {
+         // Enable TX equalization (0xe824)
+         scu_afe_register_write(
+            this_controller,
+            scu_afe_xcvr[phy_id].afe_tx_control,
+            0x00040000
+         );
+         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+      }
+
+      if (  (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
+         || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2)
+         || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0) )
+      {
+         // RDPI=0x0(RX Power On), RXOOBDETPDNC=0x0, TPD=0x0(TX Power On),
+         // RDD=0x0(RX Detect Enabled) ....(0xe800)
+         scu_afe_register_write(
+            this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00004100);
+         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+      }
+      else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0)
+      {
+         scu_afe_register_write(
+            this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x00014100);
+         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+      }
+      else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1)
+      {
+         scu_afe_register_write(
+            this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control0, 0x0001c100);
+         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+      }
+
+      // Leave DFE/FFE on
+      if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
+      {
+         scu_afe_register_write(
+            this_controller,
+            scu_afe_xcvr[phy_id].afe_rx_ssc_control0,
+            0x3F09983F
+         );
+      }
+      else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2)
+      {
+         scu_afe_register_write(
+            this_controller,
+            scu_afe_xcvr[phy_id].afe_rx_ssc_control0,
+            0x3F11103F
+         );
+      }
+      else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0)
+      {
+         scu_afe_register_write(
+            this_controller,
+            scu_afe_xcvr[phy_id].afe_rx_ssc_control0,
+            0x3F11103F
+         );
+         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+
+         // Enable TX equalization (0xe824)
+         scu_afe_register_write(
+            this_controller, scu_afe_xcvr[phy_id].afe_tx_control, 0x00040000);
+      }
+      else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0)
+      {
+         scu_afe_register_write(
+            this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control1, 0x01400c0f);
+         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+
+         scu_afe_register_write(
+            this_controller, scu_afe_xcvr[phy_id].afe_rx_ssc_control0, 0x3f6f103f);
+         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+
+         // Enable TX equalization (0xe824)
+         scu_afe_register_write(
+            this_controller, scu_afe_xcvr[phy_id].afe_tx_control, 0x00040000);
+      }
+      else if (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1)
+      {
+         scu_afe_register_write(
+            this_controller, scu_afe_xcvr[phy_id].afe_xcvr_control1,
+            cable_length_long   ? 0x01500C0C :
+            cable_length_medium ? 0x01400C0D : 0x02400C0D
+         );
+         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+
+         scu_afe_register_write(
+            this_controller, scu_afe_xcvr[phy_id].afe_dfx_rx_control1, 0x000003e0);
+         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+
+         scu_afe_register_write(
+            this_controller, scu_afe_xcvr[phy_id].afe_rx_ssc_control0,
+            cable_length_long   ? 0x33091C1F :
+            cable_length_medium ? 0x3315181F : 0x2B17161F
+         );
+         scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+
+         // Enable TX equalization (0xe824)
+         scu_afe_register_write(
+            this_controller, scu_afe_xcvr[phy_id].afe_tx_control, 0x00040000);
+      }
+
+      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control0,
+         this_controller->oem_parameters.sds1.phys[phy_id].afe_tx_amp_control0
+      );
+      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control1,
+         this_controller->oem_parameters.sds1.phys[phy_id].afe_tx_amp_control1
+      );
+      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control2,
+         this_controller->oem_parameters.sds1.phys[phy_id].afe_tx_amp_control2
+      );
+      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+
+      scu_afe_register_write(
+         this_controller, scu_afe_xcvr[phy_id].afe_tx_amp_control3,
+         this_controller->oem_parameters.sds1.phys[phy_id].afe_tx_amp_control3
+      );
+      scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+   }
+
+   // Transfer control to the PEs
+   scu_afe_register_write(
+      this_controller, afe_dfx_master_control0, 0x00010f00);
+   scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+}
+#else
+   #error "Unsupported board type"
+#endif
+
+//****************************************************************************-
+//* SCIC SDS Controller Internal Start/Stop Routines
+//****************************************************************************-
+
+
+/**
+ * @brief This method will attempt to transition into the ready state
+ *        for the controller and indicate that the controller start
+ *        operation has completed if all criteria are met.
+ *
+ * @param[in,out] this_controller This parameter indicates the controller
+ *                object for which to transition to ready.
+ * @param[in]     status This parameter indicates the status value to be
+ *                pass into the call to scic_cb_controller_start_complete().
+ *
+ * @return none.
+ */
+static
+void scic_sds_controller_transition_to_ready(
+   SCIC_SDS_CONTROLLER_T *this_controller,
+   SCI_STATUS             status
+)
+{
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_controller),
+      SCIC_LOG_OBJECT_CONTROLLER,
+      "scic_sds_controller_transition_to_ready(0x%x, 0x%x) enter\n",
+      this_controller, status
+   ));
+
+   if (this_controller->parent.state_machine.current_state_id
+       == SCI_BASE_CONTROLLER_STATE_STARTING)
+   {
+      // We move into the ready state, because some of the phys/ports
+      // may be up and operational.
+      sci_base_state_machine_change_state(
+         scic_sds_controller_get_base_state_machine(this_controller),
+         SCI_BASE_CONTROLLER_STATE_READY
+      );
+
+      scic_cb_controller_start_complete(this_controller, status);
+   }
+}
+
+/**
+ * @brief This method is the general timeout handler for the controller.
+ *        It will take the correct timetout action based on the current
+ *        controller state
+ *
+ * @param[in] controller This parameter indicates the controller on which
+ *            a timeout occurred.
+ *
+ * @return none
+ */
+void scic_sds_controller_timeout_handler(
+   SCI_CONTROLLER_HANDLE_T controller
+)
+{
+   SCI_BASE_CONTROLLER_STATES current_state;
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+
+   current_state = sci_base_state_machine_get_state(
+                      scic_sds_controller_get_base_state_machine(this_controller)
+                   );
+
+   if (current_state == SCI_BASE_CONTROLLER_STATE_STARTING)
+   {
+      scic_sds_controller_transition_to_ready(
+         this_controller, SCI_FAILURE_TIMEOUT
+      );
+   }
+   else if (current_state == SCI_BASE_CONTROLLER_STATE_STOPPING)
+   {
+      sci_base_state_machine_change_state(
+         scic_sds_controller_get_base_state_machine(this_controller),
+         SCI_BASE_CONTROLLER_STATE_FAILED
+      );
+
+      scic_cb_controller_stop_complete(controller, SCI_FAILURE_TIMEOUT);
+   }
+   else
+   {
+      /// @todo Now what do we want to do in this case?
+      SCIC_LOG_ERROR((
+         sci_base_object_get_logger(this_controller),
+         SCIC_LOG_OBJECT_CONTROLLER,
+         "Controller timer fired when controller was not in a state being timed.\n"
+      ));
+   }
+}
+
+/**
+ * @brief
+ *
+ * @param[in] this_controller
+ *
+ * @return SCI_STATUS
+ */
+SCI_STATUS scic_sds_controller_stop_ports(
+   SCIC_SDS_CONTROLLER_T *this_controller
+)
+{
+   U32        index;
+   SCI_STATUS status;
+   SCI_STATUS port_status;
+
+   status = SCI_SUCCESS;
+
+   for (index = 0; index < this_controller->logical_port_entries; index++)
+   {
+      port_status = this_controller->port_table[index].
+         state_handlers->parent.stop_handler(&this_controller->port_table[index].parent);
+      if (
+            (port_status != SCI_SUCCESS)
+         && (port_status != SCI_FAILURE_INVALID_STATE)
+         )
+      {
+         status = SCI_FAILURE;
+
+         SCIC_LOG_WARNING((
+            sci_base_object_get_logger(this_controller),
+            SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_PORT,
+            "Controller stop operation failed to stop port %d because of status %d.\n",
+            this_controller->port_table[index].logical_port_index, port_status
+         ));
+      }
+   }
+
+   return status;
+}
+
+/**
+ * @brief
+ *
+ * @param[in] this_controller
+ */
+static
+void scic_sds_controller_phy_timer_start(
+   SCIC_SDS_CONTROLLER_T *this_controller
+)
+{
+   scic_cb_timer_start(
+      this_controller,
+      this_controller->phy_startup_timer,
+      SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT
+   );
+
+   this_controller->phy_startup_timer_pending = TRUE;
+}
+
+/**
+ * @brief
+ *
+ * @param[in] this_controller
+ */
+void scic_sds_controller_phy_timer_stop(
+   SCIC_SDS_CONTROLLER_T *this_controller
+)
+{
+   scic_cb_timer_stop(
+      this_controller,
+      this_controller->phy_startup_timer
+   );
+
+   this_controller->phy_startup_timer_pending = FALSE;
+}
+
+/**
+ * @brief This method is called internally to determine whether the
+ *        controller start process is complete.  This is only true when:
+ *          - all links have been given an opportunity to start
+ *          - have no indication of a connected device
+ *          - have an indication of a connected device and it has
+ *             finished the link training process.
+ *
+ * @param[in] this_controller This parameter specifies the controller
+ *            object for which to start the next phy.
+ *
+ * @return BOOL
+ */
+BOOL scic_sds_controller_is_start_complete(
+   SCIC_SDS_CONTROLLER_T *this_controller
+)
+{
+   U8 index;
+
+   for (index = 0; index < SCI_MAX_PHYS; index++)
+   {
+      SCIC_SDS_PHY_T *the_phy = & this_controller->phy_table[index];
+
+      if (
+            (
+                  this_controller->oem_parameters.sds1.controller.mode_type
+               == SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE
+            )
+         || (
+               (
+                  this_controller->oem_parameters.sds1.controller.mode_type
+               == SCIC_PORT_MANUAL_CONFIGURATION_MODE
+               )
+            && (scic_sds_phy_get_port(the_phy) != SCI_INVALID_HANDLE)
+            )
+         )
+      {
+         /**
+          * The controller start operation is complete if and only
+          * if:
+          * - all links have been given an opportunity to start
+          * - have no indication of a connected device
+          * - have an indication of a connected device and it has
+          *   finished the link training process.
+          */
+        if (
+               (
+                  (the_phy->is_in_link_training == FALSE)
+               && (the_phy->parent.state_machine.current_state_id
+                   == SCI_BASE_PHY_STATE_INITIAL)
+               )
+            || (
+                  (the_phy->is_in_link_training == FALSE)
+               && (the_phy->parent.state_machine.current_state_id
+                   == SCI_BASE_PHY_STATE_STOPPED)
+               )
+            || (
+                  (the_phy->is_in_link_training == TRUE)
+               && (the_phy->parent.state_machine.current_state_id
+                   == SCI_BASE_PHY_STATE_STARTING)
+               )
+            || (
+                  this_controller->port_agent.phy_ready_mask
+                  != this_controller->port_agent.phy_configured_mask
+               )
+            )
+         {
+            return FALSE;
+         }
+      }
+   }
+
+   return TRUE;
+}
+
+/**
+ * @brief This method is called internally by the controller object to
+ *        start the next phy on the controller.  If all the phys have
+ *        been starte, then this method will attempt to transition the
+ *        controller to the READY state and inform the user
+ *        (scic_cb_controller_start_complete()).
+ *
+ * @param[in] this_controller This parameter specifies the controller
+ *            object for which to start the next phy.
+ *
+ * @return SCI_STATUS
+ */
+SCI_STATUS scic_sds_controller_start_next_phy(
+   SCIC_SDS_CONTROLLER_T *this_controller
+)
+{
+   SCI_STATUS status;
+
+   status = SCI_SUCCESS;
+
+   if (this_controller->phy_startup_timer_pending == FALSE)
+   {
+      if (this_controller->next_phy_to_start == SCI_MAX_PHYS)
+      {
+         // The controller has successfully finished the start process.
+         // Inform the SCI Core user and transition to the READY state.
+         if (scic_sds_controller_is_start_complete(this_controller) == TRUE)
+         {
+            scic_sds_controller_transition_to_ready(
+               this_controller, SCI_SUCCESS
+            );
+         }
+      }
+      else
+      {
+         SCIC_SDS_PHY_T * the_phy;
+
+         the_phy = &this_controller->phy_table[this_controller->next_phy_to_start];
+
+         if (
+               this_controller->oem_parameters.sds1.controller.mode_type
+            == SCIC_PORT_MANUAL_CONFIGURATION_MODE
+            )
+         {
+            if (scic_sds_phy_get_port(the_phy) == SCI_INVALID_HANDLE)
+            {
+               this_controller->next_phy_to_start++;
+
+               // Caution recursion ahead be forwarned
+               //
+               // The PHY was never added to a PORT in MPC mode so start the next phy in sequence
+               // This phy will never go link up and will not draw power the OEM parameters either
+               // configured the phy incorrectly for the PORT or it was never assigned to a PORT
+               return scic_sds_controller_start_next_phy(this_controller);
+            }
+         }
+
+         status = scic_phy_start(the_phy);
+
+         if (status == SCI_SUCCESS)
+         {
+            scic_sds_controller_phy_timer_start(this_controller);
+         }
+         else
+         {
+            SCIC_LOG_WARNING((
+               sci_base_object_get_logger(this_controller),
+               SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_PHY,
+               "Controller stop operation failed to stop phy %d because of status %d.\n",
+               this_controller->phy_table[this_controller->next_phy_to_start].phy_index,
+               status
+            ));
+         }
+
+         this_controller->next_phy_to_start++;
+      }
+   }
+
+   return status;
+}
+
+/**
+ * @brief
+ *
+ * @param[in] this_controller
+ *
+ * @return SCI_STATUS
+ */
+SCI_STATUS scic_sds_controller_stop_phys(
+   SCIC_SDS_CONTROLLER_T *this_controller
+)
+{
+   U32        index;
+   SCI_STATUS status;
+   SCI_STATUS phy_status;
+
+   status = SCI_SUCCESS;
+
+   for (index = 0; index < SCI_MAX_PHYS; index++)
+   {
+      phy_status = scic_phy_stop(&this_controller->phy_table[index]);
+
+      if (
+              (phy_status != SCI_SUCCESS)
+           && (phy_status != SCI_FAILURE_INVALID_STATE)
+         )
+      {
+         status = SCI_FAILURE;
+
+         SCIC_LOG_WARNING((
+            sci_base_object_get_logger(this_controller),
+            SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_PHY,
+            "Controller stop operation failed to stop phy %d because of status %d.\n",
+            this_controller->phy_table[index].phy_index, phy_status
+         ));
+      }
+   }
+
+   return status;
+}
+
+/**
+ * @brief
+ *
+ * @param[in] this_controller
+ *
+ * @return SCI_STATUS
+ */
+SCI_STATUS scic_sds_controller_stop_devices(
+   SCIC_SDS_CONTROLLER_T *this_controller
+)
+{
+   U32        index;
+   SCI_STATUS status;
+   SCI_STATUS device_status;
+
+   status = SCI_SUCCESS;
+
+   for (index = 0; index < this_controller->remote_node_entries; index++)
+   {
+      if (this_controller->device_table[index] != SCI_INVALID_HANDLE)
+      {
+         /// @todo What timeout value do we want to provide to this request?
+         device_status = scic_remote_device_stop(this_controller->device_table[index], 0);
+
+         if (
+                 (device_status != SCI_SUCCESS)
+              && (device_status != SCI_FAILURE_INVALID_STATE)
+            )
+         {
+            SCIC_LOG_WARNING((
+               sci_base_object_get_logger(this_controller),
+               SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_SSP_REMOTE_TARGET,
+               "Controller stop operation failed to stop device 0x%x because of status %d.\n",
+               this_controller->device_table[index], device_status
+            ));
+         }
+      }
+   }
+
+   return status;
+}
+
+//****************************************************************************-
+//* SCIC SDS Controller Power Control (Staggered Spinup)
+//****************************************************************************-
+
+/**
+ * This method starts the power control timer for this controller object.
+ *
+ * @param this_controller
+ */
+static
+void scic_sds_controller_power_control_timer_start(
+   SCIC_SDS_CONTROLLER_T *this_controller
+)
+{
+   scic_cb_timer_start(
+      this_controller, this_controller->power_control.timer,
+      SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL
+   );
+
+   this_controller->power_control.timer_started = TRUE;
+}
+
+/**
+ * This method stops the power control timer for this controller object.
+ *
+ * @param this_controller
+ */
+static
+void scic_sds_controller_power_control_timer_stop(
+   SCIC_SDS_CONTROLLER_T *this_controller
+)
+{
+   if (this_controller->power_control.timer_started)
+   {
+      scic_cb_timer_stop(
+         this_controller, this_controller->power_control.timer
+      );
+
+      this_controller->power_control.timer_started = FALSE;
+   }
+}
+
+/**
+ * This method stops and starts the power control timer for this controller object.
+ *
+ * @param this_controller
+ */
+static
+void scic_sds_controller_power_control_timer_restart(
+   SCIC_SDS_CONTROLLER_T *this_controller
+)
+{
+   scic_sds_controller_power_control_timer_stop(this_controller);
+   scic_sds_controller_power_control_timer_start(this_controller);
+}
+
+
+/**
+ * @brief
+ *
+ * @param[in] controller
+ */
+void scic_sds_controller_power_control_timer_handler(
+   void *controller
+)
+{
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+
+   this_controller->power_control.remote_devices_granted_power = 0;
+
+   if (this_controller->power_control.phys_waiting == 0)
+   {
+      this_controller->power_control.timer_started = FALSE;
+   }
+   else
+   {
+      SCIC_SDS_PHY_T *the_phy = NULL;
+      U8 i;
+
+      for (i=0;
+              (i < SCI_MAX_PHYS)
+           && (this_controller->power_control.phys_waiting != 0);
+           i++)
+      {
+         if (this_controller->power_control.requesters[i] != NULL)
+         {
+            if ( this_controller->power_control.remote_devices_granted_power <
+                 this_controller->oem_parameters.sds1.controller.max_number_concurrent_device_spin_up
+               )
+            {
+               the_phy = this_controller->power_control.requesters[i];
+               this_controller->power_control.requesters[i] = NULL;
+               this_controller->power_control.phys_waiting--;
+               this_controller->power_control.remote_devices_granted_power ++;
+               scic_sds_phy_consume_power_handler(the_phy);
+
+               if (the_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS)
+               {
+                  U8 j;
+                  SCIC_SDS_PHY_T * current_requester_phy;
+
+                  for (j = 0; j < SCI_MAX_PHYS; j++)
+                  {
+                     current_requester_phy = this_controller->power_control.requesters[j];
+
+                     //Search the power_control queue to see if there are other phys attached to
+                     //the same remote device. If found, take all of them out of await_sas_power state.
+                     if (current_requester_phy != NULL &&
+                         current_requester_phy != the_phy &&
+                         current_requester_phy->phy_type.sas.identify_address_frame_buffer.sas_address.high
+                            == the_phy->phy_type.sas.identify_address_frame_buffer.sas_address.high &&
+                         current_requester_phy->phy_type.sas.identify_address_frame_buffer.sas_address.low
+                            == the_phy->phy_type.sas.identify_address_frame_buffer.sas_address.low)
+                     {
+                        this_controller->power_control.requesters[j] = NULL;
+                        this_controller->power_control.phys_waiting--;
+                        scic_sds_phy_consume_power_handler(current_requester_phy);
+                     }
+                  }
+               }
+            }
+            else
+            {
+               break;
+            }
+         }
+      }
+
+      // It doesn't matter if the power list is empty, we need to start the
+      // timer in case another phy becomes ready.
+      scic_sds_controller_power_control_timer_start(this_controller);
+   }
+}
+
+/**
+ * @brief This method inserts the phy in the stagger spinup control queue.
+ *
+ * @param[in] this_controller
+ * @param[in] the_phy
+ */
+void scic_sds_controller_power_control_queue_insert(
+   SCIC_SDS_CONTROLLER_T *this_controller,
+   SCIC_SDS_PHY_T        *the_phy
+)
+{
+   ASSERT (the_phy != NULL);
+
+   if( this_controller->power_control.remote_devices_granted_power <
+       this_controller->oem_parameters.sds1.controller.max_number_concurrent_device_spin_up
+     )
+   {
+      this_controller->power_control.remote_devices_granted_power ++;
+      scic_sds_phy_consume_power_handler(the_phy);
+
+      //stop and start the power_control timer. When the timer fires, the
+      //no_of_devices_granted_power will be set to 0
+      scic_sds_controller_power_control_timer_restart (this_controller);
+   }
+   else
+   {
+      //there are phys, attached to the same sas address as this phy, are already
+      //in READY state, this phy don't need wait.
+      U8 i;
+      SCIC_SDS_PHY_T * current_phy;
+      for(i = 0; i < SCI_MAX_PHYS; i++)
+      {
+         current_phy = &this_controller->phy_table[i];
+
+         if (current_phy->parent.state_machine.current_state_id == SCI_BASE_PHY_STATE_READY &&
+             current_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS &&
+             current_phy->phy_type.sas.identify_address_frame_buffer.sas_address.high
+                == the_phy->phy_type.sas.identify_address_frame_buffer.sas_address.high &&
+             current_phy->phy_type.sas.identify_address_frame_buffer.sas_address.low
+                == the_phy->phy_type.sas.identify_address_frame_buffer.sas_address.low)
+         {
+            scic_sds_phy_consume_power_handler(the_phy);
+            break;
+         }
+      }
+
+      if (i == SCI_MAX_PHYS)
+      {
+         //Add the phy in the waiting list
+         this_controller->power_control.requesters[the_phy->phy_index] = the_phy;
+         this_controller->power_control.phys_waiting++;
+      }
+   }
+}
+
+/**
+ * @brief This method removes the phy from the stagger spinup control
+ *        queue.
+ *
+ * @param[in] this_controller
+ * @param[in] the_phy
+ */
+void scic_sds_controller_power_control_queue_remove(
+   SCIC_SDS_CONTROLLER_T *this_controller,
+   SCIC_SDS_PHY_T        *the_phy
+)
+{
+   ASSERT (the_phy != NULL);
+
+   if (this_controller->power_control.requesters[the_phy->phy_index] != NULL)
+   {
+      this_controller->power_control.phys_waiting--;
+   }
+
+   this_controller->power_control.requesters[the_phy->phy_index] = NULL;
+}
+
+//****************************************************************************-
+//* SCIC SDS Controller Completion Routines
+//****************************************************************************-
+
+/**
+ * @brief This method returns a TRUE value if the completion queue has
+ *        entries that can be processed
+ *
+ * @param[in] this_controller
+ *
+ * @return BOOL
+ * @retval TRUE if the completion queue has entries to process
+ *         FALSE if the completion queue has no entries to process
+ */
+static
+BOOL scic_sds_controller_completion_queue_has_entries(
+   SCIC_SDS_CONTROLLER_T *this_controller
+)
+{
+   U32 get_value = this_controller->completion_queue_get;
+   U32 get_index = get_value & SMU_COMPLETION_QUEUE_GET_POINTER_MASK;
+   if (
+           NORMALIZE_GET_POINTER_CYCLE_BIT(get_value)
+        == COMPLETION_QUEUE_CYCLE_BIT(this_controller->completion_queue[get_index])
+      )
+   {
+      return TRUE;
+   }
+
+   return FALSE;
+}
+
+// ---------------------------------------------------------------------------
+
+/**
+ * @brief This method processes a task completion notification.  This is
+ *        called from within the controller completion handler.
+ *
+ * @param[in] this_controller
+ * @param[in] completion_entry
+ *
+ * @return none
+ */
+static
+void scic_sds_controller_task_completion(
+   SCIC_SDS_CONTROLLER_T *this_controller,
+   U32                   completion_entry
+)
+{
+   U32 index;
+   SCIC_SDS_REQUEST_T *io_request;
+
+   index = SCU_GET_COMPLETION_INDEX(completion_entry);
+   io_request = this_controller->io_request_table[index];
+
+   // Make sure that we really want to process this IO request
+   if (
+           (io_request != SCI_INVALID_HANDLE)
+        && (io_request->io_tag != SCI_CONTROLLER_INVALID_IO_TAG)
+        && (
+                scic_sds_io_tag_get_sequence(io_request->io_tag)
+             == this_controller->io_request_sequence[index]
+           )
+      )
+   {
+      // Yep this is a valid io request pass it along to the io request handler
+      scic_sds_io_request_tc_completion(io_request, completion_entry);
+   }
+}
+
+/**
+ * @brief This method processes an SDMA completion event.  This is called
+ *        from within the controller completion handler.
+ *
+ * @param[in] this_controller
+ * @param[in] completion_entry
+ *
+ * @return none
+ */
+static
+void scic_sds_controller_sdma_completion(
+   SCIC_SDS_CONTROLLER_T *this_controller,
+   U32                   completion_entry
+)
+{
+   U32 index;
+   SCIC_SDS_REQUEST_T       *io_request;
+   SCIC_SDS_REMOTE_DEVICE_T *device;
+
+   index = SCU_GET_COMPLETION_INDEX(completion_entry);
+
+   switch (scu_get_command_request_type(completion_entry))
+   {
+   case SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC:
+   case SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_TC:
+      io_request = this_controller->io_request_table[index];
+      SCIC_LOG_ERROR((
+         sci_base_object_get_logger(this_controller),
+           SCIC_LOG_OBJECT_CONTROLLER
+         | SCIC_LOG_OBJECT_SMP_IO_REQUEST
+         | SCIC_LOG_OBJECT_SSP_IO_REQUEST
+         | SCIC_LOG_OBJECT_STP_IO_REQUEST,
+         "SCIC SDS Completion type SDMA %x for io request %x\n",
+         completion_entry,
+         io_request
+      ));
+      /// @todo For a post TC operation we need to fail the IO request
+      break;
+
+   case SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC:
+   case SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC:
+   case SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC:
+      device = this_controller->device_table[index];
+      SCIC_LOG_ERROR((
+         sci_base_object_get_logger(this_controller),
+           SCIC_LOG_OBJECT_CONTROLLER
+         | SCIC_LOG_OBJECT_SSP_REMOTE_TARGET
+         | SCIC_LOG_OBJECT_SMP_REMOTE_TARGET
+         | SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
+         "SCIC SDS Completion type SDMA %x for remote device %x\n",
+         completion_entry,
+         device
+      ));
+      /// @todo For a port RNC operation we need to fail the device
+      break;
+
+   default:
+      SCIC_LOG_ERROR((
+         sci_base_object_get_logger(this_controller),
+         SCIC_LOG_OBJECT_CONTROLLER,
+         "SCIC SDS Completion unknown SDMA completion type %x\n",
+         completion_entry
+      ));
+      break;
+   }
+
+   /// This is an unexpected completion type and is un-recoverable
+   /// Transition to the failed state and wait for a controller reset
+   sci_base_state_machine_change_state(
+      scic_sds_controller_get_base_state_machine(this_controller),
+      SCI_BASE_CONTROLLER_STATE_FAILED
+   );
+}
+
+/**
+ * This method processes an unsolicited frame message.  This is called from
+ * within the controller completion handler.
+ *
+ * @param[in] this_controller
+ * @param[in] completion_entry
+ *
+ * @return none
+ */
+static
+void scic_sds_controller_unsolicited_frame(
+   SCIC_SDS_CONTROLLER_T *this_controller,
+   U32                   completion_entry
+)
+{
+   U32 index;
+   U32 frame_index;
+
+   SCU_UNSOLICITED_FRAME_HEADER_T * frame_header;
+   SCIC_SDS_PHY_T                 * phy;
+   SCIC_SDS_REMOTE_DEVICE_T       * device;
+
+   SCI_STATUS result = SCI_FAILURE;
+
+   frame_index = SCU_GET_FRAME_INDEX(completion_entry);
+
+   frame_header
+      = this_controller->uf_control.buffers.array[frame_index].header;
+   this_controller->uf_control.buffers.array[frame_index].state
+      = UNSOLICITED_FRAME_IN_USE;
+
+   if (SCU_GET_FRAME_ERROR(completion_entry))
+   {
+      /// @todo If the IAF frame or SIGNATURE FIS frame has an error will
+      ///       this cause a problem? We expect the phy initialization will
+      ///       fail if there is an error in the frame.
+      scic_sds_controller_release_frame(this_controller, frame_index);
+      return;
+   }
+
+   if (frame_header->is_address_frame)
+   {
+      index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry);
+      phy = &this_controller->phy_table[index];
+      if (phy != NULL)
+      {
+         result = scic_sds_phy_frame_handler(phy, frame_index);
+      }
+   }
+   else
+   {
+
+      index = SCU_GET_COMPLETION_INDEX(completion_entry);
+
+      if (index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX)
+      {
+         // This is a signature fis or a frame from a direct attached SATA
+         // device that has not yet been created.  In either case forwared
+         // the frame to the PE and let it take care of the frame data.
+         index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry);
+         phy = &this_controller->phy_table[index];
+         result = scic_sds_phy_frame_handler(phy, frame_index);
+      }
+      else
+      {
+         if (index < this_controller->remote_node_entries)
+            device = this_controller->device_table[index];
+         else
+            device = NULL;
+
+         if (device != NULL)
+            result = scic_sds_remote_device_frame_handler(device, frame_index);
+         else
+            scic_sds_controller_release_frame(this_controller, frame_index);
+      }
+   }
+
+   if (result != SCI_SUCCESS)
+   {
+      /// @todo Is there any reason to report some additional error message
+      ///       when we get this failure notifiction?
+   }
+}
+
+/**
+ * @brief This method processes an event completion entry.  This is called
+ *        from within the controller completion handler.
+ *
+ * @param[in] this_controller
+ * @param[in] completion_entry
+ *
+ * @return none
+ */
+static
+void scic_sds_controller_event_completion(
+   SCIC_SDS_CONTROLLER_T *this_controller,
+   U32                   completion_entry
+)
+{
+   U32 index;
+   SCIC_SDS_REQUEST_T       *io_request;
+   SCIC_SDS_REMOTE_DEVICE_T *device;
+   SCIC_SDS_PHY_T           *phy;
+
+   index = SCU_GET_COMPLETION_INDEX(completion_entry);
+
+   switch (scu_get_event_type(completion_entry))
+   {
+   case SCU_EVENT_TYPE_SMU_COMMAND_ERROR:
+      /// @todo The driver did something wrong and we need to fix the condtion.
+      SCIC_LOG_ERROR((
+         sci_base_object_get_logger(this_controller),
+         SCIC_LOG_OBJECT_CONTROLLER,
+         "SCIC Controller 0x%x received SMU command error 0x%x\n",
+         this_controller, completion_entry
+      ));
+      break;
+
+   case SCU_EVENT_TYPE_FATAL_MEMORY_ERROR:
+       // report fatal memory error
+       this_controller->parent.error = SCI_CONTROLLER_FATAL_MEMORY_ERROR;
+
+       sci_base_state_machine_change_state(
+          scic_sds_controller_get_base_state_machine(this_controller),
+          SCI_BASE_CONTROLLER_STATE_FAILED
+       );
+
+       //continue as in following events
+   case SCU_EVENT_TYPE_SMU_PCQ_ERROR:
+   case SCU_EVENT_TYPE_SMU_ERROR:
+      SCIC_LOG_ERROR((
+         sci_base_object_get_logger(this_controller),
+         SCIC_LOG_OBJECT_CONTROLLER,
+         "SCIC Controller 0x%x received fatal controller event 0x%x\n",
+         this_controller, completion_entry
+      ));
+      break;
+
+   case SCU_EVENT_TYPE_TRANSPORT_ERROR:
+      io_request = this_controller->io_request_table[index];
+      scic_sds_io_request_event_handler(io_request, completion_entry);
+      break;
+
+   case SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT:
+      switch (scu_get_event_specifier(completion_entry))
+      {
+      case SCU_EVENT_SPECIFIC_SMP_RESPONSE_NO_PE:
+      case SCU_EVENT_SPECIFIC_TASK_TIMEOUT:
+         io_request = this_controller->io_request_table[index];
+         if (io_request != SCI_INVALID_HANDLE)
+         {
+            scic_sds_io_request_event_handler(io_request, completion_entry);
+         }
+         else
+         {
+            SCIC_LOG_WARNING((
+               sci_base_object_get_logger(this_controller),
+               SCIC_LOG_OBJECT_CONTROLLER |
+               SCIC_LOG_OBJECT_SMP_IO_REQUEST |
+               SCIC_LOG_OBJECT_SSP_IO_REQUEST |
+               SCIC_LOG_OBJECT_STP_IO_REQUEST,
+               "SCIC Controller 0x%x received event 0x%x for io request object that doesnt exist.\n",
+               this_controller, completion_entry
+            ));
+         }
+         break;
+
+      case SCU_EVENT_SPECIFIC_IT_NEXUS_TIMEOUT:
+         device = this_controller->device_table[index];
+         if (device != SCI_INVALID_HANDLE)
+         {
+            scic_sds_remote_device_event_handler(device, completion_entry);
+         }
+         else
+         {
+            SCIC_LOG_WARNING((
+               sci_base_object_get_logger(this_controller),
+               SCIC_LOG_OBJECT_CONTROLLER |
+               SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
+               SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+               SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
+               "SCIC Controller 0x%x received event 0x%x for remote device object that doesnt exist.\n",
+               this_controller, completion_entry
+            ));
+         }
+         break;
+      }
+      break;
+
+   case SCU_EVENT_TYPE_BROADCAST_CHANGE:
+      // direct the broadcast change event to the phy first and then let
+      // the phy redirect the broadcast change to the port object
+   case SCU_EVENT_TYPE_ERR_CNT_EVENT:
+      // direct error counter event to the phy object since that is where
+      // we get the event notification.  This is a type 4 event.
+   case SCU_EVENT_TYPE_OSSP_EVENT:
+      index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry);
+      phy = &this_controller->phy_table[index];
+      scic_sds_phy_event_handler(phy, completion_entry);
+      break;
+
+   case SCU_EVENT_TYPE_RNC_SUSPEND_TX:
+   case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX:
+   case SCU_EVENT_TYPE_RNC_OPS_MISC:
+      if (index < this_controller->remote_node_entries)
+      {
+         device = this_controller->device_table[index];
+
+         if (device != NULL)
+         {
+            scic_sds_remote_device_event_handler(device, completion_entry);
+         }
+      }
+      else
+      {
+         SCIC_LOG_ERROR((
+            sci_base_object_get_logger(this_controller),
+            SCIC_LOG_OBJECT_CONTROLLER |
+            SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
+            SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+            SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
+            "SCIC Controller 0x%x received event 0x%x for remote device object 0x%0x that doesnt exist.\n",
+            this_controller, completion_entry, index
+         ));
+      }
+      break;
+
+   default:
+      SCIC_LOG_WARNING((
+         sci_base_object_get_logger(this_controller),
+         SCIC_LOG_OBJECT_CONTROLLER,
+         "SCIC Controller received unknown event code %x\n",
+         completion_entry
+      ));
+      break;
+   }
+}
+
+/**
+ * @brief This method is a private routine for processing the completion
+ *        queue entries.
+ *
+ * @param[in] this_controller
+ *
+ * @return none
+ */
+static
+void scic_sds_controller_process_completions(
+   SCIC_SDS_CONTROLLER_T *this_controller
+)
+{
+   U32 completion_count = 0;
+   U32 completion_entry;
+   U32 get_index;
+   U32 get_cycle;
+   U32 event_index;
+   U32 event_cycle;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_controller),
+      SCIC_LOG_OBJECT_CONTROLLER,
+      "scic_sds_controller_process_completions(0x%x) enter\n",
+      this_controller
+   ));
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_controller),
+      SCIC_LOG_OBJECT_COMPLETION_QUEUE,
+      "completion queue begining get : 0x%08x\n",
+      this_controller->completion_queue_get
+   ));
+
+   // Get the component parts of the completion queue
+   get_index = NORMALIZE_GET_POINTER(this_controller->completion_queue_get);
+   get_cycle = SMU_CQGR_CYCLE_BIT & this_controller->completion_queue_get;
+
+   event_index = NORMALIZE_EVENT_POINTER(this_controller->completion_queue_get);
+   event_cycle = SMU_CQGR_EVENT_CYCLE_BIT & this_controller->completion_queue_get;
+
+   while (
+               NORMALIZE_GET_POINTER_CYCLE_BIT(get_cycle)
+            == COMPLETION_QUEUE_CYCLE_BIT(this_controller->completion_queue[get_index])
+         )
+   {
+      completion_count++;
+
+      completion_entry = this_controller->completion_queue[get_index];
+      INCREMENT_COMPLETION_QUEUE_GET(this_controller, get_index, get_cycle);
+
+      SCIC_LOG_TRACE((
+         sci_base_object_get_logger(this_controller),
+         SCIC_LOG_OBJECT_COMPLETION_QUEUE,
+         "completion queue entry : 0x%08x\n",
+         completion_entry
+      ));
+
+      switch (SCU_GET_COMPLETION_TYPE(completion_entry))
+      {
+      case SCU_COMPLETION_TYPE_TASK:
+         scic_sds_controller_task_completion(this_controller, completion_entry);
+         break;
+
+      case SCU_COMPLETION_TYPE_SDMA:
+         scic_sds_controller_sdma_completion(this_controller, completion_entry);
+         break;
+
+      case SCU_COMPLETION_TYPE_UFI:
+         scic_sds_controller_unsolicited_frame(this_controller, completion_entry);
+         break;
+
+      case SCU_COMPLETION_TYPE_EVENT:
+         scic_sds_controller_event_completion(this_controller, completion_entry);
+         break;
+
+      case SCU_COMPLETION_TYPE_NOTIFY:
+         // Presently we do the same thing with a notify event that we do with the
+         // other event codes.
+         INCREMENT_EVENT_QUEUE_GET(this_controller, event_index, event_cycle);
+         scic_sds_controller_event_completion(this_controller, completion_entry);
+         break;
+
+      default:
+         SCIC_LOG_WARNING((
+            sci_base_object_get_logger(this_controller),
+            SCIC_LOG_OBJECT_CONTROLLER,
+            "SCIC Controller received unknown completion type %x\n",
+            completion_entry
+         ));
+         break;
+      }
+   }
+
+   // Update the get register if we completed one or more entries
+   if (completion_count > 0)
+   {
+      this_controller->completion_queue_get =
+           SMU_CQGR_GEN_BIT(ENABLE)
+         | SMU_CQGR_GEN_BIT(EVENT_ENABLE)
+         | event_cycle | SMU_CQGR_GEN_VAL(EVENT_POINTER, event_index)
+         | get_cycle   | SMU_CQGR_GEN_VAL(POINTER, get_index)  ;
+
+      SMU_CQGR_WRITE(this_controller, this_controller->completion_queue_get);
+   }
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_controller),
+      SCIC_LOG_OBJECT_COMPLETION_QUEUE,
+      "completion queue ending get : 0x%08x\n",
+      this_controller->completion_queue_get
+   ));
+
+}
+
+/**
+ * @brief This method is a private routine for processing the completion
+ *        queue entries.
+ *
+ * @param[in] this_controller
+ *
+ * @return none
+ */
+static
+void scic_sds_controller_transitioned_process_completions(
+   SCIC_SDS_CONTROLLER_T * this_controller
+)
+{
+   U32 completion_count = 0;
+   U32 completion_entry;
+   U32 get_index;
+   U32 get_cycle;
+   U32 event_index;
+   U32 event_cycle;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_controller),
+      SCIC_LOG_OBJECT_CONTROLLER,
+      "scic_sds_controller_transitioned_process_completions(0x%x) enter\n",
+      this_controller
+   ));
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_controller),
+      SCIC_LOG_OBJECT_COMPLETION_QUEUE,
+      "completion queue begining get : 0x%08x\n",
+      this_controller->completion_queue_get
+   ));
+
+   // Get the component parts of the completion queue
+   get_index = NORMALIZE_GET_POINTER(this_controller->completion_queue_get);
+   get_cycle = SMU_CQGR_CYCLE_BIT & this_controller->completion_queue_get;
+
+   event_index = NORMALIZE_EVENT_POINTER(this_controller->completion_queue_get);
+   event_cycle = SMU_CQGR_EVENT_CYCLE_BIT & this_controller->completion_queue_get;
+
+   while (
+               NORMALIZE_GET_POINTER_CYCLE_BIT(get_cycle)
+            == COMPLETION_QUEUE_CYCLE_BIT(
+                  this_controller->completion_queue[get_index])
+         )
+   {
+      completion_count++;
+
+      completion_entry = this_controller->completion_queue[get_index];
+      INCREMENT_COMPLETION_QUEUE_GET(this_controller, get_index, get_cycle);
+
+      SCIC_LOG_TRACE((
+         sci_base_object_get_logger(this_controller),
+         SCIC_LOG_OBJECT_COMPLETION_QUEUE,
+         "completion queue entry : 0x%08x\n",
+         completion_entry
+      ));
+
+      switch (SCU_GET_COMPLETION_TYPE(completion_entry))
+      {
+      case SCU_COMPLETION_TYPE_TASK:
+         scic_sds_controller_task_completion(this_controller, completion_entry);
+      break;
+
+      case SCU_COMPLETION_TYPE_NOTIFY:
+         INCREMENT_EVENT_QUEUE_GET(this_controller, event_index, event_cycle);
+         // Fall-through
+
+      case SCU_COMPLETION_TYPE_EVENT:
+      case SCU_COMPLETION_TYPE_SDMA:
+      case SCU_COMPLETION_TYPE_UFI:
+      default:
+         SCIC_LOG_WARNING((
+            sci_base_object_get_logger(this_controller),
+            SCIC_LOG_OBJECT_CONTROLLER,
+            "SCIC Controller ignoring completion type %x\n",
+            completion_entry
+         ));
+      break;
+      }
+   }
+
+   // Update the get register if we completed one or more entries
+   if (completion_count > 0)
+   {
+      this_controller->completion_queue_get =
+           SMU_CQGR_GEN_BIT(ENABLE)
+         | SMU_CQGR_GEN_BIT(EVENT_ENABLE)
+         | event_cycle | SMU_CQGR_GEN_VAL(EVENT_POINTER, event_index)
+         | get_cycle   | SMU_CQGR_GEN_VAL(POINTER, get_index)  ;
+
+      SMU_CQGR_WRITE(this_controller, this_controller->completion_queue_get);
+   }
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_controller),
+      SCIC_LOG_OBJECT_COMPLETION_QUEUE,
+      "completion queue ending get : 0x%08x\n",
+      this_controller->completion_queue_get
+   ));
+}
+
+//****************************************************************************-
+//* SCIC SDS Controller Interrupt and Completion functions
+//****************************************************************************-
+
+/**
+ * @brief This method provides standard (common) processing of interrupts
+ *        for polling and legacy based interrupts.
+ *
+ * @param[in] controller
+ * @param[in] interrupt_status
+ *
+ * @return This method returns a boolean (BOOL) indication as to
+ *         whether an completions are pending to be processed.
+ * @retval TRUE if an interrupt is to be processed
+ * @retval FALSE if no interrupt was pending
+ */
+static
+BOOL scic_sds_controller_standard_interrupt_handler(
+   SCIC_SDS_CONTROLLER_T *this_controller,
+   U32                    interrupt_status
+)
+{
+   BOOL  is_completion_needed = FALSE;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_controller),
+      SCIC_LOG_OBJECT_CONTROLLER,
+      "scic_sds_controller_standard_interrupt_handler(0x%d,0x%d) enter\n",
+      this_controller, interrupt_status
+   ));
+
+   if (
+         (interrupt_status & SMU_ISR_QUEUE_ERROR)
+      || (
+            (interrupt_status & SMU_ISR_QUEUE_SUSPEND)
+         && (!scic_sds_controller_completion_queue_has_entries(this_controller))
+         )
+      )
+   {
+      // We have a fatal error on the read of the completion queue bar
+      // OR
+      // We have a fatal error there is nothing in the completion queue
+      // but we have a report from the hardware that the queue is full
+      /// @todo how do we request the a controller reset
+      is_completion_needed = TRUE;
+      this_controller->encountered_fatal_error = TRUE;
+   }
+
+   if (scic_sds_controller_completion_queue_has_entries(this_controller))
+   {
+      is_completion_needed = TRUE;
+   }
+
+   return is_completion_needed;
+}
+
+/**
+ * @brief This is the method provided to handle polling for interrupts
+ *        for the controller object.
+ *
+ * @param[in] controller
+ *
+ * @return BOOL
+ * @retval TRUE if an interrupt is to be processed
+ * @retval FALSE if no interrupt was pending
+ */
+static
+BOOL scic_sds_controller_polling_interrupt_handler(
+   SCI_CONTROLLER_HANDLE_T controller
+)
+{
+   U32                    interrupt_status;
+   SCIC_SDS_CONTROLLER_T *this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIC_LOG_OBJECT_CONTROLLER,
+      "scic_sds_controller_polling_interrupt_handler(0x%d) enter\n",
+      controller
+   ));
+
+   /*
+    * In INTERRUPT_POLLING_MODE we exit the interrupt handler if the hardware
+    * indicates nothing is pending. Since we are not being called from a real
+    * interrupt, we don't want to confuse the hardware by servicing the
+    * completion queue before the hardware indicates it is ready. We'll
+    * simply wait for another polling interval and check again.
+    */
+   interrupt_status = SMU_ISR_READ(this_controller);
+   if ((interrupt_status &
+         (SMU_ISR_COMPLETION |
+          SMU_ISR_QUEUE_ERROR |
+          SMU_ISR_QUEUE_SUSPEND)) == 0)
+   {
+      return FALSE;
+   }
+
+   return scic_sds_controller_standard_interrupt_handler(
+             controller, interrupt_status
+          );
+}
+
+/**
+ * @brief This is the method provided to handle completions when interrupt
+ *        polling is in use.
+ *
+ * @param[in] controller
+ *
+ * @return none
+ */
+static
+void scic_sds_controller_polling_completion_handler(
+   SCI_CONTROLLER_HANDLE_T controller
+)
+{
+   SCIC_SDS_CONTROLLER_T *this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIC_LOG_OBJECT_CONTROLLER,
+      "scic_sds_controller_polling_completion_handler(0x%d) enter\n",
+      controller
+   ));
+
+   if (this_controller->encountered_fatal_error == TRUE)
+   {
+      SCIC_LOG_ERROR((
+         sci_base_object_get_logger(this_controller),
+         SCIC_LOG_OBJECT_CONTROLLER,
+         "SCIC Controller has encountered a fatal error.\n"
+      ));
+
+      sci_base_state_machine_change_state(
+         scic_sds_controller_get_base_state_machine(this_controller),
+         SCI_BASE_CONTROLLER_STATE_FAILED
+      );
+   }
+   else if (scic_sds_controller_completion_queue_has_entries(this_controller))
+   {
+      if (this_controller->restrict_completions == FALSE)
+         scic_sds_controller_process_completions(this_controller);
+      else
+         scic_sds_controller_transitioned_process_completions(this_controller);
+   }
+
+   /*
+    * The interrupt handler does not adjust the CQ's
+    * get pointer.  So, SCU's INTx pin stays asserted during the
+    * interrupt handler even though it tries to clear the interrupt
+    * source.  Therefore, the completion handler must ensure that the
+    * interrupt source is cleared.  Otherwise, we get a spurious
+    * interrupt for which the interrupt handler will not issue a
+    * corresponding completion event. Also, we unmask interrupts.
+    */
+   SMU_ISR_WRITE(
+      this_controller,
+      (U32)(SMU_ISR_COMPLETION | SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND)
+   );
+}
+
+#if !defined(DISABLE_INTERRUPTS)
+/**
+ * @brief This is the method provided to handle legacy interrupts for the
+ *        controller object.
+ *
+ * @param[in] controller
+ *
+ * @return BOOL
+ * @retval TRUE if an interrupt is processed
+ *         FALSE if no interrupt was processed
+ */
+static
+BOOL scic_sds_controller_legacy_interrupt_handler(
+   SCI_CONTROLLER_HANDLE_T controller
+)
+{
+   U32                    interrupt_status;
+   BOOL                   is_completion_needed;
+   SCIC_SDS_CONTROLLER_T *this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
+
+   interrupt_status     = SMU_ISR_READ(this_controller);
+   is_completion_needed = scic_sds_controller_standard_interrupt_handler(
+                             this_controller, interrupt_status
+                          );
+
+   return is_completion_needed;
+}
+
+
+/**
+ * @brief This is the method provided to handle legacy completions it is
+ *        expected that the SCI User will call this completion handler
+ *        anytime the interrupt handler reports that it has handled an
+ *        interrupt.
+ *
+ * @param[in] controller
+ *
+ * @return none
+ */
+static
+void scic_sds_controller_legacy_completion_handler(
+   SCI_CONTROLLER_HANDLE_T controller
+)
+{
+   SCIC_SDS_CONTROLLER_T *this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIC_LOG_OBJECT_CONTROLLER,
+      "scic_sds_controller_legacy_completion_handler(0x%d) enter\n",
+      controller
+   ));
+
+   scic_sds_controller_polling_completion_handler(controller);
+
+   SMU_IMR_WRITE(this_controller, 0x00000000);
+
+#ifdef IMR_READ_FENCE
+   {
+      volatile U32 int_mask_value = 0;
+      ULONG count = 0;
+
+      /*
+       * Temporary code since we have seen with legacy interrupts
+       * that interrupts are still masked after clearing the mask
+       * above. This may be an Arlington problem or it may be an
+       * old driver problem.  Presently this code is turned off
+       * since we have not seen this problem recently.
+       */
+      do
+      {
+         int_mask_value = SMU_IMR_READ(this_controler);
+
+         if (count++ > 10)
+         {
+            #ifdef ALLOW_ENTER_DEBUGGER
+            __debugbreak();
+            #endif
+            break;
+         }
+      } while (int_mask_value != 0);
+   }
+#endif
+}
+
+/**
+ * @brief This is the method provided to handle an MSIX interrupt message
+ *        when there is just a single MSIX message being provided by the
+ *        hardware.  This mode of operation is single vector mode.
+ *
+ * @param[in] controller
+ *
+ * @return BOOL
+ * @retval TRUE if an interrupt is processed
+ *         FALSE if no interrupt was processed
+ */
+static
+BOOL scic_sds_controller_single_vector_interrupt_handler(
+   SCI_CONTROLLER_HANDLE_T controller
+)
+{
+   U32 interrupt_status;
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+
+   // Mask the interrupts
+   // There is a race in the hardware that could cause us not to be notified
+   // of an interrupt completion if we do not take this step.  We will unmask
+   // the interrupts in the completion routine.
+   SMU_IMR_WRITE(this_controller, 0xFFFFFFFF);
+
+   interrupt_status = SMU_ISR_READ(this_controller);
+   interrupt_status &= (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND);
+
+   if (
+           (interrupt_status == 0)
+        && scic_sds_controller_completion_queue_has_entries(this_controller)
+      )
+   {
+      // There is at least one completion queue entry to process so we can
+      // return a success and ignore for now the case of an error interrupt
+      SMU_ISR_WRITE(this_controller, SMU_ISR_COMPLETION);
+
+      return TRUE;
+   }
+
+
+   if (interrupt_status != 0)
+   {
+      // There is an error interrupt pending so let it through and handle
+      // in the callback
+      return TRUE;
+   }
+
+   // Clear any offending interrupts since we could not find any to handle
+   // and unmask them all
+   SMU_ISR_WRITE(this_controller, 0x00000000);
+   SMU_IMR_WRITE(this_controller, 0x00000000);
+
+   return FALSE;
+}
+
+/**
+ * @brief This is the method provided to handle completions for a single
+ *        MSIX message.
+ *
+ * @param[in] controller
+ */
+static
+void scic_sds_controller_single_vector_completion_handler(
+   SCI_CONTROLLER_HANDLE_T controller
+)
+{
+   U32 interrupt_status;
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIC_LOG_OBJECT_CONTROLLER,
+      "scic_sds_controller_single_vector_completion_handler(0x%d) enter\n",
+      controller
+   ));
+
+   interrupt_status = SMU_ISR_READ(this_controller);
+   interrupt_status &= (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND);
+
+   if (interrupt_status & SMU_ISR_QUEUE_ERROR)
+   {
+      SCIC_LOG_ERROR((
+         sci_base_object_get_logger(this_controller),
+         SCIC_LOG_OBJECT_CONTROLLER,
+         "SCIC Controller has encountered a fatal error.\n"
+      ));
+
+      // We have a fatal condition and must reset the controller
+      // Leave the interrupt mask in place and get the controller reset
+      sci_base_state_machine_change_state(
+         scic_sds_controller_get_base_state_machine(this_controller),
+         SCI_BASE_CONTROLLER_STATE_FAILED
+      );
+      return;
+   }
+
+   if (
+           (interrupt_status & SMU_ISR_QUEUE_SUSPEND)
+        && !scic_sds_controller_completion_queue_has_entries(this_controller)
+      )
+   {
+      SCIC_LOG_ERROR((
+         sci_base_object_get_logger(this_controller),
+         SCIC_LOG_OBJECT_CONTROLLER,
+         "SCIC Controller has encountered a fatal error.\n"
+      ));
+
+      // We have a fatal condtion and must reset the controller
+      // Leave the interrupt mask in place and get the controller reset
+      sci_base_state_machine_change_state(
+         scic_sds_controller_get_base_state_machine(this_controller),
+         SCI_BASE_CONTROLLER_STATE_FAILED
+      );
+      return;
+   }
+
+   if (scic_sds_controller_completion_queue_has_entries(this_controller))
+   {
+      scic_sds_controller_process_completions(this_controller);
+
+      // We dont care which interrupt got us to processing the completion queu
+      // so clear them both.
+      SMU_ISR_WRITE(
+         this_controller,
+         (SMU_ISR_COMPLETION | SMU_ISR_QUEUE_SUSPEND)
+      );
+   }
+
+   SMU_IMR_WRITE(this_controller, 0x00000000);
+}
+
+/**
+ * @brief This is the method provided to handle a MSIX message for a normal
+ *        completion.
+ *
+ * @param[in] controller
+ *
+ * @return BOOL
+ * @retval TRUE if an interrupt is processed
+ *         FALSE if no interrupt was processed
+ */
+static
+BOOL scic_sds_controller_normal_vector_interrupt_handler(
+   SCI_CONTROLLER_HANDLE_T controller
+)
+{
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+
+   if (scic_sds_controller_completion_queue_has_entries(this_controller))
+   {
+      return TRUE;
+   }
+   else
+   {
+      // we have a spurious interrupt it could be that we have already
+      // emptied the completion queue from a previous interrupt
+      SMU_ISR_WRITE(this_controller, SMU_ISR_COMPLETION);
+
+      // There is a race in the hardware that could cause us not to be notified
+      // of an interrupt completion if we do not take this step.  We will mask
+      // then unmask the interrupts so if there is another interrupt pending
+      // the clearing of the interrupt source we get the next interrupt message.
+      SMU_IMR_WRITE(this_controller, 0xFF000000);
+      SMU_IMR_WRITE(this_controller, 0x00000000);
+   }
+
+   return FALSE;
+}
+
+/**
+ * @brief This is the method provided to handle the completions for a
+ *        normal MSIX message.
+ *
+ * @param[in] controller
+ */
+static
+void scic_sds_controller_normal_vector_completion_handler(
+   SCI_CONTROLLER_HANDLE_T controller
+)
+{
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIC_LOG_OBJECT_CONTROLLER,
+      "scic_sds_controller_normal_vector_completion_handler(0x%d) enter\n",
+      controller
+   ));
+
+   // Empty out the completion queue
+   if (scic_sds_controller_completion_queue_has_entries(this_controller))
+   {
+      scic_sds_controller_process_completions(this_controller);
+   }
+
+   // Clear the interrupt and enable all interrupts again
+   SMU_ISR_WRITE(this_controller, SMU_ISR_COMPLETION);
+   // Could we write the value of SMU_ISR_COMPLETION?
+   SMU_IMR_WRITE(this_controller, 0xFF000000);
+   SMU_IMR_WRITE(this_controller, 0x00000000);
+}
+
+/**
+ * @brief This is the method provided to handle the error MSIX message
+ *        interrupt.  This is the normal operating mode for the hardware if
+ *        MSIX is enabled.
+ *
+ * @param[in] controller
+ *
+ * @return BOOL
+ * @retval TRUE if an interrupt is processed
+ *         FALSE if no interrupt was processed
+ */
+static
+BOOL scic_sds_controller_error_vector_interrupt_handler(
+   SCI_CONTROLLER_HANDLE_T controller
+)
+{
+   U32 interrupt_status;
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+
+
+   interrupt_status = SMU_ISR_READ(this_controller);
+   interrupt_status &= (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND);
+
+   if (interrupt_status != 0)
+   {
+      // There is an error interrupt pending so let it through and handle
+      // in the callback
+      return TRUE;
+   }
+
+   // There is a race in the hardware that could cause us not to be notified
+   // of an interrupt completion if we do not take this step.  We will mask
+   // then unmask the error interrupts so if there was another interrupt
+   // pending we will be notified.
+   // Could we write the value of (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND)?
+   SMU_IMR_WRITE(this_controller, 0x000000FF);
+   SMU_IMR_WRITE(this_controller, 0x00000000);
+
+   return FALSE;
+}
+
+/**
+ * @brief This is the method provided to handle the error completions when
+ *        the hardware is using two MSIX messages.
+ *
+ * @param[in] controller
+ */
+static
+void scic_sds_controller_error_vector_completion_handler(
+   SCI_CONTROLLER_HANDLE_T controller
+)
+{
+   U32 interrupt_status;
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIC_LOG_OBJECT_CONTROLLER,
+      "scic_sds_controller_error_vector_completion_handler(0x%d) enter\n",
+      controller
+   ));
+
+   interrupt_status = SMU_ISR_READ(this_controller);
+
+   if (
+            (interrupt_status & SMU_ISR_QUEUE_SUSPEND)
+         && scic_sds_controller_completion_queue_has_entries(this_controller)
+      )
+   {
+      scic_sds_controller_process_completions(this_controller);
+
+      SMU_ISR_WRITE(this_controller, SMU_ISR_QUEUE_SUSPEND);
+   }
+   else
+   {
+      SCIC_LOG_ERROR((
+         sci_base_object_get_logger(this_controller),
+         SCIC_LOG_OBJECT_CONTROLLER,
+         "SCIC Controller reports CRC error on completion ISR %x\n",
+         interrupt_status
+      ));
+
+      sci_base_state_machine_change_state(
+         scic_sds_controller_get_base_state_machine(this_controller),
+         SCI_BASE_CONTROLLER_STATE_FAILED
+      );
+
+      return;
+   }
+
+   // If we dont process any completions I am not sure that we want to do this.
+   // We are in the middle of a hardware fault and should probably be reset.
+   SMU_IMR_WRITE(this_controller, 0x00000000);
+}
+
+#endif // !defined(DISABLE_INTERRUPTS)
+
+//****************************************************************************-
+//* SCIC SDS Controller External Methods
+//****************************************************************************-
+
+/**
+ * @brief This method returns the sizeof the SCIC SDS Controller Object
+ *
+ * @return U32
+ */
+U32 scic_sds_controller_get_object_size(void)
+{
+   return sizeof(SCIC_SDS_CONTROLLER_T);
+}
+
+/**
+ * This method returns the minimum number of timers that are required by the
+ * controller object.  This will include required timers for phys and ports.
+ *
+ * @return U32
+ * @retval The minimum number of timers that are required to make this
+ *         controller operational.
+ */
+U32 scic_sds_controller_get_min_timer_count(void)
+{
+   return   SCIC_SDS_CONTROLLER_MIN_TIMER_COUNT
+          + scic_sds_port_get_min_timer_count()
+          + scic_sds_phy_get_min_timer_count();
+}
+
+/**
+ * This method returns the maximum number of timers that are required by the
+ * controller object.  This will include required timers for phys and ports.
+ *
+ * @return U32
+ * @retval The maximum number of timers that will be used by the controller
+ *         object
+ */
+U32 scic_sds_controller_get_max_timer_count(void)
+{
+   return   SCIC_SDS_CONTROLLER_MAX_TIMER_COUNT
+          + scic_sds_port_get_max_timer_count()
+          + scic_sds_phy_get_max_timer_count();
+}
+
+/**
+ * @brief
+ *
+ * @param[in] this_controller
+ * @param[in] the_port
+ * @param[in] the_phy
+ *
+ * @return none
+ */
+void scic_sds_controller_link_up(
+   SCIC_SDS_CONTROLLER_T *this_controller,
+   SCIC_SDS_PORT_T       *the_port,
+   SCIC_SDS_PHY_T        *the_phy
+)
+{
+   if (this_controller->state_handlers->link_up_handler != NULL)
+   {
+      this_controller->state_handlers->link_up_handler(
+         this_controller, the_port, the_phy);
+   }
+   else
+   {
+      SCIC_LOG_INFO((
+         sci_base_object_get_logger(this_controller),
+         SCIC_LOG_OBJECT_CONTROLLER,
+         "SCIC Controller linkup event from phy %d in unexpected state %d\n",
+         the_phy->phy_index,
+         sci_base_state_machine_get_state(
+            scic_sds_controller_get_base_state_machine(this_controller))
+      ));
+   }
+}
+
+/**
+ * @brief
+ *
+ * @param[in] this_controller
+ * @param[in] the_port
+ * @param[in] the_phy
+ */
+void scic_sds_controller_link_down(
+   SCIC_SDS_CONTROLLER_T *this_controller,
+   SCIC_SDS_PORT_T       *the_port,
+   SCIC_SDS_PHY_T        *the_phy
+)
+{
+   if (this_controller->state_handlers->link_down_handler != NULL)
+   {
+      this_controller->state_handlers->link_down_handler(
+         this_controller, the_port, the_phy);
+   }
+   else
+   {
+      SCIC_LOG_INFO((
+         sci_base_object_get_logger(this_controller),
+         SCIC_LOG_OBJECT_CONTROLLER,
+         "SCIC Controller linkdown event from phy %d in unexpected state %d\n",
+         the_phy->phy_index,
+         sci_base_state_machine_get_state(
+            scic_sds_controller_get_base_state_machine(this_controller))
+      ));
+   }
+}
+
+/**
+ * @brief This method is called by the remote device to inform the controller
+ *        that this remote device has started.
+ *
+ * @param[in] this_controller
+ * @param[in] the_device
+ */
+void scic_sds_controller_remote_device_started(
+   SCIC_SDS_CONTROLLER_T    * this_controller,
+   SCIC_SDS_REMOTE_DEVICE_T * the_device
+)
+{
+   if (this_controller->state_handlers->remote_device_started_handler != NULL)
+   {
+      this_controller->state_handlers->remote_device_started_handler(
+         this_controller, the_device
+      );
+   }
+   else
+   {
+      SCIC_LOG_INFO((
+         sci_base_object_get_logger(this_controller),
+         SCIC_LOG_OBJECT_CONTROLLER,
+         "SCIC Controller 0x%x remote device started event from device 0x%x in unexpected state %d\n",
+         this_controller,
+         the_device,
+         sci_base_state_machine_get_state(
+            scic_sds_controller_get_base_state_machine(this_controller))
+      ));
+   }
+}
+
+/**
+ * @brief This is a helper method to determine if any remote devices on this
+ *        controller are still in the stopping state.
+ *
+ * @param[in] this_controller
+ */
+BOOL scic_sds_controller_has_remote_devices_stopping(
+   SCIC_SDS_CONTROLLER_T * this_controller
+)
+{
+   U32 index;
+
+   for (index = 0; index < this_controller->remote_node_entries; index++)
+   {
+      if (
+            (this_controller->device_table[index] != NULL)
+         && (
+               this_controller->device_table[index]->parent.state_machine.current_state_id
+            == SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
+            )
+         )
+      {
+         return TRUE;
+      }
+   }
+
+   return FALSE;
+}
+
+/**
+ * @brief This method is called by the remote device to inform the controller
+ *        object that the remote device has stopped.
+ *
+ * @param[in] this_controller
+ * @param[in] the_device
+ */
+void scic_sds_controller_remote_device_stopped(
+   SCIC_SDS_CONTROLLER_T    * this_controller,
+   SCIC_SDS_REMOTE_DEVICE_T * the_device
+)
+{
+   if (this_controller->state_handlers->remote_device_stopped_handler != NULL)
+   {
+      this_controller->state_handlers->remote_device_stopped_handler(
+         this_controller, the_device
+      );
+   }
+   else
+   {
+      SCIC_LOG_INFO((
+         sci_base_object_get_logger(this_controller),
+         SCIC_LOG_OBJECT_CONTROLLER,
+         "SCIC Controller 0x%x remote device stopped event from device 0x%x in unexpected state %d\n",
+         this_controller,
+         the_device,
+         sci_base_state_machine_get_state(
+            scic_sds_controller_get_base_state_machine(this_controller))
+      ));
+   }
+}
+
+/**
+ * @brief This method will write to the SCU PCP register the request value.
+ *        The method is used to suspend/resume ports, devices, and phys.
+ *
+ * @param[in] this_controller
+ * @param[in] request
+ */
+void scic_sds_controller_post_request(
+   SCIC_SDS_CONTROLLER_T *this_controller,
+   U32                    request
+)
+{
+   SCIC_LOG_INFO((
+      sci_base_object_get_logger(this_controller),
+      SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_COMPLETION_QUEUE,
+      "SCIC Controller 0x%08x post request 0x%08x\n",
+      this_controller, request
+   ));
+
+   SMU_PCP_WRITE(this_controller, request);
+}
+
+/**
+ * @brief This method will copy the soft copy of the task context into
+ *        the physical memory accessible by the controller.
+ *
+ * @note After this call is made the SCIC_SDS_IO_REQUEST object will
+ *       always point to the physical memory version of the task context.
+ *       Thus, all subsequent updates to the task context are performed in
+ *       the TC table (i.e. DMAable memory).
+ *
+ * @param[in]  this_controller This parameter specifies the controller for
+ *             which to copy the task context.
+ * @param[in]  this_request This parameter specifies the request for which
+ *             the task context is being copied.
+ *
+ * @return none
+ */
+void scic_sds_controller_copy_task_context(
+   SCIC_SDS_CONTROLLER_T *this_controller,
+   SCIC_SDS_REQUEST_T    *this_request
+)
+{
+   SCU_TASK_CONTEXT_T *task_context_buffer;
+
+   task_context_buffer = scic_sds_controller_get_task_context_buffer(
+                            this_controller, this_request->io_tag
+                         );
+
+   memcpy(
+      task_context_buffer,
+      this_request->task_context_buffer,
+      SCI_FIELD_OFFSET(SCU_TASK_CONTEXT_T, sgl_snapshot_ac)
+   );
+
+   // Now that the soft copy of the TC has been copied into the TC
+   // table accessible by the silicon.  Thus, any further changes to
+   // the TC (e.g. TC termination) occur in the appropriate location.
+   this_request->task_context_buffer = task_context_buffer;
+}
+
+/**
+ * @brief This method returns the task context buffer for the given io tag.
+ *
+ * @param[in] this_controller
+ * @param[in] io_tag
+ *
+ * @return struct SCU_TASK_CONTEXT*
+ */
+SCU_TASK_CONTEXT_T * scic_sds_controller_get_task_context_buffer(
+   SCIC_SDS_CONTROLLER_T * this_controller,
+   U16                     io_tag
+)
+{
+   U16 task_index = scic_sds_io_tag_get_index(io_tag);
+
+   if (task_index < this_controller->task_context_entries)
+   {
+      return &this_controller->task_context_table[task_index];
+   }
+
+   return NULL;
+}
+
+/**
+ * @brief This method returnst the sequence value from the io tag value
+ *
+ * @param[in] this_controller
+ * @param[in] io_tag
+ *
+ * @return U16
+ */
+U16 scic_sds_controller_get_io_sequence_from_tag(
+   SCIC_SDS_CONTROLLER_T *this_controller,
+   U16                    io_tag
+)
+{
+   return scic_sds_io_tag_get_sequence(io_tag);
+}
+
+/**
+ * @brief This method returns the IO request associated with the tag value
+ *
+ * @param[in] this_controller
+ * @param[in] io_tag
+ *
+ * @return SCIC_SDS_IO_REQUEST_T*
+ * @retval NULL if there is no valid IO request at the tag value
+ */
+SCIC_SDS_REQUEST_T *scic_sds_controller_get_io_request_from_tag(
+   SCIC_SDS_CONTROLLER_T *this_controller,
+   U16                    io_tag
+)
+{
+   U16 task_index;
+   U16 task_sequence;
+
+   task_index = scic_sds_io_tag_get_index(io_tag);
+
+   if (task_index  < this_controller->task_context_entries)
+   {
+      if (this_controller->io_request_table[task_index] != SCI_INVALID_HANDLE)
+      {
+         task_sequence = scic_sds_io_tag_get_sequence(io_tag);
+
+         if (task_sequence == this_controller->io_request_sequence[task_index])
+         {
+            return this_controller->io_request_table[task_index];
+         }
+      }
+   }
+
+   return SCI_INVALID_HANDLE;
+}
+
+/**
+ * @brief This method allocates remote node index and the reserves the
+ *        remote node context space for use. This method can fail if there
+ *        are no more remote node index available.
+ *
+ * @param[in] this_controller This is the controller object which contains
+ *            the set of free remote node ids
+ * @param[in] the_devce This is the device object which is requesting the a
+ *            remote node id
+ * @param[out] node_id This is the remote node id that is assinged to the
+ *             device if one is available
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_OUT_OF_RESOURCES if there are no available remote
+ *         node index available.
+ */
+SCI_STATUS scic_sds_controller_allocate_remote_node_context(
+   SCIC_SDS_CONTROLLER_T    * this_controller,
+   SCIC_SDS_REMOTE_DEVICE_T * the_device,
+   U16                      * node_id
+)
+{
+   U16 node_index;
+   U32 remote_node_count = scic_sds_remote_device_node_count(the_device);
+
+   node_index = scic_sds_remote_node_table_allocate_remote_node(
+                  &this_controller->available_remote_nodes, remote_node_count
+              );
+
+   if (node_index != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX)
+   {
+      this_controller->device_table[node_index] = the_device;
+
+      *node_id = node_index;
+
+      return SCI_SUCCESS;
+   }
+
+   return SCI_FAILURE_INSUFFICIENT_RESOURCES;
+}
+
+/**
+ * @brief This method frees the remote node index back to the available
+ *        pool.  Once this is done the remote node context buffer is no
+ *        longer valid and can not be used.
+ *
+ * @param[in] this_controller
+ * @param[in] the_device
+ * @param[in] node_id
+ *
+ * @return none
+ */
+void scic_sds_controller_free_remote_node_context(
+   SCIC_SDS_CONTROLLER_T    * this_controller,
+   SCIC_SDS_REMOTE_DEVICE_T * the_device,
+   U16                        node_id
+)
+{
+   U32 remote_node_count = scic_sds_remote_device_node_count(the_device);
+
+   if (this_controller->device_table[node_id] == the_device)
+   {
+      this_controller->device_table[node_id] = SCI_INVALID_HANDLE;
+
+      scic_sds_remote_node_table_release_remote_node_index(
+         &this_controller->available_remote_nodes, remote_node_count, node_id
+      );
+   }
+}
+
+/**
+ * @brief This method returns the SCU_REMOTE_NODE_CONTEXT for the specified
+ *        remote node id.
+ *
+ * @param[in] this_controller
+ * @param[in] node_id
+ *
+ * @return SCU_REMOTE_NODE_CONTEXT_T*
+ */
+SCU_REMOTE_NODE_CONTEXT_T *scic_sds_controller_get_remote_node_context_buffer(
+   SCIC_SDS_CONTROLLER_T *this_controller,
+   U16                    node_id
+)
+{
+   if (
+           (node_id < this_controller->remote_node_entries)
+        && (this_controller->device_table[node_id] != SCI_INVALID_HANDLE)
+      )
+   {
+      return &this_controller->remote_node_context_table[node_id];
+   }
+
+   return NULL;
+}
+
+/**
+ * This method will combind the frame header and frame buffer to create
+ * a SATA D2H register FIS
+ *
+ * @param[out] resposne_buffer This is the buffer into which the D2H register
+ *             FIS will be constructed.
+ * @param[in]  frame_header This is the frame header returned by the hardware.
+ * @param[in]  frame_buffer This is the frame buffer returned by the hardware.
+ *
+ * @erturn none
+ */
+void scic_sds_controller_copy_sata_response(
+   void * response_buffer,
+   void * frame_header,
+   void * frame_buffer
+)
+{
+   memcpy(
+      response_buffer,
+      frame_header,
+      sizeof(U32)
+   );
+
+   memcpy(
+      (char *)((char *)response_buffer + sizeof(U32)),
+      frame_buffer,
+      sizeof(SATA_FIS_REG_D2H_T) - sizeof(U32)
+   );
+}
+
+/**
+ * @brief This method releases the frame once this is done the frame is
+ *        available for re-use by the hardware.  The data contained in the
+ *        frame header and frame buffer is no longer valid.
+ *        The UF queue get pointer is only updated if UF control indicates
+ *        this is appropriate.
+ *
+ * @param[in] this_controller
+ * @param[in] frame_index
+ *
+ * @return none
+ */
+void scic_sds_controller_release_frame(
+   SCIC_SDS_CONTROLLER_T *this_controller,
+   U32                    frame_index
+)
+{
+   if (scic_sds_unsolicited_frame_control_release_frame(
+          &this_controller->uf_control, frame_index) == TRUE)
+      SCU_UFQGP_WRITE(this_controller, this_controller->uf_control.get);
+}
+
+#ifdef SCI_LOGGING
+void scic_sds_controller_initialize_state_logging(
+   SCIC_SDS_CONTROLLER_T *this_controller
+)
+{
+   sci_base_state_machine_logger_initialize(
+      &this_controller->parent.state_machine_logger,
+      &this_controller->parent.state_machine,
+      &this_controller->parent.parent,
+      scic_cb_logger_log_states,
+      "SCIC_SDS_CONTROLLER_T", "base state machine",
+      SCIC_LOG_OBJECT_CONTROLLER
+   );
+}
+
+void scic_sds_controller_deinitialize_state_logging(
+   SCIC_SDS_CONTROLLER_T *this_controller
+)
+{
+   sci_base_state_machine_logger_deinitialize(
+      &this_controller->parent.state_machine_logger,
+      &this_controller->parent.state_machine
+   );
+}
+#endif
+
+/**
+ * @brief This method sets user parameters and OEM parameters to
+ *        default values.  Users can override these values utilizing
+ *        the scic_user_parameters_set() and scic_oem_parameters_set()
+ *        methods.
+ *
+ * @param[in] controller This parameter specifies the controller for
+ *            which to set the configuration parameters to their
+ *            default values.
+ *
+ * @return none
+ */
+static
+void scic_sds_controller_set_default_config_parameters(
+   SCIC_SDS_CONTROLLER_T *this_controller
+)
+{
+   U16 index;
+
+   // Default to APC mode.
+   this_controller->oem_parameters.sds1.controller.mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE;
+
+   // Default to 1
+   this_controller->oem_parameters.sds1.controller.max_number_concurrent_device_spin_up = 1;
+
+   // Default to no SSC operation.
+   this_controller->oem_parameters.sds1.controller.ssc_sata_tx_spread_level = 0;
+   this_controller->oem_parameters.sds1.controller.ssc_sas_tx_spread_level  = 0;
+   this_controller->oem_parameters.sds1.controller.ssc_sas_tx_type          = 0;
+
+   // Default to all phys to using short cables
+   this_controller->oem_parameters.sds1.controller.cable_selection_mask = 0;
+
+   // Initialize all of the port parameter information to narrow ports.
+   for (index = 0; index < SCI_MAX_PORTS; index++)
+   {
+      this_controller->oem_parameters.sds1.ports[index].phy_mask = 0;
+   }
+
+   // Initialize all of the phy parameter information.
+   for (index = 0; index < SCI_MAX_PHYS; index++)
+   {
+      // Default to 6G (i.e. Gen 3) for now.  User can override if
+      // they choose.
+      this_controller->user_parameters.sds1.phys[index].max_speed_generation = 2;
+
+      //the frequencies cannot be 0
+      this_controller->user_parameters.sds1.phys[index].align_insertion_frequency = 0x7f;
+      this_controller->user_parameters.sds1.phys[index].in_connection_align_insertion_frequency = 0xff;
+      this_controller->user_parameters.sds1.phys[index].notify_enable_spin_up_insertion_frequency = 0x33;
+
+      // Previous Vitesse based expanders had a arbitration issue that
+      // is worked around by having the upper 32-bits of SAS address
+      // with a value greater then the Vitesse company identifier.
+      // Hence, usage of 0x5FCFFFFF.
+      this_controller->oem_parameters.sds1.phys[index].sas_address.sci_format.high
+         = 0x5FCFFFFF;
+
+      // Add in controller index to ensure each controller will have unique SAS addresses by default.
+      this_controller->oem_parameters.sds1.phys[index].sas_address.sci_format.low
+         = 0x00000001 + this_controller->controller_index;
+
+      if (  (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A0)
+         || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_A2)
+         || (this_controller->pci_revision == SCIC_SDS_PCI_REVISION_B0) )
+      {
+         this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control0 = 0x000E7C03;
+         this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control1 = 0x000E7C03;
+         this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control2 = 0x000E7C03;
+         this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control3 = 0x000E7C03;
+      }
+      else // This must be SCIC_SDS_PCI_REVISION_C0
+      {
+         this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control0 = 0x000BDD08;
+         this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control1 = 0x000B7069;
+         this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control2 = 0x000B7C09;
+         this_controller->oem_parameters.sds1.phys[index].afe_tx_amp_control3 = 0x000AFC6E;
+      }
+   }
+
+   this_controller->user_parameters.sds1.stp_inactivity_timeout = 5;
+   this_controller->user_parameters.sds1.ssp_inactivity_timeout = 5;
+   this_controller->user_parameters.sds1.stp_max_occupancy_timeout = 5;
+   this_controller->user_parameters.sds1.ssp_max_occupancy_timeout = 20;
+   this_controller->user_parameters.sds1.no_outbound_task_timeout = 20;
+
+}
+
+
+/**
+ * @brief This method release resources in SCI controller.
+ *
+ * @param[in] this_controller This parameter specifies the core
+ *            controller and associated objects whose resources are to be
+ *            released.
+ *
+ * @return This method returns a value indicating if the operation succeeded.
+ * @retval SCI_SUCCESS This value indicates that all the timers are destroyed.
+ * @retval SCI_FAILURE This value indicates certain failure during the process
+ *            of cleaning timer resource.
+ */
+static
+SCI_STATUS scic_sds_controller_release_resource(
+   SCIC_SDS_CONTROLLER_T * this_controller
+)
+{
+   SCIC_SDS_PORT_T * port;
+   SCIC_SDS_PHY_T * phy;
+   U8 index;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_controller),
+      SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_INITIALIZATION,
+      "scic_sds_controller_release_resource(0x%x) enter\n",
+      this_controller
+   ));
+
+   if(this_controller->phy_startup_timer != NULL)
+   {
+      scic_cb_timer_destroy(this_controller, this_controller->phy_startup_timer);
+      this_controller->phy_startup_timer = NULL;
+   }
+
+   if(this_controller->power_control.timer != NULL)
+   {
+      scic_cb_timer_destroy(this_controller, this_controller->power_control.timer);
+      this_controller->power_control.timer = NULL;
+   }
+
+   if(this_controller->timeout_timer != NULL)
+   {
+      scic_cb_timer_destroy(this_controller, this_controller->timeout_timer);
+      this_controller->timeout_timer = NULL;
+   }
+
+   scic_sds_port_configuration_agent_release_resource(
+      this_controller,
+      &this_controller->port_agent);
+
+   for(index = 0; index < SCI_MAX_PORTS+1; index++)
+   {
+      port = &this_controller->port_table[index];
+      scic_sds_port_release_resource(this_controller, port);
+   }
+
+   for(index = 0; index < SCI_MAX_PHYS; index++)
+   {
+      phy = &this_controller->phy_table[index];
+      scic_sds_phy_release_resource(this_controller, phy);
+   }
+
+   return SCI_SUCCESS;
+}
+
+
+/**
+ * @brief This method process the ports configured message from port configuration
+ *           agent.
+ *
+ * @param[in] this_controller This parameter specifies the core
+ *            controller that its ports are configured.
+ *
+ * @return None.
+ */
+void scic_sds_controller_port_agent_configured_ports(
+   SCIC_SDS_CONTROLLER_T * this_controller
+)
+{
+   //simply transit to ready. The function below checks the controller state
+   scic_sds_controller_transition_to_ready(
+      this_controller, SCI_SUCCESS
+   );
+}
+
+
+//****************************************************************************-
+//* SCIC Controller Public Methods
+//****************************************************************************-
+
+SCI_STATUS scic_controller_construct(
+   SCI_LIBRARY_HANDLE_T    library,
+   SCI_CONTROLLER_HANDLE_T controller,
+   void *                  user_object
+)
+{
+   SCIC_SDS_LIBRARY_T    *my_library;
+   SCIC_SDS_CONTROLLER_T *this_controller;
+
+   my_library = (SCIC_SDS_LIBRARY_T *)library;
+   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(library),
+      SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_INITIALIZATION,
+      "scic_controller_construct(0x%x, 0x%x) enter\n",
+      library, controller
+   ));
+
+   // Just clear out the memory of the structure to be safe.
+   memset(this_controller, 0, sizeof(SCIC_SDS_CONTROLLER_T));
+
+   // Make sure that the static data is assigned before moving onto the
+   // base constroller construct as this will cause the controller to
+   // enter its initial state and the controller_index and pci_revision
+   // will be required to complete those operations correctly
+   this_controller->controller_index =
+      scic_sds_library_get_controller_index(my_library, this_controller);
+
+   this_controller->pci_revision = my_library->pci_revision;
+
+   sci_base_controller_construct(
+      &this_controller->parent,
+      sci_base_object_get_logger(my_library),
+      scic_sds_controller_state_table,
+      this_controller->memory_descriptors,
+      ARRAY_SIZE(this_controller->memory_descriptors),
+      NULL
+   );
+
+   sci_object_set_association(controller, user_object);
+
+   scic_sds_controller_initialize_state_logging(this_controller);
+
+   scic_sds_pci_bar_initialization(this_controller);
+
+   return SCI_SUCCESS;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_controller_initialize(
+   SCI_CONTROLLER_HANDLE_T   controller
+)
+{
+   SCI_STATUS status = SCI_FAILURE_INVALID_STATE;
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIC_LOG_OBJECT_CONTROLLER,
+      "scic_controller_initialize(0x%x, 0x%d) enter\n",
+      controller
+   ));
+
+   if (this_controller->state_handlers->parent.initialize_handler != NULL)
+   {
+      status = this_controller->state_handlers->parent.initialize_handler(
+                  (SCI_BASE_CONTROLLER_T *)controller
+               );
+   }
+   else
+   {
+      SCIC_LOG_WARNING((
+         sci_base_object_get_logger(this_controller),
+         SCIC_LOG_OBJECT_CONTROLLER,
+         "SCIC Controller initialize operation requested in invalid state %d\n",
+         sci_base_state_machine_get_state(
+            scic_sds_controller_get_base_state_machine(this_controller))
+      ));
+   }
+
+   return status;
+}
+
+// ---------------------------------------------------------------------------
+
+U32 scic_controller_get_suggested_start_timeout(
+   SCI_CONTROLLER_HANDLE_T  controller
+)
+{
+   // Validate the user supplied parameters.
+   if (controller == SCI_INVALID_HANDLE)
+      return 0;
+
+   // The suggested minimum timeout value for a controller start operation:
+   //
+   //     Signature FIS Timeout
+   //   + Phy Start Timeout
+   //   + Number of Phy Spin Up Intervals
+   //   ---------------------------------
+   //   Number of milliseconds for the controller start operation.
+   //
+   // NOTE: The number of phy spin up intervals will be equivalent
+   //       to the number of phys divided by the number phys allowed
+   //       per interval - 1 (once OEM parameters are supported).
+   //       Currently we assume only 1 phy per interval.
+
+   return (SCIC_SDS_SIGNATURE_FIS_TIMEOUT
+           + SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT
+           + ((SCI_MAX_PHYS-1) * SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL));
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_controller_start(
+   SCI_CONTROLLER_HANDLE_T controller,
+   U32 timeout
+)
+{
+   SCI_STATUS status = SCI_FAILURE_INVALID_STATE;
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIC_LOG_OBJECT_CONTROLLER,
+      "scic_controller_start(0x%x, 0x%d) enter\n",
+      controller, timeout
+   ));
+
+   if (this_controller->state_handlers->parent.start_handler != NULL)
+   {
+      status = this_controller->state_handlers->parent.start_handler(
+                  (SCI_BASE_CONTROLLER_T *)controller, timeout
+               );
+   }
+   else
+   {
+      SCIC_LOG_WARNING((
+         sci_base_object_get_logger(this_controller),
+         SCIC_LOG_OBJECT_CONTROLLER,
+         "SCIC Controller start operation requested in invalid state %d\n",
+         sci_base_state_machine_get_state(
+            scic_sds_controller_get_base_state_machine(this_controller))
+      ));
+   }
+
+   return status;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_controller_stop(
+   SCI_CONTROLLER_HANDLE_T controller,
+   U32 timeout
+)
+{
+   SCI_STATUS status = SCI_FAILURE_INVALID_STATE;
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIC_LOG_OBJECT_CONTROLLER,
+      "scic_controller_stop(0x%x, 0x%d) enter\n",
+      controller, timeout
+   ));
+
+   if (this_controller->state_handlers->parent.stop_handler != NULL)
+   {
+      status = this_controller->state_handlers->parent.stop_handler(
+                  (SCI_BASE_CONTROLLER_T *)controller, timeout
+               );
+   }
+   else
+   {
+      SCIC_LOG_WARNING((
+         sci_base_object_get_logger(this_controller),
+         SCIC_LOG_OBJECT_CONTROLLER,
+         "SCIC Controller stop operation requested in invalid state %d\n",
+         sci_base_state_machine_get_state(
+            scic_sds_controller_get_base_state_machine(this_controller))
+      ));
+   }
+
+   return status;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_controller_reset(
+   SCI_CONTROLLER_HANDLE_T controller
+)
+{
+   SCI_STATUS status = SCI_FAILURE_INVALID_STATE;
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIC_LOG_OBJECT_CONTROLLER,
+      "scic_controller_reset(0x%x) enter\n",
+      controller
+   ));
+
+   if (this_controller->state_handlers->parent.reset_handler != NULL)
+   {
+      status = this_controller->state_handlers->parent.reset_handler(
+                  (SCI_BASE_CONTROLLER_T *)controller
+               );
+   }
+   else
+   {
+      SCIC_LOG_WARNING((
+         sci_base_object_get_logger(this_controller),
+         SCIC_LOG_OBJECT_CONTROLLER,
+         "SCIC Controller reset operation requested in invalid state %d\n",
+         sci_base_state_machine_get_state(
+            scic_sds_controller_get_base_state_machine(this_controller))
+      ));
+   }
+
+   return status;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_controller_get_handler_methods(
+   SCIC_INTERRUPT_TYPE                interrupt_type,
+   U16                                message_count,
+   SCIC_CONTROLLER_HANDLER_METHODS_T *handler_methods
+)
+{
+   SCI_STATUS status = SCI_FAILURE_UNSUPPORTED_MESSAGE_COUNT;
+
+   switch (interrupt_type)
+   {
+#if !defined(DISABLE_INTERRUPTS)
+   case SCIC_LEGACY_LINE_INTERRUPT_TYPE:
+      if (message_count == 0)
+      {
+         handler_methods[0].interrupt_handler
+            = scic_sds_controller_legacy_interrupt_handler;
+         handler_methods[0].completion_handler
+            = scic_sds_controller_legacy_completion_handler;
+
+         status = SCI_SUCCESS;
+      }
+      break;
+
+   case SCIC_MSIX_INTERRUPT_TYPE:
+      if (message_count == 1)
+      {
+         handler_methods[0].interrupt_handler
+            = scic_sds_controller_single_vector_interrupt_handler;
+         handler_methods[0].completion_handler
+            = scic_sds_controller_single_vector_completion_handler;
+
+         status = SCI_SUCCESS;
+      }
+      else if (message_count == 2)
+      {
+         handler_methods[0].interrupt_handler
+            = scic_sds_controller_normal_vector_interrupt_handler;
+         handler_methods[0].completion_handler
+            = scic_sds_controller_normal_vector_completion_handler;
+
+         handler_methods[1].interrupt_handler
+            = scic_sds_controller_error_vector_interrupt_handler;
+         handler_methods[1].completion_handler
+            = scic_sds_controller_error_vector_completion_handler;
+
+         status = SCI_SUCCESS;
+      }
+      break;
+#endif // !defined(DISABLE_INTERRUPTS)
+
+   case SCIC_NO_INTERRUPTS:
+      if (message_count == 0)
+      {
+
+         handler_methods[0].interrupt_handler
+            = scic_sds_controller_polling_interrupt_handler;
+         handler_methods[0].completion_handler
+            = scic_sds_controller_polling_completion_handler;
+
+         status = SCI_SUCCESS;
+      }
+      break;
+
+   default:
+      status = SCI_FAILURE_INVALID_PARAMETER_VALUE;
+      break;
+   }
+
+   return status;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_IO_STATUS scic_controller_start_io(
+   SCI_CONTROLLER_HANDLE_T    controller,
+   SCI_REMOTE_DEVICE_HANDLE_T remote_device,
+   SCI_IO_REQUEST_HANDLE_T    io_request,
+   U16                        io_tag
+)
+{
+   SCI_STATUS          status;
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIC_LOG_OBJECT_CONTROLLER,
+      "scic_controller_start_io(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
+      controller, remote_device, io_request, io_tag
+   ));
+
+   status = this_controller->state_handlers->parent.start_io_handler(
+               &this_controller->parent,
+               (SCI_BASE_REMOTE_DEVICE_T *)remote_device,
+               (SCI_BASE_REQUEST_T *)io_request,
+               io_tag
+            );
+
+   return (SCI_IO_STATUS)status;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_controller_terminate_request(
+   SCI_CONTROLLER_HANDLE_T    controller,
+   SCI_REMOTE_DEVICE_HANDLE_T remote_device,
+   SCI_IO_REQUEST_HANDLE_T    request
+)
+{
+   SCI_STATUS status;
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIC_LOG_OBJECT_CONTROLLER,
+      "scic_controller_terminate_request(0x%x, 0x%x, 0x%x) enter\n",
+      controller, remote_device, request
+   ));
+
+   status = this_controller->state_handlers->terminate_request_handler(
+      &this_controller->parent,
+      (SCI_BASE_REMOTE_DEVICE_T *)remote_device,
+      (SCI_BASE_REQUEST_T *)request
+   );
+
+   return status;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_controller_complete_io(
+   SCI_CONTROLLER_HANDLE_T controller,
+   SCI_REMOTE_DEVICE_HANDLE_T remote_device,
+   SCI_IO_REQUEST_HANDLE_T io_request
+)
+{
+   SCI_STATUS status;
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIC_LOG_OBJECT_CONTROLLER,
+      "scic_controller_complete_io(0x%x, 0x%x, 0x%x) enter\n",
+      controller, remote_device, io_request
+   ));
+
+   status = this_controller->state_handlers->parent.complete_io_handler(
+      &this_controller->parent,
+      (SCI_BASE_REMOTE_DEVICE_T *)remote_device,
+      (SCI_BASE_REQUEST_T *)io_request
+   );
+
+   return status;
+}
+
+// ---------------------------------------------------------------------------
+
+#if !defined(DISABLE_TASK_MANAGEMENT)
+
+SCI_TASK_STATUS scic_controller_start_task(
+   SCI_CONTROLLER_HANDLE_T    controller,
+   SCI_REMOTE_DEVICE_HANDLE_T remote_device,
+   SCI_TASK_REQUEST_HANDLE_T  task_request,
+   U16                        task_tag
+)
+{
+   SCI_STATUS             status = SCI_FAILURE_INVALID_STATE;
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIC_LOG_OBJECT_CONTROLLER,
+      "scic_controller_start_task(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
+      controller, remote_device, task_request, task_tag
+   ));
+
+   if (this_controller->state_handlers->parent.start_task_handler != NULL)
+   {
+      status = this_controller->state_handlers->parent.start_task_handler(
+                  &this_controller->parent,
+                  (SCI_BASE_REMOTE_DEVICE_T *)remote_device,
+                  (SCI_BASE_REQUEST_T *)task_request,
+                  task_tag
+               );
+   }
+   else
+   {
+      SCIC_LOG_INFO((
+         sci_base_object_get_logger(controller),
+         SCIC_LOG_OBJECT_CONTROLLER,
+         "SCIC Controller starting task from invalid state\n"
+      ));
+   }
+
+   return (SCI_TASK_STATUS)status;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_controller_complete_task(
+   SCI_CONTROLLER_HANDLE_T    controller,
+   SCI_REMOTE_DEVICE_HANDLE_T remote_device,
+   SCI_TASK_REQUEST_HANDLE_T  task_request
+)
+{
+   SCI_STATUS status = SCI_FAILURE_INVALID_STATE;
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIC_LOG_OBJECT_CONTROLLER,
+      "scic_controller_complete_task(0x%x, 0x%x, 0x%x) enter\n",
+      controller, remote_device, task_request
+   ));
+
+   if (this_controller->state_handlers->parent.complete_task_handler != NULL)
+   {
+      status = this_controller->state_handlers->parent.complete_task_handler(
+                  &this_controller->parent,
+                  (SCI_BASE_REMOTE_DEVICE_T *)remote_device,
+                  (SCI_BASE_REQUEST_T *)task_request
+               );
+   }
+   else
+   {
+      SCIC_LOG_INFO((
+         sci_base_object_get_logger(controller),
+         SCIC_LOG_OBJECT_CONTROLLER,
+         "SCIC Controller completing task from invalid state\n"
+      ));
+   }
+
+   return status;
+}
+
+#endif // !defined(DISABLE_TASK_MANAGEMENT)
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_controller_get_port_handle(
+   SCI_CONTROLLER_HANDLE_T controller,
+   U8                      port_index,
+   SCI_PORT_HANDLE_T *     port_handle
+)
+{
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIC_LOG_OBJECT_CONTROLLER,
+      "scic_controller_get_port_handle(0x%x, 0x%x, 0x%x) enter\n",
+      controller, port_index, port_handle
+   ));
+
+   if (port_index < this_controller->logical_port_entries)
+   {
+      *port_handle = &this_controller->port_table[port_index];
+
+      return SCI_SUCCESS;
+   }
+
+   return SCI_FAILURE_INVALID_PORT;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_controller_get_phy_handle(
+   SCI_CONTROLLER_HANDLE_T controller,
+   U8                      phy_index,
+   SCI_PHY_HANDLE_T *      phy_handle
+)
+{
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIC_LOG_OBJECT_CONTROLLER,
+      "scic_controller_get_phy_handle(0x%x, 0x%x, 0x%x) enter\n",
+      controller, phy_index, phy_handle
+   ));
+
+   if (phy_index < ARRAY_SIZE(this_controller->phy_table))
+   {
+      *phy_handle = &this_controller->phy_table[phy_index];
+
+      return SCI_SUCCESS;
+   }
+
+   SCIC_LOG_ERROR((
+      sci_base_object_get_logger(this_controller),
+      SCIC_LOG_OBJECT_PORT | SCIC_LOG_OBJECT_CONTROLLER,
+      "Controller:0x%x PhyId:0x%x invalid phy index\n",
+      this_controller, phy_index
+   ));
+
+   return SCI_FAILURE_INVALID_PHY;
+}
+
+// ---------------------------------------------------------------------------
+
+U16 scic_controller_allocate_io_tag(
+   SCI_CONTROLLER_HANDLE_T controller
+)
+{
+   U16 task_context;
+   U16 sequence_count;
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIC_LOG_OBJECT_CONTROLLER,
+      "scic_controller_allocate_io_tag(0x%x) enter\n",
+      controller
+   ));
+
+   if (!sci_pool_empty(this_controller->tci_pool))
+   {
+      sci_pool_get(this_controller->tci_pool, task_context);
+
+      sequence_count = this_controller->io_request_sequence[task_context];
+
+      return scic_sds_io_tag_construct(sequence_count, task_context);
+   }
+
+   return SCI_CONTROLLER_INVALID_IO_TAG;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_controller_free_io_tag(
+   SCI_CONTROLLER_HANDLE_T controller,
+   U16                     io_tag
+)
+{
+   U16 sequence;
+   U16 index;
+
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+
+   ASSERT(io_tag != SCI_CONTROLLER_INVALID_IO_TAG);
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIC_LOG_OBJECT_CONTROLLER,
+      "scic_controller_free_io_tag(0x%x, 0x%x) enter\n",
+      controller, io_tag
+   ));
+
+   sequence = scic_sds_io_tag_get_sequence(io_tag);
+   index    = scic_sds_io_tag_get_index(io_tag);
+
+   if (!sci_pool_full(this_controller->tci_pool))
+   {
+      if (sequence == this_controller->io_request_sequence[index])
+      {
+         scic_sds_io_sequence_increment(
+            this_controller->io_request_sequence[index]);
+
+         sci_pool_put(this_controller->tci_pool, index);
+
+         return SCI_SUCCESS;
+      }
+   }
+
+   return SCI_FAILURE_INVALID_IO_TAG;
+}
+
+// ---------------------------------------------------------------------------
+
+void scic_controller_enable_interrupts(
+   SCI_CONTROLLER_HANDLE_T controller
+)
+{
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+
+   ASSERT(this_controller->smu_registers != NULL);
+
+   SMU_IMR_WRITE(this_controller, 0x00000000);
+}
+
+// ---------------------------------------------------------------------------
+
+void scic_controller_disable_interrupts(
+   SCI_CONTROLLER_HANDLE_T controller
+)
+{
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+
+   ASSERT(this_controller->smu_registers != NULL);
+
+   SMU_IMR_WRITE(this_controller, 0xffffffff);
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_controller_set_mode(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   SCI_CONTROLLER_MODE       operating_mode
+)
+{
+   SCIC_SDS_CONTROLLER_T *this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
+   SCI_STATUS             status          = SCI_SUCCESS;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIC_LOG_OBJECT_CONTROLLER,
+      "scic_controller_set_mode(0x%x, 0x%x) enter\n",
+      controller, operating_mode
+   ));
+
+   if (
+         (this_controller->parent.state_machine.current_state_id
+          == SCI_BASE_CONTROLLER_STATE_INITIALIZING)
+      || (this_controller->parent.state_machine.current_state_id
+          == SCI_BASE_CONTROLLER_STATE_INITIALIZED)
+      )
+   {
+      switch (operating_mode)
+      {
+      case SCI_MODE_SPEED:
+         this_controller->remote_node_entries =
+            MIN(this_controller->remote_node_entries, SCI_MAX_REMOTE_DEVICES);
+         this_controller->task_context_entries =
+            MIN(this_controller->task_context_entries, SCU_IO_REQUEST_COUNT);
+         this_controller->uf_control.buffers.count =
+            MIN(this_controller->uf_control.buffers.count, SCU_UNSOLICITED_FRAME_COUNT);
+         this_controller->completion_event_entries =
+            MIN(this_controller->completion_event_entries, SCU_EVENT_COUNT);
+         this_controller->completion_queue_entries =
+            MIN(this_controller->completion_queue_entries, SCU_COMPLETION_QUEUE_COUNT);
+
+         scic_sds_controller_build_memory_descriptor_table(this_controller);
+      break;
+
+      case SCI_MODE_SIZE:
+         this_controller->remote_node_entries =
+            MIN(this_controller->remote_node_entries, SCI_MIN_REMOTE_DEVICES);
+         this_controller->task_context_entries =
+            MIN(this_controller->task_context_entries, SCI_MIN_IO_REQUESTS);
+         this_controller->uf_control.buffers.count =
+            MIN(this_controller->uf_control.buffers.count, SCU_MIN_UNSOLICITED_FRAMES);
+         this_controller->completion_event_entries =
+            MIN(this_controller->completion_event_entries, SCU_MIN_EVENTS);
+         this_controller->completion_queue_entries =
+            MIN(this_controller->completion_queue_entries, SCU_MIN_COMPLETION_QUEUE_ENTRIES);
+
+         scic_sds_controller_build_memory_descriptor_table(this_controller);
+      break;
+
+      default:
+         status = SCI_FAILURE_INVALID_PARAMETER_VALUE;
+      break;
+      }
+   }
+   else
+      status = SCI_FAILURE_INVALID_STATE;
+
+   return status;
+}
+
+/**
+ * This method will reset the controller hardware.
+ *
+ * @param[in] this_controller The controller that is to be reset.
+ */
+void scic_sds_controller_reset_hardware(
+   SCIC_SDS_CONTROLLER_T * this_controller
+)
+{
+   // Disable interrupts so we dont take any spurious interrupts
+   scic_controller_disable_interrupts(this_controller);
+
+   // Reset the SCU
+   SMU_SMUSRCR_WRITE(this_controller, 0xFFFFFFFF);
+
+   // Delay for 1ms to before clearing the CQP and UFQPR.
+   scic_cb_stall_execution(1000);
+
+   // The write to the CQGR clears the CQP
+   SMU_CQGR_WRITE(this_controller, 0x00000000);
+
+   // The write to the UFQGP clears the UFQPR
+   SCU_UFQGP_WRITE(this_controller, 0x00000000);
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_user_parameters_set(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   SCIC_USER_PARAMETERS_T  * scic_parms
+)
+{
+   SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
+
+   if (
+         (this_controller->parent.state_machine.current_state_id
+          == SCI_BASE_CONTROLLER_STATE_RESET)
+      || (this_controller->parent.state_machine.current_state_id
+          == SCI_BASE_CONTROLLER_STATE_INITIALIZING)
+      || (this_controller->parent.state_machine.current_state_id
+          == SCI_BASE_CONTROLLER_STATE_INITIALIZED)
+      )
+   {
+      U16  index;
+
+      // Validate the user parameters.  If they are not legal, then
+      // return a failure.
+      for (index = 0; index < SCI_MAX_PHYS; index++)
+      {
+         if (!
+               (  scic_parms->sds1.phys[index].max_speed_generation
+                  <= SCIC_SDS_PARM_MAX_SPEED
+               && scic_parms->sds1.phys[index].max_speed_generation
+                  > SCIC_SDS_PARM_NO_SPEED
+               )
+            )
+            return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+
+         if (
+               (scic_parms->sds1.phys[index].in_connection_align_insertion_frequency < 3) ||
+               (scic_parms->sds1.phys[index].align_insertion_frequency == 0) ||
+               (scic_parms->sds1.phys[index].notify_enable_spin_up_insertion_frequency == 0)
+            )
+         {
+            return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+         }
+      }
+
+      if (
+            (scic_parms->sds1.stp_inactivity_timeout == 0) ||
+            (scic_parms->sds1.ssp_inactivity_timeout == 0) ||
+            (scic_parms->sds1.stp_max_occupancy_timeout == 0) ||
+            (scic_parms->sds1.ssp_max_occupancy_timeout == 0) ||
+            (scic_parms->sds1.no_outbound_task_timeout == 0)
+         )
+      {
+         return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+      }
+
+      memcpy(
+         (&this_controller->user_parameters), scic_parms, sizeof(*scic_parms));
+
+      return SCI_SUCCESS;
+   }
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+// ---------------------------------------------------------------------------
+
+void scic_user_parameters_get(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   SCIC_USER_PARAMETERS_T   * scic_parms
+)
+{
+   SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
+
+   memcpy(scic_parms, (&this_controller->user_parameters), sizeof(*scic_parms));
+}
+
+// ---------------------------------------------------------------------------
+SCI_STATUS scic_oem_parameters_set(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   SCIC_OEM_PARAMETERS_T   * scic_parms,
+   U8 scic_parms_version
+)
+{
+   SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
+   SCI_BIOS_OEM_PARAM_ELEMENT_T *old_oem_params =
+                (SCI_BIOS_OEM_PARAM_ELEMENT_T *)(&(scic_parms->sds1));
+
+
+   if (
+         (this_controller->parent.state_machine.current_state_id
+          == SCI_BASE_CONTROLLER_STATE_RESET)
+      || (this_controller->parent.state_machine.current_state_id
+          == SCI_BASE_CONTROLLER_STATE_INITIALIZING)
+      || (this_controller->parent.state_machine.current_state_id
+          == SCI_BASE_CONTROLLER_STATE_INITIALIZED)
+      )
+   {
+      U16  index;
+      U8   combined_phy_mask = 0;
+
+      /*
+       * Set the OEM parameter version for the controller. This comes
+       * from the OEM parameter block header or the registry depending
+       * on what WCDL is set to retrieve.
+       */
+      this_controller->oem_parameters_version = scic_parms_version;
+
+      // Validate the oem parameters.  If they are not legal, then
+      // return a failure.
+      for(index=0; index<SCI_MAX_PORTS; index++)
+      {
+         if (scic_parms->sds1.ports[index].phy_mask > SCIC_SDS_PARM_PHY_MASK_MAX)
+         {
+            return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+         }
+      }
+
+      for(index=0; index<SCI_MAX_PHYS; index++)
+      {
+         if (
+             scic_parms->sds1.phys[index].sas_address.sci_format.high == 0
+                 && scic_parms->sds1.phys[index].sas_address.sci_format.low  == 0
+        )
+        {
+            return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+        }
+
+#if defined(PBG_HBA_A0_BUILD) || defined(PBG_HBA_A2_BUILD) || defined(PBG_HBA_BETA_BUILD) || defined(PBG_BUILD)
+        if (
+              (scic_parms->sds1.phys[index].afe_tx_amp_control0 == 0) ||
+              (scic_parms->sds1.phys[index].afe_tx_amp_control1 == 0) ||
+              (scic_parms->sds1.phys[index].afe_tx_amp_control2 == 0) ||
+              (scic_parms->sds1.phys[index].afe_tx_amp_control3 == 0)
+              )
+        {
+           return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+        }
+#endif
+      }
+
+      if (scic_parms->sds1.controller.mode_type == SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE)
+      {
+         for(index=0; index<SCI_MAX_PHYS; index++)
+         {
+            if (scic_parms->sds1.ports[index].phy_mask != 0)
+            {
+               return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+            }
+         }
+      }
+      else if (scic_parms->sds1.controller.mode_type == SCIC_PORT_MANUAL_CONFIGURATION_MODE)
+      {
+         for(index=0; index<SCI_MAX_PHYS; index++)
+         {
+            combined_phy_mask |= scic_parms->sds1.ports[index].phy_mask;
+         }
+
+         if (combined_phy_mask == 0)
+         {
+            return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+         }
+      }
+      else
+      {
+         return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+      }
+
+      if (scic_parms->sds1.controller.max_number_concurrent_device_spin_up > MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT)
+      {
+         return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+      }
+
+      if (old_oem_params->controller.do_enable_ssc != 0)
+      {
+         if (  (scic_parms_version == SCI_OEM_PARAM_VER_1_0)
+            && (old_oem_params->controller.do_enable_ssc != 0x01))
+             return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+
+         if (scic_parms_version >= SCI_OEM_PARAM_VER_1_1)
+         {
+            SCI_BIOS_OEM_PARAM_ELEMENT_v_1_1_T *oem_params =
+                (SCI_BIOS_OEM_PARAM_ELEMENT_v_1_1_T*)(&(scic_parms->sds1));
+
+            U8 test = oem_params->controller.ssc_sata_tx_spread_level;
+            if ( !((test == 0x0) || (test == 0x2) || (test == 0x3) ||
+                 (test == 0x6) || (test == 0x7)) )
+                return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+
+            test = oem_params->controller.ssc_sas_tx_spread_level;
+            if (oem_params->controller.ssc_sas_tx_type == 0)
+            {
+                if ( !((test == 0x0) || (test == 0x2) || (test == 0x3)) )
+                    return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+            }
+            else
+            if (oem_params->controller.ssc_sas_tx_type == 1)
+            {
+                if ( !((test == 0x0) || (test == 0x3) || (test == 0x6)) )
+                    return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+            }
+         }
+      }
+
+      memcpy(
+         (&this_controller->oem_parameters), scic_parms, sizeof(*scic_parms));
+      return SCI_SUCCESS;
+   }
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+// ---------------------------------------------------------------------------
+
+void scic_oem_parameters_get(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   SCIC_OEM_PARAMETERS_T   * scic_parms
+)
+{
+   SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
+
+   memcpy(scic_parms, (&this_controller->oem_parameters), sizeof(*scic_parms));
+}
+
+// ---------------------------------------------------------------------------
+
+#if !defined(DISABLE_INTERRUPTS)
+
+#define INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_LOWER_BOUND_NS 853
+#define INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_UPPER_BOUND_NS 1280
+#define INTERRUPT_COALESCE_TIMEOUT_MAX_US                    2700000
+#define INTERRUPT_COALESCE_NUMBER_MAX                        256
+#define INTERRUPT_COALESCE_TIMEOUT_ENCODE_MIN                7
+#define INTERRUPT_COALESCE_TIMEOUT_ENCODE_MAX                28
+
+SCI_STATUS scic_controller_set_interrupt_coalescence(
+   SCI_CONTROLLER_HANDLE_T controller,
+   U32                     coalesce_number,
+   U32                     coalesce_timeout
+)
+{
+   SCIC_SDS_CONTROLLER_T * scic_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+   U8 timeout_encode = 0;
+   U32 min = 0;
+   U32 max = 0;
+
+   //Check if the input parameters fall in the range.
+   if (coalesce_number > INTERRUPT_COALESCE_NUMBER_MAX)
+      return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+
+   //  Defined encoding for interrupt coalescing timeout:
+   //              Value   Min      Max     Units
+   //              -----   ---      ---     -----
+   //              0       -        -       Disabled
+   //              1       13.3     20.0    ns
+   //              2       26.7     40.0
+   //              3       53.3     80.0
+   //              4       106.7    160.0
+   //              5       213.3    320.0
+   //              6       426.7    640.0
+   //              7       853.3    1280.0
+   //              8       1.7      2.6     us
+   //              9       3.4      5.1
+   //              10      6.8      10.2
+   //              11      13.7     20.5
+   //              12      27.3     41.0
+   //              13      54.6     81.9
+   //              14      109.2    163.8
+   //              15      218.5    327.7
+   //              16      436.9    655.4
+   //              17      873.8    1310.7
+   //              18      1.7      2.6     ms
+   //              19      3.5      5.2
+   //              20      7.0      10.5
+   //              21      14.0     21.0
+   //              22      28.0     41.9
+   //              23      55.9     83.9
+   //              24      111.8    167.8
+   //              25      223.7    335.5
+   //              26      447.4    671.1
+   //              27      894.8    1342.2
+   //              28      1.8      2.7     s
+   //              Others Undefined
+
+   //Use the table above to decide the encode of interrupt coalescing timeout
+   //value for register writing.
+   if (coalesce_timeout == 0)
+      timeout_encode = 0;
+   else
+   {
+      //make the timeout value in unit of (10 ns).
+      coalesce_timeout = coalesce_timeout * 100;
+      min = INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_LOWER_BOUND_NS / 10;
+      max = INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_UPPER_BOUND_NS / 10;
+
+      //get the encode of timeout for register writing.
+      for ( timeout_encode = INTERRUPT_COALESCE_TIMEOUT_ENCODE_MIN;
+            timeout_encode <= INTERRUPT_COALESCE_TIMEOUT_ENCODE_MAX;
+            timeout_encode++ )
+      {
+         if (min <= coalesce_timeout &&  max > coalesce_timeout)
+            break;
+         else if (coalesce_timeout >= max && coalesce_timeout < min*2
+            && coalesce_timeout <= INTERRUPT_COALESCE_TIMEOUT_MAX_US*100)
+         {
+            if ( (coalesce_timeout-max) < (2*min - coalesce_timeout) )
+               break;
+            else
+            {
+               timeout_encode++;
+               break;
+            }
+         }
+         else
+         {
+            max = max*2;
+            min = min*2;
+         }
+      }
+
+      if ( timeout_encode == INTERRUPT_COALESCE_TIMEOUT_ENCODE_MAX+1 )
+         //the value is out of range.
+         return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+   }
+
+   SMU_ICC_WRITE(
+      scic_controller,
+      (SMU_ICC_GEN_VAL(NUMBER, coalesce_number)|
+       SMU_ICC_GEN_VAL(TIMER, timeout_encode))
+   );
+
+   scic_controller->interrupt_coalesce_number = (U16)coalesce_number;
+   scic_controller->interrupt_coalesce_timeout = coalesce_timeout/100;
+
+   return SCI_SUCCESS;
+}
+
+// ---------------------------------------------------------------------------
+
+void scic_controller_get_interrupt_coalescence(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   U32                     * coalesce_number,
+   U32                     * coalesce_timeout
+)
+{
+   SCIC_SDS_CONTROLLER_T * scic_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+   *coalesce_number = scic_controller->interrupt_coalesce_number;
+   *coalesce_timeout = scic_controller->interrupt_coalesce_timeout;
+}
+
+#endif // !defined(DISABLE_INTERRUPTS)
+
+// ---------------------------------------------------------------------------
+
+U32 scic_controller_get_scratch_ram_size(
+   SCI_CONTROLLER_HANDLE_T   controller
+)
+{
+   return SCU_SCRATCH_RAM_SIZE_IN_DWORDS;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_controller_read_scratch_ram_dword(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   U32                       offset,
+   U32                     * value
+)
+{
+   U32 zpt_index;
+   SCIC_SDS_CONTROLLER_T * scic_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+   U32 status = SMU_SMUCSR_READ(scic_controller);
+
+   //Check if the SCU Scratch RAM been initialized, if not return zeros
+   if ((status & SCU_RAM_INIT_COMPLETED) != SCU_RAM_INIT_COMPLETED)
+   {
+      *value = 0x00000000;
+      return SCI_SUCCESS;
+   }
+
+   if (offset < scic_controller_get_scratch_ram_size(controller))
+   {
+      if(offset <= SCU_MAX_ZPT_DWORD_INDEX)
+      {
+         zpt_index = offset + (offset - (offset % 4)) + 4;
+
+         *value = scu_controller_scratch_ram_register_read(scic_controller,zpt_index);
+      }
+      else //offset > SCU_MAX_ZPT_DWORD_INDEX
+      {
+         offset = offset - 132;
+
+         zpt_index = offset + (offset - (offset % 4)) + 4;
+
+         *value = scu_controller_scratch_ram_register_read_ext(scic_controller,zpt_index);
+      }
+
+      return SCI_SUCCESS;
+   }
+   else
+   {
+      return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+   }
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_controller_write_scratch_ram_dword(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   U32                       offset,
+   U32                       value
+)
+{
+   U32 zpt_index;
+
+   if (offset < scic_controller_get_scratch_ram_size(controller))
+   {
+      SCIC_SDS_CONTROLLER_T * scic_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+
+      if(offset <= SCU_MAX_ZPT_DWORD_INDEX)
+      {
+         zpt_index = offset + (offset - (offset % 4)) + 4;
+
+         scu_controller_scratch_ram_register_write(scic_controller,zpt_index,value);
+      }
+      else //offset > SCU_MAX_ZPT_DWORD_INDEX
+      {
+         offset = offset - 132;
+
+         zpt_index = offset + (offset - (offset % 4)) + 4;
+
+         scu_controller_scratch_ram_register_write_ext(scic_controller,zpt_index,value);
+
+      }
+
+      return SCI_SUCCESS;
+   }
+   else
+   {
+      return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+   }
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_controller_suspend(
+   SCI_CONTROLLER_HANDLE_T   controller
+)
+{
+   SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
+   U8 index;
+
+   // As a precaution, disable interrupts.  The user is required
+   // to re-enable interrupts if so desired after the call.
+   scic_controller_disable_interrupts(controller);
+
+   // Stop all the timers
+   // Maybe change the states of the objects to avoid processing stuff.
+
+
+   // Suspend the Ports in order to ensure no unexpected
+   // frame reception occurs on the links from the target
+   for (index = 0; index < SCI_MAX_PORTS; index++)
+      scic_sds_port_suspend_port_task_scheduler(
+         &(this_controller->port_table[index]));
+
+   // Disable/Reset the completion queue and unsolicited frame
+   // queue.
+   SMU_CQGR_WRITE(this_controller, 0x00000000);
+   SCU_UFQGP_WRITE(this_controller, 0x00000000);
+
+   // Clear any interrupts that may be pending or may have been generated
+   // by setting CQGR and CQPR back to 0
+   SMU_ISR_WRITE(this_controller, 0xFFFFFFFF);
+
+   //reset the software get pointer to completion queue.
+   this_controller->completion_queue_get = 0;
+
+   return SCI_SUCCESS;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_controller_resume(
+   SCI_CONTROLLER_HANDLE_T   controller
+)
+{
+   SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
+   U8 index;
+
+   // Initialize the completion queue and unsolicited frame queue.
+   scic_sds_controller_initialize_completion_queue(this_controller);
+   scic_sds_controller_initialize_unsolicited_frame_queue(this_controller);
+
+   this_controller->restrict_completions = FALSE;
+
+   // Release the port suspensions to allow for further successful
+   // operation.
+   for (index = 0; index < SCI_MAX_PORTS; index++)
+      scic_sds_port_resume_port_task_scheduler(
+         &(this_controller->port_table[index]));
+
+   //check the link layer status register DWORD sync acquired bit to detect
+   //link down event. If there is any link down event happened during controller
+   //suspension, restart phy state machine.
+   for (index = 0; index < SCI_MAX_PHYS; index ++)
+   {
+      SCIC_SDS_PHY_T * curr_phy = &this_controller->phy_table[index];
+      U32 link_layer_status = SCU_SAS_LLSTA_READ(curr_phy);
+
+      if ((link_layer_status & SCU_SAS_LLSTA_DWORD_SYNCA_BIT) == 0)
+      {
+         //Need to put the phy back to start OOB. Then an appropriate link event
+         //message will be send to scic user.
+         scic_sds_phy_restart_starting_state(curr_phy);
+      }
+   }
+
+   return SCI_SUCCESS;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_controller_transition(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   BOOL                      restrict_completions
+)
+{
+   SCI_STATUS              result = SCI_FAILURE_INVALID_STATE;
+   SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
+   U8                      index;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIC_LOG_OBJECT_CONTROLLER,
+      "scic_controller_transition(0x%x) enter\n",
+      controller
+   ));
+
+   if (this_controller->parent.state_machine.current_state_id
+       == SCI_BASE_CONTROLLER_STATE_READY)
+   {
+      // Ensure that there are no outstanding IO operations at this
+      // time.
+      for (index = 0; index < SCI_MAX_PORTS; index++)
+      {
+         if (this_controller->port_table[index].started_request_count != 0)
+            return result;
+      }
+
+      scic_controller_suspend(controller);
+
+      // Loop through the memory descriptor list and reprogram
+      // the silicon memory registers accordingly.
+      result = scic_sds_controller_validate_memory_descriptor_table(
+                  this_controller);
+      if (result == SCI_SUCCESS)
+      {
+         scic_sds_controller_ram_initialization(this_controller);
+         this_controller->restrict_completions = restrict_completions;
+      }
+
+      scic_controller_resume(controller);
+   }
+
+   return result;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_controller_get_max_ports(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   U8                      * count
+)
+{
+   *count = SCI_MAX_PORTS;
+   return SCI_SUCCESS;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_controller_get_max_phys(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   U8                      * count
+)
+{
+   *count = SCI_MAX_PHYS;
+   return SCI_SUCCESS;
+}
+
+
+//******************************************************************************
+//* CONTROLLER STATE MACHINE
+//******************************************************************************
+
+/**
+ * This macro returns the maximum number of logical ports supported by the
+ * hardware. The caller passes in the value read from the device context
+ * capacity register and this macro will mash and shift the value
+ * appropriately.
+ */
+#define smu_dcc_get_max_ports(dcc_value) \
+   ( \
+     (    ((U32)((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_MASK)) \
+       >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_SHIFT ) + 1\
+   )
+
+/**
+ * This macro returns the maximum number of task contexts supported by the
+ * hardware. The caller passes in the value read from the device context
+ * capacity register and this macro will mash and shift the value
+ * appropriately.
+ */
+#define smu_dcc_get_max_task_context(dcc_value) \
+   ( \
+     (   ((U32)((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_MASK)) \
+       >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_SHIFT ) + 1\
+   )
+
+/**
+ * This macro returns the maximum number of remote node contexts supported
+ * by the hardware. The caller passes in the value read from the device
+ * context capacity register and this macro will mash and shift the value
+ * appropriately.
+ */
+#define smu_dcc_get_max_remote_node_context(dcc_value) \
+   ( \
+     (  ( (U32)((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_MASK) )\
+       >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_SHIFT ) + 1\
+   )
+
+//*****************************************************************************
+//* DEFAULT STATE HANDLERS
+//*****************************************************************************
+
+/**
+ * This method is called when the SCIC_SDS_CONTROLLER default start
+ * io/task handler is in place.
+ *    - Issue a warning message
+ *
+ * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
+ *       into a SCIC_SDS_CONTROLLER object.
+ * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which, if it was
+ *       used, would be cast to a SCIC_SDS_REMOTE_DEVICE.
+ * @param[in] io_request This is the SCI_BASE_REQUEST which, if it was used,
+ *       would be cast to a SCIC_SDS_IO_REQUEST.
+ * @param[in] io_tag This is the IO tag to be assigned to the IO request or
+ *       SCI_CONTROLLER_INVALID_IO_TAG.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+static
+SCI_STATUS scic_sds_controller_default_start_operation_handler(
+   SCI_BASE_CONTROLLER_T    *controller,
+   SCI_BASE_REMOTE_DEVICE_T *remote_device,
+   SCI_BASE_REQUEST_T       *io_request,
+   U16                       io_tag
+)
+{
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger(this_controller),
+      SCIC_LOG_OBJECT_CONTROLLER,
+      "SCIC Controller requested to start an io/task from invalid state %d\n",
+      sci_base_state_machine_get_state(
+         scic_sds_controller_get_base_state_machine(this_controller))
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * This method is called when the SCIC_SDS_CONTROLLER default
+ * request handler is in place.
+ *    - Issue a warning message
+ *
+ * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
+ *       into a SCIC_SDS_CONTROLLER object.
+ * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which, if it was
+ *       used, would be cast to a SCIC_SDS_REMOTE_DEVICE.
+ * @param[in] io_request This is the SCI_BASE_REQUEST which, if it was used,
+ *       would be cast to a SCIC_SDS_IO_REQUEST.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+static
+SCI_STATUS scic_sds_controller_default_request_handler(
+   SCI_BASE_CONTROLLER_T    *controller,
+   SCI_BASE_REMOTE_DEVICE_T *remote_device,
+   SCI_BASE_REQUEST_T       *io_request
+)
+{
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger(this_controller),
+      SCIC_LOG_OBJECT_CONTROLLER,
+      "SCIC Controller request operation from invalid state %d\n",
+      sci_base_state_machine_get_state(
+         scic_sds_controller_get_base_state_machine(this_controller))
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+//*****************************************************************************
+//* GENERAL (COMMON) STATE HANDLERS
+//*****************************************************************************
+
+/**
+ * This method is called when the SCIC_SDS_CONTROLLER is in the ready state
+ * reset handler is in place.
+ *    - Transition to SCI_BASE_CONTROLLER_STATE_RESETTING
+ *
+ * @param[in] controller The SCI_BASE_CONTROLLER object which is cast into a
+ *       SCIC_SDS_CONTROLLER object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS
+ */
+static
+SCI_STATUS scic_sds_controller_general_reset_handler(
+   SCI_BASE_CONTROLLER_T *controller
+)
+{
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIC_LOG_OBJECT_CONTROLLER,
+      "scic_sds_controller_resetting_state_enter(0x%x) enter\n",
+      controller
+   ));
+
+   //Release resource. So far only resource to be released are timers.
+   scic_sds_controller_release_resource(this_controller);
+
+   // The reset operation is not a graceful cleanup just perform the state
+   // transition.
+   sci_base_state_machine_change_state(
+      scic_sds_controller_get_base_state_machine(this_controller),
+      SCI_BASE_CONTROLLER_STATE_RESETTING
+   );
+
+   return SCI_SUCCESS;
+}
+
+//*****************************************************************************
+//* RESET STATE HANDLERS
+//*****************************************************************************
+
+/**
+ * This method is the SCIC_SDS_CONTROLLER initialize handler for the reset
+ * state.
+ *    - Currently this function does nothing
+ *
+ * @param[in] controller This is the SCI_BASE_CONTROLLER object which is cast
+ *       into a SCIC_SDS_CONTROLLER object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE
+ *
+ * @todo This function is not yet implemented and is a valid request from the
+ *       reset state.
+ */
+static
+SCI_STATUS scic_sds_controller_reset_state_initialize_handler(
+   SCI_BASE_CONTROLLER_T *controller
+)
+{
+   U32 index;
+   SCI_STATUS result = SCI_SUCCESS;
+   SCIC_SDS_CONTROLLER_T *this_controller;
+
+   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_INITIALIZATION,
+      "scic_sds_controller_reset_state_initialize_handler(0x%x) enter\n",
+      controller
+   ));
+
+   sci_base_state_machine_change_state(
+      scic_sds_controller_get_base_state_machine(this_controller),
+      SCI_BASE_CONTROLLER_STATE_INITIALIZING
+   );
+
+   this_controller->timeout_timer = scic_cb_timer_create(
+      controller,
+      scic_sds_controller_timeout_handler,
+      controller
+   );
+
+   scic_sds_controller_initialize_power_control(this_controller);
+
+   /// todo: This should really be done in the reset state enter but
+   ///       the controller has not yet been initialized before getting
+   ///       to the reset enter state so the PCI BAR is not yet assigned
+   scic_sds_controller_reset_hardware(this_controller);
+
+#if defined(ARLINGTON_BUILD)
+   scic_sds_controller_lex_atux_initialization(this_controller);
+#elif    defined(PLEASANT_RIDGE_BUILD) \
+      || defined(PBG_HBA_A0_BUILD) \
+      || defined(PBG_HBA_A2_BUILD)
+   scic_sds_controller_afe_initialization(this_controller);
+#elif defined(PBG_HBA_BETA_BUILD) || defined(PBG_BUILD)
+   // There is nothing to do here for B0 since we do not have to
+   // program the AFE registers.
+   /// @todo The AFE settings are supposed to be correct for the B0 but
+   ///       presently they seem to be wrong.
+   scic_sds_controller_afe_initialization(this_controller);
+#else  // !defined(ARLINGTON_BUILD) && !defined(PLEASANT_RIDGE_BUILD)
+   // What other systems do we want to add here?
+#endif // !defined(ARLINGTON_BUILD) && !defined(PLEASANT_RIDGE_BUILD)
+
+   if (SCI_SUCCESS == result)
+   {
+      U32 status;
+      U32 terminate_loop;
+
+      // Take the hardware out of reset
+      SMU_SMUSRCR_WRITE(this_controller, 0x00000000);
+
+      /// @todo Provide meaningfull error code for hardware failure
+      //result = SCI_FAILURE_CONTROLLER_HARDWARE;
+      result = SCI_FAILURE;
+      terminate_loop = 100;
+
+      while (terminate_loop-- && (result != SCI_SUCCESS))
+      {
+         // Loop until the hardware reports success
+         scic_cb_stall_execution(SCU_CONTEXT_RAM_INIT_STALL_TIME);
+         status = SMU_SMUCSR_READ(this_controller);
+
+         if ((status & SCU_RAM_INIT_COMPLETED) == SCU_RAM_INIT_COMPLETED)
+         {
+            result = SCI_SUCCESS;
+         }
+      }
+   }
+
+#ifdef ARLINGTON_BUILD
+   scic_sds_controller_enable_chipwatch(this_controller);
+#endif
+
+   if (result == SCI_SUCCESS)
+   {
+      U32 max_supported_ports;
+      U32 max_supported_devices;
+      U32 max_supported_io_requests;
+      U32 device_context_capacity;
+
+      // Determine what are the actaul device capacities that the
+      // hardware will support
+      device_context_capacity = SMU_DCC_READ(this_controller);
+
+      max_supported_ports =
+         smu_dcc_get_max_ports(device_context_capacity);
+      max_supported_devices =
+         smu_dcc_get_max_remote_node_context(device_context_capacity);
+      max_supported_io_requests =
+         smu_dcc_get_max_task_context(device_context_capacity);
+
+      // Make all PEs that are unassigned match up with the logical ports
+      for (index = 0; index < max_supported_ports; index++)
+      {
+         scu_register_write(
+            this_controller,
+            this_controller->scu_registers->peg0.ptsg.protocol_engine[index],
+            index
+         );
+      }
+
+      // Now that we have the correct hardware reported minimum values
+      // build the MDL for the controller.  Default to a performance
+      // configuration.
+      scic_controller_set_mode(this_controller, SCI_MODE_SPEED);
+
+      // Record the smaller of the two capacity values
+      this_controller->logical_port_entries =
+         MIN(max_supported_ports, this_controller->logical_port_entries);
+
+      this_controller->task_context_entries =
+         MIN(max_supported_io_requests, this_controller->task_context_entries);
+
+      this_controller->remote_node_entries =
+         MIN(max_supported_devices, this_controller->remote_node_entries);
+   }
+
+   // Initialize hardware PCI Relaxed ordering in DMA engines
+   if (result == SCI_SUCCESS)
+   {
+      U32 dma_configuration;
+
+      // Configure the payload DMA
+      dma_configuration = SCU_PDMACR_READ(this_controller);
+      dma_configuration |= SCU_PDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE);
+      SCU_PDMACR_WRITE(this_controller, dma_configuration);
+
+      // Configure the control DMA
+      dma_configuration = SCU_CDMACR_READ(this_controller);
+      dma_configuration |= SCU_CDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE);
+      SCU_CDMACR_WRITE(this_controller, dma_configuration);
+   }
+
+   // Initialize the PHYs before the PORTs because the PHY registers
+   // are accessed during the port initialization.
+   if (result == SCI_SUCCESS)
+   {
+      // Initialize the phys
+      for (index = 0;
+           (result == SCI_SUCCESS) && (index < SCI_MAX_PHYS);
+           index++)
+      {
+         result = scic_sds_phy_initialize(
+            &this_controller->phy_table[index],
+            &this_controller->scu_registers->peg0.pe[index].tl,
+            &this_controller->scu_registers->peg0.pe[index].ll
+         );
+      }
+   }
+
+   //Initialize the SGPIO Unit for HARDWARE controlled SGPIO
+   if(result == SCI_SUCCESS)
+   {
+      scic_sgpio_hardware_initialize(this_controller);
+   }
+
+   if (result == SCI_SUCCESS)
+   {
+      // Initialize the logical ports
+      for (index = 0;
+              (index < this_controller->logical_port_entries)
+           && (result == SCI_SUCCESS);
+           index++)
+      {
+         result = scic_sds_port_initialize(
+            &this_controller->port_table[index],
+            &this_controller->scu_registers->peg0.ptsg.port[index],
+            &this_controller->scu_registers->peg0.ptsg.protocol_engine,
+            &this_controller->scu_registers->peg0.viit[index]
+         );
+      }
+   }
+
+   if (SCI_SUCCESS == result)
+   {
+      result = scic_sds_port_configuration_agent_initialize(
+                  this_controller,
+                  &this_controller->port_agent
+               );
+   }
+
+   // Advance the controller state machine
+   if (result == SCI_SUCCESS)
+   {
+      sci_base_state_machine_change_state(
+         scic_sds_controller_get_base_state_machine(this_controller),
+         SCI_BASE_CONTROLLER_STATE_INITIALIZED
+      );
+   }
+   else
+   {
+      //stay in the same state and release the resource
+      scic_sds_controller_release_resource(this_controller);
+
+      SCIC_LOG_TRACE((
+         sci_base_object_get_logger(controller),
+         SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_INITIALIZATION,
+         "Invalid Port Configuration from scic_sds_controller_reset_state_initialize_handler(0x%x) \n",
+         controller
+      ));
+
+   }
+
+   return result;
+}
+
+//*****************************************************************************
+//* INITIALIZED STATE HANDLERS
+//*****************************************************************************
+
+/**
+ * This method is the SCIC_SDS_CONTROLLER start handler for the initialized
+ * state.
+ *    - Validate we have a good memory descriptor table
+ *    - Initialze the physical memory before programming the hardware
+ *    - Program the SCU hardware with the physical memory addresses passed in
+ *      the memory descriptor table.
+ *    - Initialzie the TCi pool
+ *    - Initialize the RNi pool
+ *    - Initialize the completion queue
+ *    - Initialize the unsolicited frame data
+ *    - Take the SCU port task scheduler out of reset
+ *    - Start the first phy object.
+ *    - Transition to SCI_BASE_CONTROLLER_STATE_STARTING.
+ *
+ * @param[in] controller This is the SCI_BASE_CONTROLLER object which is cast
+ *       into a SCIC_SDS_CONTROLLER object.
+ * @param[in] timeout This is the allowed time for the controller object to
+ *       reach the started state.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS if all of the controller start operations complete
+ * @retval SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD if one or more of the
+ *         memory descriptor fields is invalid.
+ */
+static
+SCI_STATUS scic_sds_controller_initialized_state_start_handler(
+   SCI_BASE_CONTROLLER_T * controller,
+   U32                     timeout
+)
+{
+   U16                     index;
+   SCI_STATUS              result;
+   SCIC_SDS_CONTROLLER_T * this_controller;
+
+   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+
+   // Make sure that the SCI User filled in the memory descriptor table correctly
+   result = scic_sds_controller_validate_memory_descriptor_table(this_controller);
+
+   if (result == SCI_SUCCESS)
+   {
+      // The memory descriptor list looks good so program the hardware
+      scic_sds_controller_ram_initialization(this_controller);
+   }
+
+   if (SCI_SUCCESS == result)
+   {
+      // Build the TCi free pool
+      sci_pool_initialize(this_controller->tci_pool);
+      for (index = 0; index < this_controller->task_context_entries; index++)
+      {
+         sci_pool_put(this_controller->tci_pool, index);
+      }
+
+      // Build the RNi free pool
+      scic_sds_remote_node_table_initialize(
+         &this_controller->available_remote_nodes,
+         this_controller->remote_node_entries
+      );
+   }
+
+   if (SCI_SUCCESS == result)
+   {
+      // Before anything else lets make sure we will not be interrupted
+      // by the hardware.
+      scic_controller_disable_interrupts(controller);
+
+      // Enable the port task scheduler
+      scic_sds_controller_enable_port_task_scheduler(this_controller);
+
+      // Assign all the task entries to this controller physical function
+      scic_sds_controller_assign_task_entries(this_controller);
+
+      // Now initialze the completion queue
+      scic_sds_controller_initialize_completion_queue(this_controller);
+
+      // Initialize the unsolicited frame queue for use
+      scic_sds_controller_initialize_unsolicited_frame_queue(this_controller);
+
+      // Setup the phy start timer
+      result = scic_sds_controller_initialize_phy_startup(this_controller);
+   }
+
+   // Start all of the ports on this controller
+   for (
+          index = 0;
+          (index < this_controller->logical_port_entries) && (result == SCI_SUCCESS);
+          index++
+       )
+   {
+      result = this_controller->port_table[index].
+         state_handlers->parent.start_handler(&this_controller->port_table[index].parent);
+   }
+
+   if (SCI_SUCCESS == result)
+   {
+      scic_sds_controller_start_next_phy(this_controller);
+
+      // See if the user requested to timeout this operation.
+      if (timeout != 0)
+         scic_cb_timer_start(controller, this_controller->timeout_timer, timeout);
+
+      sci_base_state_machine_change_state(
+         scic_sds_controller_get_base_state_machine(this_controller),
+         SCI_BASE_CONTROLLER_STATE_STARTING
+      );
+   }
+
+   return result;
+}
+
+//*****************************************************************************
+//* STARTING STATE HANDLERS
+//*****************************************************************************
+
+/**
+ * This method is called when the SCIC_SDS_CONTROLLER is in the starting state
+ * link up handler is called.  This method will perform the following:
+ *    - Stop the phy timer
+ *    - Start the next phy
+ *    - Report the link up condition to the port object
+ *
+ * @param[in] controller This is SCIC_SDS_CONTROLLER which receives the link up
+ *       notification.
+ * @param[in] port This is SCIC_SDS_PORT with which the phy is associated.
+ * @param[in] phy This is the SCIC_SDS_PHY which has gone link up.
+ *
+ * @return none
+ */
+static
+void scic_sds_controller_starting_state_link_up_handler(
+   SCIC_SDS_CONTROLLER_T *this_controller,
+   SCIC_SDS_PORT_T       *port,
+   SCIC_SDS_PHY_T        *phy
+)
+{
+   scic_sds_controller_phy_timer_stop(this_controller);
+
+   this_controller->port_agent.link_up_handler(
+      this_controller, &this_controller->port_agent, port, phy
+   );
+   //scic_sds_port_link_up(port, phy);
+
+   scic_sds_controller_start_next_phy(this_controller);
+}
+
+/**
+ * This method is called when the SCIC_SDS_CONTROLLER is in the starting state
+ * link down handler is called.
+ *    - Report the link down condition to the port object
+ *
+ * @param[in] controller This is SCIC_SDS_CONTROLLER which receives the
+ *       link down notification.
+ * @param[in] port This is SCIC_SDS_PORT with which the phy is associated.
+ * @param[in] phy This is the SCIC_SDS_PHY which has gone link down.
+ *
+ * @return none
+ */
+static
+void scic_sds_controller_starting_state_link_down_handler(
+   SCIC_SDS_CONTROLLER_T *this_controller,
+   SCIC_SDS_PORT_T       *port,
+   SCIC_SDS_PHY_T        *phy
+)
+{
+   this_controller->port_agent.link_down_handler(
+      this_controller, &this_controller->port_agent, port, phy
+   );
+   //scic_sds_port_link_down(port, phy);
+}
+
+//*****************************************************************************
+//* READY STATE HANDLERS
+//*****************************************************************************
+
+/**
+ * This method is called when the SCIC_SDS_CONTROLLER is in the ready state
+ * stop handler is called.
+ *    - Start the timeout timer
+ *    - Transition to SCI_BASE_CONTROLLER_STATE_STOPPING.
+ *
+ * @param[in] controller The SCI_BASE_CONTROLLER object which is cast into a
+ *       SCIC_SDS_CONTROLLER object.
+ * @param[in] timeout The timeout for when the stop operation should report a
+ *       failure.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS
+ */
+static
+SCI_STATUS scic_sds_controller_ready_state_stop_handler(
+   SCI_BASE_CONTROLLER_T *controller,
+   U32                   timeout
+)
+{
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+
+   // See if the user requested to timeout this operation
+   if (timeout != 0)
+      scic_cb_timer_start(controller, this_controller->timeout_timer, timeout);
+
+   sci_base_state_machine_change_state(
+      scic_sds_controller_get_base_state_machine(this_controller),
+      SCI_BASE_CONTROLLER_STATE_STOPPING
+   );
+
+   return SCI_SUCCESS;
+}
+
+/**
+ * This method is called when the SCIC_SDS_CONTROLLER is in the ready state
+ * and the start io handler is called.
+ *    - Start the io request on the remote device
+ *    - if successful
+ *       - assign the io_request to the io_request_table
+ *       - post the request to the hardware
+ *
+ * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
+ *       into a SCIC_SDS_CONTROLLER object.
+ * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
+ *       SCIC_SDS_REMOTE_DEVICE object.
+ * @param[in] io_request This is the SCI_BASE_REQUEST which is cast to a
+ *       SCIC_SDS_IO_REQUEST object.
+ * @param[in] io_tag This is the IO tag to be assigned to the IO request or
+ *       SCI_CONTROLLER_INVALID_IO_TAG.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS if the start io operation succeeds
+ * @retval SCI_FAILURE_INSUFFICIENT_RESOURCES if the IO tag could not be
+ *         allocated for the io request.
+ * @retval SCI_FAILURE_INVALID_STATE if one or more objects are not in a valid
+ *         state to accept io requests.
+ *
+ * @todo How does the io_tag parameter get assigned to the io request?
+ */
+static
+SCI_STATUS scic_sds_controller_ready_state_start_io_handler(
+   SCI_BASE_CONTROLLER_T    *controller,
+   SCI_BASE_REMOTE_DEVICE_T *remote_device,
+   SCI_BASE_REQUEST_T       *io_request,
+   U16                       io_tag
+)
+{
+   SCI_STATUS status;
+
+   SCIC_SDS_CONTROLLER_T    *this_controller;
+   SCIC_SDS_REQUEST_T       *the_request;
+   SCIC_SDS_REMOTE_DEVICE_T *the_device;
+
+   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+   the_request = (SCIC_SDS_REQUEST_T *)io_request;
+   the_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
+
+   status = scic_sds_remote_device_start_io(this_controller, the_device, the_request);
+
+   if (status == SCI_SUCCESS)
+   {
+      this_controller->io_request_table[
+            scic_sds_io_tag_get_index(the_request->io_tag)] = the_request;
+
+      scic_sds_controller_post_request(
+         this_controller,
+         scic_sds_request_get_post_context(the_request)
+      );
+   }
+
+   return status;
+}
+
+/**
+ * This method is called when the SCIC_SDS_CONTROLLER is in the ready state
+ * and the complete io handler is called.
+ *    - Complete the io request on the remote device
+ *    - if successful
+ *       - remove the io_request to the io_request_table
+ *
+ * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
+ *       into a SCIC_SDS_CONTROLLER object.
+ * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
+ *       SCIC_SDS_REMOTE_DEVICE object.
+ * @param[in] io_request This is the SCI_BASE_REQUEST which is cast to a
+ *       SCIC_SDS_IO_REQUEST object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS if the start io operation succeeds
+ * @retval SCI_FAILURE_INVALID_STATE if one or more objects are not in a valid
+ *         state to accept io requests.
+ */
+static
+SCI_STATUS scic_sds_controller_ready_state_complete_io_handler(
+   SCI_BASE_CONTROLLER_T    *controller,
+   SCI_BASE_REMOTE_DEVICE_T *remote_device,
+   SCI_BASE_REQUEST_T       *io_request
+)
+{
+   U16        index;
+   SCI_STATUS status;
+   SCIC_SDS_CONTROLLER_T    *this_controller;
+   SCIC_SDS_REQUEST_T       *the_request;
+   SCIC_SDS_REMOTE_DEVICE_T *the_device;
+
+   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+   the_request = (SCIC_SDS_REQUEST_T *)io_request;
+   the_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
+
+   status = scic_sds_remote_device_complete_io(
+                  this_controller, the_device, the_request);
+
+   if (status == SCI_SUCCESS)
+   {
+      index = scic_sds_io_tag_get_index(the_request->io_tag);
+      this_controller->io_request_table[index] = SCI_INVALID_HANDLE;
+   }
+
+   return status;
+}
+
+/**
+ * This method is called when the SCIC_SDS_CONTROLLER is in the ready state
+ * and the continue io handler is called.
+ *
+ * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
+ *       into a SCIC_SDS_CONTROLLER object.
+ * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
+ *       SCIC_SDS_REMOTE_DEVICE object.
+ * @param[in] io_request This is the SCI_BASE_REQUEST which is cast to a
+ *       SCIC_SDS_IO_REQUEST object.
+ *
+ * @return SCI_STATUS
+ */
+static
+SCI_STATUS scic_sds_controller_ready_state_continue_io_handler(
+   SCI_BASE_CONTROLLER_T    *controller,
+   SCI_BASE_REMOTE_DEVICE_T *remote_device,
+   SCI_BASE_REQUEST_T       *io_request
+)
+{
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   SCIC_SDS_REQUEST_T    *the_request;
+
+   the_request     = (SCIC_SDS_REQUEST_T *)io_request;
+   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+
+   this_controller->io_request_table[
+      scic_sds_io_tag_get_index(the_request->io_tag)] = the_request;
+
+   scic_sds_controller_post_request(
+      this_controller,
+      scic_sds_request_get_post_context(the_request)
+   );
+
+   return SCI_SUCCESS;
+}
+
+/**
+ * This method is called when the SCIC_SDS_CONTROLLER is in the ready state
+ * and the start task handler is called.
+ *    - The remote device is requested to start the task request
+ *    - if successful
+ *       - assign the task to the io_request_table
+ *       - post the request to the SCU hardware
+ *
+ * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
+ *       into a SCIC_SDS_CONTROLLER object.
+ * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
+ *       SCIC_SDS_REMOTE_DEVICE object.
+ * @param[in] io_request This is the SCI_BASE_REQUEST which is cast to a
+ *       SCIC_SDS_IO_REQUEST object.
+ * @param[in] task_tag This is the task tag to be assigned to the task request
+ *       or SCI_CONTROLLER_INVALID_IO_TAG.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS if the start io operation succeeds
+ * @retval SCI_FAILURE_INSUFFICIENT_RESOURCES if the IO tag could not be
+ *         allocated for the io request.
+ * @retval SCI_FAILURE_INVALID_STATE if one or more objects are not in a valid
+ *         state to accept io requests.
+ *
+ * @todo How does the io tag get assigned in this code path?
+ */
+static
+SCI_STATUS scic_sds_controller_ready_state_start_task_handler(
+   SCI_BASE_CONTROLLER_T    *controller,
+   SCI_BASE_REMOTE_DEVICE_T *remote_device,
+   SCI_BASE_REQUEST_T       *io_request,
+   U16                       task_tag
+)
+{
+   SCIC_SDS_CONTROLLER_T    *this_controller = (SCIC_SDS_CONTROLLER_T *)
+                                               controller;
+   SCIC_SDS_REQUEST_T       *the_request     = (SCIC_SDS_REQUEST_T *)
+                                               io_request;
+   SCIC_SDS_REMOTE_DEVICE_T *the_device      = (SCIC_SDS_REMOTE_DEVICE_T *)
+                                               remote_device;
+   SCI_STATUS                status;
+
+   status = scic_sds_remote_device_start_task(
+               this_controller, the_device, the_request
+            );
+
+   if (status == SCI_SUCCESS)
+   {
+      this_controller->io_request_table[
+         scic_sds_io_tag_get_index(the_request->io_tag)] = the_request;
+
+      scic_sds_controller_post_request(
+         this_controller,
+         scic_sds_request_get_post_context(the_request)
+      );
+   }
+   else if (status == SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS)
+   {
+      this_controller->io_request_table[
+         scic_sds_io_tag_get_index(the_request->io_tag)] = the_request;
+
+      //We will let framework know this task request started successfully,
+      //although core is still woring on starting the request (to post tc when
+      //RNC is resumed.)
+      status = SCI_SUCCESS;
+   }
+   return status;
+}
+
+/**
+ * This method is called when the SCIC_SDS_CONTROLLER is in the ready state
+ * and the terminate request handler is called.
+ *    - call the io request terminate function
+ *    - if successful
+ *       - post the terminate request to the SCU hardware
+ *
+ * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
+ *       into a SCIC_SDS_CONTROLLER object.
+ * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
+ *       SCIC_SDS_REMOTE_DEVICE object.
+ * @param[in] io_request This is the SCI_BASE_REQUEST which is cast to a
+ *       SCIC_SDS_IO_REQUEST object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS if the start io operation succeeds
+ * @retval SCI_FAILURE_INVALID_STATE if one or more objects are not in a valid
+ *         state to accept io requests.
+ */
+static
+SCI_STATUS scic_sds_controller_ready_state_terminate_request_handler(
+   SCI_BASE_CONTROLLER_T    *controller,
+   SCI_BASE_REMOTE_DEVICE_T *remote_device,
+   SCI_BASE_REQUEST_T       *io_request
+)
+{
+   SCIC_SDS_CONTROLLER_T    *this_controller = (SCIC_SDS_CONTROLLER_T *)
+                                               controller;
+   SCIC_SDS_REQUEST_T       *the_request     = (SCIC_SDS_REQUEST_T *)
+                                               io_request;
+   SCI_STATUS                status;
+
+   status = scic_sds_io_request_terminate(the_request);
+   if (status == SCI_SUCCESS)
+   {
+      // Utilize the original post context command and or in the POST_TC_ABORT
+      // request sub-type.
+      scic_sds_controller_post_request(
+         this_controller,
+         scic_sds_request_get_post_context(the_request)
+         | SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT
+      );
+   }
+
+   return status;
+}
+
+/**
+ * This method is called when the SCIC_SDS_CONTROLLER is in the starting state
+ * link up handler is called.  This method will perform the following:
+ *    - Stop the phy timer
+ *    - Start the next phy
+ *    - Report the link up condition to the port object
+ *
+ * @param[in] controller This is SCIC_SDS_CONTROLLER which receives the link up
+ *       notification.
+ * @param[in] port This is SCIC_SDS_PORT with which the phy is associated.
+ * @param[in] phy This is the SCIC_SDS_PHY which has gone link up.
+ *
+ * @return none
+ */
+static
+void scic_sds_controller_ready_state_link_up_handler(
+   SCIC_SDS_CONTROLLER_T *this_controller,
+   SCIC_SDS_PORT_T       *port,
+   SCIC_SDS_PHY_T        *phy
+)
+{
+   this_controller->port_agent.link_up_handler(
+      this_controller, &this_controller->port_agent, port, phy
+   );
+}
+
+/**
+ * This method is called when the SCIC_SDS_CONTROLLER is in the starting state
+ * link down handler is called.
+ *    - Report the link down condition to the port object
+ *
+ * @param[in] controller This is SCIC_SDS_CONTROLLER which receives the
+ *       link down notification.
+ * @param[in] port This is SCIC_SDS_PORT with which the phy is associated.
+ * @param[in] phy This is the SCIC_SDS_PHY which has gone link down.
+ *
+ * @return none
+ */
+static
+void scic_sds_controller_ready_state_link_down_handler(
+   SCIC_SDS_CONTROLLER_T *this_controller,
+   SCIC_SDS_PORT_T       *port,
+   SCIC_SDS_PHY_T        *phy
+)
+{
+   this_controller->port_agent.link_down_handler(
+      this_controller, &this_controller->port_agent, port, phy
+   );
+}
+
+//*****************************************************************************
+//* STOPPING STATE HANDLERS
+//*****************************************************************************
+
+/**
+ * This method is called when the SCIC_SDS_CONTROLLER is in a stopping state
+ * and the complete io handler is called.
+ *    - This function is not yet implemented
+ *
+ * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
+ *       into a SCIC_SDS_CONTROLLER object.
+ * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
+ *       SCIC_SDS_REMOTE_DEVICE object.
+ * @param[in] io_request This is the SCI_BASE_REQUEST which is cast to a
+ *       SCIC_SDS_IO_REQUEST object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE
+ */
+static
+SCI_STATUS scic_sds_controller_stopping_state_complete_io_handler(
+   SCI_BASE_CONTROLLER_T    *controller,
+   SCI_BASE_REMOTE_DEVICE_T *remote_device,
+   SCI_BASE_REQUEST_T       *io_request
+)
+{
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+
+   /// @todo Implement this function
+   return SCI_FAILURE;
+}
+
+/**
+ * This method is called when the SCIC_SDS_CONTROLLER is in a stopping state
+ * and the a remote device has stopped.
+ *
+ * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
+ *       into a SCIC_SDS_CONTROLLER object.
+ * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
+ *       SCIC_SDS_REMOTE_DEVICE object.
+ *
+ * @return none
+ */
+static
+void scic_sds_controller_stopping_state_device_stopped_handler(
+   SCIC_SDS_CONTROLLER_T    * controller,
+   SCIC_SDS_REMOTE_DEVICE_T * remote_device
+)
+{
+   if (!scic_sds_controller_has_remote_devices_stopping(controller))
+   {
+      sci_base_state_machine_change_state(
+         &controller->parent.state_machine,
+         SCI_BASE_CONTROLLER_STATE_STOPPED
+      );
+   }
+}
+
+//*****************************************************************************
+//* STOPPED STATE HANDLERS
+//*****************************************************************************
+
+//*****************************************************************************
+//* FAILED STATE HANDLERS
+//*****************************************************************************
+
+/**
+ * This method is called when the SCIC_SDS_CONTROLLER failed state start
+ * io/task handler is in place.
+ *    - Issue a warning message
+ *
+ * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
+ *       into a SCIC_SDS_CONTROLLER object.
+ * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which, if it was
+ *       used, would be cast to a SCIC_SDS_REMOTE_DEVICE.
+ * @param[in] io_request This is the SCI_BASE_REQUEST which, if it was used,
+ *       would be cast to a SCIC_SDS_IO_REQUEST.
+ * @param[in] io_tag This is the IO tag to be assigned to the IO request or
+ *       SCI_CONTROLLER_INVALID_IO_TAG.
+ *
+ * @return SCI_FAILURE
+ * @retval SCI_FAILURE
+ */
+static
+SCI_STATUS scic_sds_controller_failed_state_start_operation_handler(
+   SCI_BASE_CONTROLLER_T    *controller,
+   SCI_BASE_REMOTE_DEVICE_T *remote_device,
+   SCI_BASE_REQUEST_T       *io_request,
+   U16                       io_tag
+)
+{
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger(this_controller),
+      SCIC_LOG_OBJECT_CONTROLLER,
+      "SCIC Controller requested to start an io/task from failed state %d\n",
+      sci_base_state_machine_get_state(
+         scic_sds_controller_get_base_state_machine(this_controller))
+   ));
+
+   return SCI_FAILURE;
+}
+
+/**
+ * This method is called when the SCIC_SDS_CONTROLLER is in the failed state
+ * reset handler is in place.
+ *    - Transition to SCI_BASE_CONTROLLER_STATE_RESETTING
+ *
+ * @param[in] controller The SCI_BASE_CONTROLLER object which is cast into a
+ *       SCIC_SDS_CONTROLLER object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE if fatal memory error occurred
+ */
+static
+SCI_STATUS scic_sds_controller_failed_state_reset_handler(
+   SCI_BASE_CONTROLLER_T *controller
+)
+{
+    SCIC_SDS_CONTROLLER_T *this_controller;
+    this_controller = (SCIC_SDS_CONTROLLER_T *)controller;
+
+    if (this_controller->parent.error == SCI_CONTROLLER_FATAL_MEMORY_ERROR) {
+        SCIC_LOG_TRACE((
+           sci_base_object_get_logger(controller),
+           SCIC_LOG_OBJECT_CONTROLLER,
+           "scic_sds_controller_resetting_state_enter(0x%x) enter\n not allowed with fatal memory error",
+           controller
+        ));
+
+        return SCI_FAILURE;
+    } else {
+        return scic_sds_controller_general_reset_handler(controller);
+    }
+}
+
+/**
+ * This method is called when the SCIC_SDS_CONTROLLER is in the failed state
+ * and the terminate request handler is called.
+ *    - call the io request terminate function
+ *    - if successful
+ *       - post the terminate request to the SCU hardware
+ *
+ * @param[in] controller This is SCI_BASE_CONTROLLER object which is cast
+ *       into a SCIC_SDS_CONTROLLER object.
+ * @param[in] remote_device This is SCI_BASE_REMOTE_DEVICE which is cast to a
+ *       SCIC_SDS_REMOTE_DEVICE object.
+ * @param[in] io_request This is the SCI_BASE_REQUEST which is cast to a
+ *       SCIC_SDS_IO_REQUEST object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS if the start io operation succeeds
+ * @retval SCI_FAILURE_INVALID_STATE if one or more objects are not in a valid
+ *         state to accept io requests.
+ */
+static
+SCI_STATUS scic_sds_controller_failed_state_terminate_request_handler(
+   SCI_BASE_CONTROLLER_T    *controller,
+   SCI_BASE_REMOTE_DEVICE_T *remote_device,
+   SCI_BASE_REQUEST_T       *io_request
+)
+{
+   SCIC_SDS_REQUEST_T       *the_request     = (SCIC_SDS_REQUEST_T *)
+                                               io_request;
+
+   return scic_sds_io_request_terminate(the_request);
+}
+
+SCIC_SDS_CONTROLLER_STATE_HANDLER_T
+   scic_sds_controller_state_handler_table[SCI_BASE_CONTROLLER_MAX_STATES] =
+{
+   // SCI_BASE_CONTROLLER_STATE_INITIAL
+   {
+      {
+         NULL,
+         NULL,
+         NULL,
+         NULL,
+         scic_sds_controller_default_start_operation_handler,
+         scic_sds_controller_default_start_operation_handler,
+         scic_sds_controller_default_request_handler,
+         scic_sds_controller_default_request_handler,
+         scic_sds_controller_default_request_handler,
+         NULL,
+         NULL
+      },
+      scic_sds_controller_default_request_handler,
+      NULL,
+      NULL,
+      NULL,
+      NULL
+   },
+   // SCI_BASE_CONTROLLER_STATE_RESET
+   {
+      {
+         NULL,
+         NULL,
+         NULL,
+         scic_sds_controller_reset_state_initialize_handler,
+         scic_sds_controller_default_start_operation_handler,
+         scic_sds_controller_default_start_operation_handler,
+         scic_sds_controller_default_request_handler,
+         scic_sds_controller_default_request_handler,
+         scic_sds_controller_default_request_handler,
+         NULL,
+         NULL
+      },
+      scic_sds_controller_default_request_handler,
+      NULL,
+      NULL,
+      NULL,
+      NULL
+   },
+   // SCI_BASE_CONTROLLER_STATE_INITIALIZING
+   {
+      {
+         NULL,
+         NULL,
+         NULL,
+         NULL,
+         scic_sds_controller_default_start_operation_handler,
+         scic_sds_controller_default_start_operation_handler,
+         scic_sds_controller_default_request_handler,
+         scic_sds_controller_default_request_handler,
+         scic_sds_controller_default_request_handler,
+         NULL,
+         NULL
+      },
+      scic_sds_controller_default_request_handler,
+      NULL,
+      NULL,
+      NULL,
+      NULL
+   },
+   // SCI_BASE_CONTROLLER_STATE_INITIALIZED
+   {
+      {
+         scic_sds_controller_initialized_state_start_handler,
+         NULL,
+         NULL,
+         NULL,
+         scic_sds_controller_default_start_operation_handler,
+         scic_sds_controller_default_start_operation_handler,
+         scic_sds_controller_default_request_handler,
+         scic_sds_controller_default_request_handler,
+         scic_sds_controller_default_request_handler,
+         NULL,
+         NULL
+      },
+      scic_sds_controller_default_request_handler,
+      NULL,
+      NULL,
+      NULL,
+      NULL
+   },
+   // SCI_BASE_CONTROLLER_STATE_STARTING
+   {
+      {
+         NULL,
+         NULL,
+         NULL,
+         NULL,
+         scic_sds_controller_default_start_operation_handler,
+         scic_sds_controller_default_start_operation_handler,
+         scic_sds_controller_default_request_handler,
+         scic_sds_controller_default_request_handler,
+         scic_sds_controller_default_request_handler,
+         NULL,
+         NULL
+      },
+      scic_sds_controller_default_request_handler,
+      scic_sds_controller_starting_state_link_up_handler,
+      scic_sds_controller_starting_state_link_down_handler,
+      NULL,
+      NULL
+   },
+   // SCI_BASE_CONTROLLER_STATE_READY
+   {
+      {
+         NULL,
+         scic_sds_controller_ready_state_stop_handler,
+         scic_sds_controller_general_reset_handler,
+         NULL,
+         scic_sds_controller_ready_state_start_io_handler,
+         scic_sds_controller_default_start_operation_handler,
+         scic_sds_controller_ready_state_complete_io_handler,
+         scic_sds_controller_default_request_handler,
+         scic_sds_controller_ready_state_continue_io_handler,
+         scic_sds_controller_ready_state_start_task_handler,
+         scic_sds_controller_ready_state_complete_io_handler
+      },
+      scic_sds_controller_ready_state_terminate_request_handler,
+      scic_sds_controller_ready_state_link_up_handler,
+      scic_sds_controller_ready_state_link_down_handler,
+      NULL,
+      NULL
+   },
+   // SCI_BASE_CONTROLLER_STATE_RESETTING
+   {
+      {
+         NULL,
+         NULL,
+         NULL,
+         NULL,
+         scic_sds_controller_default_start_operation_handler,
+         scic_sds_controller_default_start_operation_handler,
+         scic_sds_controller_default_request_handler,
+         scic_sds_controller_default_request_handler,
+         scic_sds_controller_default_request_handler,
+         NULL,
+         NULL
+      },
+      scic_sds_controller_default_request_handler,
+      NULL,
+      NULL,
+      NULL,
+      NULL
+   },
+   // SCI_BASE_CONTROLLER_STATE_STOPPING
+   {
+      {
+         NULL,
+         NULL,
+         NULL,
+         NULL,
+         scic_sds_controller_default_start_operation_handler,
+         scic_sds_controller_default_start_operation_handler,
+         scic_sds_controller_stopping_state_complete_io_handler,
+         scic_sds_controller_default_request_handler,
+         scic_sds_controller_default_request_handler,
+         NULL,
+         NULL
+      },
+      scic_sds_controller_default_request_handler,
+      NULL,
+      NULL,
+      NULL,
+      scic_sds_controller_stopping_state_device_stopped_handler
+   },
+   // SCI_BASE_CONTROLLER_STATE_STOPPED
+   {
+      {
+         NULL,
+         NULL,
+         scic_sds_controller_failed_state_reset_handler,
+         NULL,
+         scic_sds_controller_default_start_operation_handler,
+         scic_sds_controller_default_start_operation_handler,
+         scic_sds_controller_default_request_handler,
+         scic_sds_controller_default_request_handler,
+         scic_sds_controller_default_request_handler,
+         NULL,
+         NULL
+      },
+      scic_sds_controller_default_request_handler,
+      NULL,
+      NULL,
+      NULL,
+      NULL
+   },
+   // SCI_BASE_CONTROLLER_STATE_FAILED
+   {
+      {
+         NULL,
+         NULL,
+         scic_sds_controller_general_reset_handler,
+         NULL,
+         scic_sds_controller_failed_state_start_operation_handler,
+         scic_sds_controller_failed_state_start_operation_handler,
+         scic_sds_controller_default_request_handler,
+         scic_sds_controller_default_request_handler,
+         scic_sds_controller_default_request_handler,
+         NULL,
+         NULL
+      },
+      scic_sds_controller_failed_state_terminate_request_handler,
+      NULL,
+      NULL,
+      NULL
+   }
+};
+
+/**
+ * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
+ * entry to the SCI_BASE_CONTROLLER_STATE_INITIAL.
+ *    - Set the state handlers to the controllers initial state.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_CONTROLLER object.
+ *
+ * @return none
+ *
+ * @todo This function should initialze the controller object.
+ */
+static
+void scic_sds_controller_initial_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller= (SCIC_SDS_CONTROLLER_T *)object;
+
+   scic_sds_controller_set_base_state_handlers(
+      this_controller, SCI_BASE_CONTROLLER_STATE_INITIAL);
+
+   sci_base_state_machine_change_state(
+      &this_controller->parent.state_machine, SCI_BASE_CONTROLLER_STATE_RESET);
+}
+
+/**
+ * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
+ * entry to the SCI_BASE_CONTROLLER_STATE_RESET.
+ *    - Set the state handlers to the controllers reset state.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_CONTROLLER object.
+ *
+ * @return none
+ */
+static
+void scic_sds_controller_reset_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   U8 index;
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller= (SCIC_SDS_CONTROLLER_T *)object;
+
+   scic_sds_controller_set_base_state_handlers(
+      this_controller, SCI_BASE_CONTROLLER_STATE_RESET);
+
+   scic_sds_port_configuration_agent_construct(&this_controller->port_agent);
+
+   // Construct the ports for this controller
+   for (index = 0; index < (SCI_MAX_PORTS + 1); index++)
+   {
+      scic_sds_port_construct(
+         &this_controller->port_table[index],
+         (index == SCI_MAX_PORTS) ? SCIC_SDS_DUMMY_PORT : index,
+         this_controller
+      );
+   }
+
+   // Construct the phys for this controller
+   for (index = 0; index < SCI_MAX_PHYS; index++)
+   {
+      // Add all the PHYs to the dummy port
+      scic_sds_phy_construct(
+         &this_controller->phy_table[index],
+         &this_controller->port_table[SCI_MAX_PORTS],
+         index
+      );
+   }
+
+   this_controller->invalid_phy_mask = 0;
+
+   // Set the default maximum values
+   this_controller->completion_event_entries      = SCU_EVENT_COUNT;
+   this_controller->completion_queue_entries      = SCU_COMPLETION_QUEUE_COUNT;
+   this_controller->remote_node_entries           = SCI_MAX_REMOTE_DEVICES;
+   this_controller->logical_port_entries          = SCI_MAX_PORTS;
+   this_controller->task_context_entries          = SCU_IO_REQUEST_COUNT;
+   this_controller->uf_control.buffers.count      = SCU_UNSOLICITED_FRAME_COUNT;
+   this_controller->uf_control.address_table.count= SCU_UNSOLICITED_FRAME_COUNT;
+
+   // Initialize the User and OEM parameters to default values.
+   scic_sds_controller_set_default_config_parameters(this_controller);
+}
+
+/**
+ * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
+ * entry to the SCI_BASE_CONTROLLER_STATE_INITIALIZING.
+ *    - Set the state handlers to the controllers initializing state.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_CONTROLLER object.
+ *
+ * @return none
+ */
+static
+void scic_sds_controller_initializing_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller= (SCIC_SDS_CONTROLLER_T *)object;
+
+   scic_sds_controller_set_base_state_handlers(
+      this_controller, SCI_BASE_CONTROLLER_STATE_INITIALIZING);
+}
+
+/**
+ * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
+ * entry to the SCI_BASE_CONTROLLER_STATE_INITIALIZED.
+ *    - Set the state handlers to the controllers initialized state.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_CONTROLLER object.
+ *
+ * @return none
+ */
+static
+void scic_sds_controller_initialized_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller= (SCIC_SDS_CONTROLLER_T *)object;
+
+   scic_sds_controller_set_base_state_handlers(
+      this_controller, SCI_BASE_CONTROLLER_STATE_INITIALIZED);
+}
+
+/**
+ * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
+ * entry to the SCI_BASE_CONTROLLER_STATE_STARTING.
+ *    - Set the state handlers to the controllers starting state.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_CONTROLLER object.
+ *
+ * @return none
+ */
+static
+void scic_sds_controller_starting_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller= (SCIC_SDS_CONTROLLER_T *)object;
+
+   scic_sds_controller_set_base_state_handlers(
+      this_controller, SCI_BASE_CONTROLLER_STATE_STARTING);
+
+}
+
+/**
+ * This method implements the actions taken by the SCIC_SDS_CONTROLLER on exit
+ * from the SCI_BASE_CONTROLLER_STATE_STARTING.
+ *    - This function stops the controller starting timeout timer.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_CONTROLLER object.
+ *
+ * @return none
+ */
+static
+void scic_sds_controller_starting_state_exit(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller= (SCIC_SDS_CONTROLLER_T *)object;
+
+   scic_cb_timer_stop(object, this_controller->timeout_timer);
+
+   // We are done with this timer since we are exiting the starting
+   // state so remove it
+   scic_cb_timer_destroy(
+      this_controller,
+      this_controller->phy_startup_timer
+   );
+
+   this_controller->phy_startup_timer = NULL;
+}
+
+/**
+ * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
+ * entry to the SCI_BASE_CONTROLLER_STATE_READY.
+ *    - Set the state handlers to the controllers ready state.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_CONTROLLER object.
+ *
+ * @return none
+ */
+static
+void scic_sds_controller_ready_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   U32 clock_gating_unit_value;
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller= (SCIC_SDS_CONTROLLER_T *)object;
+
+   scic_sds_controller_set_base_state_handlers(
+      this_controller, SCI_BASE_CONTROLLER_STATE_READY);
+
+   /**
+    * enable clock gating for power control of the scu unit
+    */
+   clock_gating_unit_value = SMU_CGUCR_READ(this_controller);
+
+   clock_gating_unit_value &= ~( SMU_CGUCR_GEN_BIT(REGCLK_ENABLE)
+                               | SMU_CGUCR_GEN_BIT(TXCLK_ENABLE)
+                               | SMU_CGUCR_GEN_BIT(XCLK_ENABLE) );
+   clock_gating_unit_value |= SMU_CGUCR_GEN_BIT(IDLE_ENABLE);
+
+   SMU_CGUCR_WRITE(this_controller, clock_gating_unit_value);
+
+   //set the default interrupt coalescence number and timeout value.
+   scic_controller_set_interrupt_coalescence(
+      this_controller, 0x10, 250);
+}
+
+/**
+ * This method implements the actions taken by the SCIC_SDS_CONTROLLER on exit
+ * from the SCI_BASE_CONTROLLER_STATE_READY.
+ *    - This function does nothing.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_CONTROLLER object.
+ *
+ * @return none
+ */
+static
+void scic_sds_controller_ready_state_exit(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   U32 clock_gating_unit_value;
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller= (SCIC_SDS_CONTROLLER_T *)object;
+
+   /**
+    * restore clock gating for power control of the scu unit
+    */
+   clock_gating_unit_value = SMU_CGUCR_READ(this_controller);
+
+   clock_gating_unit_value &= ~SMU_CGUCR_GEN_BIT(IDLE_ENABLE);
+   clock_gating_unit_value |= ( SMU_CGUCR_GEN_BIT(REGCLK_ENABLE)
+                              | SMU_CGUCR_GEN_BIT(TXCLK_ENABLE)
+                              | SMU_CGUCR_GEN_BIT(XCLK_ENABLE) );
+
+   SMU_CGUCR_WRITE(this_controller, clock_gating_unit_value);
+
+   //disable interrupt coalescence.
+   scic_controller_set_interrupt_coalescence(this_controller, 0, 0);
+}
+
+/**
+ * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
+ * entry to the SCI_BASE_CONTROLLER_STATE_READY.
+ *    - Set the state handlers to the controllers ready state.
+ *    - Stop all of the remote devices on this controller
+ *    - Stop the ports on this controller
+ *    - Stop the phys on this controller
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_CONTROLLER object.
+ *
+ * @return none
+ */
+static
+void scic_sds_controller_stopping_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller= (SCIC_SDS_CONTROLLER_T *)object;
+
+   scic_sds_controller_set_base_state_handlers(
+      this_controller, SCI_BASE_CONTROLLER_STATE_STOPPING);
+
+   // Stop all of the components for this controller in the reverse order
+   // from which they are initialized.
+   scic_sds_controller_stop_devices(this_controller);
+   scic_sds_controller_stop_ports(this_controller);
+
+   if (!scic_sds_controller_has_remote_devices_stopping(this_controller))
+   {
+      sci_base_state_machine_change_state(
+         &this_controller->parent.state_machine,
+         SCI_BASE_CONTROLLER_STATE_STOPPED
+      );
+   }
+}
+
+/**
+ * This method implements the actions taken by the SCIC_SDS_CONTROLLER on exit
+ * from the SCI_BASE_CONTROLLER_STATE_STOPPING.
+ *    - This function stops the controller stopping timeout timer.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_CONTROLLER object.
+ *
+ * @return none
+ */
+static
+void scic_sds_controller_stopping_state_exit(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller= (SCIC_SDS_CONTROLLER_T *)object;
+
+   scic_cb_timer_stop(this_controller, this_controller->timeout_timer);
+}
+
+/**
+ * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
+ * entry to the SCI_BASE_CONTROLLER_STATE_STOPPED.
+ *    - Set the state handlers to the controllers stopped state.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_CONTROLLER object.
+ *
+ * @return none
+ */
+static
+void scic_sds_controller_stopped_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller= (SCIC_SDS_CONTROLLER_T *)object;
+
+   scic_sds_controller_set_base_state_handlers(
+      this_controller, SCI_BASE_CONTROLLER_STATE_STOPPED);
+
+   // We are done with this timer until the next timer we initialize
+   scic_cb_timer_destroy(
+      this_controller,
+      this_controller->timeout_timer
+   );
+   this_controller->timeout_timer = NULL;
+
+   // Controller has stopped so disable all the phys on this controller
+   scic_sds_controller_stop_phys(this_controller);
+
+   scic_sds_port_configuration_agent_destroy(
+      this_controller,
+      &this_controller->port_agent
+   );
+
+   scic_cb_controller_stop_complete(this_controller, SCI_SUCCESS);
+}
+
+/**
+ * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
+ * entry to the SCI_BASE_CONTROLLER_STATE_RESETTING.
+ *    - Set the state handlers to the controllers resetting state.
+ *    - Write to the SCU hardware reset register to force a reset
+ *    - Transition to the SCI_BASE_CONTROLLER_STATE_RESET
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_CONTROLLER object.
+ *
+ * @return none
+ */
+static
+void scic_sds_controller_resetting_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller= (SCIC_SDS_CONTROLLER_T *)object;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_controller),
+      SCIC_LOG_OBJECT_CONTROLLER,
+      "scic_sds_controller_resetting_state_enter(0x%x) enter\n",
+      this_controller
+   ));
+
+   scic_sds_controller_set_base_state_handlers(
+      this_controller, SCI_BASE_CONTROLLER_STATE_RESETTING);
+
+   scic_sds_controller_reset_hardware(this_controller);
+
+   sci_base_state_machine_change_state(
+      scic_sds_controller_get_base_state_machine(this_controller),
+      SCI_BASE_CONTROLLER_STATE_RESET
+   );
+}
+
+static
+SCI_STATUS scic_sds_abort_reqests(
+        SCIC_SDS_CONTROLLER_T * controller,
+        SCIC_SDS_REMOTE_DEVICE_T * remote_device,
+        SCIC_SDS_PORT_T * port
+)
+{
+    SCI_STATUS          status           = SCI_SUCCESS;
+    SCI_STATUS          terminate_status = SCI_SUCCESS;
+    SCIC_SDS_REQUEST_T *the_request;
+    U32                 index;
+    U32                 request_count;
+
+    if (remote_device != NULL)
+        request_count = remote_device->started_request_count;
+    else if (port != NULL)
+        request_count = port->started_request_count;
+    else
+        request_count = SCI_MAX_IO_REQUESTS;
+
+
+    for (index = 0;
+         (index < SCI_MAX_IO_REQUESTS) && (request_count > 0);
+         index++)
+    {
+       the_request = controller->io_request_table[index];
+
+       if (the_request != NULL)
+       {
+           if (the_request->target_device == remote_device
+                   || the_request->target_device->owning_port == port
+                   || (remote_device == NULL && port == NULL))
+           {
+               terminate_status = scic_controller_terminate_request(
+                                     controller,
+                                     the_request->target_device,
+                                     the_request
+                                  );
+
+               if (terminate_status != SCI_SUCCESS)
+                  status = terminate_status;
+
+               request_count--;
+           }
+       }
+    }
+
+    return status;
+}
+
+SCI_STATUS scic_sds_terminate_reqests(
+        SCIC_SDS_CONTROLLER_T *this_controller,
+        SCIC_SDS_REMOTE_DEVICE_T *this_remote_device,
+        SCIC_SDS_PORT_T *this_port
+)
+{
+    SCI_STATUS status = SCI_SUCCESS;
+    SCI_STATUS abort_status = SCI_SUCCESS;
+
+    // move all request to abort state
+    abort_status = scic_sds_abort_reqests(this_controller, this_remote_device, this_port);
+
+    if (abort_status != SCI_SUCCESS)
+        status = abort_status;
+
+    //move all request to complete state
+    if (this_controller->parent.error == SCI_CONTROLLER_FATAL_MEMORY_ERROR)
+        abort_status = scic_sds_abort_reqests(this_controller, this_remote_device, this_port);
+
+    if (abort_status != SCI_SUCCESS)
+        status = abort_status;
+
+    return status;
+}
+
+static
+SCI_STATUS scic_sds_terminate_all_requests(
+        SCIC_SDS_CONTROLLER_T * controller
+)
+{
+    return scic_sds_terminate_reqests(controller, NULL, NULL);
+}
+
+/**
+ * This method implements the actions taken by the SCIC_SDS_CONTROLLER on
+ * entry to the SCI_BASE_CONTROLLER_STATE_FAILED.
+ *    - Set the state handlers to the controllers failed state.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_CONTROLLER object.
+ *
+ * @return none
+ */
+static
+void scic_sds_controller_failed_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_CONTROLLER_T *this_controller;
+   this_controller= (SCIC_SDS_CONTROLLER_T *)object;
+
+   scic_sds_controller_set_base_state_handlers(
+      this_controller, SCI_BASE_CONTROLLER_STATE_FAILED);
+
+   if (this_controller->parent.error == SCI_CONTROLLER_FATAL_MEMORY_ERROR)
+   scic_sds_terminate_all_requests(this_controller);
+   else
+       scic_sds_controller_release_resource(this_controller);
+
+   //notify framework the controller failed.
+   scic_cb_controller_error(this_controller,
+           this_controller->parent.error);
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_BASE_STATE_T
+   scic_sds_controller_state_table[SCI_BASE_CONTROLLER_MAX_STATES] =
+{
+   {
+      SCI_BASE_CONTROLLER_STATE_INITIAL,
+      scic_sds_controller_initial_state_enter,
+      NULL,
+   },
+   {
+      SCI_BASE_CONTROLLER_STATE_RESET,
+      scic_sds_controller_reset_state_enter,
+      NULL,
+   },
+   {
+      SCI_BASE_CONTROLLER_STATE_INITIALIZING,
+      scic_sds_controller_initializing_state_enter,
+      NULL,
+   },
+   {
+      SCI_BASE_CONTROLLER_STATE_INITIALIZED,
+      scic_sds_controller_initialized_state_enter,
+      NULL,
+   },
+   {
+      SCI_BASE_CONTROLLER_STATE_STARTING,
+      scic_sds_controller_starting_state_enter,
+      scic_sds_controller_starting_state_exit,
+   },
+   {
+      SCI_BASE_CONTROLLER_STATE_READY,
+      scic_sds_controller_ready_state_enter,
+      scic_sds_controller_ready_state_exit,
+   },
+   {
+      SCI_BASE_CONTROLLER_STATE_RESETTING,
+      scic_sds_controller_resetting_state_enter,
+      NULL,
+   },
+   {
+      SCI_BASE_CONTROLLER_STATE_STOPPING,
+      scic_sds_controller_stopping_state_enter,
+      scic_sds_controller_stopping_state_exit,
+   },
+   {
+      SCI_BASE_CONTROLLER_STATE_STOPPED,
+      scic_sds_controller_stopped_state_enter,
+      NULL,
+   },
+   {
+      SCI_BASE_CONTROLLER_STATE_FAILED,
+      scic_sds_controller_failed_state_enter,
+      NULL,
+   }
+};
diff --git a/sys/dev/disk/isci/scil/scic_sds_controller.h b/sys/dev/disk/isci/scil/scic_sds_controller.h
new file mode 100644
index 0000000..9cc2107
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_sds_controller.h
@@ -0,0 +1,840 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_sds_controller.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIC_SDS_CONTROLLER_H_
+#define _SCIC_SDS_CONTROLLER_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains the structures, constants and prototypes used for
+ *        the core controller object.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_pool.h>
+#include <dev/disk/isci/scil/sci_controller_constants.h>
+#include <dev/disk/isci/scil/sci_memory_descriptor_list.h>
+#include <dev/disk/isci/scil/sci_base_controller.h>
+#include <dev/disk/isci/scil/scic_config_parameters.h>
+#include <dev/disk/isci/scil/scic_sds_port.h>
+#include <dev/disk/isci/scil/scic_sds_phy.h>
+#include <dev/disk/isci/scil/scic_sds_remote_node_table.h>
+#include <dev/disk/isci/scil/scu_registers.h>
+#include <dev/disk/isci/scil/scu_constants.h>
+#include <dev/disk/isci/scil/scu_remote_node_context.h>
+#include <dev/disk/isci/scil/scu_task_context.h>
+#include <dev/disk/isci/scil/scu_unsolicited_frame.h>
+#include <dev/disk/isci/scil/scic_sds_unsolicited_frame_control.h>
+#include <dev/disk/isci/scil/scic_sds_port_configuration_agent.h>
+#include <dev/disk/isci/scil/scic_sds_pci.h>
+
+struct SCIC_SDS_REMOTE_DEVICE;
+struct SCIC_SDS_REQUEST;
+
+
+#define SCU_COMPLETION_RAM_ALIGNMENT            (64)
+
+/**
+ * @enum SCIC_SDS_CONTROLLER_MEMORY_DESCRIPTORS
+ *
+ * This enumeration depects the types of MDEs that are going to be created for
+ * the controller object.
+ */
+enum SCIC_SDS_CONTROLLER_MEMORY_DESCRIPTORS
+{
+   /**
+    * Completion queue MDE entry
+    */
+   SCU_MDE_COMPLETION_QUEUE,
+
+   /**
+    * Remote node context MDE entry
+    */
+   SCU_MDE_REMOTE_NODE_CONTEXT,
+
+   /**
+    * Task context MDE entry
+    */
+   SCU_MDE_TASK_CONTEXT,
+
+   /**
+    * Unsolicited frame buffer MDE entrys this is the start of the unsolicited
+    * frame buffer entries.
+    */
+   SCU_MDE_UF_BUFFER,
+
+   SCU_MAX_MDES
+};
+
+/**
+ * @struct SCIC_POWER_CONTROL
+ *
+ * This structure defines the fields for managing power control for direct
+ * attached disk devices.
+ */
+typedef struct SCIC_POWER_CONTROL
+{
+   /**
+    * This field is set when the power control timer is running and cleared when
+    * it is not.
+    */
+   BOOL timer_started;
+
+   /**
+    * This field is the handle to the driver timer object.  This timer is used to
+    * control when the directed attached disks can consume power.
+    */
+   void *timer;
+
+   /**
+   * This field is used to keep track of how many phys are put into the
+   * requesters field.
+   */
+   U8 phys_waiting;
+
+   /**
+   * This field is used to keep track of how many remote devices have been granted to consume power
+   */
+   U8 remote_devices_granted_power;
+
+   /**
+    * This field is an array of phys that we are waiting on. The phys are direct
+    * mapped into requesters via SCIC_SDS_PHY_T.phy_index
+    */
+   SCIC_SDS_PHY_T *requesters[SCI_MAX_PHYS];
+
+} SCIC_POWER_CONTROL_T;
+
+/**
+ * @struct SCIC_SDS_CONTROLLER
+ *
+ * This structure represents the SCU contoller object.
+ */
+typedef struct SCIC_SDS_CONTROLLER
+{
+   /**
+    * The SCI_BASE_CONTROLLER is the parent object for the SCIC_SDS_CONTROLLER
+    * object.
+    */
+   SCI_BASE_CONTROLLER_T parent;
+
+   /**
+    * This field is the driver timer object handler used to time the controller
+    * object start and stop requests.
+    */
+   void *timeout_timer;
+
+   /**
+    * This field is the current set of state handlers assigned to this controller
+    * object.
+    */
+   struct SCIC_SDS_CONTROLLER_STATE_HANDLER *state_handlers;
+
+   /**
+    * This field contains the user parameters to be utilized for this
+    * core controller object.
+    */
+   SCIC_USER_PARAMETERS_T  user_parameters;
+
+   /**
+    * This field contains the OEM parameters version defining the structure
+    * layout. It comes from the version in the OEM block header.
+    */
+   U8 oem_parameters_version;
+
+   /**
+    * This field contains the OEM parameters to be utilized for this
+    * core controller object.
+    */
+   SCIC_OEM_PARAMETERS_T  oem_parameters;
+
+   /**
+    * This field contains the port configuration agent for this controller.
+    */
+   SCIC_SDS_PORT_CONFIGURATION_AGENT_T port_agent;
+
+   /**
+    * This field is the array of port objects that are controlled by this
+    * controller object.  There is one dummy port object also contained within
+    * this controller object.
+    */
+   struct SCIC_SDS_PORT port_table[SCI_MAX_PORTS + 1];
+
+   /**
+    * This field is the array of phy objects that are controlled by this
+    * controller object.
+    */
+   struct SCIC_SDS_PHY phy_table[SCI_MAX_PHYS];
+
+   /**
+    * This field is the array of device objects that are currently constructed
+    * for this controller object.  This table is used as a fast lookup of device
+    * objects that need to handle device completion notifications from the
+    * hardware. The table is RNi based.
+    */
+   struct SCIC_SDS_REMOTE_DEVICE *device_table[SCI_MAX_REMOTE_DEVICES];
+
+   /**
+    * This field is the array of IO request objects that are currently active for
+    * this controller object.  This table is used as a fast lookup of the io
+    * request object that need to handle completion queue notifications.  The
+    * table is TCi based.
+    */
+   struct SCIC_SDS_REQUEST *io_request_table[SCI_MAX_IO_REQUESTS];
+
+   /**
+    * This field is the free RNi data structure
+    */
+   SCIC_REMOTE_NODE_TABLE_T available_remote_nodes;
+
+   /**
+    * This field is the TCi pool used to manage the task context index.
+    */
+   SCI_POOL_CREATE(tci_pool, U16, SCI_MAX_IO_REQUESTS);
+
+   /**
+    * This filed is the SCIC_POWER_CONTROL data used to controll when direct
+    * attached devices can consume power.
+    */
+   SCIC_POWER_CONTROL_T power_control;
+
+   /**
+    * This field is the array of sequence values for the IO Tag fields.  Even
+    * though only 4 bits of the field is used for the sequence the sequence is 16
+    * bits in size so the sequence can be bitwise or'd with the TCi to build the
+    * IO Tag value.
+    */
+   U16 io_request_sequence[SCI_MAX_IO_REQUESTS];
+
+   /**
+    * This field in the array of sequence values for the RNi.  These are used
+    * to control io request build to io request start operations.  The sequence
+    * value is recorded into an io request when it is built and is checked on
+    * the io request start operation to make sure that there was not a device
+    * hot plug between the build and start operation.
+    */
+   U8  remote_device_sequence[SCI_MAX_REMOTE_DEVICES];
+
+   /**
+    * This field is a pointer to the memory allocated by the driver for the task
+    * context table.  This data is shared between the hardware and software.
+    */
+   SCU_TASK_CONTEXT_T *task_context_table;
+
+   /**
+    * This field is a pointer to the memory allocated by the driver for the
+    * remote node context table.  This table is shared between the hardware and
+    * software.
+    */
+   SCU_REMOTE_NODE_CONTEXT_T *remote_node_context_table;
+
+   /**
+    * This field is the array of physical memory requiremets for this controller
+    * object.
+    */
+   SCI_PHYSICAL_MEMORY_DESCRIPTOR_T memory_descriptors[SCU_MAX_MDES];
+
+   /**
+    * This field is a pointer to the completion queue.  This memory is
+    * written to by the hardware and read by the software.
+    */
+   U32 *completion_queue;
+
+   /**
+    * This field is the software copy of the completion queue get pointer.  The
+    * controller object writes this value to the hardware after processing the
+    * completion entries.
+    */
+   U32 completion_queue_get;
+
+   /**
+    * This field is the minimum of the number of hardware supported port entries
+    * and the software requested port entries.
+    */
+   U32 logical_port_entries;
+
+   /**
+    * This field is the minimum number of hardware supported completion queue
+    * entries and the software requested completion queue entries.
+    */
+   U32 completion_queue_entries;
+
+   /**
+    * This field is the minimum number of hardware supported event entries and
+    * the software requested event entries.
+    */
+   U32 completion_event_entries;
+
+   /**
+    * This field is the minimum number of devices supported by the hardware and
+    * the number of devices requested by the software.
+    */
+   U32 remote_node_entries;
+
+   /**
+    * This field is the minimum number of IO requests supported by the hardware
+    * and the number of IO requests requested by the software.
+    */
+   U32 task_context_entries;
+
+   /**
+    * This object contains all of the unsolicited frame specific
+    * data utilized by the core controller.
+    */
+   SCIC_SDS_UNSOLICITED_FRAME_CONTROL_T uf_control;
+
+   /**
+    * This field records the fact that the controller has encountered a fatal
+    * error and must be reset.
+    */
+   BOOL encountered_fatal_error;
+
+   /**
+    * This field specifies that the controller should ignore
+    * completion processing for non-fastpath events.  This will
+    * cause the completions to be thrown away.
+    */
+   BOOL restrict_completions;
+
+   // Phy Startup Data
+   /**
+    * This field is the driver timer handle for controller phy request startup.
+    * On controller start the controller will start each PHY individually in
+    * order of phy index.
+    */
+   void *phy_startup_timer;
+
+   /**
+    * This field is set when the phy_startup_timer is running and is cleared when
+    * the phy_startup_timer is stopped.
+    */
+   BOOL phy_startup_timer_pending;
+
+   /**
+    * This field is the index of the next phy start.  It is initialized to 0 and
+    * increments for each phy index that is started.
+    */
+   U32 next_phy_to_start;
+
+   /**
+    * This field controlls the invalid link up notifications to the SCI_USER.  If
+    * an invalid_link_up notification is reported a bit for the PHY index is set
+    * so further notifications are not made.  Once the PHY object reports link up
+    * and is made part of a port then this bit for the PHY index is cleared.
+    */
+   U8  invalid_phy_mask;
+
+   /**
+    * This is the controller index for this controller object.
+    */
+   U8 controller_index;
+
+   /**
+    * This field is the PCI revision code for the controller object.
+    */
+   enum SCU_CONTROLLER_PCI_REVISION_CODE pci_revision;
+
+   /*
+    * This field saves the current interrupt coalescing number of the controller.
+    */
+   U16 interrupt_coalesce_number;
+
+   /*
+    * This field saves the current interrupt coalescing timeout value in microseconds.
+    */
+   U32 interrupt_coalesce_timeout;
+
+   // Hardware memory mapped register space
+#ifdef ARLINGTON_BUILD
+   /**
+    * This field is a pointer to the memory mapped register space for the
+    * LEX_REGISTERS.
+    */
+   LEX_REGISTERS_T *lex_registers;
+#endif
+
+   /**
+    * This field is a pointer to the memory mapped register space for the
+    * SMU_REGISTERS.
+    */
+   SMU_REGISTERS_T *smu_registers;
+
+   /**
+    * This field is a pointer to the memory mapped register space for the
+    * SCU_REGISTERS.
+    */
+   SCU_REGISTERS_T *scu_registers;
+
+} SCIC_SDS_CONTROLLER_T;
+
+
+typedef void (*SCIC_SDS_CONTROLLER_PHY_HANDLER_T)(
+                     struct SCIC_SDS_CONTROLLER *controller,
+                     struct SCIC_SDS_PORT       *port,
+                     struct SCIC_SDS_PHY        *phy
+                     );
+
+typedef void (*SCIC_SDS_CONTROLLER_DEVICE_HANDLER_T)(
+                     struct SCIC_SDS_CONTROLLER    * controller,
+                     struct SCIC_SDS_REMOTE_DEVICE * device
+                     );
+/**
+ * @struct SCIC_SDS_CONTROLLER_STATE_HANDLER
+ *
+ * This structure contains the SDS core specific definition for the state
+ * handlers.
+ */
+typedef struct SCIC_SDS_CONTROLLER_STATE_HANDLER
+{
+   SCI_BASE_CONTROLLER_STATE_HANDLER_T parent;
+
+   SCI_BASE_CONTROLLER_REQUEST_HANDLER_T terminate_request_handler;
+   SCIC_SDS_CONTROLLER_PHY_HANDLER_T     link_up_handler;
+   SCIC_SDS_CONTROLLER_PHY_HANDLER_T     link_down_handler;
+   SCIC_SDS_CONTROLLER_DEVICE_HANDLER_T  remote_device_started_handler;
+   SCIC_SDS_CONTROLLER_DEVICE_HANDLER_T  remote_device_stopped_handler;
+
+} SCIC_SDS_CONTROLLER_STATE_HANDLER_T;
+
+extern SCIC_SDS_CONTROLLER_STATE_HANDLER_T
+       scic_sds_controller_state_handler_table[];
+extern SCI_BASE_STATE_T scic_sds_controller_state_table[];
+
+/**
+ * This macro will increment the specified index to and if the index wraps
+ * to 0 it will toggel the cycle bit.
+ */
+#define INCREMENT_QUEUE_GET(index, cycle, entry_count, bit_toggle) \
+{ \
+   if ((index) + 1 == entry_count) \
+   { \
+      (index) = 0; \
+      (cycle) = (cycle) ^ (bit_toggle); \
+   } \
+   else \
+   { \
+      index = index + 1; \
+   } \
+}
+
+/**
+ * This is a helper macro that sets the state handlers for the controller
+ * object
+ */
+#define scic_sds_controller_set_state_handlers(this_controller, handlers) \
+   ((this_controller)->state_handlers = (handlers))
+
+/**
+ * This is a helper macro that gets the base state machine for the
+ * controller object
+ */
+#define scic_sds_controller_get_base_state_machine(this_contoroller) \
+   (&(this_controller)->parent.state_machine)
+
+/**
+ * This is a helper macro to get the port configuration agent from the
+ * controller object.
+ */
+#define scic_sds_controller_get_port_configuration_agent(controller) \
+   (&(controller)->port_agent)
+
+/**
+ * This is a helper macro that sets the base state machine state handlers
+ * based on the state id
+ */
+#define scic_sds_controller_set_base_state_handlers(this_controller, state_id) \
+   scic_sds_controller_set_state_handlers( \
+      this_controller, &scic_sds_controller_state_handler_table[(state_id)])
+
+/**
+ * This macro writes to the smu_register for this controller
+ */
+#define smu_register_write(controller, reg, value) \
+   scic_sds_pci_write_smu_dword((controller), &(reg), (value))
+
+/**
+ * This macro reads the smu_register for this controller
+ */
+#define smu_register_read(controller, reg) \
+   scic_sds_pci_read_smu_dword((controller), &(reg))
+
+/**
+ * This mcaro writes the scu_register for this controller
+ */
+#define scu_register_write(controller, reg, value) \
+   scic_sds_pci_write_scu_dword((controller), &(reg), (value))
+
+/**
+ * This macro reads the scu_register for this controller
+ */
+#define scu_register_read(controller, reg) \
+   scic_sds_pci_read_scu_dword((controller), &(reg))
+
+#ifdef ARLINGTON_BUILD
+   /**
+    * This macro writes to the lex_register for this controller.
+    */
+   #define lex_register_write(controller, reg, value) \
+      scic_cb_pci_write_dword((controller), (reg), (value))
+
+   /**
+    * This macro reads from the lex_register for this controller.
+    */
+   #define lex_register_read(controller, reg) \
+      scic_cb_pci_read_dword((controller), (reg))
+#endif // ARLINGTON_BUILD
+
+/**
+ * This macro returns the protocol engine group for this controller object.
+ * Presently we only support protocol engine group 0 so just return that
+ */
+#define scic_sds_controller_get_protocol_engine_group(controller) 0
+
+/**
+ * This macro constructs an IO tag from the sequence and index values.
+ */
+#define scic_sds_io_tag_construct(sequence, task_index) \
+   ((sequence) << 12 | (task_index))
+
+/**
+ * This macro returns the IO sequence from the IO tag value.
+ */
+#define scic_sds_io_tag_get_sequence(io_tag) \
+   (((io_tag) & 0xF000) >> 12)
+
+/**
+ * This macro returns the TCi from the io tag value
+ */
+#define scic_sds_io_tag_get_index(io_tag) \
+   ((io_tag) & 0x0FFF)
+
+/**
+ * This is a helper macro to increment the io sequence count.
+ *
+ * We may find in the future that it will be faster to store the sequence
+ * count in such a way as we dont perform the shift operation to build io
+ * tag values so therefore need a way to incrment them correctly
+ */
+#define scic_sds_io_sequence_increment(value) \
+   ((value) = (((value) + 1) & 0x000F))
+
+#define scic_sds_remote_device_node_count(device) \
+   ( \
+      ( \
+         (device)->target_protocols.u.bits.attached_stp_target \
+      && ((device)->is_direct_attached != TRUE) \
+      ) \
+      ? SCU_STP_REMOTE_NODE_COUNT : SCU_SSP_REMOTE_NODE_COUNT \
+   )
+
+/**
+ * This macro will set the bit in the invalid phy mask for this controller
+ * object.  This is used to control messages reported for invalid link up
+ * notifications.
+ */
+#define scic_sds_controller_set_invalid_phy(controller, phy) \
+   ((controller)->invalid_phy_mask |= (1 << (phy)->phy_index))
+
+/**
+ * This macro will clear the bit in the invalid phy mask for this controller
+ * object.  This is used to control messages reported for invalid link up
+ * notifications.
+ */
+#define scic_sds_controller_clear_invalid_phy(controller, phy) \
+   ((controller)->invalid_phy_mask &= ~(1 << (phy)->phy_index))
+
+// ---------------------------------------------------------------------------
+
+U32 scic_sds_controller_get_object_size(void);
+
+// ---------------------------------------------------------------------------
+
+U32 scic_sds_controller_get_min_timer_count(void);
+U32 scic_sds_controller_get_max_timer_count(void);
+
+// ---------------------------------------------------------------------------
+
+void scic_sds_controller_post_request(
+   SCIC_SDS_CONTROLLER_T *this_controller,
+   U32                    request
+);
+
+// ---------------------------------------------------------------------------
+
+void scic_sds_controller_release_frame(
+   SCIC_SDS_CONTROLLER_T *this_controller,
+   U32                   frame_index
+);
+
+void scic_sds_controller_copy_sata_response(
+   void * response_buffer,
+   void * frame_header,
+   void * frame_buffer
+);
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_sds_controller_allocate_remote_node_context(
+   SCIC_SDS_CONTROLLER_T         *this_controller,
+   struct SCIC_SDS_REMOTE_DEVICE *the_device,
+   U16                           *node_id
+);
+
+void scic_sds_controller_free_remote_node_context(
+   SCIC_SDS_CONTROLLER_T         *this_controller,
+   struct SCIC_SDS_REMOTE_DEVICE *the_device,
+   U16                            node_id
+);
+
+SCU_REMOTE_NODE_CONTEXT_T *scic_sds_controller_get_remote_node_context_buffer(
+   SCIC_SDS_CONTROLLER_T *this_controller,
+   U16                    node_id
+);
+
+// ---------------------------------------------------------------------------
+
+struct SCIC_SDS_REQUEST *scic_sds_controller_get_io_request_from_tag(
+   SCIC_SDS_CONTROLLER_T *this_controller,
+   U16                    io_tag
+);
+
+U16 scic_sds_controller_get_io_sequence_from_tag(
+   SCIC_SDS_CONTROLLER_T *this_controller,
+   U16                    io_tag
+);
+
+SCU_TASK_CONTEXT_T *scic_sds_controller_get_task_context_buffer(
+   SCIC_SDS_CONTROLLER_T *this_controller,
+   U16                   io_tag
+);
+
+//-----------------------------------------------------------------------------
+
+SCI_STATUS scic_sds_terminate_reqests(
+        SCIC_SDS_CONTROLLER_T *this_controller,
+        struct SCIC_SDS_REMOTE_DEVICE *this_remote_device,
+        struct SCIC_SDS_PORT *this_port
+);
+
+//*****************************************************************************
+//* CORE CONTROLLER POWER CONTROL METHODS
+//*****************************************************************************
+
+void scic_sds_controller_power_control_timer_handler(
+   void *controller
+);
+
+void scic_sds_controller_power_control_queue_insert(
+   SCIC_SDS_CONTROLLER_T *this_controller,
+   struct SCIC_SDS_PHY   *the_phy
+);
+
+void scic_sds_controller_power_control_queue_remove(
+   SCIC_SDS_CONTROLLER_T *this_controller,
+   struct SCIC_SDS_PHY   *the_phy
+);
+
+//*****************************************************************************
+//* CORE CONTROLLER PHY MESSAGE PROCESSING
+//*****************************************************************************
+
+void scic_sds_controller_link_up(
+   SCIC_SDS_CONTROLLER_T *this_controller,
+   struct SCIC_SDS_PORT  *the_port,
+   struct SCIC_SDS_PHY   *the_phy
+);
+
+void scic_sds_controller_link_down(
+   SCIC_SDS_CONTROLLER_T *this_controller,
+   struct SCIC_SDS_PORT  *the_port,
+   struct SCIC_SDS_PHY   *the_phy
+);
+
+//*****************************************************************************
+//* CORE CONTROLLER PORT AGENT MESSAGE PROCESSING
+//*****************************************************************************
+void scic_sds_controller_port_agent_configured_ports(
+   SCIC_SDS_CONTROLLER_T * this_controller
+);
+
+//*****************************************************************************
+//* CORE CONTROLLER REMOTE DEVICE MESSAGE PROCESSING
+//*****************************************************************************
+
+BOOL scic_sds_controller_has_remote_devices_stopping(
+   SCIC_SDS_CONTROLLER_T * this_controller
+);
+
+void scic_sds_controller_remote_device_started(
+   SCIC_SDS_CONTROLLER_T         * this_controller,
+   struct SCIC_SDS_REMOTE_DEVICE * the_device
+);
+
+void scic_sds_controller_remote_device_stopped(
+   SCIC_SDS_CONTROLLER_T         * this_controller,
+   struct SCIC_SDS_REMOTE_DEVICE * the_device
+);
+
+//*****************************************************************************
+//* CORE CONTROLLER PRIVATE METHODS
+//*****************************************************************************
+
+#ifdef SCI_LOGGING
+void scic_sds_controller_initialize_state_logging(
+   SCIC_SDS_CONTROLLER_T *this_controller
+);
+
+void scic_sds_controller_deinitialize_state_logging(
+   SCIC_SDS_CONTROLLER_T *this_controller
+);
+#else
+#define scic_sds_controller_initialize_state_logging(x)
+#define scic_sds_controller_deinitialize_state_logging(x)
+#endif
+
+SCI_STATUS scic_sds_controller_validate_memory_descriptor_table(
+   SCIC_SDS_CONTROLLER_T *this_controller
+);
+
+void scic_sds_controller_ram_initialization(
+   SCIC_SDS_CONTROLLER_T *this_controller
+);
+
+void scic_sds_controller_assign_task_entries(
+   SCIC_SDS_CONTROLLER_T *this_controller
+);
+
+void scic_sds_controller_afe_initialization(
+   SCIC_SDS_CONTROLLER_T * this_controller
+);
+
+void scic_sds_controller_enable_port_task_scheduler(
+   SCIC_SDS_CONTROLLER_T *this_controller
+);
+
+void scic_sds_controller_initialize_completion_queue(
+   SCIC_SDS_CONTROLLER_T *this_controller
+);
+
+void scic_sds_controller_initialize_unsolicited_frame_queue(
+   SCIC_SDS_CONTROLLER_T *this_controller
+);
+
+void scic_sds_controller_phy_timer_stop(
+   SCIC_SDS_CONTROLLER_T *this_controller
+);
+
+BOOL scic_sds_controller_is_start_complete(
+   SCIC_SDS_CONTROLLER_T *this_controller
+);
+
+SCI_STATUS scic_sds_controller_start_next_phy(
+   SCIC_SDS_CONTROLLER_T *this_controller
+);
+
+SCI_STATUS scic_sds_controller_stop_phys(
+   SCIC_SDS_CONTROLLER_T *this_controller
+);
+
+SCI_STATUS scic_sds_controller_stop_ports(
+   SCIC_SDS_CONTROLLER_T *this_controller
+);
+
+SCI_STATUS scic_sds_controller_stop_devices(
+   SCIC_SDS_CONTROLLER_T *this_controller
+);
+
+void scic_sds_controller_copy_task_context(
+   SCIC_SDS_CONTROLLER_T   *this_controller,
+   struct SCIC_SDS_REQUEST *this_request
+);
+
+void scic_sds_controller_timeout_handler(
+   SCI_CONTROLLER_HANDLE_T controller
+);
+
+void scic_sds_controller_initialize_power_control(
+   SCIC_SDS_CONTROLLER_T *this_controller
+);
+
+void scic_sds_controller_register_setup(
+   SCIC_SDS_CONTROLLER_T *this_controller
+);
+
+void scic_sds_controller_reset_hardware(
+   SCIC_SDS_CONTROLLER_T * this_controller
+);
+
+#ifdef ARLINGTON_BUILD
+void scic_sds_controller_lex_atux_initialization(
+   SCIC_SDS_CONTROLLER_T *this_controller
+);
+
+void scic_sds_controller_enable_chipwatch(
+   SCIC_SDS_CONTROLLER_T *this_controller
+);
+#endif // ARLINGTON_BUILD
+
+void scic_sds_controller_build_memory_descriptor_table(
+   SCIC_SDS_CONTROLLER_T *this_controller
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIC_SDS_CONTROLLER_H_
diff --git a/sys/dev/disk/isci/scil/scic_sds_controller_registers.h b/sys/dev/disk/isci/scil/scic_sds_controller_registers.h
new file mode 100644
index 0000000..2386749
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_sds_controller_registers.h
@@ -0,0 +1,598 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_sds_controller_registers.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIC_SDS_CONTROLLER_REGISTERS_H_
+#define _SCIC_SDS_CONTROLLER_REGISTERS_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains macros used to perform the register reads/writes
+ *        to the SCU hardware.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/scu_registers.h>
+#include <dev/disk/isci/scil/scic_sds_controller.h>
+
+/**
+ * @name SMU_REGISTER_ACCESS_MACROS
+ */
+/*@{*/
+#define scic_sds_controller_smu_register_read(controller, reg) \
+   smu_register_read( \
+      (controller), \
+      (controller)->smu_registers->reg \
+   )
+
+#define scic_sds_controller_smu_register_write(controller, reg, value) \
+   smu_register_write( \
+      (controller), \
+      (controller)->smu_registers->reg, \
+      (value) \
+   )
+/*@}*/
+
+/**
+ * @name AFE_REGISTER_ACCESS_MACROS
+ */
+/*@{*/
+#define scu_afe_register_write(controller, reg, value) \
+   scu_register_write( \
+      (controller), \
+      (controller)->scu_registers->afe.reg, \
+      (value) \
+   )
+
+#define scu_afe_register_read(controller, reg) \
+   scu_register_read( \
+      (controller), \
+      (controller)->scu_registers->afe.reg \
+   )
+/*@}*/
+
+/**
+ * @name SGPIO_PEG0_REGISTER_ACCESS_MACROS
+ */
+/*@{*/
+#define scu_sgpio_peg0_register_read(controller, reg) \
+   scu_register_read( \
+      (controller), \
+      (controller)->scu_registers->peg0.sgpio.reg \
+   )
+
+#define scu_sgpio_peg0_register_write(controller, reg, value) \
+   scu_register_write( \
+      (controller), \
+      (controller)->scu_registers->peg0.sgpio.reg, \
+      (value) \
+   )
+/*@}*/
+
+/**
+ * @name VIIT_REGISTER_ACCESS_MACROS
+ */
+/*@{*/
+#define scu_controller_viit_register_write(controller, index, reg, value) \
+   scu_register_write( \
+      (controller), \
+      (controller)->scu_registers->peg0.viit[index].reg, \
+      value \
+   )
+/*@}*/
+
+/**
+ * @name SCRATCH_RAM_REGISTER_ACCESS_MACROS
+ */
+/*@{*/
+// Scratch RAM access may be needed before the scu_registers pointer
+//  has been initialized.  So instead, explicitly cast BAR1 to a
+//  SCU_REGISTERS_T data structure.
+
+// Scratch RAM is stored in the Zoning Permission Table for OROM use.
+#define scu_controller_scratch_ram_register_write(controller, index, value) \
+   scu_register_write( \
+      (controller), \
+      ((SCU_REGISTERS_T *)scic_cb_pci_get_bar(controller, PATSBURG_SCU_BAR))->peg0.zpt0.table[index], \
+      value \
+   )
+
+#define scu_controller_scratch_ram_register_read(controller, index) \
+   scu_register_read( \
+      (controller), \
+      ((SCU_REGISTERS_T *)scic_cb_pci_get_bar(controller, PATSBURG_SCU_BAR))->peg0.zpt0.table[index] \
+   )
+
+#define scu_controller_scratch_ram_register_write_ext(controller, index, value) \
+   scu_register_write( \
+      (controller), \
+      ((SCU_REGISTERS_T *)scic_cb_pci_get_bar(controller, PATSBURG_SCU_BAR))->peg0.zpt1.table[index], \
+      value \
+   )
+
+#define scu_controller_scratch_ram_register_read_ext(controller, index) \
+   scu_register_read( \
+      (controller), \
+      ((SCU_REGISTERS_T *)scic_cb_pci_get_bar(controller, PATSBURG_SCU_BAR))->peg0.zpt1.table[index] \
+   )
+/*@}*/
+
+
+//*****************************************************************************
+//* SMU REGISTERS
+//*****************************************************************************
+
+/**
+ * @name SMU_REGISTERS
+ */
+/*@{*/
+#define SMU_PCP_WRITE(controller, value) \
+    scic_sds_controller_smu_register_write( \
+       controller, post_context_port, value \
+    )
+
+#define SMU_TCR_READ(controller, value) \
+    scic_sds_controller_smu_register_read( \
+       controller, task_context_range \
+    )
+
+#define SMU_TCR_WRITE(controller, value) \
+    scic_sds_controller_smu_register_write( \
+       controller, task_context_range, value \
+    )
+
+#define SMU_HTTBAR_WRITE(controller, address) \
+{ \
+   scic_sds_controller_smu_register_write( \
+      controller, \
+      host_task_table_lower, \
+      sci_cb_physical_address_lower(address) \
+   );\
+   scic_sds_controller_smu_register_write( \
+      controller, \
+      host_task_table_upper, \
+      sci_cb_physical_address_upper(address) \
+   ); \
+}
+
+#define SMU_CQBAR_WRITE(controller, address) \
+{ \
+   scic_sds_controller_smu_register_write( \
+      controller, \
+      completion_queue_lower, \
+      sci_cb_physical_address_lower(address) \
+   ); \
+   scic_sds_controller_smu_register_write( \
+      controller, \
+      completion_queue_upper, \
+      sci_cb_physical_address_upper(address) \
+   ); \
+}
+
+#define SMU_CQGR_WRITE(controller, value) \
+    scic_sds_controller_smu_register_write( \
+       controller, completion_queue_get, value \
+    )
+
+#define SMU_CQGR_READ(controller, value) \
+    scic_sds_controller_smu_register_read( \
+       controller, completion_queue_get \
+    )
+
+#define SMU_CQPR_WRITE(controller, value) \
+    scic_sds_controller_smu_register_write( \
+       controller, completion_queue_put, value \
+    )
+
+#define SMU_RNCBAR_WRITE(controller, address) \
+{ \
+   scic_sds_controller_smu_register_write( \
+      controller, \
+      remote_node_context_lower, \
+      sci_cb_physical_address_lower(address) \
+   ); \
+   scic_sds_controller_smu_register_write( \
+      controller, \
+      remote_node_context_upper, \
+      sci_cb_physical_address_upper(address) \
+   ); \
+}
+
+#define SMU_AMR_READ(controller) \
+   scic_sds_controller_smu_register_read( \
+      controller, address_modifier \
+   )
+
+#define SMU_IMR_READ(controller) \
+   scic_sds_controller_smu_register_read( \
+      controller, interrupt_mask \
+   )
+
+#define SMU_IMR_WRITE(controller, mask) \
+   scic_sds_controller_smu_register_write( \
+      controller, interrupt_mask, mask \
+   )
+
+#define SMU_ISR_READ(controller) \
+   scic_sds_controller_smu_register_read( \
+      controller, interrupt_status \
+   )
+
+#define SMU_ISR_WRITE(controller, status) \
+   scic_sds_controller_smu_register_write( \
+      controller, interrupt_status, status \
+   )
+
+#define SMU_ICC_READ(controller) \
+   scic_sds_controller_smu_register_read( \
+      controller, interrupt_coalesce_control \
+   )
+
+#define SMU_ICC_WRITE(controller, value) \
+   scic_sds_controller_smu_register_write( \
+      controller, interrupt_coalesce_control, value \
+   )
+
+#define SMU_CQC_WRITE(controller, value) \
+    scic_sds_controller_smu_register_write( \
+       controller, completion_queue_control, value \
+    )
+
+#define SMU_SMUSRCR_WRITE(controller, value) \
+   scic_sds_controller_smu_register_write( \
+      controller, soft_reset_control, value \
+   )
+
+#define SMU_TCA_WRITE(controller, index, value) \
+    scic_sds_controller_smu_register_write( \
+       controller, task_context_assignment[index], value \
+    )
+
+#define SMU_TCA_READ(controller, index) \
+    scic_sds_controller_smu_register_read( \
+       controller, task_context_assignment[index] \
+    )
+
+#define SMU_DCC_READ(controller) \
+   scic_sds_controller_smu_register_read( \
+      controller, device_context_capacity \
+   )
+
+#define SMU_DFC_READ(controller) \
+   scic_sds_controller_smu_register_read( \
+      controller, device_function_capacity \
+   )
+
+#define SMU_SMUCSR_READ(controller) \
+   scic_sds_controller_smu_register_read( \
+      controller, control_status \
+   )
+
+#define SMU_CGUCR_READ(controller) \
+   scic_sds_controller_smu_register_read( \
+      controller, clock_gating_control \
+   )
+
+#define SMU_CGUCR_WRITE(controller, value) \
+   scic_sds_controller_smu_register_write( \
+      controller, clock_gating_control, value \
+   )
+
+#define SMU_CQPR_READ(controller) \
+    scic_sds_controller_smu_register_read( \
+       controller, completion_queue_put \
+    )
+
+/*@}*/
+
+/**
+ * @name SCU_REGISTER_ACCESS_MACROS
+ */
+/*@{*/
+#define scic_sds_controller_scu_register_read(controller, reg) \
+   scu_register_read( \
+      (controller), \
+      (controller)->scu_registers->reg \
+   )
+
+#define scic_sds_controller_scu_register_write(controller, reg, value) \
+   scu_register_write( \
+      (controller), \
+      (controller)->scu_registers->reg, \
+      (value) \
+   )
+/*@}*/
+
+
+//****************************************************************************
+//*  SCU SDMA REGISTERS
+//****************************************************************************
+
+/**
+ * @name SCU_SDMA_REGISTER_ACCESS_MACROS
+ */
+/*@{*/
+#define scu_sdma_register_read(controller, reg) \
+   scu_register_read( \
+      (controller), \
+      (controller)->scu_registers->sdma.reg \
+   )
+
+#define scu_sdma_register_write(controller, reg, value) \
+   scu_register_write( \
+      (controller), \
+      (controller)->scu_registers->sdma.reg, \
+      (value) \
+   )
+/*@}*/
+
+/**
+ * @name SCU_SDMA_REGISTERS
+ */
+/*@{*/
+#define SCU_PUFATHAR_WRITE(controller, address) \
+{ \
+   scu_sdma_register_write( \
+      controller, \
+      uf_address_table_lower, \
+      sci_cb_physical_address_lower(address) \
+   ); \
+   scu_sdma_register_write( \
+      controller, \
+      uf_address_table_upper, \
+      sci_cb_physical_address_upper(address) \
+   ); \
+}
+
+#define SCU_UFHBAR_WRITE(controller, address) \
+{ \
+   scu_sdma_register_write( \
+      controller, \
+      uf_header_base_address_lower, \
+      sci_cb_physical_address_lower(address) \
+   ); \
+   scu_sdma_register_write( \
+      controller, \
+      uf_header_base_address_upper, \
+      sci_cb_physical_address_upper(address) \
+   ); \
+}
+
+#define SCU_UFQC_READ(controller) \
+    scu_sdma_register_read( \
+       controller,  \
+       unsolicited_frame_queue_control \
+    )
+
+#define SCU_UFQC_WRITE(controller, value) \
+    scu_sdma_register_write( \
+       controller, \
+       unsolicited_frame_queue_control, \
+       value \
+    )
+
+#define SCU_UFQPP_READ(controller) \
+    scu_sdma_register_read( \
+       controller, \
+       unsolicited_frame_put_pointer \
+    )
+
+#define SCU_UFQPP_WRITE(controller, value) \
+   scu_sdma_register_write( \
+      controller, \
+      unsolicited_frame_put_pointer, \
+      value \
+   )
+
+#define SCU_UFQGP_WRITE(controller, value) \
+   scu_sdma_register_write( \
+      controller, \
+      unsolicited_frame_get_pointer, \
+      value \
+   )
+
+#define SCU_PDMACR_READ(controller) \
+   scu_sdma_register_read( \
+      controller, \
+      pdma_configuration \
+   )
+
+#define SCU_PDMACR_WRITE(controller, value) \
+   scu_sdma_register_write( \
+      controller, \
+      pdma_configuration, \
+      value \
+   )
+
+#define SCU_CDMACR_READ(controller) \
+   scu_sdma_register_read( \
+     controller, \
+     cdma_configuration \
+   )
+
+#define SCU_CDMACR_WRITE(controller, value) \
+   scu_sdma_register_write( \
+      controller, \
+      cdma_configuration, \
+      value \
+   )
+/*@}*/
+
+//*****************************************************************************
+//* SCU CRAM AND FBRAM Registers
+//*****************************************************************************
+/**
+ * @name SCU_CRAM_REGISTER_ACCESS_MACROS
+ */
+/*@{*/
+#define scu_cram_register_read(controller, reg) \
+   scu_register_read( \
+      (controller), \
+      (controller)->scu_registers->cram.reg \
+   )
+
+#define scu_cram_register_write(controller, reg, value) \
+   scu_register_write( \
+      (controller), \
+      (controller)->scu_registers->cram.reg, \
+      (value) \
+   )
+/*@}*/
+
+/**
+ * @name SCU_FBRAM_REGISTER_ACCESS_MACROS
+ */
+/*@{*/
+#define scu_fbram_register_read(controller, reg) \
+   scu_register_read( \
+      (controller), \
+      (controller)->scu_registers->fbram.reg \
+   )
+
+#define scu_fbram_register_write(controller, reg, value) \
+   scu_register_write( \
+      (controller), \
+      (controller)->scu_registers->fbram.reg, \
+      (value) \
+   )
+/*@}*/
+
+
+/**
+ * @name SCU_CRAM_REGISTERS
+ */
+/*@{*/
+
+// SRAM ECC CONTROL REGISTER BITS
+#define SIGNLE_BIT_ERROR_CORRECTION_ENABLE 0x00000001
+#define MULTI_BIT_ERROR_REPORTING_ENABLE   0x00000002
+#define SINGLE_BIT_ERROR_REPORTING_ENABLE  0x00000004
+
+//SRAM ECC control register (SECR0)
+#define SCU_SECR0_WRITE(controller, value) \
+    scu_cram_register_write( \
+      controller, \
+      sram_ecc_control_0, \
+      value \
+   )
+/*@}*/
+
+/**
+ * @name SCU_FBRAM_REGISTERS
+ */
+/*@{*/
+
+//SRAM ECC control register (SECR1)
+#define SCU_SECR1_WRITE(controller, value) \
+    scu_fbram_register_write( \
+      controller, \
+      sram_ecc_control_1, \
+      value \
+   )
+/*@}*/
+
+
+//*****************************************************************************
+//* SCU Port Task Scheduler Group Registers
+//*****************************************************************************
+
+/**
+ * @name SCU_PTSG_REGISTER_ACCESS_MACROS
+ */
+/*@{*/
+#define scu_ptsg_register_read(controller, reg) \
+   scu_register_read( \
+      (controller), \
+      (controller)->scu_registers->peg0.ptsg.reg \
+   )
+
+#define scu_ptsg_register_write(controller, reg, value) \
+   scu_register_write( \
+      (controller), \
+      (controller)->scu_registers->peg0.ptsg.reg, \
+      (value) \
+   )
+/*@}*/
+
+/**
+ * @name SCU_PTSG_REGISTERS
+ */
+/*@{*/
+#define SCU_PTSGCR_READ(controller) \
+    scu_ptsg_register_read( \
+       (controller), \
+       control \
+    )
+
+#define SCU_PTSGCR_WRITE(controller, value) \
+    scu_ptsg_register_write( \
+       (controller), \
+       control, \
+       value \
+    )
+
+#define SCU_PTSGRTC_READ(controller) \
+    scu_ptsg_register_read( \
+       contoller, \
+       real_time_clock \
+    )
+/*@}*/
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIC_SDS_CONTROLLER_REGISTERS_H_
diff --git a/sys/dev/disk/isci/scil/scic_sds_library.c b/sys/dev/disk/isci/scil/scic_sds_library.c
new file mode 100644
index 0000000..b00d778
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_sds_library.c
@@ -0,0 +1,285 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_sds_library.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains the implementation of the public methods for a
+ *        SCIC_SDS_LIBRARY object.
+ */
+
+#include <dev/disk/isci/scil/scic_library.h>
+#include <dev/disk/isci/scil/scic_sds_library.h>
+#include <dev/disk/isci/scil/scic_sds_controller.h>
+#include <dev/disk/isci/scil/scic_sds_request.h>
+#include <dev/disk/isci/scil/scic_sds_remote_device.h>
+#include <dev/disk/isci/scil/intel_pci.h>
+#include <dev/disk/isci/scil/scic_sds_pci.h>
+#include <dev/disk/isci/scil/scu_constants.h>
+
+struct SCIC_SDS_CONTROLLER;
+
+#define SCIC_LIBRARY_CONTROLLER_MEMORY_START(library) \
+   ((char *)(library) + sizeof(SCIC_SDS_LIBRARY_T))
+
+// ---------------------------------------------------------------------------
+
+U32 scic_library_get_object_size(
+   U8 max_controller_count
+)
+{
+   return   sizeof(SCIC_SDS_LIBRARY_T)
+          + scic_sds_controller_get_object_size() * max_controller_count;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_LIBRARY_HANDLE_T scic_library_construct(
+   void                    * library_memory,
+   U8                        max_controller_count
+)
+{
+   SCI_STATUS status;
+   SCIC_SDS_LIBRARY_T *this_library;
+
+   this_library = (SCIC_SDS_LIBRARY_T *)library_memory;
+
+   this_library->max_controller_count = max_controller_count;
+
+   this_library->controllers =
+      (SCIC_SDS_CONTROLLER_T *)((char *)library_memory + sizeof(SCIC_SDS_LIBRARY_T));
+
+   SCI_BASE_LIBRARY_CONSTRUCT(this_library,
+                              &this_library->parent,
+                              max_controller_count,
+                              struct SCIC_SDS_CONTROLLER,
+                              status);
+   return this_library;
+}
+
+// ---------------------------------------------------------------------------
+
+void scic_library_set_pci_info(
+   SCI_LIBRARY_HANDLE_T      library,
+   SCI_PCI_COMMON_HEADER_T * pci_header
+)
+{
+   SCIC_SDS_LIBRARY_T *this_library;
+   this_library = (SCIC_SDS_LIBRARY_T *)library;
+
+   this_library->pci_device   = pci_header->device_id;
+
+#if defined(PBG_HBA_A0_BUILD)
+   this_library->pci_revision = SCIC_SDS_PCI_REVISION_A0;
+#elif defined(PBG_HBA_A2_BUILD)
+   this_library->pci_revision = SCIC_SDS_PCI_REVISION_A2;
+#elif defined(PBG_HBA_BETA_BUILD)
+   this_library->pci_revision = SCIC_SDS_PCI_REVISION_B0;
+#elif defined(PBG_BUILD)
+   // The SCU PCI function revision ID for A0/A2 is not populated
+   // properly.  As a result, we force the revision ID to A2 for
+   // this situation.  Therefore, the standard PBG build will not
+   // work for A0.
+   if (pci_header->revision == SCIC_SDS_PCI_REVISION_A0)
+      this_library->pci_revision = SCIC_SDS_PCI_REVISION_A2;
+   else
+      this_library->pci_revision = pci_header->revision;
+#endif
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_library_allocate_controller(
+   SCI_LIBRARY_HANDLE_T    library,
+   SCI_CONTROLLER_HANDLE_T *new_controller
+)
+{
+   SCI_STATUS status;
+   SCIC_SDS_LIBRARY_T *this_library;
+
+   this_library = (SCIC_SDS_LIBRARY_T *)library;
+
+   if (
+         (  (this_library->pci_device >= 0x1D60)
+         && (this_library->pci_device <= 0x1D62)
+         )
+      || (  (this_library->pci_device >= 0x1D64)
+         && (this_library->pci_device <= 0x1D65)
+         )
+      || (  (this_library->pci_device >= 0x1D68)
+         && (this_library->pci_device <= 0x1D6F)
+         )
+      )
+   {
+      SCI_BASE_LIBRARY_ALLOCATE_CONTROLLER(
+         this_library, new_controller, &status);
+   }
+   else
+      status = SCI_FAILURE_UNSUPPORTED_PCI_DEVICE_ID;
+
+   return status;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_library_free_controller(
+   SCI_LIBRARY_HANDLE_T library,
+   SCI_CONTROLLER_HANDLE_T controller
+)
+{
+   SCI_STATUS status;
+   SCIC_SDS_LIBRARY_T *this_library;
+   this_library = (SCIC_SDS_LIBRARY_T *)library;
+
+   SCI_BASE_LIBRARY_FREE_CONTROLLER(
+      this_library, controller, struct SCIC_SDS_CONTROLLER, &status);
+
+   return status;
+}
+
+// ---------------------------------------------------------------------------
+
+U8 scic_library_get_pci_device_controller_count(
+   SCI_LIBRARY_HANDLE_T library
+)
+{
+   SCIC_SDS_LIBRARY_T *this_library;
+   U16 device_id;
+
+   this_library = (SCIC_SDS_LIBRARY_T *)library;
+   device_id = this_library->pci_device;
+
+   //Check if we are on a b0 or c0 which has 2 controllers
+   if (
+         // Warning: If 0x1d66 is ever defined to be a single controller
+         //          this logic will fail.
+         //          If 0x1d63 or 0x1d67 is ever defined to be dual
+         //          controller this logic will fail.
+         ((device_id & 0xFFF1) == 0x1D60)
+      && (
+            (this_library->pci_revision == SCU_PBG_HBA_REV_B0)
+         || (this_library->pci_revision == SCU_PBG_HBA_REV_C0)
+         || (this_library->pci_revision == SCU_PBG_HBA_REV_C1)
+         )
+      )
+      return 2;
+   else
+      return 1;
+}
+
+// ---------------------------------------------------------------------------
+
+U32 scic_library_get_max_sge_size(
+   SCI_LIBRARY_HANDLE_T library
+)
+{
+   return SCU_IO_REQUEST_MAX_SGE_SIZE;
+}
+
+// ---------------------------------------------------------------------------
+
+U32 scic_library_get_max_sge_count(
+   SCI_LIBRARY_HANDLE_T library
+)
+{
+   return SCU_IO_REQUEST_SGE_COUNT;
+}
+
+// ---------------------------------------------------------------------------
+
+U32 scic_library_get_max_io_length(
+   SCI_LIBRARY_HANDLE_T library
+)
+{
+   return SCU_IO_REQUEST_MAX_TRANSFER_LENGTH;
+}
+
+// ---------------------------------------------------------------------------
+
+U16 scic_library_get_min_timer_count(void)
+{
+   return (U16) (scic_sds_controller_get_min_timer_count()
+               + scic_sds_remote_device_get_min_timer_count()
+               + scic_sds_request_get_min_timer_count());
+}
+
+// ---------------------------------------------------------------------------
+
+U16 scic_library_get_max_timer_count(void)
+{
+   return (U16) (scic_sds_controller_get_max_timer_count()
+               + scic_sds_remote_device_get_max_timer_count()
+               + scic_sds_request_get_max_timer_count());
+}
+
+/**
+ *
+ */
+U8 scic_sds_library_get_controller_index(
+   SCIC_SDS_LIBRARY_T    * library,
+   SCIC_SDS_CONTROLLER_T * controller
+)
+{
+   U8 index;
+
+   for (index = 0; index < library->max_controller_count; index++)
+   {
+      if (controller == &library->controllers[index])
+      {
+         return index;
+      }
+   }
+
+   return 0xff;
+}
diff --git a/sys/dev/disk/isci/scil/scic_sds_library.h b/sys/dev/disk/isci/scil/scic_sds_library.h
new file mode 100644
index 0000000..8087b60
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_sds_library.h
@@ -0,0 +1,118 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_sds_library.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIC_SDS_LIBRARY_H_
+#define _SCIC_SDS_LIBRARY_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains the structures used by the core library object.
+ *        All of the functionality for the core library is in the
+ *        sci_base_library.h file.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_base_library.h>
+#include <dev/disk/isci/scil/scic_sds_pci.h>
+
+// Forward declar the controllers
+struct SCIC_SDS_CONTROLLER;
+
+/**
+ * @struct SCIC_SDS_LIBRARY
+ *
+ * This structure contains data used by the core library.
+ */
+typedef struct SCIC_SDS_LIBRARY
+{
+  /*
+   * The SCI_BASE_LIBRARY is the parent object for the SCIC_SDS_LIBRARY
+   * object.
+   */
+   SCI_BASE_LIBRARY_T parent;
+
+   /**
+    * This is the count of the maximum number of controllers that this library
+    * can contain.
+    */
+   U32 max_controller_count;
+
+   /**
+    * The PCI header for this library object all libraries must have the same
+    * pci device id.
+    */
+   U16 pci_device;
+   U8  pci_revision;
+
+   /**
+    * This field is the array of controllers that are contained within the
+    * library object.
+    */
+   struct SCIC_SDS_CONTROLLER *controllers;
+
+} SCIC_SDS_LIBRARY_T;
+
+U8 scic_sds_library_get_controller_index(
+   struct SCIC_SDS_LIBRARY    * library,
+   struct SCIC_SDS_CONTROLLER * controller
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIC_SDS_LIBRARY_H_
diff --git a/sys/dev/disk/isci/scil/scic_sds_logger.h b/sys/dev/disk/isci/scil/scic_sds_logger.h
new file mode 100644
index 0000000..0ae7f2b
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_sds_logger.h
@@ -0,0 +1,93 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_sds_logger.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIC_SDS_LOGGER_H_
+#define _SCIC_SDS_LOGGER_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains some macros to remap the user callbacks for log
+ *        messages.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/scic_logger.h>
+#include <dev/disk/isci/scil/scic_user_callback.h>
+
+#if defined (SCI_LOGGING)
+
+#define SCIC_LOG_ERROR(x)    scic_cb_logger_log_error x
+#define SCIC_LOG_WARNING(x)  scic_cb_logger_log_warning x
+#define SCIC_LOG_INFO(x)     scic_cb_logger_log_info x
+#define SCIC_LOG_TRACE(x)    scic_cb_logger_log_trace x
+#define SCIC_LOG_STATES(x)   scic_cb_logger_log_states x
+
+#else // defined (SCI_LOGGING)
+
+#define SCIC_LOG_ERROR(x)
+#define SCIC_LOG_WARNING(x)
+#define SCIC_LOG_INFO(x)
+#define SCIC_LOG_TRACE(x)
+#define SCIC_LOG_STATES(x)
+
+#endif // defined (SCI_LOGGING)
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIC_SDS_LOGGER_H_
diff --git a/sys/dev/disk/isci/scil/scic_sds_pci.c b/sys/dev/disk/isci/scil/scic_sds_pci.c
new file mode 100644
index 0000000..2cace14
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_sds_pci.c
@@ -0,0 +1,246 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_sds_pci.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains the method implementations utilized in writing
+ *        out PCI data for the SCI core.
+ */
+
+#include <dev/disk/isci/scil/scic_user_callback.h>
+
+#include <dev/disk/isci/scil/scic_sds_pci.h>
+#include <dev/disk/isci/scil/scic_sds_controller.h>
+
+/**
+ * @brief This method reads from the driver the BARs that are needed to
+ *        determine the virtual memory space for the controller registers
+ *
+ * @param[in] this_controller The controller for which to read the base
+ *            address registers.
+ */
+void scic_sds_pci_bar_initialization(
+   SCIC_SDS_CONTROLLER_T* this_controller
+)
+{
+#ifdef ARLINGTON_BUILD
+
+   #define ARLINGTON_LEX_BAR  0
+   #define ARLINGTON_SMU_BAR  1
+   #define ARLINGTON_SCU_BAR  2
+   #define LEX_REGISTER_OFFSET 0x40000
+
+   this_controller->lex_registers =
+      ((char *)scic_cb_pci_get_bar(
+                     this_controller, ARLINGTON_LEX_BAR) + LEX_REGISTER_OFFSET);
+   this_controller->smu_registers =
+      (SMU_REGISTERS_T *)scic_cb_pci_get_bar(this_controller, ARLINGTON_SMU_BAR);
+   this_controller->scu_registers =
+      (SCU_REGISTERS_T *)scic_cb_pci_get_bar(this_controller, ARLINGTON_SCU_BAR);
+
+#else // !ARLINGTON_BUILD
+
+#if !defined(ENABLE_PCI_IO_SPACE_ACCESS)
+
+   this_controller->smu_registers =
+      (SMU_REGISTERS_T *)(
+         (char *)scic_cb_pci_get_bar(this_controller, PATSBURG_SMU_BAR)
+                +(0x4000 * this_controller->controller_index));
+   this_controller->scu_registers =
+      (SCU_REGISTERS_T *)(
+         (char *)scic_cb_pci_get_bar(this_controller, PATSBURG_SCU_BAR)
+                +(0x400000 * this_controller->controller_index));
+
+#else // !defined(ENABLE_PCI_IO_SPACE_ACCESS)
+
+   if (this_controller->controller_index == 0)
+   {
+      this_controller->smu_registers = (SMU_REGISTERS_T *)
+         scic_cb_pci_get_bar(this_controller, PATSBURG_IO_SPACE_BAR0);
+   }
+   else
+   {
+      if (this_controller->pci_revision == SCU_PBG_HBA_REV_B0)
+      {
+         // SCU B0 violates PCI spec for size of IO bar this is corrected
+         // in subsequent version of the hardware so we can safely use the
+         // else condition below.
+         this_controller->smu_registers = (SMU_REGISTERS_T *)
+            (scic_cb_pci_get_bar(this_controller, PATSBURG_IO_SPACE_BAR0) + 0x100);
+      }
+      else
+      {
+         this_controller->smu_registers = (SMU_REGISTERS_T *)
+            scic_cb_pci_get_bar(this_controller, PATSBURG_IO_SPACE_BAR1);
+      }
+   }
+
+   // No need to get the bar.  We will be using the offset to write to
+   // input/output ports via 0xA0 and 0xA4.
+   this_controller->scu_registers = (SCU_REGISTERS_T *) 0;
+
+#endif // !defined(ENABLE_PCI_IO_SPACE_ACCESS)
+
+#endif // ARLINGTON_BUILD
+}
+
+#if defined(ENABLE_PCI_IO_SPACE_ACCESS) && !defined(ARLINGTON_BUILD)
+
+/**
+ * @brief This method will read from PCI memory for the SMU register
+ *        space via IO space access.
+ *
+ * @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?
+ */
+U32 scic_sds_pci_read_smu_dword(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   void                    * address
+)
+{
+   return scic_cb_pci_read_dword(controller, address);
+}
+
+/**
+ * @brief This method will write to PCI memory for the SMU register
+ *        space via IO space access.
+ *
+ * @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 This PCI memory access calls likely need to be optimized into macro?
+ */
+void scic_sds_pci_write_smu_dword(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   void                    * address,
+   U32                       write_value
+)
+{
+   scic_cb_pci_write_dword(controller, address, write_value);
+}
+
+/**
+ * @brief This method will read from PCI memory for the SCU register
+ *        space via IO space access.
+ *
+ * @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?
+ */
+U32 scic_sds_pci_read_scu_dword(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   void                    * address
+)
+{
+   SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
+
+   scic_cb_pci_write_dword(
+      controller,
+      (void*) ((char *)(this_controller->smu_registers) + SCU_MMR_ADDRESS_WINDOW_OFFSET),
+      (U32) address
+   );
+
+   return scic_cb_pci_read_dword(
+             controller,
+             (void*) ((char *)(this_controller->smu_registers) + SCU_MMR_DATA_WINDOW_OFFSET)
+          );
+}
+
+/**
+ * @brief This method will write to PCI memory for the SCU register
+ *        space via IO space access.
+ *
+ * @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 This PCI memory access calls likely need to be optimized into macro?
+ */
+void scic_sds_pci_write_scu_dword(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   void                    * address,
+   U32                       write_value
+)
+{
+   SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller;
+
+   scic_cb_pci_write_dword(
+      controller,
+      (void*) ((char *)(this_controller->smu_registers) + SCU_MMR_ADDRESS_WINDOW_OFFSET),
+      (U32) address
+   );
+
+   scic_cb_pci_write_dword(
+      controller,
+      (void*) ((char *)(this_controller->smu_registers) + SCU_MMR_DATA_WINDOW_OFFSET),
+      write_value
+   );
+}
+
+#endif // defined(ENABLE_PCI_IO_SPACE_ACCESS)
diff --git a/sys/dev/disk/isci/scil/scic_sds_pci.h b/sys/dev/disk/isci/scil/scic_sds_pci.h
new file mode 100644
index 0000000..38c4726
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_sds_pci.h
@@ -0,0 +1,138 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_sds_pci.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIC_SDS_PCI_H_
+#define _SCIC_SDS_PCI_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains the prototypes/macros utilized in writing
+ *        out PCI data for the SCI core.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_types.h>
+
+#define PATSBURG_SMU_BAR       0
+#define PATSBURG_SCU_BAR       1
+#define PATSBURG_IO_SPACE_BAR0 2
+#define PATSBURG_IO_SPACE_BAR1 3
+
+#define SCIC_SDS_PCI_REVISION_A0 0
+#define SCIC_SDS_PCI_REVISION_A2 2
+#define SCIC_SDS_PCI_REVISION_B0 4
+#define SCIC_SDS_PCI_REVISION_C0 5
+#define SCIC_SDS_PCI_REVISION_C1 6
+
+enum SCU_CONTROLLER_PCI_REVISION_CODE
+{
+   SCU_PBG_HBA_REV_A0 = SCIC_SDS_PCI_REVISION_A0,
+   SCU_PBG_HBA_REV_A2 = SCIC_SDS_PCI_REVISION_A2,
+   SCU_PBG_HBA_REV_B0 = SCIC_SDS_PCI_REVISION_B0,
+   SCU_PBG_HBA_REV_C0 = SCIC_SDS_PCI_REVISION_C0,
+   SCU_PBG_HBA_REV_C1 = SCIC_SDS_PCI_REVISION_C1
+};
+
+struct SCIC_SDS_CONTROLLER;
+
+void scic_sds_pci_bar_initialization(
+   struct SCIC_SDS_CONTROLLER * this_controller
+);
+
+#if !defined(ENABLE_PCI_IO_SPACE_ACCESS) || defined(ARLINGTON_BUILD)
+
+#define scic_sds_pci_read_smu_dword  scic_cb_pci_read_dword
+#define scic_sds_pci_write_smu_dword scic_cb_pci_write_dword
+#define scic_sds_pci_read_scu_dword  scic_cb_pci_read_dword
+#define scic_sds_pci_write_scu_dword scic_cb_pci_write_dword
+
+#else // !defined(ENABLE_PCI_IO_SPACE_ACCESS)
+
+// These two registers form the Data/Index pair equivalent in the
+// SCU. They are only used for access registers in BAR 1, not BAR 0.
+#define SCU_MMR_ADDRESS_WINDOW_OFFSET 0xA0
+#define SCU_MMR_DATA_WINDOW_OFFSET    0xA4
+
+U32 scic_sds_pci_read_smu_dword(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   void                    * address
+);
+
+void scic_sds_pci_write_smu_dword(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   void                    * address,
+   U32                       write_value
+);
+
+U32 scic_sds_pci_read_scu_dword(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   void                    * address
+);
+
+void scic_sds_pci_write_scu_dword(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   void                    * address,
+   U32                       write_value
+);
+
+#endif // !defined(ENABLE_PCI_IO_SPACE_ACCESS)
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIC_SDS_PCI_H_
diff --git a/sys/dev/disk/isci/scil/scic_sds_phy.c b/sys/dev/disk/isci/scil/scic_sds_phy.c
new file mode 100644
index 0000000..c0609ba
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_sds_phy.c
@@ -0,0 +1,4034 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_sds_phy.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains the implementation of the SCIC_SDS_PHY public and
+ *        protected methods.
+ */
+
+#include <dev/disk/isci/scil/scic_user_callback.h>
+#include <dev/disk/isci/scil/scic_phy.h>
+#include <dev/disk/isci/scil/scic_sds_phy.h>
+#include <dev/disk/isci/scil/scic_sds_port.h>
+#include <dev/disk/isci/scil/scic_sds_controller_registers.h>
+#include <dev/disk/isci/scil/scic_sds_phy_registers.h>
+#include <dev/disk/isci/scil/scic_sds_logger.h>
+#include <dev/disk/isci/scil/scic_sds_remote_node_context.h>
+#include <dev/disk/isci/scil/sci_util.h>
+#include <dev/disk/isci/scil/scic_sds_controller.h>
+#include <dev/disk/isci/scil/scu_event_codes.h>
+#include <dev/disk/isci/scil/sci_base_state.h>
+#include <dev/disk/isci/scil/intel_ata.h>
+#include <dev/disk/isci/scil/intel_sata.h>
+#include <dev/disk/isci/scil/sci_base_state_machine.h>
+#include <dev/disk/isci/scil/scic_sds_port_registers.h>
+
+#define SCIC_SDS_PHY_MIN_TIMER_COUNT  (SCI_MAX_PHYS)
+#define SCIC_SDS_PHY_MAX_TIMER_COUNT  (SCI_MAX_PHYS)
+
+// Maximum arbitration wait time in micro-seconds
+#define SCIC_SDS_PHY_MAX_ARBITRATION_WAIT_TIME  (700)
+
+#define AFE_REGISTER_WRITE_DELAY 10
+
+//*****************************************************************************
+//* SCIC SDS PHY Internal Methods
+//*****************************************************************************
+
+/**
+ * @brief This method will initialize the phy transport layer registers
+ *
+ * @param[in] this_phy
+ * @param[in] transport_layer_registers
+ *
+ * @return SCI_STATUS
+ */
+static
+SCI_STATUS scic_sds_phy_transport_layer_initialization(
+   SCIC_SDS_PHY_T                  *this_phy,
+   SCU_TRANSPORT_LAYER_REGISTERS_T *transport_layer_registers
+)
+{
+   U32 tl_control;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_phy),
+      SCIC_LOG_OBJECT_PHY,
+      "scic_sds_phy_link_layer_initialization(this_phy:0x%x, link_layer_registers:0x%x)\n",
+      this_phy, transport_layer_registers
+   ));
+
+   this_phy->transport_layer_registers = transport_layer_registers;
+
+   SCU_STPTLDARNI_WRITE(this_phy, SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX);
+
+   // Hardware team recommends that we enable the STP prefetch for all transports
+   tl_control = SCU_TLCR_READ(this_phy);
+   tl_control |= SCU_TLCR_GEN_BIT(STP_WRITE_DATA_PREFETCH);
+   SCU_TLCR_WRITE(this_phy, tl_control);
+
+   return SCI_SUCCESS;
+}
+
+/**
+ * @brief This method will initialize the phy link layer registers
+ *
+ * @param[in] this_phy
+ * @param[in] link_layer_registers
+ *
+ * @return SCI_STATUS
+ */
+static
+SCI_STATUS scic_sds_phy_link_layer_initialization(
+   SCIC_SDS_PHY_T             *this_phy,
+   SCU_LINK_LAYER_REGISTERS_T *link_layer_registers
+)
+{
+   U32                phy_configuration;
+   SAS_CAPABILITIES_T phy_capabilities;
+   U32                parity_check = 0;
+   U32                parity_count = 0;
+   U32                link_layer_control;
+   U32                phy_timer_timeout_values;
+   U32                clksm_value = 0;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_phy),
+      SCIC_LOG_OBJECT_PHY,
+      "scic_sds_phy_link_layer_initialization(this_phy:0x%x, link_layer_registers:0x%x)\n",
+      this_phy, link_layer_registers
+   ));
+
+   this_phy->link_layer_registers = link_layer_registers;
+
+   // Set our IDENTIFY frame data
+   #define SCI_END_DEVICE 0x01
+
+   SCU_SAS_TIID_WRITE(
+      this_phy,
+      (   SCU_SAS_TIID_GEN_BIT(SMP_INITIATOR)
+        | SCU_SAS_TIID_GEN_BIT(SSP_INITIATOR)
+        | SCU_SAS_TIID_GEN_BIT(STP_INITIATOR)
+        | SCU_SAS_TIID_GEN_BIT(DA_SATA_HOST)
+        | SCU_SAS_TIID_GEN_VAL(DEVICE_TYPE, SCI_END_DEVICE) )
+      );
+
+   // Write the device SAS Address
+   SCU_SAS_TIDNH_WRITE(this_phy, 0xFEDCBA98);
+   SCU_SAS_TIDNL_WRITE(this_phy, this_phy->phy_index);
+
+   // Write the source SAS Address
+   SCU_SAS_TISSAH_WRITE(
+      this_phy,
+      this_phy->owning_port->owning_controller->oem_parameters.sds1.phys[
+          this_phy->phy_index].sas_address.sci_format.high
+   );
+   SCU_SAS_TISSAL_WRITE(
+      this_phy,
+      this_phy->owning_port->owning_controller->oem_parameters.sds1.phys[
+          this_phy->phy_index].sas_address.sci_format.low
+   );
+
+   // Clear and Set the PHY Identifier
+   SCU_SAS_TIPID_WRITE(this_phy, 0x00000000);
+   SCU_SAS_TIPID_WRITE(this_phy, SCU_SAS_TIPID_GEN_VALUE(ID, this_phy->phy_index));
+
+   // Change the initial state of the phy configuration register
+   phy_configuration = SCU_SAS_PCFG_READ(this_phy);
+
+   // Hold OOB state machine in reset
+   phy_configuration |=  SCU_SAS_PCFG_GEN_BIT(OOB_RESET);
+   SCU_SAS_PCFG_WRITE(this_phy, phy_configuration);
+
+   // Configure the SNW capabilities
+   phy_capabilities.u.all = 0;
+   phy_capabilities.u.bits.start                      = 1;
+   phy_capabilities.u.bits.gen3_without_ssc_supported = 1;
+   phy_capabilities.u.bits.gen2_without_ssc_supported = 1;
+   phy_capabilities.u.bits.gen1_without_ssc_supported = 1;
+
+   /*
+    * Set up SSC settings according to version of OEM Parameters.
+    */
+   {
+       U8 header_version, enable_sata, enable_sas,
+          sata_spread, sas_type, sas_spread;
+       OEM_SSC_PARAMETERS_T ssc;
+
+       header_version = this_phy->owning_port->owning_controller->
+                        oem_parameters_version;
+
+       ssc.bf.ssc_sata_tx_spread_level =
+          this_phy->owning_port->owning_controller->oem_parameters.sds1.controller.ssc_sata_tx_spread_level;
+       ssc.bf.ssc_sas_tx_spread_level =
+          this_phy->owning_port->owning_controller->oem_parameters.sds1.controller.ssc_sas_tx_spread_level;
+       ssc.bf.ssc_sas_tx_type =
+          this_phy->owning_port->owning_controller->oem_parameters.sds1.controller.ssc_sas_tx_type;
+       enable_sata = enable_sas = sata_spread = sas_type = sas_spread = 0;
+
+       if (header_version == SCI_OEM_PARAM_VER_1_0)
+       {
+           /*
+            * Version 1.0 is merely turning SSC on to default values.;
+            */
+           if (ssc.do_enable_ssc != 0)
+           {
+               enable_sas = enable_sata = TRUE;
+               sas_type = 0x0;      // Downspreading
+               sata_spread = 0x2;   // +0 to -1419 PPM
+               sas_spread = 0x2;    // +0 to -1419 PPM
+           }
+       }
+       else // header_version >= SCI_OEM_PARAM_VER_1_1
+       {
+          /*
+           * Version 1.1 can turn on SAS and SATA independently and
+           * specify spread levels. Also can specify spread type for SAS.
+           */
+          if ((sata_spread = ssc.bf.ssc_sata_tx_spread_level) != 0)
+             enable_sata = TRUE;  // Downspreading only
+          if ((sas_spread = ssc.bf.ssc_sas_tx_spread_level) != 0)
+          {
+             enable_sas = TRUE;
+             sas_type = ssc.bf.ssc_sas_tx_type;
+          }
+       }
+
+       if (enable_sas == TRUE)
+       {
+           U32 reg_val = scu_afe_register_read(
+                             this_phy->owning_port->owning_controller,
+                             scu_afe_xcvr[this_phy->phy_index].
+                             afe_xcvr_control0);
+           reg_val |= (0x00100000 | (((U32)sas_type) << 19));
+           scu_afe_register_write(
+               this_phy->owning_port->owning_controller,
+               scu_afe_xcvr[this_phy->phy_index].afe_xcvr_control0,
+               reg_val);
+
+           reg_val = scu_afe_register_read(
+                             this_phy->owning_port->owning_controller,
+                             scu_afe_xcvr[this_phy->phy_index].
+                             afe_tx_ssc_control);
+           reg_val |= (((U32)(sas_spread)) << 8);
+           scu_afe_register_write(
+               this_phy->owning_port->owning_controller,
+               scu_afe_xcvr[this_phy->phy_index].afe_tx_ssc_control,
+               reg_val);
+      phy_capabilities.u.bits.gen3_with_ssc_supported = 1;
+      phy_capabilities.u.bits.gen2_with_ssc_supported = 1;
+      phy_capabilities.u.bits.gen1_with_ssc_supported = 1;
+   }
+
+       if (enable_sata == TRUE)
+       {
+           U32 reg_val = scu_afe_register_read(
+                         this_phy->owning_port->owning_controller,
+                         scu_afe_xcvr[this_phy->phy_index].
+                         afe_tx_ssc_control);
+           reg_val |= (U32)sata_spread;
+           scu_afe_register_write(
+               this_phy->owning_port->owning_controller,
+               scu_afe_xcvr[this_phy->phy_index].afe_tx_ssc_control,
+               reg_val);
+
+           reg_val = scu_link_layer_register_read(
+                         this_phy,
+                         stp_control);
+           reg_val |= (U32)(1 << 12);
+           scu_link_layer_register_write(
+               this_phy,
+               stp_control,
+               reg_val);
+       }
+   }
+
+   // The SAS specification indicates that the phy_capabilities that
+   // are transmitted shall have an even parity.  Calculate the parity.
+   parity_check = phy_capabilities.u.all;
+   while (parity_check != 0)
+   {
+      if (parity_check & 0x1)
+         parity_count++;
+      parity_check >>= 1;
+   }
+
+   // If parity indicates there are an odd number of bits set, then
+   // set the parity bit to 1 in the phy capabilities.
+   if ((parity_count % 2) != 0)
+      phy_capabilities.u.bits.parity = 1;
+
+   SCU_SAS_PHYCAP_WRITE(this_phy, phy_capabilities.u.all);
+
+   // Set the enable spinup period but disable the ability to send notify enable spinup
+   SCU_SAS_ENSPINUP_WRITE(
+     this_phy,
+     SCU_ENSPINUP_GEN_VAL(
+        COUNT,
+        this_phy->owning_port->owning_controller->user_parameters.sds1.
+           phys[this_phy->phy_index].notify_enable_spin_up_insertion_frequency
+     )
+   );
+
+   // Write the ALIGN Insertion Ferequency for connected phy and inpendent of connected state
+   clksm_value = SCU_ALIGN_INSERTION_FREQUENCY_GEN_VAL (
+                     CONNECTED,
+                     this_phy->owning_port->owning_controller->user_parameters.sds1.
+                        phys[this_phy->phy_index].in_connection_align_insertion_frequency
+                 );
+
+   clksm_value |= SCU_ALIGN_INSERTION_FREQUENCY_GEN_VAL (
+                     GENERAL,
+                     this_phy->owning_port->owning_controller->user_parameters.sds1.
+                        phys[this_phy->phy_index].align_insertion_frequency
+                  );
+
+   SCU_SAS_CLKSM_WRITE ( this_phy, clksm_value);
+
+
+#if defined(PBG_HBA_A0_BUILD) || defined(PBG_HBA_A2_BUILD) || defined(PBG_HBA_BETA_BUILD)
+   /// @todo Provide a way to write this register correctly
+   scu_link_layer_register_write(this_phy, afe_lookup_table_control, 0x02108421);
+#elif defined(PBG_BUILD)
+   if (
+         (this_phy->owning_port->owning_controller->pci_revision == SCIC_SDS_PCI_REVISION_C0)
+      || (this_phy->owning_port->owning_controller->pci_revision == SCIC_SDS_PCI_REVISION_C1)
+      )
+   {
+      scu_link_layer_register_write(this_phy, afe_lookup_table_control, 0x04210400);
+      scu_link_layer_register_write(this_phy, sas_primitive_timeout, 0x20A7C05);
+   }
+   else
+   {
+      scu_link_layer_register_write(this_phy, afe_lookup_table_control, 0x02108421);
+   }
+#else
+   /// @todo Provide a way to write this register correctly
+   scu_link_layer_register_write(this_phy, afe_lookup_table_control, 0x0e739ce7);
+#endif
+
+   link_layer_control = SCU_SAS_LLCTL_GEN_VAL(
+                           NO_OUTBOUND_TASK_TIMEOUT,
+                           (U8) this_phy->owning_port->owning_controller->
+                           user_parameters.sds1.no_outbound_task_timeout
+                        );
+
+#if PHY_MAX_LINK_SPEED_GENERATION == SCIC_SDS_PARM_GEN1_SPEED
+#define COMPILED_MAX_LINK_RATE SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN1
+#elif PHY_MAX_LINK_SPEED_GENERATION == SCIC_SDS_PARM_GEN2_SPEED
+#define COMPILED_MAX_LINK_RATE SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN2
+#else
+#define COMPILED_MAX_LINK_RATE SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN3
+#endif // PHY_MAX_LINK_SPEED_GENERATION
+
+   if (this_phy->owning_port->owning_controller->user_parameters.sds1.
+       phys[this_phy->phy_index].max_speed_generation == SCIC_SDS_PARM_GEN3_SPEED)
+   {
+      link_layer_control |= SCU_SAS_LLCTL_GEN_VAL(
+                               MAX_LINK_RATE, COMPILED_MAX_LINK_RATE
+                            );
+   }
+   else if (this_phy->owning_port->owning_controller->user_parameters.sds1.
+       phys[this_phy->phy_index].max_speed_generation == SCIC_SDS_PARM_GEN2_SPEED)
+   {
+      link_layer_control |= SCU_SAS_LLCTL_GEN_VAL(
+                               MAX_LINK_RATE,
+                               MIN(
+                                  SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN2,
+                                  COMPILED_MAX_LINK_RATE)
+                            );
+   }
+   else
+   {
+      link_layer_control |= SCU_SAS_LLCTL_GEN_VAL(
+                               MAX_LINK_RATE,
+                               MIN(
+                                  SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN1,
+                                  COMPILED_MAX_LINK_RATE)
+                            );
+   }
+
+   scu_link_layer_register_write(
+      this_phy, link_layer_control, link_layer_control
+   );
+
+   phy_timer_timeout_values = scu_link_layer_register_read(
+                                 this_phy,
+                                 phy_timer_timeout_values
+                              );
+
+   // Clear the default 0x36 (54us) RATE_CHANGE timeout value.
+   phy_timer_timeout_values &= ~SCU_SAS_PHYTOV_GEN_VAL(RATE_CHANGE, 0xFF);
+
+   // Set RATE_CHANGE timeout value to 0x3B (59us).  This ensures SCU can
+   //  lock with 3Gb drive when SCU max rate is set to 1.5Gb.
+   phy_timer_timeout_values |= SCU_SAS_PHYTOV_GEN_VAL(RATE_CHANGE, 0x3B);
+
+   scu_link_layer_register_write(
+      this_phy, phy_timer_timeout_values, phy_timer_timeout_values
+   );
+
+   // Program the max ARB time for the PHY to 700us so we inter-operate with
+   // the PMC expander which shuts down PHYs if the expander PHY generates too
+   // many breaks.  This time value will guarantee that the initiator PHY will
+   // generate the break.
+#if defined(PBG_HBA_A0_BUILD) || defined(PBG_HBA_A2_BUILD)
+   scu_link_layer_register_write(
+      this_phy,
+      maximum_arbitration_wait_timer_timeout,
+      SCIC_SDS_PHY_MAX_ARBITRATION_WAIT_TIME
+   );
+#endif // defined(PBG_HBA_A0_BUILD) || defined(PBG_HBA_A2_BUILD)
+
+   // Disable the link layer hang detection timer
+   scu_link_layer_register_write(
+      this_phy, link_layer_hang_detection_timeout, 0x00000000
+   );
+
+   // We can exit the initial state to the stopped state
+   sci_base_state_machine_change_state(
+      scic_sds_phy_get_base_state_machine(this_phy),
+      SCI_BASE_PHY_STATE_STOPPED
+   );
+
+   return SCI_SUCCESS;
+}
+
+/**
+ * This function will handle the sata SIGNATURE FIS timeout condition.  It
+ * will restart the starting substate machine since we dont know what has
+ * actually happening.
+ *
+ * @param[in] cookie This object is cast to the SCIC_SDS_PHY_T object.
+ *
+ * @return none
+ */
+void scic_sds_phy_sata_timeout( SCI_OBJECT_HANDLE_T cookie)
+{
+   SCIC_SDS_PHY_T * this_phy = (SCIC_SDS_PHY_T *)cookie;
+
+   SCIC_LOG_INFO((
+      sci_base_object_get_logger(this_phy),
+      SCIC_LOG_OBJECT_PHY,
+      "SCIC SDS Phy 0x%x did not receive signature fis before timeout.\n",
+      this_phy
+   ));
+
+   sci_base_state_machine_stop(
+      scic_sds_phy_get_starting_substate_machine(this_phy));
+
+   sci_base_state_machine_change_state(
+      scic_sds_phy_get_base_state_machine(this_phy),
+      SCI_BASE_PHY_STATE_STARTING
+   );
+}
+
+//*****************************************************************************
+//* SCIC SDS PHY External Methods
+//*****************************************************************************
+
+/**
+ * @brief This method returns the object size for a phy object.
+ *
+ * @return U32
+ */
+U32 scic_sds_phy_get_object_size(void)
+{
+   return sizeof(SCIC_SDS_PHY_T);
+}
+
+/**
+ * @brief This method returns the minimum number of timers required for a
+ *        phy object.
+ *
+ * @return U32
+ */
+U32 scic_sds_phy_get_min_timer_count(void)
+{
+   return SCIC_SDS_PHY_MIN_TIMER_COUNT;
+}
+
+/**
+ * @brief This method returns the maximum number of timers required for a
+ *        phy object.
+ *
+ * @return U32
+ */
+U32 scic_sds_phy_get_max_timer_count(void)
+{
+   return SCIC_SDS_PHY_MAX_TIMER_COUNT;
+}
+
+#ifdef SCI_LOGGING
+static
+void scic_sds_phy_initialize_state_logging(
+   SCIC_SDS_PHY_T *this_phy
+)
+{
+   sci_base_state_machine_logger_initialize(
+      &this_phy->parent.state_machine_logger,
+      &this_phy->parent.state_machine,
+      &this_phy->parent.parent,
+      scic_cb_logger_log_states,
+      "SCIC_SDS_PHY_T", "base state machine",
+      SCIC_LOG_OBJECT_PHY
+   );
+
+   sci_base_state_machine_logger_initialize(
+      &this_phy->starting_substate_machine_logger,
+      &this_phy->starting_substate_machine,
+      &this_phy->parent.parent,
+      scic_cb_logger_log_states,
+      "SCIC_SDS_PHY_T", "starting substate machine",
+      SCIC_LOG_OBJECT_PHY
+   );
+}
+#endif // SCI_LOGGING
+
+#ifdef SCIC_DEBUG_ENABLED
+/**
+ * Debug code to record the state transitions in the phy
+ *
+ * @param our_observer
+ * @param the_state_machine
+ */
+void scic_sds_phy_observe_state_change(
+   SCI_BASE_OBSERVER_T * our_observer,
+   SCI_BASE_SUBJECT_T  * the_subject
+)
+{
+   SCIC_SDS_PHY_T           *this_phy;
+   SCI_BASE_STATE_MACHINE_T *the_state_machine;
+
+   U8  transition_requestor;
+   U32 base_state_id;
+   U32 starting_substate_id;
+
+   the_state_machine = (SCI_BASE_STATE_MACHINE_T *)the_subject;
+   this_phy = (SCIC_SDS_PHY_T *)the_state_machine->state_machine_owner;
+
+   if (the_state_machine == &this_phy->parent.state_machine)
+   {
+      transition_requestor = 0x01;
+   }
+   else if (the_state_machine == &this_phy->starting_substate_machine)
+   {
+      transition_requestor = 0x02;
+   }
+   else
+   {
+      transition_requestor = 0xFF;
+   }
+
+   base_state_id =
+      sci_base_state_machine_get_state(&this_phy->parent.state_machine);
+   starting_substate_id =
+      sci_base_state_machine_get_state(&this_phy->starting_substate_machine);
+
+   this_phy->state_record.state_transition_table[
+      this_phy->state_record.index++] = ( (transition_requestor << 24)
+                                        | ((U8)base_state_id << 8)
+                                        | ((U8)starting_substate_id));
+
+   this_phy->state_record.index =
+      this_phy->state_record.index & (MAX_STATE_TRANSITION_RECORD - 1);
+
+}
+#endif // SCIC_DEBUG_ENABLED
+
+#ifdef SCIC_DEBUG_ENABLED
+/**
+ * This method initializes the state record debug information for the phy
+ * object.
+ *
+ * @pre The state machines for the phy object must be constructed before this
+ *      function is called.
+ *
+ * @param this_phy The phy which is being initialized.
+ */
+void scic_sds_phy_initialize_state_recording(
+   SCIC_SDS_PHY_T *this_phy
+)
+{
+   this_phy->state_record.index = 0;
+
+   sci_base_observer_initialize(
+      &this_phy->state_record.base_state_observer,
+      scic_sds_phy_observe_state_change,
+      &this_phy->parent.state_machine.parent
+   );
+
+   sci_base_observer_initialize(
+      &this_phy->state_record.starting_state_observer,
+      scic_sds_phy_observe_state_change,
+      &this_phy->starting_substate_machine.parent
+   );
+}
+#endif // SCIC_DEBUG_ENABLED
+
+/**
+ * @brief This method will construct the SCIC_SDS_PHY object
+ *
+ * @param[in] this_phy
+ * @param[in] owning_port
+ * @param[in] phy_index
+ *
+ * @return none
+ */
+void scic_sds_phy_construct(
+   SCIC_SDS_PHY_T  *this_phy,
+   SCIC_SDS_PORT_T *owning_port,
+   U8              phy_index
+)
+{
+   // Call the base constructor first
+   // Copy the logger from the port (this could be the dummy port)
+   sci_base_phy_construct(
+      &this_phy->parent,
+      sci_base_object_get_logger(owning_port),
+      scic_sds_phy_state_table
+      );
+
+   // Copy the rest of the input data to our locals
+   this_phy->owning_port = owning_port;
+   this_phy->phy_index = phy_index;
+   this_phy->bcn_received_while_port_unassigned = FALSE;
+   this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN;
+   this_phy->link_layer_registers = NULL;
+   this_phy->max_negotiated_speed = SCI_SAS_NO_LINK_RATE;
+   this_phy->sata_timeout_timer = NULL;
+
+   // Clear out the identification buffer data
+   memset(&this_phy->phy_type, 0, sizeof(this_phy->phy_type));
+
+   // Clear out the error counter data
+   memset(this_phy->error_counter, 0, sizeof(this_phy->error_counter));
+
+   // Initialize the the substate machines
+   sci_base_state_machine_construct(
+      &this_phy->starting_substate_machine,
+      &this_phy->parent.parent,
+      scic_sds_phy_starting_substates,
+      SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL
+      );
+
+   #ifdef SCI_LOGGING
+   scic_sds_phy_initialize_state_logging(this_phy);
+   #endif // SCI_LOGGING
+
+   #ifdef SCIC_DEBUG_ENABLED
+   scic_sds_phy_initialize_state_recording(this_phy);
+   #endif // SCIC_DEBUG_ENABLED
+}
+
+/**
+ * @brief This method returns the port currently containing this phy.
+ *        If the phy is currently contained by the dummy port, then
+ *        the phy is considered to not be part of a port.
+ *
+ * @param[in] this_phy This parameter specifies the phy for which to
+ *            retrieve the containing port.
+ *
+ * @return This method returns a handle to a port that contains
+ *         the supplied phy.
+ * @retval SCI_INVALID_HANDLE This value is returned if the phy is not
+ *         part of a real port (i.e. it's contained in the dummy port).
+ * @retval !SCI_INVALID_HANDLE All other values indicate a handle/pointer
+ *         to the port containing the phy.
+ */
+SCI_PORT_HANDLE_T scic_sds_phy_get_port(
+   SCIC_SDS_PHY_T *this_phy
+)
+{
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_phy),
+      SCIC_LOG_OBJECT_PHY,
+      "scic_phy_get_port(0x%x) enter\n",
+      this_phy
+   ));
+
+   if (scic_sds_port_get_index(this_phy->owning_port) == SCIC_SDS_DUMMY_PORT)
+      return SCI_INVALID_HANDLE;
+
+   return this_phy->owning_port;
+}
+
+/**
+ * @brief This method will assign a port to the phy object.
+ *
+ * @param[in, out] this_phy This parameter specifies the phy for which
+ *    to assign a port object.
+ * @param[in] the_port This parameter is the port to assing to the phy.
+ */
+void scic_sds_phy_set_port(
+   SCIC_SDS_PHY_T * this_phy,
+   SCIC_SDS_PORT_T * the_port
+)
+{
+   this_phy->owning_port = the_port;
+
+   if (this_phy->bcn_received_while_port_unassigned)
+   {
+      this_phy->bcn_received_while_port_unassigned = FALSE;
+      scic_sds_port_broadcast_change_received(this_phy->owning_port, this_phy);
+   }
+}
+
+/**
+ * @brief This method will initialize the constructed phy
+ *
+ * @param[in] this_phy
+ * @param[in] link_layer_registers
+ *
+ * @return SCI_STATUS
+ */
+SCI_STATUS scic_sds_phy_initialize(
+   SCIC_SDS_PHY_T             *this_phy,
+   void                       *transport_layer_registers,
+   SCU_LINK_LAYER_REGISTERS_T *link_layer_registers
+)
+{
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_phy),
+      SCIC_LOG_OBJECT_PHY,
+      "scic_sds_phy_initialize(this_phy:0x%x, link_layer_registers:0x%x)\n",
+      this_phy, link_layer_registers
+   ));
+
+   // Perfrom the initialization of the TL hardware
+   scic_sds_phy_transport_layer_initialization(this_phy, transport_layer_registers);
+
+   // Perofrm the initialization of the PE hardware
+   scic_sds_phy_link_layer_initialization(this_phy, link_layer_registers);
+
+   // There is nothing that needs to be done in this state just
+   // transition to the stopped state.
+   sci_base_state_machine_change_state(
+      scic_sds_phy_get_base_state_machine(this_phy),
+      SCI_BASE_PHY_STATE_STOPPED
+   );
+
+   return SCI_SUCCESS;
+}
+
+/**
+ * This method assigns the direct attached device ID for this phy.
+ *
+ * @param[in] this_phy The phy for which the direct attached device id is to
+ *       be assigned.
+ * @param[in] device_id The direct attached device ID to assign to the phy.
+ *       This will either be the RNi for the device or an invalid RNi if there
+ *       is no current device assigned to the phy.
+ */
+void scic_sds_phy_setup_transport(
+   SCIC_SDS_PHY_T * this_phy,
+   U32              device_id
+)
+{
+   U32 tl_control;
+
+   SCU_STPTLDARNI_WRITE(this_phy, device_id);
+
+   // The read should guarntee that the first write gets posted
+   // before the next write
+   tl_control = SCU_TLCR_READ(this_phy);
+   tl_control |= SCU_TLCR_GEN_BIT(CLEAR_TCI_NCQ_MAPPING_TABLE);
+   SCU_TLCR_WRITE(this_phy, tl_control);
+}
+
+/**
+ * This function will perform the register reads/writes to suspend the SCU
+ * hardware protocol engine.
+ *
+ * @param[in,out] this_phy The phy object to be suspended.
+ *
+ * @return none
+ */
+void scic_sds_phy_suspend(
+   SCIC_SDS_PHY_T * this_phy
+)
+{
+   U32 scu_sas_pcfg_value;
+
+   scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy);
+   scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE);
+   SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value);
+
+   scic_sds_phy_setup_transport(
+      this_phy, SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX
+   );
+}
+
+/**
+ * This function will perform the register reads/writes required to resume the
+ * SCU hardware protocol engine.
+ *
+ * @param[in,out] this_phy The phy object to resume.
+ *
+ * @return none
+ */
+void scic_sds_phy_resume(
+   SCIC_SDS_PHY_T * this_phy
+)
+{
+   U32 scu_sas_pcfg_value;
+
+   scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy);
+
+   scu_sas_pcfg_value &= ~SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE);
+
+   SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value);
+}
+
+/**
+ * @brief This method returns the local sas address assigned to this phy.
+ *
+ * @param[in] this_phy This parameter specifies the phy for which
+ *            to retrieve the local SAS address.
+ * @param[out] sas_address This parameter specifies the location into
+ *             which to copy the local SAS address.
+ *
+ * @return none
+ */
+void scic_sds_phy_get_sas_address(
+   SCIC_SDS_PHY_T *this_phy,
+   SCI_SAS_ADDRESS_T *sas_address
+)
+{
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_phy),
+      SCIC_LOG_OBJECT_PHY,
+      "scic_sds_phy_get_sas_address(this_phy:0x%x, sas_address:0x%x)\n",
+      this_phy, sas_address
+   ));
+
+   sas_address->high = SCU_SAS_TISSAH_READ(this_phy);
+   sas_address->low  = SCU_SAS_TISSAL_READ(this_phy);
+}
+
+/**
+ * @brief This method returns the remote end-point (i.e. attached)
+ *        sas address assigned to this phy.
+ *
+ * @param[in] this_phy This parameter specifies the phy for which
+ *            to retrieve the remote end-point SAS address.
+ * @param[out] sas_address This parameter specifies the location into
+ *             which to copy the remote end-point SAS address.
+ *
+ * @return none
+ */
+void scic_sds_phy_get_attached_sas_address(
+   SCIC_SDS_PHY_T    *this_phy,
+   SCI_SAS_ADDRESS_T *sas_address
+)
+{
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_phy),
+      SCIC_LOG_OBJECT_PHY,
+      "scic_sds_phy_get_attached_sas_address(0x%x, 0x%x) enter\n",
+      this_phy, sas_address
+   ));
+
+   sas_address->high
+      = this_phy->phy_type.sas.identify_address_frame_buffer.sas_address.high;
+   sas_address->low
+      = this_phy->phy_type.sas.identify_address_frame_buffer.sas_address.low;
+}
+
+/**
+ * @brief This method returns the supported protocols assigned to
+ *        this phy
+ *
+ * @param[in] this_phy
+ * @param[out] protocols
+ */
+void scic_sds_phy_get_protocols(
+   SCIC_SDS_PHY_T *this_phy,
+   SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T * protocols
+)
+{
+   U32 tiid_value = SCU_SAS_TIID_READ(this_phy);
+
+   //Check each bit of this register. please refer to
+   //SAS Transmit Identification Register (SAS_TIID).
+   if (tiid_value & 0x2)
+      protocols->u.bits.smp_target = 1;
+
+   if (tiid_value & 0x4)
+      protocols->u.bits.stp_target = 1;
+
+   if (tiid_value & 0x8)
+      protocols->u.bits.ssp_target = 1;
+
+   if (tiid_value & 0x200)
+      protocols->u.bits.smp_initiator = 1;
+
+   if ((tiid_value & 0x400))
+      protocols->u.bits.stp_initiator = 1;
+
+   if (tiid_value & 0x800)
+      protocols->u.bits.ssp_initiator = 1;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_phy),
+      SCIC_LOG_OBJECT_PHY,
+      "scic_sds_phy_get_protocols(this_phy:0x%x, protocols:0x%x)\n",
+      this_phy, protocols->u.all
+   ));
+}
+
+/**
+ * This method returns the supported protocols for the attached phy.  If this
+ * is a SAS phy the protocols are returned from the identify address frame.
+ * If this is a SATA phy then protocols are made up and the target phy is an
+ * STP target phy.
+ *
+ * @note The caller will get the entire set of bits for the protocol value.
+ *
+ * @param[in] this_phy The parameter is the phy object for which the attached
+ *       phy protcols are to be returned.
+ * @param[out] protocols The parameter is the returned protocols for the
+ *       attached phy.
+ */
+void scic_sds_phy_get_attached_phy_protocols(
+   SCIC_SDS_PHY_T *this_phy,
+   SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T * protocols
+)
+{
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_phy),
+      SCIC_LOG_OBJECT_PHY,
+      "scic_sds_phy_get_attached_phy_protocols(this_phy:0x%x, protocols:0x%x[0x%x])\n",
+      this_phy, protocols, protocols->u.all
+   ));
+
+   protocols->u.all = 0;
+
+   if (this_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS)
+   {
+      protocols->u.all =
+         this_phy->phy_type.sas.identify_address_frame_buffer.protocols.u.all;
+   }
+   else if (this_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA)
+   {
+      protocols->u.bits.stp_target = 1;
+   }
+}
+
+
+/**
+ * @brief This method release resources in for a scic phy.
+ *
+ * @param[in] controller This parameter specifies the core controller, one of
+ *            its phy's resources are to be released.
+ * @param[in] this_phy This parameter specifies the phy whose resourse is to
+ *            be released.
+ */
+void scic_sds_phy_release_resource(
+   SCIC_SDS_CONTROLLER_T * controller,
+   SCIC_SDS_PHY_T        * this_phy
+)
+{
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_phy),
+      SCIC_LOG_OBJECT_PHY,
+      "scic_sds_phy_release_resource(0x%x, 0x%x)\n",
+      controller, this_phy
+   ));
+
+   //Currently, the only resource to be released is a timer.
+   if (this_phy->sata_timeout_timer != NULL)
+   {
+      scic_cb_timer_destroy(controller, this_phy->sata_timeout_timer);
+      this_phy->sata_timeout_timer = NULL;
+   }
+}
+
+
+//*****************************************************************************
+//* SCIC SDS PHY Handler Redirects
+//*****************************************************************************
+
+/**
+ * @brief This method will attempt to reset the phy.  This
+ *        request is only valid when the phy is in an ready
+ *        state
+ *
+ * @param[in] this_phy
+ *
+ * @return SCI_STATUS
+ */
+SCI_STATUS scic_sds_phy_reset(
+   SCIC_SDS_PHY_T * this_phy
+)
+{
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_phy),
+      SCIC_LOG_OBJECT_PHY,
+      "scic_sds_phy_reset(this_phy:0x%08x)\n",
+      this_phy
+   ));
+
+   return this_phy->state_handlers->parent.reset_handler(
+                                             &this_phy->parent
+                                           );
+}
+
+/**
+ * @brief This method will process the event code recieved.
+ *
+ * @param[in] this_phy
+ * @param[in] event_code
+ *
+ * @return SCI_STATUS
+ */
+SCI_STATUS scic_sds_phy_event_handler(
+   SCIC_SDS_PHY_T *this_phy,
+   U32 event_code
+)
+{
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_phy),
+      SCIC_LOG_OBJECT_PHY,
+      "scic_sds_phy_event_handler(this_phy:0x%08x, event_code:%x)\n",
+      this_phy, event_code
+   ));
+
+   return this_phy->state_handlers->event_handler(this_phy, event_code);
+}
+
+/**
+ * @brief This method will process the frame index recieved.
+ *
+ * @param[in] this_phy
+ * @param[in] frame_index
+ *
+ * @return SCI_STATUS
+ */
+SCI_STATUS scic_sds_phy_frame_handler(
+   SCIC_SDS_PHY_T *this_phy,
+   U32 frame_index
+)
+{
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_phy),
+      SCIC_LOG_OBJECT_PHY,
+      "scic_sds_phy_frame_handler(this_phy:0x%08x, frame_index:%d)\n",
+      this_phy, frame_index
+   ));
+
+   return this_phy->state_handlers->frame_handler(this_phy, frame_index);
+}
+
+/**
+ * @brief This method will give the phy permission to consume power
+ *
+ * @param[in] this_phy
+ *
+ * @return SCI_STATUS
+ */
+SCI_STATUS scic_sds_phy_consume_power_handler(
+   SCIC_SDS_PHY_T *this_phy
+)
+{
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_phy),
+      SCIC_LOG_OBJECT_PHY,
+      "scic_sds_phy_consume_power_handler(this_phy:0x%08x)\n",
+      this_phy
+   ));
+
+   return this_phy->state_handlers->consume_power_handler(this_phy);
+}
+
+//*****************************************************************************
+//* SCIC PHY Public Methods
+//*****************************************************************************
+
+SCI_STATUS scic_phy_get_properties(
+   SCI_PHY_HANDLE_T        phy,
+   SCIC_PHY_PROPERTIES_T * properties
+)
+{
+   SCIC_SDS_PHY_T *this_phy;
+   U8 max_speed_generation;
+
+   this_phy = (SCIC_SDS_PHY_T *)phy;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_phy),
+      SCIC_LOG_OBJECT_PHY,
+      "scic_phy_get_properties(0x%x, 0x%x) enter\n",
+      this_phy, properties
+   ));
+
+   if (phy == SCI_INVALID_HANDLE)
+   {
+      return SCI_FAILURE_INVALID_PHY;
+   }
+
+   memset(properties, 0, sizeof(SCIC_PHY_PROPERTIES_T));
+
+   //get max link rate of this phy set by user.
+   max_speed_generation =
+      this_phy->owning_port->owning_controller->user_parameters.sds1.
+         phys[this_phy->phy_index].max_speed_generation;
+
+   properties->negotiated_link_rate     = this_phy->max_negotiated_speed;
+
+   if (max_speed_generation == SCIC_SDS_PARM_GEN3_SPEED)
+      properties->max_link_rate            = SCI_SAS_600_GB;
+   else if (max_speed_generation == SCIC_SDS_PARM_GEN2_SPEED)
+      properties->max_link_rate            = SCI_SAS_300_GB;
+   else
+      properties->max_link_rate            = SCI_SAS_150_GB;
+
+   properties->index                    = this_phy->phy_index;
+   properties->owning_port              = scic_sds_phy_get_port(this_phy);
+
+   scic_sds_phy_get_protocols(this_phy, &properties->transmit_iaf.protocols);
+
+   properties->transmit_iaf.sas_address.high =
+      this_phy->owning_port->owning_controller->oem_parameters.sds1.
+         phys[this_phy->phy_index].sas_address.sci_format.high;
+
+   properties->transmit_iaf.sas_address.low =
+      this_phy->owning_port->owning_controller->oem_parameters.sds1.
+         phys[this_phy->phy_index].sas_address.sci_format.low;
+
+   return SCI_SUCCESS;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_sas_phy_get_properties(
+   SCI_PHY_HANDLE_T            phy,
+   SCIC_SAS_PHY_PROPERTIES_T * properties
+)
+{
+   SCIC_SDS_PHY_T *this_phy;
+   this_phy = (SCIC_SDS_PHY_T *)phy;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_phy),
+      SCIC_LOG_OBJECT_PHY,
+      "scic_sas_phy_get_properties(0x%x, 0x%x) enter\n",
+      this_phy, properties
+   ));
+
+   if (this_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS)
+   {
+      memcpy(
+         &properties->received_iaf,
+         &this_phy->phy_type.sas.identify_address_frame_buffer,
+         sizeof(SCI_SAS_IDENTIFY_ADDRESS_FRAME_T)
+      );
+
+      properties->received_capabilities.u.all
+         = SCU_SAS_RECPHYCAP_READ(this_phy);
+
+      return SCI_SUCCESS;
+   }
+
+   return SCI_FAILURE;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_sata_phy_get_properties(
+   SCI_PHY_HANDLE_T             phy,
+   SCIC_SATA_PHY_PROPERTIES_T * properties
+)
+{
+   SCIC_SDS_PHY_T *this_phy;
+   this_phy = (SCIC_SDS_PHY_T *)phy;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_phy),
+      SCIC_LOG_OBJECT_PHY,
+      "scic_sata_phy_get_properties(0x%x, 0x%x) enter\n",
+      this_phy, properties
+   ));
+
+   if (this_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA)
+   {
+      memcpy(
+         &properties->signature_fis,
+         &this_phy->phy_type.sata.signature_fis_buffer,
+         sizeof(SATA_FIS_REG_D2H_T)
+      );
+
+      /// @todo add support for port selectors.
+      properties->is_port_selector_present = FALSE;
+
+      return SCI_SUCCESS;
+   }
+
+   return SCI_FAILURE;
+}
+
+// ---------------------------------------------------------------------------
+
+#if !defined(DISABLE_PORT_SELECTORS)
+
+SCI_STATUS scic_sata_phy_send_port_selection_signal(
+   SCI_PHY_HANDLE_T  phy
+)
+{
+   SCIC_SDS_PHY_T *this_phy;
+   this_phy = (SCIC_SDS_PHY_T *)phy;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_phy),
+      SCIC_LOG_OBJECT_PHY,
+      "scic_sata_phy_send_port_selection_signals(0x%x) enter\n",
+      this_phy
+   ));
+
+   /// @todo To be implemented
+   ASSERT(FALSE);
+   return SCI_FAILURE;
+}
+
+#endif // !defined(DISABLE_PORT_SELECTORS)
+
+// ---------------------------------------------------------------------------
+
+#if !defined(DISABLE_PHY_COUNTERS)
+
+SCI_STATUS scic_phy_enable_counter(
+   SCI_PHY_HANDLE_T       phy,
+   SCIC_PHY_COUNTER_ID_T  counter_id
+)
+{
+   SCIC_SDS_PHY_T *this_phy;
+   SCI_STATUS status = SCI_SUCCESS;
+   this_phy = (SCIC_SDS_PHY_T *)phy;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_phy),
+      SCIC_LOG_OBJECT_PHY,
+      "scic_phy_enable_counter(0x%x, 0x%x) enter\n",
+      this_phy, counter_id
+   ));
+
+   switch(counter_id)
+   {
+      case SCIC_PHY_COUNTER_RECEIVED_DONE_ACK_NAK_TIMEOUT:
+         {
+            U32 control = SCU_SAS_ECENCR_READ(this_phy);
+            control |= (1 << SCU_ERR_CNT_RX_DONE_ACK_NAK_TIMEOUT_INDEX);
+            SCU_SAS_ECENCR_WRITE(this_phy, control);
+         }
+         break;
+      case SCIC_PHY_COUNTER_TRANSMITTED_DONE_ACK_NAK_TIMEOUT:
+         {
+            U32 control = SCU_SAS_ECENCR_READ(this_phy);
+            control |= (1 << SCU_ERR_CNT_TX_DONE_ACK_NAK_TIMEOUT_INDEX);
+            SCU_SAS_ECENCR_WRITE(this_phy, control);
+         }
+         break;
+      case SCIC_PHY_COUNTER_INACTIVITY_TIMER_EXPIRED:
+         {
+            U32 control = SCU_SAS_ECENCR_READ(this_phy);
+            control |= (1 << SCU_ERR_CNT_INACTIVITY_TIMER_EXPIRED_INDEX);
+            SCU_SAS_ECENCR_WRITE(this_phy, control);
+         }
+         break;
+      case SCIC_PHY_COUNTER_RECEIVED_DONE_CREDIT_TIMEOUT:
+         {
+            U32 control = SCU_SAS_ECENCR_READ(this_phy);
+            control |= (1 << SCU_ERR_CNT_RX_DONE_CREDIT_TIMEOUT_INDEX);
+            SCU_SAS_ECENCR_WRITE(this_phy, control);
+         }
+         break;
+      case SCIC_PHY_COUNTER_TRANSMITTED_DONE_CREDIT_TIMEOUT:
+         {
+            U32 control = SCU_SAS_ECENCR_READ(this_phy);
+            control |= (1 << SCU_ERR_CNT_TX_DONE_CREDIT_TIMEOUT_INDEX);
+            SCU_SAS_ECENCR_WRITE(this_phy, control);
+         }
+         break;
+      case SCIC_PHY_COUNTER_RECEIVED_CREDIT_BLOCKED:
+         {
+            U32 control = SCU_SAS_ECENCR_READ(this_phy);
+            control |= (1 << SCU_ERR_CNT_RX_CREDIT_BLOCKED_RECEIVED_INDEX);
+            SCU_SAS_ECENCR_WRITE(this_phy, control);
+         }
+         break;
+
+         // These error counters are enabled by default, and cannot be
+         //  disabled.  Return SCI_SUCCESS to denote that they are
+         //  enabled, hiding the fact that enabling the counter is
+         //  a no-op.
+      case SCIC_PHY_COUNTER_RECEIVED_FRAME:
+      case SCIC_PHY_COUNTER_TRANSMITTED_FRAME:
+      case SCIC_PHY_COUNTER_RECEIVED_FRAME_DWORD:
+      case SCIC_PHY_COUNTER_TRANSMITTED_FRAME_DWORD:
+      case SCIC_PHY_COUNTER_LOSS_OF_SYNC_ERROR:
+      case SCIC_PHY_COUNTER_RECEIVED_DISPARITY_ERROR:
+      case SCIC_PHY_COUNTER_RECEIVED_FRAME_CRC_ERROR:
+      case SCIC_PHY_COUNTER_RECEIVED_SHORT_FRAME:
+      case SCIC_PHY_COUNTER_RECEIVED_FRAME_WITHOUT_CREDIT:
+      case SCIC_PHY_COUNTER_RECEIVED_FRAME_AFTER_DONE:
+      case SCIC_PHY_COUNTER_SN_DWORD_SYNC_ERROR:
+         break;
+
+      default:
+         status = SCI_FAILURE;
+         break;
+   }
+   return status;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_phy_disable_counter(
+   SCI_PHY_HANDLE_T       phy,
+   SCIC_PHY_COUNTER_ID_T  counter_id
+)
+{
+   SCIC_SDS_PHY_T *this_phy;
+   SCI_STATUS status = SCI_SUCCESS;
+
+   this_phy = (SCIC_SDS_PHY_T *)phy;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_phy),
+      SCIC_LOG_OBJECT_PHY,
+      "scic_phy_disable_counter(0x%x, 0x%x) enter\n",
+      this_phy, counter_id
+   ));
+
+   switch(counter_id)
+   {
+      case SCIC_PHY_COUNTER_RECEIVED_DONE_ACK_NAK_TIMEOUT:
+         {
+            U32 control = SCU_SAS_ECENCR_READ(this_phy);
+            control &= ~(1 << SCU_ERR_CNT_RX_DONE_ACK_NAK_TIMEOUT_INDEX);
+            SCU_SAS_ECENCR_WRITE(this_phy, control);
+         }
+         break;
+      case SCIC_PHY_COUNTER_TRANSMITTED_DONE_ACK_NAK_TIMEOUT:
+         {
+            U32 control = SCU_SAS_ECENCR_READ(this_phy);
+            control &= ~(1 << SCU_ERR_CNT_TX_DONE_ACK_NAK_TIMEOUT_INDEX);
+            SCU_SAS_ECENCR_WRITE(this_phy, control);
+         }
+         break;
+      case SCIC_PHY_COUNTER_INACTIVITY_TIMER_EXPIRED:
+         {
+            U32 control = SCU_SAS_ECENCR_READ(this_phy);
+            control &= ~(1 << SCU_ERR_CNT_INACTIVITY_TIMER_EXPIRED_INDEX);
+            SCU_SAS_ECENCR_WRITE(this_phy, control);
+         }
+         break;
+      case SCIC_PHY_COUNTER_RECEIVED_DONE_CREDIT_TIMEOUT:
+         {
+            U32 control = SCU_SAS_ECENCR_READ(this_phy);
+            control &= ~(1 << SCU_ERR_CNT_RX_DONE_CREDIT_TIMEOUT_INDEX);
+            SCU_SAS_ECENCR_WRITE(this_phy, control);
+         }
+         break;
+      case SCIC_PHY_COUNTER_TRANSMITTED_DONE_CREDIT_TIMEOUT:
+         {
+            U32 control = SCU_SAS_ECENCR_READ(this_phy);
+            control &= ~(1 << SCU_ERR_CNT_TX_DONE_CREDIT_TIMEOUT_INDEX);
+            SCU_SAS_ECENCR_WRITE(this_phy, control);
+         }
+         break;
+      case SCIC_PHY_COUNTER_RECEIVED_CREDIT_BLOCKED:
+         {
+            U32 control = SCU_SAS_ECENCR_READ(this_phy);
+            control &= ~(1 << SCU_ERR_CNT_RX_CREDIT_BLOCKED_RECEIVED_INDEX);
+            SCU_SAS_ECENCR_WRITE(this_phy, control);
+         }
+         break;
+
+         // These error counters cannot be disabled, so return SCI_FAILURE.
+      case SCIC_PHY_COUNTER_RECEIVED_FRAME:
+      case SCIC_PHY_COUNTER_TRANSMITTED_FRAME:
+      case SCIC_PHY_COUNTER_RECEIVED_FRAME_DWORD:
+      case SCIC_PHY_COUNTER_TRANSMITTED_FRAME_DWORD:
+      case SCIC_PHY_COUNTER_LOSS_OF_SYNC_ERROR:
+      case SCIC_PHY_COUNTER_RECEIVED_DISPARITY_ERROR:
+      case SCIC_PHY_COUNTER_RECEIVED_FRAME_CRC_ERROR:
+      case SCIC_PHY_COUNTER_RECEIVED_SHORT_FRAME:
+      case SCIC_PHY_COUNTER_RECEIVED_FRAME_WITHOUT_CREDIT:
+      case SCIC_PHY_COUNTER_RECEIVED_FRAME_AFTER_DONE:
+      case SCIC_PHY_COUNTER_SN_DWORD_SYNC_ERROR:
+      default:
+         status = SCI_FAILURE;
+         break;
+   }
+   return status;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_phy_get_counter(
+   SCI_PHY_HANDLE_T        phy,
+   SCIC_PHY_COUNTER_ID_T   counter_id,
+   U32                   * data
+)
+{
+   SCIC_SDS_PHY_T *this_phy;
+   SCI_STATUS status = SCI_SUCCESS;
+   this_phy = (SCIC_SDS_PHY_T *)phy;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_phy),
+      SCIC_LOG_OBJECT_PHY,
+      "scic_phy_get_counter(0x%x, 0x%x) enter\n",
+      this_phy, counter_id
+   ));
+
+   switch(counter_id)
+   {
+      case SCIC_PHY_COUNTER_RECEIVED_FRAME:
+         *data = scu_link_layer_register_read(this_phy, received_frame_count);
+         break;
+      case SCIC_PHY_COUNTER_TRANSMITTED_FRAME:
+         *data = scu_link_layer_register_read(this_phy, transmit_frame_count);
+         break;
+      case SCIC_PHY_COUNTER_RECEIVED_FRAME_DWORD:
+         *data = scu_link_layer_register_read(this_phy, received_dword_count);
+         break;
+      case SCIC_PHY_COUNTER_TRANSMITTED_FRAME_DWORD:
+         *data = scu_link_layer_register_read(this_phy, transmit_dword_count);
+         break;
+      case SCIC_PHY_COUNTER_LOSS_OF_SYNC_ERROR:
+         *data = scu_link_layer_register_read(this_phy, loss_of_sync_error_count);
+         break;
+      case SCIC_PHY_COUNTER_RECEIVED_DISPARITY_ERROR:
+         *data = scu_link_layer_register_read(this_phy, running_disparity_error_count);
+         break;
+      case SCIC_PHY_COUNTER_RECEIVED_FRAME_CRC_ERROR:
+         *data = scu_link_layer_register_read(this_phy, received_frame_crc_error_count);
+         break;
+      case SCIC_PHY_COUNTER_RECEIVED_DONE_ACK_NAK_TIMEOUT:
+         *data = this_phy->error_counter[SCU_ERR_CNT_RX_DONE_ACK_NAK_TIMEOUT_INDEX];
+         break;
+      case SCIC_PHY_COUNTER_TRANSMITTED_DONE_ACK_NAK_TIMEOUT:
+         *data = this_phy->error_counter[SCU_ERR_CNT_TX_DONE_ACK_NAK_TIMEOUT_INDEX];
+         break;
+      case SCIC_PHY_COUNTER_INACTIVITY_TIMER_EXPIRED:
+         *data = this_phy->error_counter[SCU_ERR_CNT_INACTIVITY_TIMER_EXPIRED_INDEX];
+         break;
+      case SCIC_PHY_COUNTER_RECEIVED_DONE_CREDIT_TIMEOUT:
+         *data = this_phy->error_counter[SCU_ERR_CNT_RX_DONE_CREDIT_TIMEOUT_INDEX];
+         break;
+      case SCIC_PHY_COUNTER_TRANSMITTED_DONE_CREDIT_TIMEOUT:
+         *data = this_phy->error_counter[SCU_ERR_CNT_TX_DONE_CREDIT_TIMEOUT_INDEX];
+         break;
+      case SCIC_PHY_COUNTER_RECEIVED_CREDIT_BLOCKED:
+         *data = this_phy->error_counter[SCU_ERR_CNT_RX_CREDIT_BLOCKED_RECEIVED_INDEX];
+         break;
+      case SCIC_PHY_COUNTER_RECEIVED_SHORT_FRAME:
+         *data = scu_link_layer_register_read(this_phy, received_short_frame_count);
+         break;
+      case SCIC_PHY_COUNTER_RECEIVED_FRAME_WITHOUT_CREDIT:
+         *data = scu_link_layer_register_read(this_phy, received_frame_without_credit_count);
+         break;
+      case SCIC_PHY_COUNTER_RECEIVED_FRAME_AFTER_DONE:
+         *data = scu_link_layer_register_read(this_phy, received_frame_after_done_count);
+         break;
+      case SCIC_PHY_COUNTER_SN_DWORD_SYNC_ERROR:
+         *data = scu_link_layer_register_read(this_phy, phy_reset_problem_count);
+         break;
+      default:
+         status = SCI_FAILURE;
+         break;
+   }
+
+   return status;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_phy_clear_counter(
+   SCI_PHY_HANDLE_T       phy,
+   SCIC_PHY_COUNTER_ID_T  counter_id
+)
+{
+   SCIC_SDS_PHY_T *this_phy;
+   SCI_STATUS status = SCI_SUCCESS;
+   this_phy = (SCIC_SDS_PHY_T *)phy;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_phy),
+      SCIC_LOG_OBJECT_PHY,
+      "scic_phy_clear_counter(0x%x, 0x%x) enter\n",
+      this_phy, counter_id
+   ));
+
+   switch(counter_id)
+   {
+      case SCIC_PHY_COUNTER_RECEIVED_FRAME:
+         scu_link_layer_register_write(this_phy, received_frame_count, 0);
+         break;
+      case SCIC_PHY_COUNTER_TRANSMITTED_FRAME:
+         scu_link_layer_register_write(this_phy, transmit_frame_count, 0);
+         break;
+      case SCIC_PHY_COUNTER_RECEIVED_FRAME_DWORD:
+         scu_link_layer_register_write(this_phy, received_dword_count, 0);
+         break;
+      case SCIC_PHY_COUNTER_TRANSMITTED_FRAME_DWORD:
+         scu_link_layer_register_write(this_phy, transmit_dword_count, 0);
+         break;
+      case SCIC_PHY_COUNTER_LOSS_OF_SYNC_ERROR:
+         scu_link_layer_register_write(this_phy, loss_of_sync_error_count, 0);
+         break;
+      case SCIC_PHY_COUNTER_RECEIVED_DISPARITY_ERROR:
+         scu_link_layer_register_write(this_phy, running_disparity_error_count, 0);
+         break;
+      case SCIC_PHY_COUNTER_RECEIVED_FRAME_CRC_ERROR:
+         scu_link_layer_register_write(this_phy, received_frame_crc_error_count, 0);
+         break;
+      case SCIC_PHY_COUNTER_RECEIVED_DONE_ACK_NAK_TIMEOUT:
+         this_phy->error_counter[SCU_ERR_CNT_RX_DONE_ACK_NAK_TIMEOUT_INDEX] = 0;
+         break;
+      case SCIC_PHY_COUNTER_TRANSMITTED_DONE_ACK_NAK_TIMEOUT:
+         this_phy->error_counter[SCU_ERR_CNT_TX_DONE_ACK_NAK_TIMEOUT_INDEX] = 0;
+         break;
+      case SCIC_PHY_COUNTER_INACTIVITY_TIMER_EXPIRED:
+         this_phy->error_counter[SCU_ERR_CNT_INACTIVITY_TIMER_EXPIRED_INDEX] = 0;
+         break;
+      case SCIC_PHY_COUNTER_RECEIVED_DONE_CREDIT_TIMEOUT:
+         this_phy->error_counter[SCU_ERR_CNT_RX_DONE_CREDIT_TIMEOUT_INDEX] = 0;
+         break;
+      case SCIC_PHY_COUNTER_TRANSMITTED_DONE_CREDIT_TIMEOUT:
+         this_phy->error_counter[SCU_ERR_CNT_TX_DONE_CREDIT_TIMEOUT_INDEX] = 0;
+         break;
+      case SCIC_PHY_COUNTER_RECEIVED_CREDIT_BLOCKED:
+         this_phy->error_counter[SCU_ERR_CNT_RX_CREDIT_BLOCKED_RECEIVED_INDEX] = 0;
+         break;
+      case SCIC_PHY_COUNTER_RECEIVED_SHORT_FRAME:
+         scu_link_layer_register_write(this_phy, received_short_frame_count, 0);
+         break;
+      case SCIC_PHY_COUNTER_RECEIVED_FRAME_WITHOUT_CREDIT:
+         scu_link_layer_register_write(this_phy, received_frame_without_credit_count, 0);
+         break;
+      case SCIC_PHY_COUNTER_RECEIVED_FRAME_AFTER_DONE:
+         scu_link_layer_register_write(this_phy, received_frame_after_done_count, 0);
+         break;
+      case SCIC_PHY_COUNTER_SN_DWORD_SYNC_ERROR:
+         scu_link_layer_register_write(this_phy, phy_reset_problem_count, 0);
+         break;
+      default:
+         status = SCI_FAILURE;
+   }
+
+   return status;
+}
+
+#endif // !defined(DISABLE_PHY_COUNTERS)
+
+SCI_STATUS scic_phy_stop(
+   SCI_PHY_HANDLE_T       phy
+)
+{
+   SCIC_SDS_PHY_T *this_phy;
+   this_phy = (SCIC_SDS_PHY_T *)phy;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_phy),
+      SCIC_LOG_OBJECT_PHY,
+      "scic_phy_stop(this_phy:0x%x)\n",
+      this_phy
+   ));
+
+   return this_phy->state_handlers->parent.stop_handler(&this_phy->parent);
+}
+
+SCI_STATUS scic_phy_start(
+   SCI_PHY_HANDLE_T       phy
+)
+{
+   SCIC_SDS_PHY_T *this_phy;
+   this_phy = (SCIC_SDS_PHY_T *)phy;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_phy),
+      SCIC_LOG_OBJECT_PHY,
+      "scic_phy_start(this_phy:0x%x)\n",
+      this_phy
+   ));
+
+   return this_phy->state_handlers->parent.start_handler(&this_phy->parent);
+}
+
+//******************************************************************************
+//* PHY STATE MACHINE
+//******************************************************************************
+
+//***************************************************************************
+//*  DEFAULT HANDLERS
+//***************************************************************************
+
+/**
+ * This is the default method for phy a start request.  It will report a
+ * warning and exit.
+ *
+ * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
+ *       SCIC_SDS_PHY object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+SCI_STATUS scic_sds_phy_default_start_handler(
+   SCI_BASE_PHY_T *phy
+)
+{
+   SCIC_SDS_PHY_T *this_phy;
+   this_phy = (SCIC_SDS_PHY_T *)phy;
+
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger(this_phy),
+      SCIC_LOG_OBJECT_PHY,
+      "SCIC Phy 0x%08x requested to start from invalid state %d\n",
+      this_phy,
+      sci_base_state_machine_get_state(&this_phy->parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+
+}
+
+/**
+ * This is the default method for phy a stop request.  It will report a
+ * warning and exit.
+ *
+ * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
+ *       SCIC_SDS_PHY object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+SCI_STATUS scic_sds_phy_default_stop_handler(
+   SCI_BASE_PHY_T *phy
+)
+{
+   SCIC_SDS_PHY_T *this_phy;
+   this_phy = (SCIC_SDS_PHY_T *)phy;
+
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger(this_phy),
+      SCIC_LOG_OBJECT_PHY,
+      "SCIC Phy 0x%08x requested to stop from invalid state %d\n",
+      this_phy,
+      sci_base_state_machine_get_state(&this_phy->parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * This is the default method for phy a reset request.  It will report a
+ * warning and exit.
+ *
+ * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
+ *       SCIC_SDS_PHY object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+SCI_STATUS scic_sds_phy_default_reset_handler(
+   SCI_BASE_PHY_T * phy
+)
+{
+   SCIC_SDS_PHY_T *this_phy;
+   this_phy = (SCIC_SDS_PHY_T *)phy;
+
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger(this_phy),
+      SCIC_LOG_OBJECT_PHY,
+      "SCIC Phy 0x%08x requested to reset from invalid state %d\n",
+      this_phy,
+      sci_base_state_machine_get_state(&this_phy->parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * This is the default method for phy a destruct request.  It will report a
+ * warning and exit.
+ *
+ * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
+ *       SCIC_SDS_PHY object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+SCI_STATUS scic_sds_phy_default_destroy_handler(
+   SCI_BASE_PHY_T *phy
+)
+{
+   SCIC_SDS_PHY_T *this_phy;
+   this_phy = (SCIC_SDS_PHY_T *)phy;
+
+   /// @todo Implement something for the default
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger(this_phy),
+      SCIC_LOG_OBJECT_PHY,
+      "SCIC Phy 0x%08x requested to destroy from invalid state %d\n",
+      this_phy,
+      sci_base_state_machine_get_state(&this_phy->parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * This is the default method for a phy frame handling request.  It will
+ * report a warning, release the frame and exit.
+ *
+ * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
+ *       SCIC_SDS_PHY object.
+ * @param[in] frame_index This is the frame index that was received from the
+ *       SCU hardware.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+SCI_STATUS scic_sds_phy_default_frame_handler(
+   SCIC_SDS_PHY_T *this_phy,
+   U32            frame_index
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger(this_phy),
+      SCIC_LOG_OBJECT_PHY,
+      "SCIC Phy 0x%08x recieved unexpected frame data %d while in state %d\n",
+      this_phy, frame_index,
+      sci_base_state_machine_get_state(&this_phy->parent.state_machine)
+   ));
+
+   scic_sds_controller_release_frame(
+      scic_sds_phy_get_controller(this_phy), frame_index);
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * This is the default method for a phy event handler.  It will report a
+ * warning and exit.
+ *
+ * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
+ *       SCIC_SDS_PHY object.
+ * @param[in] event_code This is the event code that was received from the SCU
+ *       hardware.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+SCI_STATUS scic_sds_phy_default_event_handler(
+   SCIC_SDS_PHY_T *this_phy,
+   U32            event_code
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger(this_phy),
+      SCIC_LOG_OBJECT_PHY,
+      "SCIC Phy 0x%08x received unexpected event status %x while in state %d\n",
+      this_phy, event_code,
+      sci_base_state_machine_get_state(&this_phy->parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * This is the default method for a phy consume power handler.  It will report
+ * a warning and exit.
+ *
+ * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
+ *       SCIC_SDS_PHY object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+SCI_STATUS scic_sds_phy_default_consume_power_handler(
+   SCIC_SDS_PHY_T *this_phy
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger(this_phy),
+      SCIC_LOG_OBJECT_PHY,
+      "SCIC Phy 0x%08x given unexpected permission to consume power while in state %d\n",
+      this_phy,
+      sci_base_state_machine_get_state(&this_phy->parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+//******************************************************************************
+//* PHY STOPPED STATE HANDLERS
+//******************************************************************************
+
+/**
+ * This method takes the SCIC_SDS_PHY from a stopped state and attempts to
+ * start it.
+ *    - The phy state machine is transitioned to the
+ *      SCI_BASE_PHY_STATE_STARTING.
+ *
+ * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
+ *       SCIC_SDS_PHY object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS
+ */
+static
+SCI_STATUS scic_sds_phy_stopped_state_start_handler(
+   SCI_BASE_PHY_T *phy
+)
+{
+   SCIC_SDS_PHY_T *this_phy;
+   this_phy = (SCIC_SDS_PHY_T *)phy;
+
+
+
+   // Create the SIGNATURE FIS Timeout timer for this phy
+   this_phy->sata_timeout_timer = scic_cb_timer_create(
+      scic_sds_phy_get_controller(this_phy),
+      scic_sds_phy_sata_timeout,
+      this_phy
+   );
+
+   if (this_phy->sata_timeout_timer != NULL)
+   {
+      sci_base_state_machine_change_state(
+         scic_sds_phy_get_base_state_machine(this_phy),
+         SCI_BASE_PHY_STATE_STARTING
+      );
+   }
+
+   return SCI_SUCCESS;
+}
+
+/**
+ * This method takes the SCIC_SDS_PHY from a stopped state and destroys it.
+ *    - This function takes no action.
+ *
+ * @todo Shouldnt this function transition the SCI_BASE_PHY::state_machine to
+ *        the SCI_BASE_PHY_STATE_FINAL?
+ *
+ * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
+ *       SCIC_SDS_PHY object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS
+ */
+static
+SCI_STATUS scic_sds_phy_stopped_state_destroy_handler(
+   SCI_BASE_PHY_T *phy
+)
+{
+   SCIC_SDS_PHY_T *this_phy;
+   this_phy = (SCIC_SDS_PHY_T *)phy;
+
+   /// @todo what do we actually need to do here?
+   return SCI_SUCCESS;
+}
+
+//******************************************************************************
+//* PHY STARTING STATE HANDLERS
+//******************************************************************************
+
+// All of these state handlers are mapped to the starting sub-state machine
+
+//******************************************************************************
+//* PHY READY STATE HANDLERS
+//******************************************************************************
+
+/**
+ * This method takes the SCIC_SDS_PHY from a ready state and attempts to stop
+ * it.
+ *    - The phy state machine is transitioned to the SCI_BASE_PHY_STATE_STOPPED.
+ *
+ * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
+ *       SCIC_SDS_PHY object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS
+ */
+static
+SCI_STATUS scic_sds_phy_ready_state_stop_handler(
+   SCI_BASE_PHY_T *phy
+)
+{
+   SCIC_SDS_PHY_T *this_phy;
+   this_phy = (SCIC_SDS_PHY_T *)phy;
+
+   sci_base_state_machine_change_state(
+      scic_sds_phy_get_base_state_machine(this_phy),
+      SCI_BASE_PHY_STATE_STOPPED
+   );
+
+   scic_sds_controller_link_down(
+      scic_sds_phy_get_controller(this_phy),
+      scic_sds_phy_get_port(this_phy),
+      this_phy
+   );
+
+   return SCI_SUCCESS;
+}
+
+/**
+ * This method takes the SCIC_SDS_PHY from a ready state and attempts to reset
+ * it.
+ *    - The phy state machine is transitioned to the SCI_BASE_PHY_STATE_STARTING.
+ *
+ * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
+ *       SCIC_SDS_PHY object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS
+ */
+static
+SCI_STATUS scic_sds_phy_ready_state_reset_handler(
+   SCI_BASE_PHY_T * phy
+)
+{
+   SCIC_SDS_PHY_T * this_phy;
+   this_phy = (SCIC_SDS_PHY_T *)phy;
+
+   sci_base_state_machine_change_state(
+      scic_sds_phy_get_base_state_machine(this_phy),
+      SCI_BASE_PHY_STATE_RESETTING
+   );
+
+   return SCI_SUCCESS;
+}
+
+/**
+ * This method request the SCIC_SDS_PHY handle the received event.  The only
+ * event that we are interested in while in the ready state is the link
+ * failure event.
+ *    - decoded event is a link failure
+ *       - transition the SCIC_SDS_PHY back to the SCI_BASE_PHY_STATE_STARTING
+ *         state.
+ *    - any other event recived will report a warning message
+ *
+ * @param[in] phy This is the SCIC_SDS_PHY object which has received the
+ *       event.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS if the event received is a link failure
+ * @retval SCI_FAILURE_INVALID_STATE for any other event received.
+ */
+static
+SCI_STATUS scic_sds_phy_ready_state_event_handler(
+   SCIC_SDS_PHY_T *this_phy,
+   U32            event_code
+)
+{
+   SCI_STATUS result = SCI_FAILURE;
+
+   switch (scu_get_event_code(event_code))
+   {
+   case SCU_EVENT_LINK_FAILURE:
+      // Link failure change state back to the starting state
+      sci_base_state_machine_change_state(
+         scic_sds_phy_get_base_state_machine(this_phy),
+         SCI_BASE_PHY_STATE_STARTING
+         );
+
+      result = SCI_SUCCESS;
+      break;
+
+   case SCU_EVENT_BROADCAST_CHANGE:
+      // Broadcast change received. Notify the port.
+      if (scic_sds_phy_get_port(this_phy) != SCI_INVALID_HANDLE)
+         scic_sds_port_broadcast_change_received(this_phy->owning_port, this_phy);
+      else
+         this_phy->bcn_received_while_port_unassigned = TRUE;
+      break;
+
+   case SCU_EVENT_ERR_CNT(RX_CREDIT_BLOCKED_RECEIVED):
+   case SCU_EVENT_ERR_CNT(TX_DONE_CREDIT_TIMEOUT):
+   case SCU_EVENT_ERR_CNT(RX_DONE_CREDIT_TIMEOUT):
+   case SCU_EVENT_ERR_CNT(INACTIVITY_TIMER_EXPIRED):
+   case SCU_EVENT_ERR_CNT(TX_DONE_ACK_NAK_TIMEOUT):
+   case SCU_EVENT_ERR_CNT(RX_DONE_ACK_NAK_TIMEOUT):
+      {
+         U32 error_counter_index =
+                scu_get_event_specifier(event_code) >> SCU_EVENT_SPECIFIC_CODE_SHIFT;
+
+         this_phy->error_counter[error_counter_index]++;
+         result = SCI_SUCCESS;
+      }
+      break;
+
+   default:
+      SCIC_LOG_WARNING((
+         sci_base_object_get_logger(this_phy),
+         SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS,
+         "SCIC PHY 0x%x ready state machine recieved unexpected event_code %x\n",
+         this_phy, event_code
+      ));
+      result = SCI_FAILURE_INVALID_STATE;
+      break;
+   }
+
+   return result;
+}
+
+// ---------------------------------------------------------------------------
+
+/**
+ * This is the resetting state event handler.
+ *
+ * @param[in] this_phy This is the SCIC_SDS_PHY object which is receiving the
+ *       event.
+ * @param[in] event_code This is the event code to be processed.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+static
+SCI_STATUS scic_sds_phy_resetting_state_event_handler(
+   SCIC_SDS_PHY_T *this_phy,
+   U32            event_code
+)
+{
+   SCI_STATUS result = SCI_FAILURE;
+
+   switch (scu_get_event_code(event_code))
+   {
+   case SCU_EVENT_HARD_RESET_TRANSMITTED:
+      // Link failure change state back to the starting state
+      sci_base_state_machine_change_state(
+         scic_sds_phy_get_base_state_machine(this_phy),
+         SCI_BASE_PHY_STATE_STARTING
+         );
+
+      result = SCI_SUCCESS;
+      break;
+
+   default:
+      SCIC_LOG_WARNING((
+         sci_base_object_get_logger(this_phy),
+         SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS,
+         "SCIC PHY 0x%x resetting state machine recieved unexpected event_code %x\n",
+         this_phy, event_code
+      ));
+
+      result = SCI_FAILURE_INVALID_STATE;
+      break;
+   }
+
+   return result;
+}
+
+// ---------------------------------------------------------------------------
+
+SCIC_SDS_PHY_STATE_HANDLER_T
+   scic_sds_phy_state_handler_table[SCI_BASE_PHY_MAX_STATES] =
+{
+   // SCI_BASE_PHY_STATE_INITIAL
+   {
+      {
+         scic_sds_phy_default_start_handler,
+         scic_sds_phy_default_stop_handler,
+         scic_sds_phy_default_reset_handler,
+         scic_sds_phy_default_destroy_handler
+      },
+      scic_sds_phy_default_frame_handler,
+      scic_sds_phy_default_event_handler,
+      scic_sds_phy_default_consume_power_handler
+   },
+   // SCI_BASE_PHY_STATE_STOPPED
+   {
+      {
+         scic_sds_phy_stopped_state_start_handler,
+         scic_sds_phy_default_stop_handler,
+         scic_sds_phy_default_reset_handler,
+         scic_sds_phy_stopped_state_destroy_handler
+      },
+      scic_sds_phy_default_frame_handler,
+      scic_sds_phy_default_event_handler,
+      scic_sds_phy_default_consume_power_handler
+   },
+   // SCI_BASE_PHY_STATE_STARTING
+   {
+      {
+         scic_sds_phy_default_start_handler,
+         scic_sds_phy_default_stop_handler,
+         scic_sds_phy_default_reset_handler,
+         scic_sds_phy_default_destroy_handler
+      },
+      scic_sds_phy_default_frame_handler,
+      scic_sds_phy_default_event_handler,
+      scic_sds_phy_default_consume_power_handler
+   },
+   // SCI_BASE_PHY_STATE_READY
+   {
+      {
+         scic_sds_phy_default_start_handler,
+         scic_sds_phy_ready_state_stop_handler,
+         scic_sds_phy_ready_state_reset_handler,
+         scic_sds_phy_default_destroy_handler
+      },
+      scic_sds_phy_default_frame_handler,
+      scic_sds_phy_ready_state_event_handler,
+      scic_sds_phy_default_consume_power_handler
+   },
+   // SCI_BASE_PHY_STATE_RESETTING
+   {
+      {
+         scic_sds_phy_default_start_handler,
+         scic_sds_phy_default_stop_handler,
+         scic_sds_phy_default_reset_handler,
+         scic_sds_phy_default_destroy_handler
+      },
+      scic_sds_phy_default_frame_handler,
+      scic_sds_phy_resetting_state_event_handler,
+      scic_sds_phy_default_consume_power_handler
+   },
+   // SCI_BASE_PHY_STATE_FINAL
+   {
+      {
+         scic_sds_phy_default_start_handler,
+         scic_sds_phy_default_stop_handler,
+         scic_sds_phy_default_reset_handler,
+         scic_sds_phy_default_destroy_handler
+      },
+      scic_sds_phy_default_frame_handler,
+      scic_sds_phy_default_event_handler,
+      scic_sds_phy_default_consume_power_handler
+   }
+};
+
+//****************************************************************************
+//*  PHY STATE PRIVATE METHODS
+//****************************************************************************
+
+/**
+ * This method will stop the SCIC_SDS_PHY object. This does not reset the
+ * protocol engine it just suspends it and places it in a state where it will
+ * not cause the end device to power up.
+ *
+ * @param[in] this_phy This is the SCIC_SDS_PHY object to stop.
+ *
+ * @return none
+ */
+static
+void scu_link_layer_stop_protocol_engine(
+   SCIC_SDS_PHY_T *this_phy
+)
+{
+   U32 scu_sas_pcfg_value;
+   U32 enable_spinup_value;
+
+   // Suspend the protocol engine and place it in a sata spinup hold state
+   scu_sas_pcfg_value  = SCU_SAS_PCFG_READ(this_phy);
+   scu_sas_pcfg_value |= (
+                           SCU_SAS_PCFG_GEN_BIT(OOB_RESET)
+                         | SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE)
+                         | SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD)
+                         );
+   SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value);
+
+   // Disable the notify enable spinup primitives
+   enable_spinup_value = SCU_SAS_ENSPINUP_READ(this_phy);
+   enable_spinup_value &= ~SCU_ENSPINUP_GEN_BIT(ENABLE);
+   SCU_SAS_ENSPINUP_WRITE(this_phy, enable_spinup_value);
+}
+
+/**
+ * This method will start the OOB/SN state machine for this SCIC_SDS_PHY
+ * object.
+ *
+ * @param[in] this_phy This is the SCIC_SDS_PHY object on which to start the
+ *       OOB/SN state machine.
+ */
+static
+void scu_link_layer_start_oob(
+   SCIC_SDS_PHY_T *this_phy
+)
+{
+   U32 scu_sas_pcfg_value;
+
+   /* Reset OOB sequence - start */
+   scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy);
+   scu_sas_pcfg_value &=
+      ~(SCU_SAS_PCFG_GEN_BIT(OOB_RESET) | SCU_SAS_PCFG_GEN_BIT(HARD_RESET));
+   SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value);
+   SCU_SAS_PCFG_READ(this_phy);
+   /* Reset OOB sequence - end */
+
+   /* Start OOB sequence - start */
+   scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy);
+   scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE);
+   SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value);
+   SCU_SAS_PCFG_READ(this_phy);
+   /* Start OOB sequence - end */
+}
+
+/**
+ * This method will transmit a hard reset request on the specified phy. The
+ * SCU hardware requires that we reset the OOB state machine and set the hard
+ * reset bit in the phy configuration register.
+ * We then must start OOB over with the hard reset bit set.
+ *
+ * @param[in] this_phy
+ */
+static
+void scu_link_layer_tx_hard_reset(
+   SCIC_SDS_PHY_T *this_phy
+)
+{
+   U32 phy_configuration_value;
+
+   // SAS Phys must wait for the HARD_RESET_TX event notification to transition
+   // to the starting state.
+   phy_configuration_value = SCU_SAS_PCFG_READ(this_phy);
+   phy_configuration_value |=
+      (SCU_SAS_PCFG_GEN_BIT(HARD_RESET) | SCU_SAS_PCFG_GEN_BIT(OOB_RESET));
+   SCU_SAS_PCFG_WRITE(this_phy, phy_configuration_value);
+
+   // Now take the OOB state machine out of reset
+   phy_configuration_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE);
+   phy_configuration_value &= ~SCU_SAS_PCFG_GEN_BIT(OOB_RESET);
+   SCU_SAS_PCFG_WRITE(this_phy, phy_configuration_value);
+}
+
+//****************************************************************************
+//*  PHY BASE STATE METHODS
+//****************************************************************************
+
+/**
+ * This method will perform the actions required by the SCIC_SDS_PHY on
+ * entering the SCI_BASE_PHY_STATE_INITIAL.
+ *    - This function sets the state handlers for the phy object base state
+ * machine initial state.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_PHY object.
+ *
+ * @return none
+ */
+static
+void scic_sds_phy_initial_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_PHY_T *this_phy;
+   this_phy = (SCIC_SDS_PHY_T *)object;
+
+   scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_INITIAL);
+}
+
+/**
+ * This method will perform the actions required by the SCIC_SDS_PHY on
+ * entering the SCI_BASE_PHY_STATE_INITIAL.
+ *    - This function sets the state handlers for the phy object base state
+ * machine initial state.
+ *    - The SCU hardware is requested to stop the protocol engine.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_PHY object.
+ *
+ * @return none
+ */
+static
+void scic_sds_phy_stopped_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_PHY_T *this_phy;
+   this_phy = (SCIC_SDS_PHY_T *)object;
+
+   /// @todo We need to get to the controller to place this PE in a reset state
+   scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_STOPPED);
+
+   if (this_phy->sata_timeout_timer != NULL)
+   {
+      scic_cb_timer_destroy(
+         scic_sds_phy_get_controller(this_phy),
+         this_phy->sata_timeout_timer
+      );
+
+      this_phy->sata_timeout_timer = NULL;
+   }
+
+   scu_link_layer_stop_protocol_engine(this_phy);
+}
+
+/**
+ * This method will perform the actions required by the SCIC_SDS_PHY on
+ * entering the SCI_BASE_PHY_STATE_STARTING.
+ *    - This function sets the state handlers for the phy object base state
+ * machine starting state.
+ *    - The SCU hardware is requested to start OOB/SN on this protocl engine.
+ *    - The phy starting substate machine is started.
+ *    - If the previous state was the ready state then the
+ *      SCIC_SDS_CONTROLLER is informed that the phy has gone link down.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_PHY object.
+ *
+ * @return none
+ */
+static
+void scic_sds_phy_starting_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_PHY_T *this_phy;
+   this_phy = (SCIC_SDS_PHY_T *)object;
+
+   scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_STARTING);
+
+   scu_link_layer_stop_protocol_engine(this_phy);
+   scu_link_layer_start_oob(this_phy);
+
+   // We don't know what kind of phy we are going to be just yet
+   this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN;
+   this_phy->bcn_received_while_port_unassigned = FALSE;
+
+   // Change over to the starting substate machine to continue
+   sci_base_state_machine_start(&this_phy->starting_substate_machine);
+
+   if (this_phy->parent.state_machine.previous_state_id
+       == SCI_BASE_PHY_STATE_READY)
+   {
+      scic_sds_controller_link_down(
+         scic_sds_phy_get_controller(this_phy),
+         scic_sds_phy_get_port(this_phy),
+         this_phy
+      );
+   }
+}
+
+/**
+ * This method will perform the actions required by the SCIC_SDS_PHY on
+ * entering the SCI_BASE_PHY_STATE_READY.
+ *    - This function sets the state handlers for the phy object base state
+ * machine ready state.
+ *    - The SCU hardware protocol engine is resumed.
+ *    - The SCIC_SDS_CONTROLLER is informed that the phy object has gone link
+ *      up.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_PHY object.
+ *
+ * @return none
+ */
+static
+void scic_sds_phy_ready_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_PHY_T *this_phy;
+   this_phy = (SCIC_SDS_PHY_T *)object;
+
+   scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_READY);
+
+   scic_sds_controller_link_up(
+      scic_sds_phy_get_controller(this_phy),
+      scic_sds_phy_get_port(this_phy),
+      this_phy
+   );
+}
+
+/**
+ * This method will perform the actions required by the SCIC_SDS_PHY on
+ * exiting the SCI_BASE_PHY_STATE_INITIAL. This function suspends the SCU
+ * hardware protocol engine represented by this SCIC_SDS_PHY object.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_PHY object.
+ *
+ * @return none
+ */
+static
+void scic_sds_phy_ready_state_exit(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_PHY_T *this_phy;
+   this_phy = (SCIC_SDS_PHY_T *)object;
+
+   scic_sds_phy_suspend(this_phy);
+}
+
+/**
+ * This method will perform the actions required by the SCIC_SDS_PHY on
+ * entering the SCI_BASE_PHY_STATE_RESETTING.
+ *    - This function sets the state handlers for the phy object base state
+ * machine resetting state.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_PHY object.
+ *
+ * @return none
+ */
+static
+void scic_sds_phy_resetting_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_PHY_T * this_phy;
+   this_phy = (SCIC_SDS_PHY_T *)object;
+
+   scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_RESETTING);
+
+   // The phy is being reset, therefore deactivate it from the port.
+   // In the resetting state we don't notify the user regarding
+   // link up and link down notifications.
+   scic_sds_port_deactivate_phy(this_phy->owning_port, this_phy, FALSE);
+
+   if (this_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS)
+   {
+      scu_link_layer_tx_hard_reset(this_phy);
+   }
+   else
+   {
+      // The SCU does not need to have a descrete reset state so just go back to
+      // the starting state.
+      sci_base_state_machine_change_state(
+         &this_phy->parent.state_machine,
+         SCI_BASE_PHY_STATE_STARTING
+      );
+   }
+}
+
+/**
+ * This method will perform the actions required by the SCIC_SDS_PHY on
+ * entering the SCI_BASE_PHY_STATE_FINAL.
+ *    - This function sets the state handlers for the phy object base state
+ * machine final state.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_PHY object.
+ *
+ * @return none
+ */
+static
+void scic_sds_phy_final_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_PHY_T *this_phy;
+   this_phy = (SCIC_SDS_PHY_T *)object;
+
+   scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_FINAL);
+
+   // Nothing to do here
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_BASE_STATE_T scic_sds_phy_state_table[SCI_BASE_PHY_MAX_STATES] =
+{
+   {
+      SCI_BASE_PHY_STATE_INITIAL,
+      scic_sds_phy_initial_state_enter,
+      NULL,
+   },
+   {
+      SCI_BASE_PHY_STATE_STOPPED,
+      scic_sds_phy_stopped_state_enter,
+      NULL,
+   },
+   {
+      SCI_BASE_PHY_STATE_STARTING,
+      scic_sds_phy_starting_state_enter,
+      NULL,
+   },
+   {
+      SCI_BASE_PHY_STATE_READY,
+      scic_sds_phy_ready_state_enter,
+      scic_sds_phy_ready_state_exit,
+   },
+   {
+      SCI_BASE_PHY_STATE_RESETTING,
+      scic_sds_phy_resetting_state_enter,
+      NULL,
+   },
+   {
+      SCI_BASE_PHY_STATE_FINAL,
+      scic_sds_phy_final_state_enter,
+      NULL,
+   }
+};
+
+//******************************************************************************
+//* PHY STARTING SUB-STATE MACHINE
+//******************************************************************************
+
+//*****************************************************************************
+//* SCIC SDS PHY HELPER FUNCTIONS
+//*****************************************************************************
+
+
+/**
+ * This method continues the link training for the phy as if it were a SAS PHY
+ * instead of a SATA PHY. This is done because the completion queue had a SAS
+ * PHY DETECTED event when the state machine was expecting a SATA PHY event.
+ *
+ * @param[in] this_phy The phy object that received SAS PHY DETECTED.
+ *
+ * @return none
+ */
+static
+void scic_sds_phy_start_sas_link_training(
+   SCIC_SDS_PHY_T * this_phy
+)
+{
+   U32 phy_control;
+
+   phy_control = SCU_SAS_PCFG_READ(this_phy);
+   phy_control |= SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD);
+   SCU_SAS_PCFG_WRITE(this_phy, phy_control);
+
+   sci_base_state_machine_change_state(
+      &this_phy->starting_substate_machine,
+      SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN
+   );
+
+   this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SAS;
+}
+
+/**
+ * This method continues the link training for the phy as if it were a SATA
+ * PHY instead of a SAS PHY.  This is done because the completion queue had a
+ * SATA SPINUP HOLD event when the state machine was expecting a SAS PHY
+ * event.
+ *
+ * @param[in] this_phy The phy object that received a SATA SPINUP HOLD event
+ *
+ * @return none
+ */
+static
+void scic_sds_phy_start_sata_link_training(
+   SCIC_SDS_PHY_T * this_phy
+)
+{
+   sci_base_state_machine_change_state(
+      &this_phy->starting_substate_machine,
+      SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER
+   );
+
+   this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SATA;
+}
+
+/**
+ * @brief This method performs processing common to all protocols upon
+ *        completion of link training.
+ *
+ * @param[in,out] this_phy This parameter specifies the phy object for which
+ *                link training has completed.
+ * @param[in]     max_link_rate This parameter specifies the maximum link
+ *                rate to be associated with this phy.
+ * @param[in]     next_state This parameter specifies the next state for the
+ *                phy's starting sub-state machine.
+ *
+ * @return none
+ */
+static
+void scic_sds_phy_complete_link_training(
+   SCIC_SDS_PHY_T *   this_phy,
+   SCI_SAS_LINK_RATE  max_link_rate,
+   U32                next_state
+)
+{
+   this_phy->max_negotiated_speed = max_link_rate;
+
+   sci_base_state_machine_change_state(
+      scic_sds_phy_get_starting_substate_machine(this_phy), next_state
+   );
+}
+
+/**
+ * This method restarts the SCIC_SDS_PHY objects base state machine in the
+ * starting state from any starting substate.
+ *
+ * @param[in] this_phy The SCIC_SDS_PHY object to restart.
+ *
+ * @return none
+ */
+void scic_sds_phy_restart_starting_state(
+   SCIC_SDS_PHY_T *this_phy
+)
+{
+   // Stop the current substate machine
+   sci_base_state_machine_stop(
+      scic_sds_phy_get_starting_substate_machine(this_phy)
+   );
+
+   // Re-enter the base state machine starting state
+   sci_base_state_machine_change_state(
+      scic_sds_phy_get_base_state_machine(this_phy),
+      SCI_BASE_PHY_STATE_STARTING
+      );
+}
+
+
+//*****************************************************************************
+//* SCIC SDS PHY general handlers
+//*****************************************************************************
+
+static
+SCI_STATUS scic_sds_phy_starting_substate_general_stop_handler(
+   SCI_BASE_PHY_T *phy
+)
+{
+   SCIC_SDS_PHY_T *this_phy;
+   this_phy = (SCIC_SDS_PHY_T *)phy;
+
+   sci_base_state_machine_stop(
+      &this_phy->starting_substate_machine
+   );
+
+   sci_base_state_machine_change_state(
+      &phy->state_machine,
+      SCI_BASE_PHY_STATE_STOPPED
+   );
+
+   return SCI_SUCCESS;
+}
+
+//*****************************************************************************
+//* SCIC SDS PHY EVENT_HANDLERS
+//*****************************************************************************
+
+/**
+ * This method is called when an event notification is received for the phy
+ * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SPEED_EN.
+ *    - decode the event
+ *       - sas phy detected causes a state transition to the wait for speed
+ *         event notification.
+ *       - any other events log a warning message and set a failure status
+ *
+ * @param[in] phy This SCIC_SDS_PHY object which has received an event.
+ * @param[in] event_code This is the event code which the phy object is to
+ *       decode.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS on any valid event notification
+ * @retval SCI_FAILURE on any unexpected event notifation
+ */
+static
+SCI_STATUS scic_sds_phy_starting_substate_await_ossp_event_handler(
+   SCIC_SDS_PHY_T *this_phy,
+   U32 event_code
+)
+{
+   U32 result = SCI_SUCCESS;
+
+   switch (scu_get_event_code(event_code))
+   {
+   case SCU_EVENT_SAS_PHY_DETECTED:
+      scic_sds_phy_start_sas_link_training(this_phy);
+      this_phy->is_in_link_training = TRUE;
+   break;
+
+   case SCU_EVENT_SATA_SPINUP_HOLD:
+      scic_sds_phy_start_sata_link_training(this_phy);
+      this_phy->is_in_link_training = TRUE;
+   break;
+
+   default:
+      SCIC_LOG_WARNING((
+         sci_base_object_get_logger(this_phy),
+         SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS,
+         "PHY starting substate machine recieved unexpected event_code %x\n",
+         event_code
+      ));
+
+      result = SCI_FAILURE;
+   break;
+   }
+
+   return result;
+}
+
+/**
+ * This method is called when an event notification is received for the phy
+ * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SPEED_EN.
+ *    - decode the event
+ *       - sas phy detected returns us back to this state.
+ *       - speed event detected causes a state transition to the wait for iaf.
+ *       - identify timeout is an un-expected event and the state machine is
+ *         restarted.
+ *       - link failure events restart the starting state machine
+ *       - any other events log a warning message and set a failure status
+ *
+ * @param[in] phy This SCIC_SDS_PHY object which has received an event.
+ * @param[in] event_code This is the event code which the phy object is to
+ *       decode.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS on any valid event notification
+ * @retval SCI_FAILURE on any unexpected event notifation
+ */
+static
+SCI_STATUS scic_sds_phy_starting_substate_await_sas_phy_speed_event_handler(
+   SCIC_SDS_PHY_T *this_phy,
+   U32 event_code
+)
+{
+   U32 result = SCI_SUCCESS;
+
+   switch (scu_get_event_code(event_code))
+   {
+   case SCU_EVENT_SAS_PHY_DETECTED:
+      // Why is this being reported again by the controller?
+      // We would re-enter this state so just stay here
+   break;
+
+   case SCU_EVENT_SAS_15:
+   case SCU_EVENT_SAS_15_SSC:
+      scic_sds_phy_complete_link_training(
+         this_phy, SCI_SAS_150_GB, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF
+      );
+   break;
+
+   case SCU_EVENT_SAS_30:
+   case SCU_EVENT_SAS_30_SSC:
+      scic_sds_phy_complete_link_training(
+         this_phy, SCI_SAS_300_GB, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF
+      );
+   break;
+
+   case SCU_EVENT_SAS_60:
+   case SCU_EVENT_SAS_60_SSC:
+      scic_sds_phy_complete_link_training(
+         this_phy, SCI_SAS_600_GB, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF
+      );
+   break;
+
+   case SCU_EVENT_SATA_SPINUP_HOLD:
+      // We were doing SAS PHY link training and received a SATA PHY event
+      // continue OOB/SN as if this were a SATA PHY
+      scic_sds_phy_start_sata_link_training(this_phy);
+   break;
+
+   case SCU_EVENT_LINK_FAILURE:
+      // Link failure change state back to the starting state
+      scic_sds_phy_restart_starting_state(this_phy);
+   break;
+
+   default:
+      SCIC_LOG_WARNING((
+         sci_base_object_get_logger(this_phy),
+         SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS,
+         "PHY starting substate machine recieved unexpected event_code %x\n",
+         event_code
+      ));
+
+      result = SCI_FAILURE;
+   break;
+   }
+
+   return result;
+}
+
+/**
+ * This method is called when an event notification is received for the phy
+ * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF.
+ *    - decode the event
+ *       - sas phy detected event backs up the state machine to the await
+ *         speed notification.
+ *       - identify timeout is an un-expected event and the state machine is
+ *         restarted.
+ *       - link failure events restart the starting state machine
+ *       - any other events log a warning message and set a failure status
+ *
+ * @param[in] phy This SCIC_SDS_PHY object which has received an event.
+ * @param[in] event_code This is the event code which the phy object is to
+ *       decode.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS on any valid event notification
+ * @retval SCI_FAILURE on any unexpected event notifation
+ */
+static
+SCI_STATUS scic_sds_phy_starting_substate_await_iaf_uf_event_handler(
+   SCIC_SDS_PHY_T *this_phy,
+   U32 event_code
+)
+{
+   U32 result = SCI_SUCCESS;
+
+   switch (scu_get_event_code(event_code))
+   {
+   case SCU_EVENT_SAS_PHY_DETECTED:
+      // Backup the state machine
+      scic_sds_phy_start_sas_link_training(this_phy);
+      break;
+
+   case SCU_EVENT_SATA_SPINUP_HOLD:
+      // We were doing SAS PHY link training and received a SATA PHY event
+      // continue OOB/SN as if this were a SATA PHY
+      scic_sds_phy_start_sata_link_training(this_phy);
+   break;
+
+   case SCU_EVENT_RECEIVED_IDENTIFY_TIMEOUT:
+   case SCU_EVENT_LINK_FAILURE:
+   case SCU_EVENT_HARD_RESET_RECEIVED:
+      // Start the oob/sn state machine over again
+      scic_sds_phy_restart_starting_state(this_phy);
+      break;
+
+   default:
+      SCIC_LOG_WARNING((
+         sci_base_object_get_logger(this_phy),
+         SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS,
+         "PHY starting substate machine recieved unexpected event_code %x\n",
+         event_code
+      ));
+
+      result = SCI_FAILURE;
+      break;
+   }
+
+   return result;
+}
+
+/**
+ * This method is called when an event notification is received for the phy
+ * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_POWER.
+ *    - decode the event
+ *       - link failure events restart the starting state machine
+ *       - any other events log a warning message and set a failure status
+ *
+ * @param[in] phy This SCIC_SDS_PHY object which has received an event.
+ * @param[in] event_code This is the event code which the phy object is to
+ *       decode.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS on a link failure event
+ * @retval SCI_FAILURE on any unexpected event notifation
+ */
+static
+SCI_STATUS scic_sds_phy_starting_substate_await_sas_power_event_handler(
+   SCIC_SDS_PHY_T *this_phy,
+   U32 event_code
+)
+{
+   U32 result = SCI_SUCCESS;
+
+   switch (scu_get_event_code(event_code))
+   {
+   case SCU_EVENT_LINK_FAILURE:
+      // Link failure change state back to the starting state
+      scic_sds_phy_restart_starting_state(this_phy);
+      break;
+
+   default:
+      SCIC_LOG_WARNING((
+         sci_base_object_get_logger(this_phy),
+         SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS,
+         "PHY starting substate machine recieved unexpected event_code %x\n",
+         event_code
+      ));
+
+      result = SCI_FAILURE;
+      break;
+   }
+
+   return result;
+}
+
+/**
+ * This method is called when an event notification is received for the phy
+ * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER.
+ *    - decode the event
+ *       - link failure events restart the starting state machine
+ *       - sata spinup hold events are ignored since they are expected
+ *       - any other events log a warning message and set a failure status
+ *
+ * @param[in] phy This SCIC_SDS_PHY object which has received an event.
+ * @param[in] event_code This is the event code which the phy object is to
+ *       decode.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS on a link failure event
+ * @retval SCI_FAILURE on any unexpected event notifation
+ */
+static
+SCI_STATUS scic_sds_phy_starting_substate_await_sata_power_event_handler(
+   SCIC_SDS_PHY_T *this_phy,
+   U32 event_code
+)
+{
+   U32 result = SCI_SUCCESS;
+
+   switch (scu_get_event_code(event_code))
+   {
+   case SCU_EVENT_LINK_FAILURE:
+      // Link failure change state back to the starting state
+      scic_sds_phy_restart_starting_state(this_phy);
+      break;
+
+   case SCU_EVENT_SATA_SPINUP_HOLD:
+      // These events are received every 10ms and are expected while in this state
+      break;
+
+   case SCU_EVENT_SAS_PHY_DETECTED:
+      // There has been a change in the phy type before OOB/SN for the
+      // SATA finished start down the SAS link traning path.
+      scic_sds_phy_start_sas_link_training(this_phy);
+   break;
+
+   default:
+      SCIC_LOG_WARNING((
+         sci_base_object_get_logger(this_phy),
+         SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS,
+         "PHY starting substate machine recieved unexpected event_code %x\n",
+         event_code
+      ));
+
+      result = SCI_FAILURE;
+      break;
+   }
+
+   return result;
+}
+
+/**
+ * This method is called when an event notification is received for the phy
+ * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN.
+ *    - decode the event
+ *       - link failure events restart the starting state machine
+ *       - sata spinup hold events are ignored since they are expected
+ *       - sata phy detected event change to the wait speed event
+ *       - any other events log a warning message and set a failure status
+ *
+ * @param[in] phy This SCIC_SDS_PHY object which has received an event.
+ * @param[in] event_code This is the event code which the phy object is to
+ *       decode.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS on a link failure event
+ * @retval SCI_FAILURE on any unexpected event notifation
+ */
+static
+SCI_STATUS scic_sds_phy_starting_substate_await_sata_phy_event_handler(
+   SCIC_SDS_PHY_T *this_phy,
+   U32 event_code
+)
+{
+   U32 result = SCI_SUCCESS;
+
+   switch (scu_get_event_code(event_code))
+   {
+   case SCU_EVENT_LINK_FAILURE:
+      // Link failure change state back to the starting state
+      scic_sds_phy_restart_starting_state(this_phy);
+      break;
+
+   case SCU_EVENT_SATA_SPINUP_HOLD:
+      // These events might be received since we dont know how many may be in
+      // the completion queue while waiting for power
+      break;
+
+   case SCU_EVENT_SATA_PHY_DETECTED:
+      this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SATA;
+
+      // We have received the SATA PHY notification change state
+      sci_base_state_machine_change_state(
+         scic_sds_phy_get_starting_substate_machine(this_phy),
+         SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN
+         );
+      break;
+
+   case SCU_EVENT_SAS_PHY_DETECTED:
+      // There has been a change in the phy type before OOB/SN for the
+      // SATA finished start down the SAS link traning path.
+      scic_sds_phy_start_sas_link_training(this_phy);
+   break;
+
+   default:
+      SCIC_LOG_WARNING((
+         sci_base_object_get_logger(this_phy),
+         SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS,
+         "PHY starting substate machine recieved unexpected event_code %x\n",
+         event_code
+      ));
+
+      result = SCI_FAILURE;
+      break;
+   }
+
+   return result;
+}
+
+/**
+ * This method is called when an event notification is received for the phy
+ * object when in the state
+ * SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN.
+ *    - decode the event
+ *       - sata phy detected returns us back to this state.
+ *       - speed event detected causes a state transition to the wait for
+ *         signature.
+ *       - link failure events restart the starting state machine
+ *       - any other events log a warning message and set a failure status
+ *
+ * @param[in] phy This SCIC_SDS_PHY object which has received an event.
+ * @param[in] event_code This is the event code which the phy object is to
+ *       decode.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS on any valid event notification
+ * @retval SCI_FAILURE on any unexpected event notifation
+ */
+static
+SCI_STATUS scic_sds_phy_starting_substate_await_sata_speed_event_handler(
+   SCIC_SDS_PHY_T *this_phy,
+   U32 event_code
+)
+{
+   U32 result = SCI_SUCCESS;
+
+   switch (scu_get_event_code(event_code))
+   {
+   case SCU_EVENT_SATA_PHY_DETECTED:
+      // The hardware reports multiple SATA PHY detected events
+      // ignore the extras
+   break;
+
+   case SCU_EVENT_SATA_15:
+   case SCU_EVENT_SATA_15_SSC:
+      scic_sds_phy_complete_link_training(
+         this_phy,
+         SCI_SAS_150_GB,
+         SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF
+      );
+   break;
+
+   case SCU_EVENT_SATA_30:
+   case SCU_EVENT_SATA_30_SSC:
+      scic_sds_phy_complete_link_training(
+         this_phy,
+         SCI_SAS_300_GB,
+         SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF
+      );
+   break;
+
+   case SCU_EVENT_SATA_60:
+   case SCU_EVENT_SATA_60_SSC:
+      scic_sds_phy_complete_link_training(
+         this_phy,
+         SCI_SAS_600_GB,
+         SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF
+      );
+   break;
+
+   case SCU_EVENT_LINK_FAILURE:
+      // Link failure change state back to the starting state
+      scic_sds_phy_restart_starting_state(this_phy);
+   break;
+
+   case SCU_EVENT_SAS_PHY_DETECTED:
+      // There has been a change in the phy type before OOB/SN for the
+      // SATA finished start down the SAS link traning path.
+      scic_sds_phy_start_sas_link_training(this_phy);
+   break;
+
+   default:
+      SCIC_LOG_WARNING((
+         sci_base_object_get_logger(this_phy),
+         SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS,
+         "PHY starting substate machine recieved unexpected event_code %x\n",
+         event_code
+      ));
+
+      result = SCI_FAILURE;
+   break;
+   }
+
+   return result;
+}
+
+/**
+ * This method is called when an event notification is received for the phy
+ * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF.
+ *    - decode the event
+ *       - sas phy detected event backs up the state machine to the await
+ *         speed notification.
+ *       - identify timeout is an un-expected event and the state machine is
+ *         restarted.
+ *       - link failure events restart the starting state machine
+ *       - any other events log a warning message and set a failure status
+ *
+ * @param[in] phy This SCIC_SDS_PHY object which has received an event.
+ * @param[in] event_code This is the event code which the phy object is to
+ *       decode.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS on any valid event notification
+ * @retval SCI_FAILURE on any unexpected event notifation
+ */
+static
+SCI_STATUS scic_sds_phy_starting_substate_await_sig_fis_event_handler(
+   SCIC_SDS_PHY_T *this_phy,
+   U32 event_code
+)
+{
+   U32 result = SCI_SUCCESS;
+
+   switch (scu_get_event_code(event_code))
+   {
+   case SCU_EVENT_SATA_PHY_DETECTED:
+      // Backup the state machine
+      sci_base_state_machine_change_state(
+         scic_sds_phy_get_starting_substate_machine(this_phy),
+         SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN
+         );
+      break;
+
+   case SCU_EVENT_LINK_FAILURE:
+      // Link failure change state back to the starting state
+      scic_sds_phy_restart_starting_state(this_phy);
+      break;
+
+   default:
+      SCIC_LOG_WARNING((
+         sci_base_object_get_logger(this_phy),
+         SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_RECEIVED_EVENTS,
+         "PHY starting substate machine recieved unexpected event_code %x\n",
+         event_code
+      ));
+
+      result = SCI_FAILURE;
+      break;
+   }
+
+   return result;
+}
+
+
+//*****************************************************************************
+//*  SCIC SDS PHY FRAME_HANDLERS
+//*****************************************************************************
+
+/**
+ * This method decodes the unsolicited frame when the SCIC_SDS_PHY is in the
+ * SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF.
+ *    - Get the UF Header
+ *    - If the UF is an IAF
+ *       - Copy IAF data to local phy object IAF data buffer.
+ *       - Change starting substate to wait power.
+ *    - else
+ *       - log warning message of unexpected unsolicted frame
+ *    - release frame buffer
+ *
+ * @param[in] phy This is SCIC_SDS_PHY object which is being requested to
+ *       decode the frame data.
+ * @param[in] frame_index This is the index of the unsolicited frame which was
+ *       received for this phy.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS
+ */
+static
+SCI_STATUS scic_sds_phy_starting_substate_await_iaf_uf_frame_handler(
+   SCIC_SDS_PHY_T *this_phy,
+   U32            frame_index
+)
+{
+   SCI_STATUS                        result;
+   U32                              *frame_words;
+   SCI_SAS_IDENTIFY_ADDRESS_FRAME_T *identify_frame;
+
+   result = scic_sds_unsolicited_frame_control_get_header(
+               &(scic_sds_phy_get_controller(this_phy)->uf_control),
+               frame_index,
+               (void **)&frame_words);
+
+   if (result != SCI_SUCCESS)
+   {
+      return result;
+   }
+
+   frame_words[0] = SCIC_SWAP_DWORD(frame_words[0]);
+   identify_frame = (SCI_SAS_IDENTIFY_ADDRESS_FRAME_T *)frame_words;
+
+   if (identify_frame->address_frame_type == 0)
+   {
+      // Byte swap the rest of the frame so we can make
+      // a copy of the buffer
+      frame_words[1] = SCIC_SWAP_DWORD(frame_words[1]);
+      frame_words[2] = SCIC_SWAP_DWORD(frame_words[2]);
+      frame_words[3] = SCIC_SWAP_DWORD(frame_words[3]);
+      frame_words[4] = SCIC_SWAP_DWORD(frame_words[4]);
+      frame_words[5] = SCIC_SWAP_DWORD(frame_words[5]);
+
+      memcpy(
+         &this_phy->phy_type.sas.identify_address_frame_buffer,
+         identify_frame,
+         sizeof(SCI_SAS_IDENTIFY_ADDRESS_FRAME_T)
+      );
+
+      if (identify_frame->protocols.u.bits.smp_target)
+      {
+         // We got the IAF for an expander PHY go to the final state since
+         // there are no power requirements for expander phys.
+         sci_base_state_machine_change_state(
+            scic_sds_phy_get_starting_substate_machine(this_phy),
+            SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL
+         );
+      }
+      else
+      {
+         // We got the IAF we can now go to the await spinup semaphore state
+         sci_base_state_machine_change_state(
+            scic_sds_phy_get_starting_substate_machine(this_phy),
+            SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER
+         );
+      }
+
+      result = SCI_SUCCESS;
+   }
+   else
+   {
+      SCIC_LOG_WARNING((
+         sci_base_object_get_logger(this_phy),
+         SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_UNSOLICITED_FRAMES,
+         "PHY starting substate machine recieved unexpected frame id %x\n",
+         frame_index
+      ));
+   }
+
+   // Regardless of the result release this frame since we are done with it
+   scic_sds_controller_release_frame(
+      scic_sds_phy_get_controller(this_phy), frame_index
+      );
+
+   return result;
+}
+
+/**
+ * This method decodes the unsolicited frame when the SCIC_SDS_PHY is in the
+ * SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF.
+ *    - Get the UF Header
+ *    - If the UF is an SIGNATURE FIS
+ *       - Copy IAF data to local phy object SIGNATURE FIS data buffer.
+ *    - else
+ *       - log warning message of unexpected unsolicted frame
+ *    - release frame buffer
+ *
+ * @param[in] phy This is SCIC_SDS_PHY object which is being requested to
+ *       decode the frame data.
+ * @param[in] frame_index This is the index of the unsolicited frame which was
+ *       received for this phy.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS
+ *
+ * @todo Must decode the SIGNATURE FIS data
+ */
+static
+SCI_STATUS scic_sds_phy_starting_substate_await_sig_fis_frame_handler(
+   SCIC_SDS_PHY_T *this_phy,
+   U32            frame_index
+)
+{
+   SCI_STATUS          result;
+   U32               * frame_words;
+   SATA_FIS_HEADER_T * fis_frame_header;
+   U32               * fis_frame_data;
+
+   result = scic_sds_unsolicited_frame_control_get_header(
+               &(scic_sds_phy_get_controller(this_phy)->uf_control),
+               frame_index,
+               (void **)&frame_words);
+
+   if (result != SCI_SUCCESS)
+   {
+      return result;
+   }
+
+   fis_frame_header = (SATA_FIS_HEADER_T *)frame_words;
+
+   if (
+         (fis_frame_header->fis_type == SATA_FIS_TYPE_REGD2H)
+      && !(fis_frame_header->status & ATA_STATUS_REG_BSY_BIT)
+      )
+   {
+      scic_sds_unsolicited_frame_control_get_buffer(
+         &(scic_sds_phy_get_controller(this_phy)->uf_control),
+         frame_index,
+         (void **)&fis_frame_data
+      );
+
+      scic_sds_controller_copy_sata_response(
+         &this_phy->phy_type.sata.signature_fis_buffer,
+         frame_words,
+         fis_frame_data
+      );
+
+      // We got the IAF we can now go to the await spinup semaphore state
+      sci_base_state_machine_change_state(
+         scic_sds_phy_get_starting_substate_machine(this_phy),
+         SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL
+         );
+
+      result = SCI_SUCCESS;
+   }
+   else
+   {
+      SCIC_LOG_WARNING((
+         sci_base_object_get_logger(this_phy),
+         SCIC_LOG_OBJECT_PHY | SCIC_LOG_OBJECT_UNSOLICITED_FRAMES,
+         "PHY starting substate machine recieved unexpected frame id %x\n",
+         frame_index
+      ));
+   }
+
+   // Regardless of the result release this frame since we are done with it
+   scic_sds_controller_release_frame(
+      scic_sds_phy_get_controller(this_phy), frame_index
+      );
+
+   return result;
+}
+
+//*****************************************************************************
+//* SCIC SDS PHY POWER_HANDLERS
+//*****************************************************************************
+
+/**
+ * This method is called by the SCIC_SDS_CONTROLLER when the phy object is
+ * granted power.
+ *    - The notify enable spinups are turned on for this phy object
+ *    - The phy state machine is transitioned to the
+ *    SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL.
+ *
+ * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
+ *       SCIC_SDS_PHY object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS
+ */
+static
+SCI_STATUS scic_sds_phy_starting_substate_await_sas_power_consume_power_handler(
+   SCIC_SDS_PHY_T *this_phy
+)
+{
+   U32 enable_spinup;
+
+   enable_spinup = SCU_SAS_ENSPINUP_READ(this_phy);
+   enable_spinup |= SCU_ENSPINUP_GEN_BIT(ENABLE);
+   SCU_SAS_ENSPINUP_WRITE(this_phy, enable_spinup);
+
+   // Change state to the final state this substate machine has run to completion
+   sci_base_state_machine_change_state(
+      scic_sds_phy_get_starting_substate_machine(this_phy),
+      SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL
+      );
+
+   return SCI_SUCCESS;
+}
+
+/**
+ * This method is called by the SCIC_SDS_CONTROLLER when the phy object is
+ * granted power.
+ *    - The phy state machine is transitioned to the
+ *    SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN.
+ *
+ * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
+ *       SCIC_SDS_PHY object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS
+ */
+static
+SCI_STATUS scic_sds_phy_starting_substate_await_sata_power_consume_power_handler(
+   SCIC_SDS_PHY_T *this_phy
+)
+{
+   U32 scu_sas_pcfg_value;
+
+   // Release the spinup hold state and reset the OOB state machine
+   scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy);
+   scu_sas_pcfg_value &=
+      ~(SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD) | SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE));
+   scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_RESET);
+   SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value);
+
+   // Now restart the OOB operation
+   scu_sas_pcfg_value &= ~SCU_SAS_PCFG_GEN_BIT(OOB_RESET);
+   scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE);
+   SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value);
+
+   // Change state to the final state this substate machine has run to completion
+   sci_base_state_machine_change_state(
+      scic_sds_phy_get_starting_substate_machine(this_phy),
+      SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN
+   );
+
+   return SCI_SUCCESS;
+}
+
+// ---------------------------------------------------------------------------
+
+SCIC_SDS_PHY_STATE_HANDLER_T
+   scic_sds_phy_starting_substate_handler_table[SCIC_SDS_PHY_STARTING_MAX_SUBSTATES] =
+{
+   // SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL
+   {
+      {
+         scic_sds_phy_default_start_handler,
+         scic_sds_phy_starting_substate_general_stop_handler,
+         scic_sds_phy_default_reset_handler,
+         scic_sds_phy_default_destroy_handler
+      },
+      scic_sds_phy_default_frame_handler,
+      scic_sds_phy_default_event_handler,
+      scic_sds_phy_default_consume_power_handler
+   },
+   // SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN
+   {
+      {
+         scic_sds_phy_default_start_handler,
+         scic_sds_phy_starting_substate_general_stop_handler,
+         scic_sds_phy_default_reset_handler,
+         scic_sds_phy_default_destroy_handler
+      },
+      scic_sds_phy_default_frame_handler,
+      scic_sds_phy_starting_substate_await_ossp_event_handler,
+      scic_sds_phy_default_consume_power_handler
+   },
+   // SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN
+   {
+      {
+         scic_sds_phy_default_start_handler,
+         scic_sds_phy_starting_substate_general_stop_handler,
+         scic_sds_phy_default_reset_handler,
+         scic_sds_phy_default_destroy_handler
+      },
+      scic_sds_phy_default_frame_handler,
+      scic_sds_phy_starting_substate_await_sas_phy_speed_event_handler,
+      scic_sds_phy_default_consume_power_handler
+   },
+   // SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF
+   {
+      {
+         scic_sds_phy_default_start_handler,
+         scic_sds_phy_default_stop_handler,
+         scic_sds_phy_default_reset_handler,
+         scic_sds_phy_default_destroy_handler
+      },
+      scic_sds_phy_starting_substate_await_iaf_uf_frame_handler,
+      scic_sds_phy_starting_substate_await_iaf_uf_event_handler,
+      scic_sds_phy_default_consume_power_handler
+   },
+   // SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER
+   {
+      {
+         scic_sds_phy_default_start_handler,
+         scic_sds_phy_starting_substate_general_stop_handler,
+         scic_sds_phy_default_reset_handler,
+         scic_sds_phy_default_destroy_handler
+      },
+      scic_sds_phy_default_frame_handler,
+      scic_sds_phy_starting_substate_await_sas_power_event_handler,
+      scic_sds_phy_starting_substate_await_sas_power_consume_power_handler
+   },
+   // SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER,
+   {
+      {
+         scic_sds_phy_default_start_handler,
+         scic_sds_phy_starting_substate_general_stop_handler,
+         scic_sds_phy_default_reset_handler,
+         scic_sds_phy_default_destroy_handler
+      },
+      scic_sds_phy_default_frame_handler,
+      scic_sds_phy_starting_substate_await_sata_power_event_handler,
+      scic_sds_phy_starting_substate_await_sata_power_consume_power_handler
+   },
+   // SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN,
+   {
+      {
+         scic_sds_phy_default_start_handler,
+         scic_sds_phy_starting_substate_general_stop_handler,
+         scic_sds_phy_default_reset_handler,
+         scic_sds_phy_default_destroy_handler
+      },
+      scic_sds_phy_default_frame_handler,
+      scic_sds_phy_starting_substate_await_sata_phy_event_handler,
+      scic_sds_phy_default_consume_power_handler
+   },
+   // SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN,
+   {
+      {
+         scic_sds_phy_default_start_handler,
+         scic_sds_phy_starting_substate_general_stop_handler,
+         scic_sds_phy_default_reset_handler,
+         scic_sds_phy_default_destroy_handler
+      },
+      scic_sds_phy_default_frame_handler,
+      scic_sds_phy_starting_substate_await_sata_speed_event_handler,
+      scic_sds_phy_default_consume_power_handler
+   },
+   // SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF,
+   {
+      {
+         scic_sds_phy_default_start_handler,
+         scic_sds_phy_starting_substate_general_stop_handler,
+         scic_sds_phy_default_reset_handler,
+         scic_sds_phy_default_destroy_handler
+      },
+      scic_sds_phy_starting_substate_await_sig_fis_frame_handler,
+      scic_sds_phy_starting_substate_await_sig_fis_event_handler,
+      scic_sds_phy_default_consume_power_handler
+   },
+   // SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL
+   {
+      {
+         scic_sds_phy_default_start_handler,
+         scic_sds_phy_starting_substate_general_stop_handler,
+         scic_sds_phy_default_reset_handler,
+         scic_sds_phy_default_destroy_handler
+      },
+      scic_sds_phy_default_frame_handler,
+      scic_sds_phy_default_event_handler,
+      scic_sds_phy_default_consume_power_handler
+   }
+};
+
+/**
+ * This macro sets the starting substate handlers by state_id
+ */
+#define scic_sds_phy_set_starting_substate_handlers(phy, state_id) \
+   scic_sds_phy_set_state_handlers( \
+      (phy), \
+      &scic_sds_phy_starting_substate_handler_table[(state_id)] \
+   )
+
+//****************************************************************************
+//*  PHY STARTING SUBSTATE METHODS
+//****************************************************************************
+
+/**
+ * This method will perform the actions required by the SCIC_SDS_PHY on
+ * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL.
+ *    - The initial state handlers are put in place for the SCIC_SDS_PHY
+ *      object.
+ *    - The state is changed to the wait phy type event notification.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_PHY object.
+ *
+ * @return none
+ */
+static
+void scic_sds_phy_starting_initial_substate_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_PHY_T *this_phy;
+   this_phy = (SCIC_SDS_PHY_T *)object;
+
+   scic_sds_phy_set_starting_substate_handlers(
+      this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL);
+
+   // This is just an temporary state go off to the starting state
+   sci_base_state_machine_change_state(
+      scic_sds_phy_get_starting_substate_machine(this_phy),
+      SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN
+   );
+}
+
+/**
+ * This method will perform the actions required by the SCIC_SDS_PHY on
+ * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_PHY_TYPE_EN.
+ *    - Set the SCIC_SDS_PHY object state handlers for this state.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_PHY object.
+ *
+ * @return none
+ */
+static
+void scic_sds_phy_starting_await_ossp_en_substate_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_PHY_T *this_phy;
+   this_phy = (SCIC_SDS_PHY_T *)object;
+
+   scic_sds_phy_set_starting_substate_handlers(
+      this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN
+      );
+}
+
+/**
+ * This method will perform the actions required by the SCIC_SDS_PHY on
+ * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SPEED_EN.
+ *    - Set the SCIC_SDS_PHY object state handlers for this state.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_PHY object.
+ *
+ * @return none
+ */
+static
+void scic_sds_phy_starting_await_sas_speed_en_substate_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_PHY_T *this_phy;
+   this_phy = (SCIC_SDS_PHY_T *)object;
+
+   scic_sds_phy_set_starting_substate_handlers(
+      this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN
+      );
+}
+
+/**
+ * This method will perform the actions required by the SCIC_SDS_PHY on
+ * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF.
+ *    - Set the SCIC_SDS_PHY object state handlers for this state.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_PHY object.
+ *
+ * @return none
+ */
+static
+void scic_sds_phy_starting_await_iaf_uf_substate_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_PHY_T *this_phy;
+   this_phy = (SCIC_SDS_PHY_T *)object;
+
+   scic_sds_phy_set_starting_substate_handlers(
+      this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF
+      );
+}
+
+/**
+ * This method will perform the actions required by the SCIC_SDS_PHY on
+ * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER.
+ *    - Set the SCIC_SDS_PHY object state handlers for this state.
+ *    - Add this phy object to the power control queue
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_PHY object.
+ *
+ * @return none
+ */
+static
+void scic_sds_phy_starting_await_sas_power_substate_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_PHY_T *this_phy;
+   this_phy = (SCIC_SDS_PHY_T *)object;
+
+   scic_sds_phy_set_starting_substate_handlers(
+      this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER
+      );
+
+   scic_sds_controller_power_control_queue_insert(
+      scic_sds_phy_get_controller(this_phy),
+      this_phy
+      );
+}
+
+/**
+ * This method will perform the actions required by the SCIC_SDS_PHY on
+ * exiting the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER.
+ *    - Remove the SCIC_SDS_PHY object from the power control queue.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_PHY object.
+ *
+ * @return none
+ */
+static
+void scic_sds_phy_starting_await_sas_power_substate_exit(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_PHY_T *this_phy;
+   this_phy = (SCIC_SDS_PHY_T *)object;
+
+   scic_sds_controller_power_control_queue_remove(
+      scic_sds_phy_get_controller(this_phy), this_phy
+   );
+}
+
+/**
+ * This method will perform the actions required by the SCIC_SDS_PHY on
+ * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER.
+ *    - Set the SCIC_SDS_PHY object state handlers for this state.
+ *    - Add this phy object to the power control queue
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_PHY object.
+ *
+ * @return none
+ */
+static
+void scic_sds_phy_starting_await_sata_power_substate_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_PHY_T *this_phy;
+   this_phy = (SCIC_SDS_PHY_T *)object;
+
+   scic_sds_phy_set_starting_substate_handlers(
+      this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER
+      );
+
+   scic_sds_controller_power_control_queue_insert(
+      scic_sds_phy_get_controller(this_phy),
+      this_phy
+      );
+}
+
+/**
+ * This method will perform the actions required by the SCIC_SDS_PHY on
+ * exiting the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER.
+ *    - Remove the SCIC_SDS_PHY object from the power control queue.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_PHY object.
+ *
+ * @return none
+ */
+static
+void scic_sds_phy_starting_await_sata_power_substate_exit(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_PHY_T *this_phy;
+   this_phy = (SCIC_SDS_PHY_T *)object;
+
+   scic_sds_controller_power_control_queue_remove(
+      scic_sds_phy_get_controller(this_phy),
+      this_phy
+      );
+}
+
+/**
+ * This method will perform the actions required by the SCIC_SDS_PHY on
+ * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN.
+ *    - Set the SCIC_SDS_PHY object state handlers for this state.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_PHY object.
+ *
+ * @return none
+ */
+static
+void scic_sds_phy_starting_await_sata_phy_substate_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_PHY_T *this_phy;
+   this_phy = (SCIC_SDS_PHY_T *)object;
+
+   scic_sds_phy_set_starting_substate_handlers(
+      this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN
+      );
+
+   scic_cb_timer_start(
+      scic_sds_phy_get_controller(this_phy),
+      this_phy->sata_timeout_timer,
+      SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT
+   );
+}
+
+/**
+ * This method will perform the actions required by the SCIC_SDS_PHY on
+ * exiting the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN.
+ *    - stop the timer that was started on entry to await sata phy
+ *      event notification
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_PHY object.
+ *
+ * @return none
+ */
+static
+void scic_sds_phy_starting_await_sata_phy_substate_exit(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_PHY_T *this_phy;
+   this_phy = (SCIC_SDS_PHY_T *)object;
+
+   scic_cb_timer_stop(
+      scic_sds_phy_get_controller(this_phy),
+      this_phy->sata_timeout_timer
+   );
+}
+
+/**
+ * This method will perform the actions required by the SCIC_SDS_PHY on
+ * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN.
+ *    - Set the SCIC_SDS_PHY object state handlers for this state.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_PHY object.
+ *
+ * @return none
+ */
+static
+void scic_sds_phy_starting_await_sata_speed_substate_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_PHY_T *this_phy;
+   this_phy = (SCIC_SDS_PHY_T *)object;
+
+   scic_sds_phy_set_starting_substate_handlers(
+      this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN
+      );
+
+   scic_cb_timer_start(
+      scic_sds_phy_get_controller(this_phy),
+      this_phy->sata_timeout_timer,
+      SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT
+   );
+}
+
+/**
+ * This method will perform the actions required by the SCIC_SDS_PHY on
+ * exiting the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN.
+ *    - stop the timer that was started on entry to await sata phy
+ *      event notification
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_PHY object.
+ *
+ * @return none
+ */
+static
+void scic_sds_phy_starting_await_sata_speed_substate_exit(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_PHY_T *this_phy;
+   this_phy = (SCIC_SDS_PHY_T *)object;
+
+   scic_cb_timer_stop(
+      scic_sds_phy_get_controller(this_phy),
+      this_phy->sata_timeout_timer
+   );
+}
+
+/**
+ * This method will perform the actions required by the SCIC_SDS_PHY on
+ * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF.
+ *    - Set the SCIC_SDS_PHY object state handlers for this state.
+ *    - Start the SIGNATURE FIS timeout timer
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_PHY object.
+ *
+ * @return none
+ */
+static
+void scic_sds_phy_starting_await_sig_fis_uf_substate_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   BOOL             continue_to_ready_state;
+   SCIC_SDS_PHY_T * this_phy;
+
+   this_phy = (SCIC_SDS_PHY_T *)object;
+
+   scic_sds_phy_set_starting_substate_handlers(
+      this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF
+   );
+
+   continue_to_ready_state = scic_sds_port_link_detected(
+                                 this_phy->owning_port,
+                                 this_phy
+                             );
+
+   if (continue_to_ready_state)
+   {
+      // Clear the PE suspend condition so we can actually receive SIG FIS
+      // The hardware will not respond to the XRDY until the PE suspend
+      // condition is cleared.
+      scic_sds_phy_resume(this_phy);
+
+      scic_cb_timer_start(
+         scic_sds_phy_get_controller(this_phy),
+         this_phy->sata_timeout_timer,
+         SCIC_SDS_SIGNATURE_FIS_TIMEOUT
+      );
+   }
+   else
+   {
+      this_phy->is_in_link_training = FALSE;
+   }
+}
+
+/**
+ * This method will perform the actions required by the SCIC_SDS_PHY on
+ * exiting the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF.
+ *    - Stop the SIGNATURE FIS timeout timer.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_PHY object.
+ *
+ * @return none
+ */
+static
+void scic_sds_phy_starting_await_sig_fis_uf_substate_exit(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_PHY_T *this_phy;
+   this_phy = (SCIC_SDS_PHY_T *)object;
+
+   scic_cb_timer_stop(
+      scic_sds_phy_get_controller(this_phy),
+      this_phy->sata_timeout_timer
+   );
+}
+
+/**
+ * This method will perform the actions required by the SCIC_SDS_PHY on
+ * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL.
+ *    - Set the SCIC_SDS_PHY object state handlers for this state.
+ *    - Change base state machine to the ready state.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_PHY object.
+ *
+ * @return none
+ */
+static
+void scic_sds_phy_starting_final_substate_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_PHY_T *this_phy;
+   this_phy = (SCIC_SDS_PHY_T *)object;
+
+   scic_sds_phy_set_starting_substate_handlers(
+      this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL
+      );
+
+   // State machine has run to completion so exit out and change
+   // the base state machine to the ready state
+   sci_base_state_machine_change_state(
+      scic_sds_phy_get_base_state_machine(this_phy),
+      SCI_BASE_PHY_STATE_READY);
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_BASE_STATE_T
+   scic_sds_phy_starting_substates[SCIC_SDS_PHY_STARTING_MAX_SUBSTATES] =
+{
+   {
+      SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL,
+      scic_sds_phy_starting_initial_substate_enter,
+      NULL,
+   },
+   {
+      SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN,
+      scic_sds_phy_starting_await_ossp_en_substate_enter,
+      NULL,
+   },
+   {
+      SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN,
+      scic_sds_phy_starting_await_sas_speed_en_substate_enter,
+      NULL,
+   },
+   {
+      SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF,
+      scic_sds_phy_starting_await_iaf_uf_substate_enter,
+      NULL,
+   },
+   {
+      SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER,
+      scic_sds_phy_starting_await_sas_power_substate_enter,
+      scic_sds_phy_starting_await_sas_power_substate_exit,
+   },
+   {
+      SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER,
+      scic_sds_phy_starting_await_sata_power_substate_enter,
+      scic_sds_phy_starting_await_sata_power_substate_exit
+   },
+   {
+      SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN,
+      scic_sds_phy_starting_await_sata_phy_substate_enter,
+      scic_sds_phy_starting_await_sata_phy_substate_exit
+   },
+   {
+      SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN,
+      scic_sds_phy_starting_await_sata_speed_substate_enter,
+      scic_sds_phy_starting_await_sata_speed_substate_exit
+   },
+   {
+      SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF,
+      scic_sds_phy_starting_await_sig_fis_uf_substate_enter,
+      scic_sds_phy_starting_await_sig_fis_uf_substate_exit
+   },
+   {
+      SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL,
+      scic_sds_phy_starting_final_substate_enter,
+      NULL,
+   }
+};
diff --git a/sys/dev/disk/isci/scil/scic_sds_phy.h b/sys/dev/disk/isci/scil/scic_sds_phy.h
new file mode 100644
index 0000000..3eddf06
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_sds_phy.h
@@ -0,0 +1,531 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_sds_phy.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIC_SDS_PHY_H_
+#define _SCIC_SDS_PHY_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains the structures, constants and prototypes for the
+ *        SCIC_SDS_PHY object.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/intel_sata.h>
+#include <dev/disk/isci/scil/intel_sas.h>
+#include <dev/disk/isci/scil/sci_base_phy.h>
+#include <dev/disk/isci/scil/scu_registers.h>
+#include <dev/disk/isci/scil/scu_event_codes.h>
+
+/**
+ * This is the timeout value for the SATA phy to wait for a SIGNATURE FIS
+ * before restarting the starting state machine.  Technically, the old
+ * parallel ATA specification required up to 30 seconds for a device to
+ * issue its signature FIS as a result of a soft reset.  Now we see that
+ * devices respond generally within 15 seconds, but we'll use 25 for now.
+ */
+#define SCIC_SDS_SIGNATURE_FIS_TIMEOUT    25000
+
+/**
+ * This is the timeout for the SATA OOB/SN because the hardware does not
+ * recognize a hot plug after OOB signal but before the SN signals.  We
+ * need to make sure after a hotplug timeout if we have not received the
+ * speed event notification from the hardware that we restart the hardware
+ * OOB state machine.
+ */
+#define SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT  250
+
+/**
+ * @enum SCIC_SDS_PHY_STARTING_SUBSTATES
+ */
+enum SCIC_SDS_PHY_STARTING_SUBSTATES
+{
+   /**
+    * Initial state
+    */
+   SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL,
+
+   /**
+    * Wait state for the hardware OSSP event type notification
+    */
+   SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN,
+
+   /**
+    * Wait state for the PHY speed notification
+    */
+   SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN,
+
+   /**
+    * Wait state for the IAF Unsolicited frame notification
+    */
+   SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF,
+
+   /**
+    * Wait state for the request to consume power
+    */
+   SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER,
+
+   /**
+    * Wait state for request to consume power
+    */
+   SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER,
+
+   /**
+    * Wait state for the SATA PHY notification
+    */
+   SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN,
+
+   /**
+    * Wait for the SATA PHY speed notification
+    */
+   SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN,
+
+   /**
+    * Wait state for the SIGNATURE FIS unsolicited frame notification
+    */
+   SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF,
+
+   /**
+    * Exit state for this state machine
+    */
+   SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL,
+
+   /**
+    * Maximum number of substates for the STARTING state machine
+    */
+   SCIC_SDS_PHY_STARTING_MAX_SUBSTATES
+};
+
+struct SCIC_SDS_PORT;
+struct SCIC_SDS_CONTROLLER;
+
+#ifdef SCIC_DEBUG_ENABLED
+#define MAX_STATE_TRANSITION_RECORD    (256)
+
+/**
+ * Debug code to record the state transitions for the phy object
+ */
+typedef struct SCIC_SDS_PHY_STATE_RECORD
+{
+   SCI_BASE_OBSERVER_T  base_state_observer;
+   SCI_BASE_OBSERVER_T  starting_state_observer;
+
+   U16 index;
+
+   U32 state_transition_table[MAX_STATE_TRANSITION_RECORD];
+
+} SCIC_SDS_PHY_STATE_RECORD_T;
+#endif // SCIC_DEBUG_ENABLED
+
+/**
+ * @enum
+ *
+ * @brief This enumeration provides a named phy type for the state machine
+ */
+enum SCIC_SDS_PHY_PROTOCOL
+{
+   /**
+    * This is an unknown phy type since there is either nothing on the other
+    * end or we have not detected the phy type as yet.
+    */
+   SCIC_SDS_PHY_PROTOCOL_UNKNOWN,
+
+   /**
+    * This is a SAS PHY
+    */
+   SCIC_SDS_PHY_PROTOCOL_SAS,
+
+   /**
+    * This is a SATA PHY
+    */
+   SCIC_SDS_PHY_PROTOCOL_SATA,
+
+   SCIC_SDS_MAX_PHY_PROTOCOLS
+};
+
+/**
+ * @struct SCIC_SDS_PHY
+ *
+ * @brief This structure  contains or references all of the data necessary to
+ *        represent the core phy object and SCU harware protocol engine.
+ */
+typedef struct SCIC_SDS_PHY
+{
+   SCI_BASE_PHY_T parent;
+
+   /**
+    * This field specifies the port object that owns/contains this phy.
+    */
+   struct SCIC_SDS_PORT * owning_port;
+
+   /**
+    * This field indicates whether the phy supports 1.5 Gb/s, 3.0 Gb/s,
+    * or 6.0 Gb/s operation.
+    */
+   SCI_SAS_LINK_RATE max_negotiated_speed;
+
+   /**
+    * This member specifies the protocol being utilized on this phy.  This
+    * field contains a legitamite value once the PHY has link trained with
+    * a remote phy.
+    */
+   enum SCIC_SDS_PHY_PROTOCOL protocol;
+
+   /**
+    * This field specifies the index with which this phy is associated (0-3).
+    */
+   U8 phy_index;
+
+   /**
+    * This member indicates if this particular PHY has received a BCN while
+    * it had no port assignement.  This BCN will be reported once the phy is
+    * assigned to a port.
+    */
+   BOOL bcn_received_while_port_unassigned;
+
+   /**
+    * This field indicates if this PHY is currently in the process of
+    * link training (i.e. it has started OOB, but has yet to perform
+    * IAF exchange/Signature FIS reception).
+    */
+   BOOL is_in_link_training;
+
+   union
+   {
+      struct
+      {
+         SCI_SAS_IDENTIFY_ADDRESS_FRAME_T identify_address_frame_buffer;
+
+      } sas;
+
+      struct
+      {
+         SATA_FIS_REG_D2H_T signature_fis_buffer;
+
+      } sata;
+
+   } phy_type;
+
+   /**
+    * This field contains a reference to the timer utilized in detecting
+    * when a signature FIS timeout has occurred.  The signature FIS is the
+    * first FIS sent by an attached SATA device after OOB/SN.
+    */
+   void * sata_timeout_timer;
+
+   struct SCIC_SDS_PHY_STATE_HANDLER *state_handlers;
+
+   SCI_BASE_STATE_MACHINE_T starting_substate_machine;
+
+   #ifdef SCI_LOGGING
+   SCI_BASE_STATE_MACHINE_LOGGER_T starting_substate_machine_logger;
+   #endif
+
+   #ifdef SCIC_DEBUG_ENABLED
+   SCIC_SDS_PHY_STATE_RECORD_T state_record;
+   #endif // SCIC_DEBUG_ENABLED
+
+   /**
+    * This field tracks how many errors of each type have been detected since
+    *  the last controller reset or counter clear.  Note that these are only
+    *  for the error types that our driver needs to count manually.  See
+    *  SCU_ERR_CNT_* values defined in scu_event_codes.h.
+    */
+   U32   error_counter[SCU_ERR_CNT_MAX_INDEX];
+
+   /**
+    * This field is the pointer to the transport layer register for the SCU
+    * hardware.
+    */
+   SCU_TRANSPORT_LAYER_REGISTERS_T *transport_layer_registers;
+
+   /**
+    * This field points to the link layer register set within the SCU.
+    */
+   SCU_LINK_LAYER_REGISTERS_T *link_layer_registers;
+
+} SCIC_SDS_PHY_T;
+
+
+typedef SCI_STATUS (*SCIC_SDS_PHY_EVENT_HANDLER_T)(SCIC_SDS_PHY_T *, U32);
+typedef SCI_STATUS (*SCIC_SDS_PHY_FRAME_HANDLER_T)(SCIC_SDS_PHY_T *, U32);
+typedef SCI_STATUS (*SCIC_SDS_PHY_POWER_HANDLER_T)(SCIC_SDS_PHY_T *);
+
+/**
+ * @struct SCIC_SDS_PHY_STATE_HANDLER
+ */
+typedef struct SCIC_SDS_PHY_STATE_HANDLER
+{
+   /**
+    * This is the SCI_BASE_PHY object state handlers.
+    */
+   SCI_BASE_PHY_STATE_HANDLER_T parent;
+
+   /**
+    * The state handler for unsolicited frames received from the SCU hardware.
+    */
+   SCIC_SDS_PHY_FRAME_HANDLER_T frame_handler;
+
+   /**
+    * The state handler for events received from the SCU hardware.
+    */
+   SCIC_SDS_PHY_EVENT_HANDLER_T event_handler;
+
+   /**
+    * The state handler for staggered spinup.
+    */
+   SCIC_SDS_PHY_POWER_HANDLER_T consume_power_handler;
+
+} SCIC_SDS_PHY_STATE_HANDLER_T;
+
+extern SCIC_SDS_PHY_STATE_HANDLER_T scic_sds_phy_state_handler_table[];
+extern SCI_BASE_STATE_T scic_sds_phy_state_table[];
+extern SCI_BASE_STATE_T scic_sds_phy_starting_substates[];
+extern SCIC_SDS_PHY_STATE_HANDLER_T
+       scic_sds_phy_starting_substate_handler_table[];
+
+
+/**
+ * This macro returns the phy index for the specified phy
+ */
+#define scic_sds_phy_get_index(phy) \
+   ((phy)->phy_index)
+
+/**
+ * @brief This macro returns the controller for this phy
+ */
+#define scic_sds_phy_get_controller(phy) \
+   (scic_sds_port_get_controller((phy)->owning_port))
+
+/**
+ * @brief This macro returns the state machine for the base phy
+ */
+#define scic_sds_phy_get_base_state_machine(phy) \
+   (&(phy)->parent.state_machine)
+
+/**
+ * @brief This macro returns the starting substate machine for
+ *        this phy
+ */
+#define scic_sds_phy_get_starting_substate_machine(phy) \
+   (&(phy)->starting_substate_machine)
+
+/**
+ * @brief This macro sets the state handlers for this phy object
+ */
+#define scic_sds_phy_set_state_handlers(phy, handlers) \
+   ((phy)->state_handlers = (handlers))
+
+/**
+ * This macro set the base state handlers for the phy object.
+ */
+#define scic_sds_phy_set_base_state_handlers(phy, state_id) \
+   scic_sds_phy_set_state_handlers( \
+      (phy), \
+      &scic_sds_phy_state_handler_table[(state_id)] \
+   )
+
+/**
+ * This macro returns TRUE if the current base state for this phy is
+ * SCI_BASE_PHY_STATE_READY
+ */
+#define scic_sds_phy_is_ready(phy) \
+   ( \
+         SCI_BASE_PHY_STATE_READY \
+      == sci_base_state_machine_get_state( \
+            scic_sds_phy_get_base_state_machine(phy) \
+         ) \
+   )
+
+// ---------------------------------------------------------------------------
+
+U32 scic_sds_phy_get_object_size(void);
+
+U32 scic_sds_phy_get_min_timer_count(void);
+
+U32 scic_sds_phy_get_max_timer_count(void);
+
+// ---------------------------------------------------------------------------
+
+void scic_sds_phy_construct(
+   struct SCIC_SDS_PHY  *this_phy,
+   struct SCIC_SDS_PORT *owning_port,
+   U8                    phy_index
+);
+
+SCI_PORT_HANDLE_T scic_sds_phy_get_port(
+   SCIC_SDS_PHY_T *this_phy
+);
+
+void scic_sds_phy_set_port(
+   struct SCIC_SDS_PHY  *this_phy,
+   struct SCIC_SDS_PORT *owning_port
+);
+
+SCI_STATUS scic_sds_phy_initialize(
+   SCIC_SDS_PHY_T             *this_phy,
+   void                       *transport_layer_registers,
+   SCU_LINK_LAYER_REGISTERS_T *link_layer_registers
+);
+
+SCI_STATUS scic_sds_phy_reset(
+   SCIC_SDS_PHY_T * this_phy
+);
+
+void scic_sds_phy_sata_timeout(
+   SCI_OBJECT_HANDLE_T cookie
+);
+
+// ---------------------------------------------------------------------------
+
+void scic_sds_phy_suspend(
+   struct SCIC_SDS_PHY  *this_phy
+);
+
+void scic_sds_phy_resume(
+   struct SCIC_SDS_PHY  *this_phy
+);
+
+void scic_sds_phy_setup_transport(
+   struct SCIC_SDS_PHY * this_phy,
+   U32                   device_id
+);
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_sds_phy_event_handler(
+   SCIC_SDS_PHY_T *this_phy,
+   U32 event_code
+);
+
+SCI_STATUS scic_sds_phy_frame_handler(
+   SCIC_SDS_PHY_T *this_phy,
+   U32 frame_index
+);
+
+SCI_STATUS scic_sds_phy_consume_power_handler(
+   SCIC_SDS_PHY_T *this_phy
+);
+
+void scic_sds_phy_get_sas_address(
+   SCIC_SDS_PHY_T    *this_phy,
+   SCI_SAS_ADDRESS_T *sas_address
+);
+
+void scic_sds_phy_get_attached_sas_address(
+   SCIC_SDS_PHY_T    *this_phy,
+   SCI_SAS_ADDRESS_T *sas_address
+);
+
+void scic_sds_phy_get_protocols(
+   SCIC_SDS_PHY_T *this_phy,
+   SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T * protocols
+);
+
+void scic_sds_phy_get_attached_phy_protocols(
+   SCIC_SDS_PHY_T *this_phy,
+   SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T * protocols
+);
+
+//****************************************************************************-
+//* SCIC SDS PHY Handler Methods
+//****************************************************************************-
+
+SCI_STATUS scic_sds_phy_default_start_handler(
+   SCI_BASE_PHY_T *phy
+);
+
+SCI_STATUS scic_sds_phy_default_stop_handler(
+   SCI_BASE_PHY_T *phy
+);
+
+SCI_STATUS scic_sds_phy_default_reset_handler(
+   SCI_BASE_PHY_T * phy
+);
+
+SCI_STATUS scic_sds_phy_default_destroy_handler(
+   SCI_BASE_PHY_T *phy
+);
+
+SCI_STATUS scic_sds_phy_default_frame_handler(
+   SCIC_SDS_PHY_T *phy,
+   U32 frame_index
+);
+
+SCI_STATUS scic_sds_phy_default_event_handler(
+   SCIC_SDS_PHY_T *phy,
+   U32 evnet_code
+);
+
+SCI_STATUS scic_sds_phy_default_consume_power_handler(
+   SCIC_SDS_PHY_T *phy
+);
+
+void scic_sds_phy_release_resource(
+   struct SCIC_SDS_CONTROLLER * controller,
+   struct SCIC_SDS_PHY        * phy
+);
+
+void scic_sds_phy_restart_starting_state(
+   struct SCIC_SDS_PHY        * this_phy
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIC_SDS_PHY_H_
diff --git a/sys/dev/disk/isci/scil/scic_sds_phy_registers.h b/sys/dev/disk/isci/scil/scic_sds_phy_registers.h
new file mode 100644
index 0000000..49cd4f7
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_sds_phy_registers.h
@@ -0,0 +1,270 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_sds_phy_registers.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIC_SDS_PHY_REGISTERS_H_
+#define _SCIC_SDS_PHY_REGISTERS_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains the macros used by the phy object to read/write
+ *        to the SCU link layer registers.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/scic_sds_controller.h>
+
+//*****************************************************************************
+//* SCU LINK LAYER REGISTER OPERATIONS
+//*****************************************************************************
+
+/**
+ * Macro to read the transport layer register associated with this phy
+ * object.
+ */
+#define scu_transport_layer_read(phy, reg) \
+   scu_register_read( \
+      scic_sds_phy_get_controller(phy), \
+      (phy)->transport_layer_registers->reg \
+   )
+
+/**
+ * Macro to write the transport layer register associated with this phy
+ * object.
+ */
+#define scu_transport_layer_write(phy, reg, value) \
+   scu_register_write( \
+      scic_sds_phy_get_controller(phy), \
+      (phy)->transport_layer_registers->reg, \
+      (value) \
+   )
+
+//****************************************************************************
+//* Transport Layer registers controlled by the phy object
+//****************************************************************************
+
+/**
+ * This macro reads the Transport layer control register
+ */
+#define SCU_TLCR_READ(phy) \
+   scu_transport_layer_read(phy, control)
+
+/**
+ * This macro writes the Transport layer control register
+ */
+#define SCU_TLCR_WRITE(phy, value) \
+   scu_transport_layer_write(phy, control, value)
+
+/**
+ * This macro reads the Transport layer address translation register
+ */
+#define SCU_TLADTR_READ(phy) \
+   scu_transport_layer_read(phy, address_translation)
+
+/**
+ * This macro writes the Transport layer address translation register
+ */
+#define SCU_TLADTR_WRITE(phy) \
+   scu_transport_layer_write(phy, address_translation, value)
+
+/**
+ * This macro writes the STP Transport Layer Direct Attached RNi register.
+ */
+#define SCU_STPTLDARNI_WRITE(phy, index) \
+   scu_transport_layer_write(phy, stp_rni, index)
+
+/**
+ * This macro reads the STP Transport Layer Direct Attached RNi register.
+ */
+#define SCU_STPTLDARNI_READ(phy) \
+   scu_transport_layer_read(phy, stp_rni)
+
+//*****************************************************************************
+//* SCU LINK LAYER REGISTER OPERATIONS
+//*****************************************************************************
+
+/**
+ * THis macro requests the SCU register write for the specified link layer
+ * register.
+ */
+#define scu_link_layer_register_read(phy, reg) \
+   scu_register_read( \
+      scic_sds_phy_get_controller(phy), \
+      (phy)->link_layer_registers->reg \
+   )
+
+/**
+ * This macro requests the SCU register read for the specified link layer
+ * register.
+ */
+#define scu_link_layer_register_write(phy, reg, value) \
+   scu_register_write( \
+      scic_sds_phy_get_controller(phy), \
+      (phy)->link_layer_registers->reg, \
+      (value) \
+   )
+
+//*****************************************************************************
+//* SCU LINK LAYER REGISTERS
+//*****************************************************************************
+
+/// This macro reads from the SAS Identify Frame PHY Identifier register
+#define SCU_SAS_TIPID_READ(phy) \
+    scu_link_layer_register_read(phy, identify_frame_phy_id)
+
+/// This macro writes to the SAS Identify Frame PHY Identifier register
+#define SCU_SAS_TIPID_WRITE(phy, value) \
+    scu_link_layer_register_write(phy, identify_frame_phy_id, value)
+
+/// This macro reads from the SAS Identification register
+#define SCU_SAS_TIID_READ(phy) \
+    scu_link_layer_register_read(phy, transmit_identification)
+
+/// This macro writes to the SAS Identification register
+#define SCU_SAS_TIID_WRITE(phy, value) \
+    scu_link_layer_register_write(phy, transmit_identification, value)
+
+/// This macro reads the SAS Device Name High register
+#define SCU_SAS_TIDNH_READ(phy) \
+    scu_link_layer_register_read(phy, sas_device_name_high)
+
+/// This macro writes the SAS Device Name High register
+#define SCU_SAS_TIDNH_WRITE(phy, value) \
+    scu_link_layer_register_write(phy, sas_device_name_high, value)
+
+/// This macro reads the SAS Device Name Low register
+#define SCU_SAS_TIDNL_READ(phy) \
+    scu_link_layer_register_read(phy, sas_device_name_low)
+
+/// This macro writes the SAS Device Name Low register
+#define SCU_SAS_TIDNL_WRITE(phy, value) \
+    scu_link_layer_register_write(phy, sas_device_name_low, value)
+
+/// This macro reads the Source SAS Address High register
+#define SCU_SAS_TISSAH_READ(phy) \
+    scu_link_layer_register_read(phy, source_sas_address_high)
+
+/// This macro writes the Source SAS Address High register
+#define SCU_SAS_TISSAH_WRITE(phy, value) \
+    scu_link_layer_register_write(phy, source_sas_address_high, value)
+
+/// This macro reads the Source SAS Address Low register
+#define SCU_SAS_TISSAL_READ(phy) \
+    scu_link_layer_register_read(phy, source_sas_address_low)
+
+/// This macro writes the Source SAS Address Low register
+#define SCU_SAS_TISSAL_WRITE(phy, value) \
+    scu_link_layer_register_write(phy, source_sas_address_low, value)
+
+/// This macro reads the PHY Configuration register
+#define SCU_SAS_PCFG_READ(phy) \
+    scu_link_layer_register_read(phy, phy_configuration);
+
+/// This macro writes the PHY Configuration register
+#define SCU_SAS_PCFG_WRITE(phy, value) \
+    scu_link_layer_register_write(phy, phy_configuration, value)
+
+/// This macro reads the PHY Enable Spinup register
+#define SCU_SAS_ENSPINUP_READ(phy) \
+    scu_link_layer_register_read(phy, notify_enable_spinup_control)
+
+/// This macro writes the PHY Enable Spinup register
+#define SCU_SAS_ENSPINUP_WRITE(phy, value) \
+    scu_link_layer_register_write(phy, notify_enable_spinup_control, value)
+
+/// This macro reads the CLKSM register
+#define SCU_SAS_CLKSM_READ(phy) \
+    scu_link_layer_register_read(phy, clock_skew_management)
+
+/// This macro writes the CLKSM register
+#define SCU_SAS_CLKSM_WRITE(phy, value) \
+    scu_link_layer_register_write(phy, clock_skew_management, value)
+
+/// This macro reads the PHY Capacity register
+#define SCU_SAS_PHYCAP_READ(phy) \
+    scu_link_layer_register_read(phy, phy_capabilities)
+
+/// This macro writes the PHY Capacity register
+#define SCU_SAS_PHYCAP_WRITE(phy, value) \
+    scu_link_layer_register_write(phy, phy_capabilities, value)
+
+/// This macro reads the Recieved PHY Capacity register
+#define SCU_SAS_RECPHYCAP_READ(phy) \
+    scu_link_layer_register_read(phy, receive_phycap)
+
+/// This macro reads the link layer control register
+#define SCU_SAS_LLCTL_READ(phy) \
+    scu_link_layer_register_read(phy, link_layer_control);
+
+/// This macro writes the link layer control register
+#define SCU_SAS_LLCTL_WRITE(phy, value) \
+    scu_link_layer_register_write(phy, link_layer_control, value);
+
+/// This macro reads the link layer status register
+#define SCU_SAS_LLSTA_READ(phy) \
+    scu_link_layer_register_read(phy, link_layer_status);
+
+#define SCU_SAS_ECENCR_READ(phy) \
+    scu_link_layer_register_read(phy, error_counter_event_notification_control)
+
+#define SCU_SAS_ECENCR_WRITE(phy, value) \
+    scu_link_layer_register_write(phy, error_counter_event_notification_control, value)
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIC_SDS_PHY_REGISTERS_H_
diff --git a/sys/dev/disk/isci/scil/scic_sds_port.c b/sys/dev/disk/isci/scil/scic_sds_port.c
new file mode 100644
index 0000000..5d224e6
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_sds_port.c
@@ -0,0 +1,3660 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_sds_port.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains the implementation for the public and protected
+ *        methods for the SCIC_SDS_PORT object.
+ */
+
+#include <dev/disk/isci/scil/scic_phy.h>
+#include <dev/disk/isci/scil/scic_port.h>
+#include <dev/disk/isci/scil/scic_controller.h>
+#include <dev/disk/isci/scil/scic_user_callback.h>
+
+#include <dev/disk/isci/scil/scic_sds_controller.h>
+#include <dev/disk/isci/scil/scic_sds_port.h>
+#include <dev/disk/isci/scil/scic_sds_phy.h>
+#include <dev/disk/isci/scil/scic_sds_remote_device.h>
+#include <dev/disk/isci/scil/scic_sds_request.h>
+#include <dev/disk/isci/scil/scic_sds_port_registers.h>
+#include <dev/disk/isci/scil/scic_sds_logger.h>
+#include <dev/disk/isci/scil/scic_sds_phy_registers.h>
+
+#include <dev/disk/isci/scil/intel_sas.h>
+#include <dev/disk/isci/scil/scic_sds_remote_node_context.h>
+#include <dev/disk/isci/scil/sci_util.h>
+
+#define SCIC_SDS_PORT_MIN_TIMER_COUNT  (SCI_MAX_PORTS)
+#define SCIC_SDS_PORT_MAX_TIMER_COUNT  (SCI_MAX_PORTS)
+
+#define SCIC_SDS_PORT_HARD_RESET_TIMEOUT  (1000)
+#define SCU_DUMMY_INDEX    (0xFFFF)
+
+/**
+ * This method will return a TRUE value if the specified phy can be assigned
+ * to this port
+ *
+ * The following is a list of phys for each port that are allowed:
+ * - Port 0 - 3 2 1 0
+ * - Port 1 -     1
+ * - Port 2 - 3 2
+ * - Port 3 - 3
+ *
+ * This method doesn't preclude all configurations.  It merely ensures
+ * that a phy is part of the allowable set of phy identifiers for
+ * that port.  For example, one could assign phy 3 to port 0 and no other
+ * phys.  Please refer to scic_sds_port_is_phy_mask_valid() for
+ * information regarding whether the phy_mask for a port can be supported.
+ *
+ * @param[in] this_port This is the port object to which the phy is being
+ *       assigned.
+ * @param[in] phy_index This is the phy index that is being assigned to the
+ *       port.
+ *
+ * @return BOOL
+ * @retval TRUE if this is a valid phy assignment for the port
+ * @retval FALSE if this is not a valid phy assignment for the port
+ */
+BOOL scic_sds_port_is_valid_phy_assignment(
+   SCIC_SDS_PORT_T *this_port,
+   U32              phy_index
+)
+{
+   // Initialize to invalid value.
+   U32  existing_phy_index = SCI_MAX_PHYS;
+   U32  index;
+
+   if ((this_port->physical_port_index == 1) && (phy_index != 1))
+   {
+      return FALSE;
+   }
+
+   if (this_port->physical_port_index == 3 && phy_index != 3)
+   {
+      return FALSE;
+   }
+
+   if (
+          (this_port->physical_port_index == 2)
+       && ((phy_index == 0) || (phy_index == 1))
+      )
+   {
+      return FALSE;
+   }
+
+   for (index = 0; index < SCI_MAX_PHYS; index++)
+   {
+      if (  (this_port->phy_table[index] != NULL)
+         && (index != phy_index) )
+      {
+         existing_phy_index = index;
+      }
+   }
+
+   // Ensure that all of the phys in the port are capable of
+   // operating at the same maximum link rate.
+   if (
+         (existing_phy_index < SCI_MAX_PHYS)
+      && (this_port->owning_controller->user_parameters.sds1.phys[
+             phy_index].max_speed_generation !=
+          this_port->owning_controller->user_parameters.sds1.phys[
+             existing_phy_index].max_speed_generation)
+      )
+      return FALSE;
+
+   return TRUE;
+}
+
+/**
+ * @brief This method requests a list (mask) of the phys contained in the
+ *        supplied SAS port.
+ *
+ * @param[in]  this_port a handle corresponding to the SAS port for which
+ *             to return the phy mask.
+ *
+ * @return Return a bit mask indicating which phys are a part of this port.
+ *         Each bit corresponds to a phy identifier (e.g. bit 0 = phy id 0).
+ */
+U32 scic_sds_port_get_phys(
+   SCIC_SDS_PORT_T * this_port
+)
+{
+   U32 index;
+   U32 mask;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_port),
+      SCIC_LOG_OBJECT_PORT,
+      "scic_sds_port_get_phys(0x%x) enter\n",
+      this_port
+   ));
+
+   mask = 0;
+
+   for (index = 0; index < SCI_MAX_PHYS; index++)
+   {
+      if (this_port->phy_table[index] != NULL)
+      {
+         mask |= (1 << index);
+      }
+   }
+
+   return mask;
+}
+
+/**
+ * This method will return a TRUE value if the port's phy mask can be
+ * supported by the SCU.
+ *
+ * The following is a list of valid PHY mask configurations for each
+ * port:
+ * - Port 0 - [[3  2] 1] 0
+ * - Port 1 -        [1]
+ * - Port 2 - [[3] 2]
+ * - Port 3 -  [3]
+ *
+ * @param[in] this_port This is the port object for which to determine
+ *       if the phy mask can be supported.
+ *
+ * @return This method returns a boolean indication specifying if the
+ *         phy mask can be supported.
+ * @retval TRUE if this is a valid phy assignment for the port
+ * @retval FALSE if this is not a valid phy assignment for the port
+ */
+BOOL scic_sds_port_is_phy_mask_valid(
+   SCIC_SDS_PORT_T *this_port,
+   U32              phy_mask
+)
+{
+   if (this_port->physical_port_index == 0)
+   {
+      if (  ((phy_mask & 0x0F) == 0x0F)
+         || ((phy_mask & 0x03) == 0x03)
+         || ((phy_mask & 0x01) == 0x01)
+         || (phy_mask == 0) )
+         return TRUE;
+   }
+   else if (this_port->physical_port_index == 1)
+   {
+      if (  ((phy_mask & 0x02) == 0x02)
+         || (phy_mask == 0) )
+         return TRUE;
+   }
+   else if (this_port->physical_port_index == 2)
+   {
+      if (  ((phy_mask & 0x0C) == 0x0C)
+         || ((phy_mask & 0x04) == 0x04)
+         || (phy_mask == 0) )
+         return TRUE;
+   }
+   else if (this_port->physical_port_index == 3)
+   {
+      if (  ((phy_mask & 0x08) == 0x08)
+         || (phy_mask == 0) )
+         return TRUE;
+   }
+
+   return FALSE;
+}
+
+/**
+ * This method retrieves a currently active (i.e. connected) phy
+ * contained in the port.  Currently, the lowest order phy that is
+ * connected is returned.
+ *
+ * @param[in] this_port This parameter specifies the port from which
+ *            to return a connected phy.
+ *
+ * @return This method returns a pointer to a SCIS_SDS_PHY object.
+ * @retval NULL This value is returned if there are no currently
+ *         active (i.e. connected to a remote end point) phys
+ *         contained in the port.
+ * @retval All other values specify a SCIC_SDS_PHY object that is
+ *         active in the port.
+ */
+SCIC_SDS_PHY_T * scic_sds_port_get_a_connected_phy(
+   SCIC_SDS_PORT_T *this_port
+)
+{
+   U32             index;
+   SCIC_SDS_PHY_T *phy;
+
+   for (index = 0; index < SCI_MAX_PHYS; index++)
+   {
+      // Ensure that the phy is both part of the port and currently
+      // connected to the remote end-point.
+      phy = this_port->phy_table[index];
+      if (
+            (phy != NULL)
+         && scic_sds_port_active_phy(this_port, phy)
+         )
+      {
+         return phy;
+      }
+   }
+
+   return NULL;
+}
+
+/**
+ * This method attempts to make the assignment of the phy to the port.
+ * If successful the phy is assigned to the ports phy table.
+ *
+ * @param[in, out] port The port object to which the phy assignement
+ *                 is being made.
+ * @param[in, out] phy The phy which is being assigned to the port.
+ *
+ * @return BOOL
+ * @retval TRUE if the phy assignment can be made.
+ * @retval FALSE if the phy assignement can not be made.
+ *
+ * @note This is a functional test that only fails if the phy is currently
+ *       assigned to a different port.
+ */
+SCI_STATUS scic_sds_port_set_phy(
+   SCIC_SDS_PORT_T *port,
+   SCIC_SDS_PHY_T  *phy
+)
+{
+   // Check to see if we can add this phy to a port
+   // that means that the phy is not part of a port and that the port does
+   // not already have a phy assinged to the phy index.
+   if (
+         (port->phy_table[phy->phy_index] == SCI_INVALID_HANDLE)
+      && (scic_sds_phy_get_port(phy) == SCI_INVALID_HANDLE)
+      && scic_sds_port_is_valid_phy_assignment(port, phy->phy_index)
+      )
+   {
+      // Phy is being added in the stopped state so we are in MPC mode
+      // make logical port index = physical port index
+      port->logical_port_index = port->physical_port_index;
+      port->phy_table[phy->phy_index] = phy;
+      scic_sds_phy_set_port(phy, port);
+
+      return SCI_SUCCESS;
+   }
+
+   return SCI_FAILURE;
+}
+
+/**
+ * This method will clear the phy assigned to this port.  This method fails
+ * if this phy is not currently assinged to this port.
+ *
+ * @param[in, out] port The port from which the phy is being cleared.
+ * @param[in, out] phy The phy being cleared from the port.
+ *
+ * @return BOOL
+ * @retval TRUE if the phy is removed from the port.
+ * @retval FALSE if this phy is not assined to this port.
+ */
+SCI_STATUS scic_sds_port_clear_phy(
+   SCIC_SDS_PORT_T *port,
+   SCIC_SDS_PHY_T  *phy
+)
+{
+   // Make sure that this phy is part of this port
+   if (
+           (port->phy_table[phy->phy_index] == phy)
+        && (scic_sds_phy_get_port(phy) == port)
+      )
+   {
+      // Yep it is assigned to this port so remove it
+      scic_sds_phy_set_port(
+         phy,
+         &scic_sds_port_get_controller(port)->port_table[SCI_MAX_PORTS]
+      );
+
+      port->phy_table[phy->phy_index] = SCI_INVALID_HANDLE;
+
+      return SCI_SUCCESS;
+   }
+
+   return SCI_FAILURE;
+}
+
+/**
+ * This method will add a PHY to the selected port.
+ *
+ * @param[in] this_port This parameter specifies the port in which the phy will
+ *            be added.
+ *
+ * @param[in] the_phy This parameter is the phy which is to be added to the
+ *            port.
+ *
+ * @return This method returns an SCI_STATUS.
+ * @retval SCI_SUCCESS the phy has been added to the port.
+ * @retval Any other status is failre to add the phy to the port.
+ */
+SCI_STATUS scic_sds_port_add_phy(
+   SCIC_SDS_PORT_T * this_port,
+   SCIC_SDS_PHY_T  * the_phy
+)
+{
+   return this_port->state_handlers->parent.add_phy_handler(
+                                          &this_port->parent, &the_phy->parent);
+}
+
+
+/**
+ * This method will remove the PHY from the selected PORT.
+ *
+ * @param[in] this_port This parameter specifies the port in which the phy will
+ *            be added.
+ *
+ * @param[in] the_phy This parameter is the phy which is to be added to the
+ *            port.
+ *
+ * @return This method returns an SCI_STATUS.
+ * @retval SCI_SUCCESS the phy has been removed from the port.
+ * @retval Any other status is failre to add the phy to the port.
+ */
+SCI_STATUS scic_sds_port_remove_phy(
+   SCIC_SDS_PORT_T * this_port,
+   SCIC_SDS_PHY_T  * the_phy
+)
+{
+   return this_port->state_handlers->parent.remove_phy_handler(
+                                          &this_port->parent, &the_phy->parent);
+}
+
+/**
+ * @brief This method requests the SAS address for the supplied SAS port
+ *        from the SCI implementation.
+ *
+ * @param[in]  this_port a handle corresponding to the SAS port for which
+ *             to return the SAS address.
+ * @param[out] sas_address This parameter specifies a pointer to a SAS
+ *             address structure into which the core will copy the SAS
+ *             address for the port.
+ *
+ * @return none
+ */
+void scic_sds_port_get_sas_address(
+   SCIC_SDS_PORT_T   * this_port,
+   SCI_SAS_ADDRESS_T * sas_address
+)
+{
+   U32 index;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_port),
+      SCIC_LOG_OBJECT_PORT,
+      "scic_sds_port_get_sas_address(0x%x, 0x%x) enter\n",
+      this_port, sas_address
+   ));
+
+   sas_address->high = 0;
+   sas_address->low  = 0;
+
+   for (index = 0; index < SCI_MAX_PHYS; index++)
+   {
+      if (this_port->phy_table[index] != NULL)
+      {
+         scic_sds_phy_get_sas_address(this_port->phy_table[index], sas_address);
+      }
+   }
+}
+
+/**
+ * @brief This method will indicate which protocols are supported by this
+ *        port.
+ *
+ * @param[in]  this_port a handle corresponding to the SAS port for which
+ *             to return the supported protocols.
+ * @param[out] protocols This parameter specifies a pointer to an IAF
+ *             protocol field structure into which the core will copy
+ *             the protocol values for the port.  The values are
+ *             returned as part of a bit mask in order to allow for
+ *             multi-protocol support.
+ *
+ * @return none
+ */
+static
+void scic_sds_port_get_protocols(
+   SCIC_SDS_PORT_T                            * this_port,
+   SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T * protocols
+)
+{
+   U8 index;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_port),
+      SCIC_LOG_OBJECT_PORT,
+      "scic_sds_port_get_protocols(0x%x, 0x%x) enter\n",
+      this_port, protocols
+   ));
+
+   protocols->u.all = 0;
+
+   for (index = 0; index < SCI_MAX_PHYS; index++)
+   {
+      if (this_port->phy_table[index] != NULL)
+      {
+         scic_sds_phy_get_protocols(this_port->phy_table[index], protocols);
+      }
+   }
+}
+
+/**
+ * @brief This method requests the SAS address for the device directly
+ *        attached to this SAS port.
+ *
+ * @param[in]  this_port a handle corresponding to the SAS port for which
+ *             to return the SAS address.
+ * @param[out] sas_address This parameter specifies a pointer to a SAS
+ *             address structure into which the core will copy the SAS
+ *             address for the device directly attached to the port.
+ *
+ * @return none
+ */
+void scic_sds_port_get_attached_sas_address(
+   SCIC_SDS_PORT_T   * this_port,
+   SCI_SAS_ADDRESS_T * sas_address
+)
+{
+   SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T protocols;
+   SCIC_SDS_PHY_T  *phy;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_port),
+      SCIC_LOG_OBJECT_PORT,
+      "scic_sds_port_get_attached_sas_address(0x%x, 0x%x) enter\n",
+      this_port, sas_address
+   ));
+
+   // Ensure that the phy is both part of the port and currently
+   // connected to the remote end-point.
+   phy = scic_sds_port_get_a_connected_phy(this_port);
+   if (phy != NULL)
+   {
+      scic_sds_phy_get_attached_phy_protocols(phy, &protocols);
+
+      if (!protocols.u.bits.stp_target)
+      {
+         scic_sds_phy_get_attached_sas_address(phy, sas_address);
+      }
+      else
+      {
+         scic_sds_phy_get_sas_address(phy, sas_address);
+         sas_address->low += phy->phy_index;
+
+		 //Need to make up attached STP device's SAS address in
+		 //the same order as recorded IAF from SSP device.
+		 sas_address->high = SCIC_SWAP_DWORD(sas_address->high);
+		 sas_address->low = SCIC_SWAP_DWORD(sas_address->low);
+      }
+   }
+   else
+   {
+      sas_address->high = 0;
+      sas_address->low  = 0;
+   }
+}
+
+/**
+ * @brief This method will indicate which protocols are supported by this
+ *        remote device.
+ *
+ * @param[in]  this_port a handle corresponding to the SAS port for which
+ *             to return the supported protocols.
+ * @param[out] protocols This parameter specifies a pointer to an IAF
+ *             protocol field structure into which the core will copy
+ *             the protocol values for the port.  The values are
+ *             returned as part of a bit mask in order to allow for
+ *             multi-protocol support.
+ *
+ * @return none
+ */
+void scic_sds_port_get_attached_protocols(
+   SCIC_SDS_PORT_T                            * this_port,
+   SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T * protocols
+)
+{
+   SCIC_SDS_PHY_T  *phy;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_port),
+      SCIC_LOG_OBJECT_PORT,
+      "scic_sds_port_get_attached_protocols(0x%x, 0x%x) enter\n",
+      this_port, protocols
+   ));
+
+   // Ensure that the phy is both part of the port and currently
+   // connected to the remote end-point.
+   phy = scic_sds_port_get_a_connected_phy(this_port);
+   if (phy != NULL)
+      scic_sds_phy_get_attached_phy_protocols(phy, protocols);
+   else
+      protocols->u.all = 0;
+}
+
+/**
+ * @brief This method returns the amount of memory requred for a port
+ *        object.
+ *
+ * @return U32
+ */
+U32 scic_sds_port_get_object_size(void)
+{
+   return sizeof(SCIC_SDS_PORT_T);
+}
+
+/**
+ * @brief This method returns the minimum number of timers required for all
+ *        port objects.
+ *
+ * @return U32
+ */
+U32 scic_sds_port_get_min_timer_count(void)
+{
+   return SCIC_SDS_PORT_MIN_TIMER_COUNT;
+}
+
+/**
+ * @brief This method returns the maximum number of timers required for all
+ *        port objects.
+ *
+ * @return U32
+ */
+U32 scic_sds_port_get_max_timer_count(void)
+{
+   return SCIC_SDS_PORT_MAX_TIMER_COUNT;
+}
+
+#ifdef SCI_LOGGING
+void scic_sds_port_initialize_state_logging(
+   SCIC_SDS_PORT_T *this_port
+)
+{
+   sci_base_state_machine_logger_initialize(
+      &this_port->parent.state_machine_logger,
+      &this_port->parent.state_machine,
+      &this_port->parent.parent,
+      scic_cb_logger_log_states,
+      "SCIC_SDS_PORT_T", "base state machine",
+      SCIC_LOG_OBJECT_PORT
+   );
+
+   sci_base_state_machine_logger_initialize(
+      &this_port->ready_substate_machine_logger,
+      &this_port->ready_substate_machine,
+      &this_port->parent.parent,
+      scic_cb_logger_log_states,
+      "SCIC_SDS_PORT_T", "ready substate machine",
+      SCIC_LOG_OBJECT_PORT
+   );
+}
+#endif
+
+/**
+ * This routine will construct a dummy remote node context data structure
+ * This structure will be posted to the hardware to work around a scheduler
+ * error in the hardware.
+ *
+ * @param[in] this_port The logical port on which we need to create the
+ *            remote node context.
+ * @param[in] rni The remote node index for this remote node context.
+ *
+ * @return none
+ */
+static
+void scic_sds_port_construct_dummy_rnc(
+   SCIC_SDS_PORT_T *this_port,
+   U16              rni
+)
+{
+   SCU_REMOTE_NODE_CONTEXT_T * rnc;
+
+   rnc = &(this_port->owning_controller->remote_node_context_table[rni]);
+
+   memset(rnc, 0, sizeof(SCU_REMOTE_NODE_CONTEXT_T));
+
+   rnc->ssp.remote_sas_address_hi = 0;
+   rnc->ssp.remote_sas_address_lo = 0;
+
+   rnc->ssp.remote_node_index = rni;
+   rnc->ssp.remote_node_port_width = 1;
+   rnc->ssp.logical_port_index = this_port->physical_port_index;
+
+   rnc->ssp.nexus_loss_timer_enable = FALSE;
+   rnc->ssp.check_bit = FALSE;
+   rnc->ssp.is_valid = TRUE;
+   rnc->ssp.is_remote_node_context = TRUE;
+   rnc->ssp.function_number = 0;
+   rnc->ssp.arbitration_wait_time = 0;
+}
+
+/**
+ * This routine will construct a dummy task context data structure.  This
+ * structure will be posted to the hardwre to work around a scheduler error
+ * in the hardware.
+ *
+ * @param[in] this_port The logical port on which we need to create the
+ *            remote node context.
+ *            context.
+ * @param[in] tci The remote node index for this remote node context.
+ *
+ */
+static
+void scic_sds_port_construct_dummy_task(
+   SCIC_SDS_PORT_T *this_port,
+   U16              tci
+)
+{
+   SCU_TASK_CONTEXT_T * task_context;
+
+   task_context = scic_sds_controller_get_task_context_buffer(this_port->owning_controller, tci);
+
+   memset(task_context, 0, sizeof(SCU_TASK_CONTEXT_T));
+
+   task_context->abort = 0;
+   task_context->priority = 0;
+   task_context->initiator_request = 1;
+   task_context->connection_rate = 1;
+   task_context->protocol_engine_index = 0;
+   task_context->logical_port_index = this_port->physical_port_index;
+   task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SSP;
+   task_context->task_index = scic_sds_io_tag_get_index(tci);
+   task_context->valid = SCU_TASK_CONTEXT_VALID;
+   task_context->context_type = SCU_TASK_CONTEXT_TYPE;
+
+   task_context->remote_node_index = this_port->reserved_rni;
+   task_context->command_code = 0;
+
+   task_context->link_layer_control = 0;
+   task_context->do_not_dma_ssp_good_response = 1;
+   task_context->strict_ordering = 0;
+   task_context->control_frame = 0;
+   task_context->timeout_enable = 0;
+   task_context->block_guard_enable = 0;
+
+   task_context->address_modifier = 0;
+
+   task_context->task_phase = 0x01;
+}
+
+/**
+ * This routine will free any allocated dummy resources for this port.
+ *
+ * @param[in, out] this_port The port on which the resources are being destroyed.
+ */
+static
+void scic_sds_port_destroy_dummy_resources(
+   SCIC_SDS_PORT_T * this_port
+)
+{
+   if (this_port->reserved_tci != SCU_DUMMY_INDEX)
+   {
+      scic_controller_free_io_tag(
+         this_port->owning_controller, this_port->reserved_tci
+      );
+   }
+
+   if (this_port->reserved_rni != SCU_DUMMY_INDEX)
+   {
+      scic_sds_remote_node_table_release_remote_node_index(
+         &this_port->owning_controller->available_remote_nodes, 1, this_port->reserved_rni
+      );
+   }
+
+   this_port->reserved_rni = SCU_DUMMY_INDEX;
+   this_port->reserved_tci = SCU_DUMMY_INDEX;
+}
+
+/**
+ * @brief
+ *
+ * @param[in] this_port
+ * @param[in] port_index
+ * @param[in] owning_controller
+ */
+void scic_sds_port_construct(
+   SCIC_SDS_PORT_T         *this_port,
+   U8                      port_index,
+   SCIC_SDS_CONTROLLER_T   *owning_controller
+)
+{
+   U32 index;
+
+   sci_base_port_construct(
+      &this_port->parent,
+      sci_base_object_get_logger(owning_controller),
+      scic_sds_port_state_table
+   );
+
+   sci_base_state_machine_construct(
+      scic_sds_port_get_ready_substate_machine(this_port),
+      &this_port->parent.parent,
+      scic_sds_port_ready_substate_table,
+      SCIC_SDS_PORT_READY_SUBSTATE_WAITING
+   );
+
+   scic_sds_port_initialize_state_logging(this_port);
+
+   this_port->logical_port_index  = SCIC_SDS_DUMMY_PORT;
+   this_port->physical_port_index = port_index;
+   this_port->active_phy_mask     = 0;
+   this_port->enabled_phy_mask    = 0;
+   this_port->owning_controller = owning_controller;
+
+   this_port->started_request_count = 0;
+   this_port->assigned_device_count = 0;
+
+   this_port->reserved_rni = SCU_DUMMY_INDEX;
+   this_port->reserved_tci = SCU_DUMMY_INDEX;
+
+   this_port->timer_handle = SCI_INVALID_HANDLE;
+
+   this_port->port_task_scheduler_registers = NULL;
+
+   for (index = 0; index < SCI_MAX_PHYS; index++)
+   {
+      this_port->phy_table[index] = NULL;
+   }
+}
+
+/**
+ * @brief This method performs initialization of the supplied port.
+ *        Initialization includes:
+ *        - state machine initialization
+ *        - member variable initialization
+ *        - configuring the phy_mask
+ *
+ * @param[in] this_port
+ * @param[in] transport_layer_registers
+ * @param[in] port_task_scheduler_registers
+ * @param[in] port_configuration_regsiter
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION This value is
+ *         returned if the phy being added to the port
+ */
+SCI_STATUS scic_sds_port_initialize(
+   SCIC_SDS_PORT_T *this_port,
+   void            *port_task_scheduler_registers,
+   void            *port_configuration_regsiter,
+   void            *viit_registers
+)
+{
+   this_port->port_task_scheduler_registers  = port_task_scheduler_registers;
+   this_port->port_pe_configuration_register = port_configuration_regsiter;
+   this_port->viit_registers                 = viit_registers;
+
+   return SCI_SUCCESS;
+}
+
+/**
+ * This method is the a general link up handler for the SCIC_SDS_PORT object.
+ * This function will determine if this SCIC_SDS_PHY can
+ * be assigned to this SCIC_SDS_PORT object. If the SCIC_SDS_PHY object can
+ * is not a valid PHY for this port then the function will notify the SCIC_USER.
+ * A PHY can only be part of a port if it's attached SAS ADDRESS is the same as
+ * all other PHYs in the same port.
+ *
+ * @param[in] this_port This is the SCIC_SDS_PORT object for which has a phy
+ *       that has gone link up.
+ * @param[in] the_phy This is the SCIC_SDS_PHY object that has gone link up.
+ * @param[in] do_notify_user This parameter specifies whether to inform
+ *            the user (via scic_cb_port_link_up()) as to the fact that
+ *            a new phy as become ready.
+ * @param[in] do_resume_phy This parameter specifies whether to resume the phy.
+ *            If this function is called from MPC mode, it will be always true.
+ *            for APC, this will be false, so that phys could be resumed later
+ *
+ * @return none
+ */
+void scic_sds_port_general_link_up_handler(
+   SCIC_SDS_PORT_T * this_port,
+   SCIC_SDS_PHY_T  * the_phy,
+   BOOL              do_notify_user,
+   BOOL              do_resume_phy
+)
+{
+   SCI_SAS_ADDRESS_T  port_sas_address;
+   SCI_SAS_ADDRESS_T  phy_sas_address;
+
+   scic_sds_port_get_attached_sas_address(this_port, &port_sas_address);
+   scic_sds_phy_get_attached_sas_address(the_phy, &phy_sas_address);
+
+   // If the SAS address of the new phy matches the SAS address of
+   // other phys in the port OR this is the first phy in the port,
+   // then activate the phy and allow it to be used for operations
+   // in this port.
+   if (
+         (
+            (phy_sas_address.high == port_sas_address.high)
+         && (phy_sas_address.low  == port_sas_address.low )
+         )
+         || (this_port->active_phy_mask == 0)
+      )
+   {
+      scic_sds_port_activate_phy(this_port, the_phy, do_notify_user, do_resume_phy);
+
+      if (this_port->parent.state_machine.current_state_id
+          == SCI_BASE_PORT_STATE_RESETTING)
+      {
+         sci_base_state_machine_change_state(
+            &this_port->parent.state_machine, SCI_BASE_PORT_STATE_READY
+         );
+      }
+   }
+   else
+   {
+      scic_sds_port_invalid_link_up(this_port, the_phy);
+   }
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_port_add_phy(
+   SCI_PORT_HANDLE_T handle,
+   SCI_PHY_HANDLE_T phy
+)
+{
+   #if defined (SCI_LOGGING)
+   SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)handle;
+   #endif // defined (SCI_LOGGING)
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_port),
+      SCIC_LOG_OBJECT_PORT,
+      "scic_port_add_phy(0x%x, 0x%x) enter\n",
+      handle, phy
+   ));
+
+   SCIC_LOG_ERROR((
+      sci_base_object_get_logger(this_port),
+      SCIC_LOG_OBJECT_PORT,
+      "Interface function scic_port_add_phy() has been deprecated. "
+      "PORT configuration is handled through the OEM parameters.\n"
+   ));
+
+   return SCI_FAILURE_ADDING_PHY_UNSUPPORTED;
+
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_port_remove_phy(
+   SCI_PORT_HANDLE_T handle,
+   SCI_PHY_HANDLE_T phy
+)
+{
+   #if defined (SCI_LOGGING)
+   SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)handle;
+   #endif // defined (SCI_LOGGING)
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_port),
+      SCIC_LOG_OBJECT_PORT,
+      "scic_port_remove_phy(0x%x, 0x%x) enter\n",
+      handle, phy
+   ));
+
+   SCIC_LOG_ERROR((
+      sci_base_object_get_logger(this_port),
+      SCIC_LOG_OBJECT_PORT,
+      "Interface function scic_port_remove_phy() has been deprecated. "
+      "PORT configuration is handled through the OEM parameters.\n"
+   ));
+
+   return SCI_FAILURE_ADDING_PHY_UNSUPPORTED;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_port_get_properties(
+   SCI_PORT_HANDLE_T        port,
+   SCIC_PORT_PROPERTIES_T * properties
+)
+{
+   SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)port;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_port),
+      SCIC_LOG_OBJECT_PORT,
+      "scic_port_get_properties(0x%x, 0x%x) enter\n",
+      port, properties
+   ));
+
+   if (
+         (port == SCI_INVALID_HANDLE)
+      || (this_port->logical_port_index == SCIC_SDS_DUMMY_PORT)
+      )
+   {
+      return SCI_FAILURE_INVALID_PORT;
+   }
+
+   properties->index    = this_port->logical_port_index;
+   properties->phy_mask = scic_sds_port_get_phys(this_port);
+   scic_sds_port_get_sas_address(this_port, &properties->local.sas_address);
+   scic_sds_port_get_protocols(this_port, &properties->local.protocols);
+   scic_sds_port_get_attached_sas_address(this_port, &properties->remote.sas_address);
+   scic_sds_port_get_attached_protocols(this_port, &properties->remote.protocols);
+
+   return SCI_SUCCESS;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_port_hard_reset(
+   SCI_PORT_HANDLE_T handle,
+   U32               reset_timeout
+)
+{
+   SCIC_SDS_PORT_T * this_port = (SCIC_SDS_PORT_T *)handle;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_port),
+      SCIC_LOG_OBJECT_PORT,
+      "scic_port_hard_reset(0x%x, 0x%x) enter\n",
+      handle, reset_timeout
+   ));
+
+   return this_port->state_handlers->parent.reset_handler(
+                                       &this_port->parent,
+                                       reset_timeout
+                                     );
+}
+
+/**
+ * This method assigns the direct attached device ID for this port.
+ *
+ * @param[in] this_port The port for which the direct attached device id is to
+ *       be assigned.
+ * @param[in] device_id The direct attached device ID to assign to the port.
+ *       This will be the RNi for the device
+ */
+void scic_sds_port_setup_transports(
+   SCIC_SDS_PORT_T * this_port,
+   U32               device_id
+)
+{
+   U8 index;
+
+   for (index = 0; index < SCI_MAX_PHYS; index++)
+   {
+      if (this_port->active_phy_mask & (1 << index))
+      {
+         scic_sds_phy_setup_transport(this_port->phy_table[index], device_id);
+      }
+   }
+}
+
+/**
+ * This method will resume the phy which is already added in the port.
+ * Activation includes:
+ * - enabling the Protocol Engine in the silicon.
+ * - update the reay mask.
+ *
+ * @param[in] this_port This is the port on which the phy should be enabled.
+ * @return none
+ */
+static
+void scic_sds_port_resume_phy(
+   SCIC_SDS_PORT_T * this_port,
+   SCIC_SDS_PHY_T  * the_phy
+)
+{
+   scic_sds_phy_resume (the_phy);
+   this_port->enabled_phy_mask |= 1 << the_phy->phy_index;
+}
+/**
+ * This method will activate the phy in the port.
+ * Activation includes:
+ * - adding the phy to the port
+ * - enabling the Protocol Engine in the silicon.
+ * - notifying the user that the link is up.
+ *
+ * @param[in] this_port This is the port on which the phy should be enabled.
+ * @param[in] the_phy This is the specific phy which to enable.
+ * @param[in] do_notify_user This parameter specifies whether to inform
+ *            the user (via scic_cb_port_link_up()) as to the fact that
+ *            a new phy as become ready.
+ * @param[in] do_resume_phy This parameter specifies whether to resume the phy.
+ *            If this function is called from MPC mode, it will be always true.
+ *            for APC, this will be false, so that phys could be resumed later
+ *
+
+ * @return none
+ */
+void scic_sds_port_activate_phy(
+   SCIC_SDS_PORT_T * this_port,
+   SCIC_SDS_PHY_T  * the_phy,
+   BOOL              do_notify_user,
+   BOOL              do_resume_phy
+)
+{
+   SCIC_SDS_CONTROLLER_T                      * controller;
+   SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T   protocols;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_port),
+      SCIC_LOG_OBJECT_PORT,
+      "scic_sds_port_activate_phy(0x%x,0x%x,0x%x) enter\n",
+      this_port, the_phy, do_notify_user
+   ));
+
+   controller = scic_sds_port_get_controller(this_port);
+   scic_sds_phy_get_attached_phy_protocols(the_phy, &protocols);
+
+   // If this is sata port then the phy has already been resumed
+   if (!protocols.u.bits.stp_target)
+   {
+      if (do_resume_phy == TRUE)
+      {
+         scic_sds_port_resume_phy(this_port, the_phy);
+      }
+   }
+
+   this_port->active_phy_mask |= 1 << the_phy->phy_index;
+
+   scic_sds_controller_clear_invalid_phy(controller, the_phy);
+
+   if (do_notify_user == TRUE)
+      scic_cb_port_link_up(this_port->owning_controller, this_port, the_phy);
+}
+
+/**
+ * This method will deactivate the supplied phy in the port.
+ *
+ * @param[in] this_port This is the port on which the phy should be
+ *            deactivated.
+ * @param[in] the_phy This is the specific phy that is no longer
+ *            active in the port.
+ * @param[in] do_notify_user This parameter specifies whether to inform
+ *            the user (via scic_cb_port_link_down()) as to the fact that
+ *            a new phy as become ready.
+ *
+ * @return none
+ */
+void scic_sds_port_deactivate_phy(
+   SCIC_SDS_PORT_T * this_port,
+   SCIC_SDS_PHY_T  * the_phy,
+   BOOL              do_notify_user
+)
+{
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_port),
+      SCIC_LOG_OBJECT_PORT,
+      "scic_sds_port_deactivate_phy(0x%x,0x%x,0x%x) enter\n",
+      this_port, the_phy, do_notify_user
+   ));
+
+   this_port->active_phy_mask &= ~(1 << the_phy->phy_index);
+   this_port->enabled_phy_mask  &= ~(1 << the_phy->phy_index);
+
+   the_phy->max_negotiated_speed = SCI_SAS_NO_LINK_RATE;
+
+   // Re-assign the phy back to the LP as if it were a narrow port for APC mode.
+   // For MPC mode, the phy will remain in the port
+   if (this_port->owning_controller->oem_parameters.sds1.controller.mode_type
+       == SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE)
+   {
+   SCU_PCSPExCR_WRITE(this_port, the_phy->phy_index, the_phy->phy_index);
+   }
+
+   if (do_notify_user == TRUE)
+      scic_cb_port_link_down(this_port->owning_controller, this_port, the_phy);
+}
+
+/**
+ * This method will disable the phy and report that the phy is not valid for this
+ * port object.
+ *
+ * @param[in] this_port This is the port on which the phy should be disabled.
+ * @param[in] the_phy This is the specific phy which to disabled.
+ *
+ * @return None
+ */
+void scic_sds_port_invalid_link_up(
+   SCIC_SDS_PORT_T * this_port,
+   SCIC_SDS_PHY_T  * the_phy
+)
+{
+   SCIC_SDS_CONTROLLER_T * controller = scic_sds_port_get_controller(this_port);
+
+   // Check to see if we have alreay reported this link as bad and if not go
+   // ahead and tell the SCI_USER that we have discovered an invalid link.
+   if ((controller->invalid_phy_mask & (1 << the_phy->phy_index)) == 0)
+   {
+      scic_sds_controller_set_invalid_phy(controller, the_phy);
+
+      scic_cb_port_invalid_link_up(controller, this_port, the_phy);
+   }
+}
+
+/**
+ * @brief This method returns FALSE if the port only has a single phy object
+ *        assigned.  If there are no phys or more than one phy then the
+ *        method will return TRUE.
+ *
+ * @param[in] this_port The port for which the wide port condition is to be
+ *            checked.
+ *
+ * @return BOOL
+ * @retval TRUE Is returned if this is a wide ported port.
+ * @retval FALSE Is returned if this is a narrow port.
+ */
+static
+BOOL scic_sds_port_is_wide(
+   SCIC_SDS_PORT_T *this_port
+)
+{
+   U32 index;
+   U32 phy_count = 0;
+
+   for (index = 0; index < SCI_MAX_PHYS; index++)
+   {
+      if (this_port->phy_table[index] != NULL)
+      {
+         phy_count++;
+      }
+   }
+
+   return (phy_count != 1);
+}
+
+/**
+ * @brief This method is called by the PHY object when the link is detected.
+ *        if the port wants the PHY to continue on to the link up state then
+ *        the port layer must return TRUE.  If the port object returns FALSE
+ *        the phy object must halt its attempt to go link up.
+ *
+ * @param[in] this_port The port associated with the phy object.
+ * @param[in] the_phy The phy object that is trying to go link up.
+ *
+ * @return TRUE if the phy object can continue to the link up condition.
+ * @retval TRUE Is returned if this phy can continue to the ready state.
+ * @retval FALSE Is returned if can not continue on to the ready state.
+ *
+ * @note This notification is in place for wide ports and direct attached
+ *       phys.  Since there are no wide ported SATA devices this could
+ *       become an invalid port configuration.
+ */
+BOOL scic_sds_port_link_detected(
+   SCIC_SDS_PORT_T *this_port,
+   SCIC_SDS_PHY_T  *the_phy
+)
+{
+   SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T protocols;
+
+   scic_sds_phy_get_attached_phy_protocols(the_phy, &protocols);
+
+   if (
+         (this_port->logical_port_index != SCIC_SDS_DUMMY_PORT)
+      && (protocols.u.bits.stp_target)
+      )
+   {
+      if (scic_sds_port_is_wide(this_port))
+      {
+         //direct attached Sata phy cannot be in wide port.
+         scic_sds_port_invalid_link_up( this_port, the_phy);
+      return FALSE;
+   }
+      else
+      {
+         SCIC_SDS_PORT_T *destination_port = &(this_port->owning_controller->port_table[the_phy->phy_index]);
+
+         //add the phy to the its logical port for direct attached SATA. The phy will be added
+         //to port whose port_index will be the phy_index.
+         SCU_PCSPExCR_WRITE( destination_port, the_phy->phy_index, the_phy->phy_index);
+      }
+   }
+
+   return TRUE;
+}
+
+/**
+ * @brief This method is the entry point for the phy to inform
+ *        the port that it is now in a ready state
+ *
+ * @param[in] this_port
+ * @param[in] phy
+ */
+void scic_sds_port_link_up(
+   SCIC_SDS_PORT_T *this_port,
+   SCIC_SDS_PHY_T  *the_phy
+)
+{
+   the_phy->is_in_link_training = FALSE;
+
+   this_port->state_handlers->link_up_handler(this_port, the_phy);
+}
+
+/**
+ * @brief This method is the entry point for the phy to inform
+ *        the port that it is no longer in a ready state
+ *
+ * @param[in] this_port
+ * @param[in] phy
+ */
+void scic_sds_port_link_down(
+   SCIC_SDS_PORT_T *this_port,
+   SCIC_SDS_PHY_T  *the_phy
+)
+{
+   this_port->state_handlers->link_down_handler(this_port, the_phy);
+}
+
+/**
+ * @brief This method is called to start an IO request on this port.
+ *
+ * @param[in] this_port
+ * @param[in] the_device
+ * @param[in] the_io_request
+ *
+ * @return SCI_STATUS
+ */
+SCI_STATUS scic_sds_port_start_io(
+   SCIC_SDS_PORT_T          *this_port,
+   SCIC_SDS_REMOTE_DEVICE_T *the_device,
+   SCIC_SDS_REQUEST_T       *the_io_request
+)
+{
+   return this_port->state_handlers->start_io_handler(
+                                       this_port, the_device, the_io_request);
+}
+
+/**
+ * @brief This method is called to complete an IO request to the port.
+ *
+ * @param[in] this_port
+ * @param[in] the_device
+ * @param[in] the_io_request
+ *
+ * @return SCI_STATUS
+ */
+SCI_STATUS scic_sds_port_complete_io(
+   SCIC_SDS_PORT_T          *this_port,
+   SCIC_SDS_REMOTE_DEVICE_T *the_device,
+   SCIC_SDS_REQUEST_T       *the_io_request
+)
+{
+   return this_port->state_handlers->complete_io_handler(
+                                       this_port, the_device, the_io_request);
+}
+
+/**
+ * @brief This method is provided to timeout requests for port operations.
+ *        Mostly its for the port reset operation.
+ *
+ * @param[in] port This is the parameter or cookie value that is provided
+ *       to the timer construct operation.
+ */
+void scic_sds_port_timeout_handler(
+   void *port
+)
+{
+   U32 current_state;
+   SCIC_SDS_PORT_T * this_port;
+
+   this_port = (SCIC_SDS_PORT_T *)port;
+   current_state = sci_base_state_machine_get_state(
+                           &this_port->parent.state_machine);
+
+   if (current_state == SCI_BASE_PORT_STATE_RESETTING)
+   {
+      // if the port is still in the resetting state then the timeout fired
+      // before the reset completed.
+      sci_base_state_machine_change_state(
+         &this_port->parent.state_machine,
+         SCI_BASE_PORT_STATE_FAILED
+      );
+   }
+   else if (current_state == SCI_BASE_PORT_STATE_STOPPED)
+   {
+      // if the port is stopped then the start request failed
+      // In this case stay in the stopped state.
+      SCIC_LOG_ERROR((
+         sci_base_object_get_logger(this_port),
+         SCIC_LOG_OBJECT_PORT,
+         "SCIC Port 0x%x failed to stop before tiemout.\n",
+         this_port
+      ));
+   }
+   else if (current_state == SCI_BASE_PORT_STATE_STOPPING)
+   {
+      // if the port is still stopping then the stop has not completed
+      scic_cb_port_stop_complete(
+         scic_sds_port_get_controller(this_port),
+         port,
+         SCI_FAILURE_TIMEOUT
+      );
+   }
+   else
+   {
+      // The port is in the ready state and we have a timer reporting a timeout
+      // this should not happen.
+      SCIC_LOG_ERROR((
+         sci_base_object_get_logger(this_port),
+         SCIC_LOG_OBJECT_PORT,
+         "SCIC Port 0x%x is processing a timeout operation in state %d.\n",
+         this_port, current_state
+      ));
+   }
+}
+
+// ---------------------------------------------------------------------------
+
+#ifdef SCIC_DEBUG_ENABLED
+void scic_sds_port_decrement_request_count(
+   SCIC_SDS_PORT_T *this_port
+)
+{
+   if (this_port->started_request_count == 0)
+   {
+      SCIC_LOG_WARNING((
+         sci_base_object_get_logger(this_port),
+         SCIC_LOG_OBJECT_PORT,
+         "SCIC Port object requested to decrement started io count past zero.\n"
+      ));
+   }
+   else
+   {
+      this_port->started_request_count--;
+   }
+}
+#endif
+
+/**
+ * @brief This function updates the hardwares VIIT entry for this port.
+ *
+ * @param[in] this_port
+ */
+void scic_sds_port_update_viit_entry(
+   SCIC_SDS_PORT_T *this_port
+)
+{
+   SCI_SAS_ADDRESS_T sas_address;
+
+   scic_sds_port_get_sas_address(this_port, &sas_address);
+
+   scu_port_viit_register_write(
+      this_port, initiator_sas_address_hi, sas_address.high);
+
+   scu_port_viit_register_write(
+      this_port, initiator_sas_address_lo, sas_address.low);
+
+   // This value get cleared just in case its not already cleared
+   scu_port_viit_register_write(
+      this_port, reserved, 0);
+
+
+   // We are required to update the status register last
+   scu_port_viit_register_write(
+      this_port, status, (
+           SCU_VIIT_ENTRY_ID_VIIT
+         | SCU_VIIT_IPPT_INITIATOR
+         | ((1UL << this_port->physical_port_index) << SCU_VIIT_ENTRY_LPVIE_SHIFT)
+         | SCU_VIIT_STATUS_ALL_VALID
+         )
+   );
+}
+
+/**
+ * @brief This method returns the maximum allowed speed for data transfers
+ *        on this port.  This maximum allowed speed evaluates to the maximum
+ *        speed of the slowest phy in the port.
+ *
+ * @param[in] this_port This parameter specifies the port for which to
+ *            retrieve the maximum allowed speed.
+ *
+ * @return This method returns the maximum negotiated speed of the slowest
+ *         phy in the port.
+ */
+SCI_SAS_LINK_RATE scic_sds_port_get_max_allowed_speed(
+   SCIC_SDS_PORT_T * this_port
+)
+{
+   U16                index             = 0;
+   SCI_SAS_LINK_RATE  max_allowed_speed = SCI_SAS_600_GB;
+   SCIC_SDS_PHY_T   * phy               = NULL;
+
+   // Loop through all of the phys in this port and find the phy with the
+   // lowest maximum link rate.
+   for (index = 0; index < SCI_MAX_PHYS; index++)
+   {
+      phy = this_port->phy_table[index];
+      if (
+            (phy != NULL)
+         && (scic_sds_port_active_phy(this_port, phy) == TRUE)
+         && (phy->max_negotiated_speed < max_allowed_speed)
+         )
+         max_allowed_speed = phy->max_negotiated_speed;
+   }
+
+   return max_allowed_speed;
+}
+
+
+/**
+ * @brief This method passes the event to core user.
+ * @param[in] this_port The port that a BCN happens.
+ * @param[in] this_phy  The phy that receives BCN.
+ *
+ * @return none
+ */
+void scic_sds_port_broadcast_change_received(
+   SCIC_SDS_PORT_T * this_port,
+   SCIC_SDS_PHY_T * this_phy
+)
+{
+   //notify the user.
+   scic_cb_port_bc_change_primitive_recieved(
+      this_port->owning_controller, this_port, this_phy
+   );
+}
+
+
+/**
+ * @brief This API methhod enables the broadcast change notification from
+ *        underneath hardware.
+ * @param[in] this_port The port that a BCN had been disabled from.
+ *
+ * @return none
+ */
+void scic_port_enable_broadcast_change_notification(
+   SCI_PORT_HANDLE_T  port
+)
+{
+   SCIC_SDS_PORT_T * this_port = (SCIC_SDS_PORT_T *)port;
+   SCIC_SDS_PHY_T * phy;
+   U32 register_value;
+   U8 index;
+
+   // Loop through all of the phys to enable BCN.
+   for (index = 0; index < SCI_MAX_PHYS; index++)
+   {
+      phy = this_port->phy_table[index];
+      if ( phy != NULL)
+      {
+         register_value = SCU_SAS_LLCTL_READ(phy);
+
+         // clear the bit by writing 1.
+         SCU_SAS_LLCTL_WRITE(phy, register_value);
+      }
+   }
+}
+
+/**
+ * @brief This method release resources in for a scic port.
+ *
+ * @param[in] controller This parameter specifies the core controller, one of
+ *            its phy's resources are to be released.
+ * @param[in] this_port This parameter specifies the port whose resourse is to
+ *            be released.
+ */
+void scic_sds_port_release_resource(
+   SCIC_SDS_CONTROLLER_T * controller,
+   SCIC_SDS_PORT_T *this_port
+)
+{
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_port),
+      SCIC_LOG_OBJECT_PORT,
+      "scic_sds_port_release_resource(0x%x, 0x%x)\n",
+      controller, this_port
+   ));
+
+   //Currently, the only resource to be released is a timer.
+   if (this_port->timer_handle != NULL)
+   {
+      scic_cb_timer_destroy(controller, this_port->timer_handle);
+      this_port->timer_handle = NULL;
+   }
+}
+
+
+//******************************************************************************
+//* PORT STATE MACHINE
+//******************************************************************************
+
+//***************************************************************************
+//*  DEFAULT HANDLERS
+//***************************************************************************
+
+/**
+ * This is the default method for port a start request.  It will report a
+ * warning and exit.
+ *
+ * @param[in] port This is the SCI_BASE_PORT object which is cast into a
+ *       SCIC_SDS_PORT object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+SCI_STATUS scic_sds_port_default_start_handler(
+   SCI_BASE_PORT_T *port
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger((SCIC_SDS_PORT_T *)port),
+      SCIC_LOG_OBJECT_PORT,
+      "SCIC Port 0x%08x requested to start while in invalid state %d\n",
+      port,
+      sci_base_state_machine_get_state(
+         scic_sds_port_get_base_state_machine((SCIC_SDS_PORT_T *)port))
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * This is the default method for a port stop request.  It will report a
+ * warning and exit.
+ *
+ * @param[in] port This is the SCI_BASE_PORT object which is cast into a
+ *       SCIC_SDS_PORT object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+SCI_STATUS scic_sds_port_default_stop_handler(
+   SCI_BASE_PORT_T *port
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger((SCIC_SDS_PORT_T *)port),
+      SCIC_LOG_OBJECT_PORT,
+      "SCIC Port 0x%08x requested to stop while in invalid state %d\n",
+      port,
+      sci_base_state_machine_get_state(
+         scic_sds_port_get_base_state_machine((SCIC_SDS_PORT_T *)port))
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * This is the default method for a port destruct request.  It will report a
+ * warning and exit.
+ *
+ * @param[in] port This is the SCI_BASE_PORT object which is cast into a
+ *       SCIC_SDS_PORT object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+SCI_STATUS scic_sds_port_default_destruct_handler(
+   SCI_BASE_PORT_T *port
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger((SCIC_SDS_PORT_T *)port),
+      SCIC_LOG_OBJECT_PORT,
+      "SCIC Port 0x%08x requested to destruct while in invalid state %d\n",
+      port,
+      sci_base_state_machine_get_state(
+         scic_sds_port_get_base_state_machine((SCIC_SDS_PORT_T *)port))
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * This is the default method for a port reset request.  It will report a
+ * warning and exit.
+ *
+ * @param[in] port This is the SCI_BASE_PORT object which is cast into a
+ *       SCIC_SDS_PORT object.
+ * @param[in] timeout This is the timeout for the reset request to complete.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+SCI_STATUS scic_sds_port_default_reset_handler(
+   SCI_BASE_PORT_T * port,
+   U32               timeout
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger((SCIC_SDS_PORT_T *)port),
+      SCIC_LOG_OBJECT_PORT,
+      "SCIC Port 0x%08x requested to reset while in invalid state %d\n",
+      port,
+      sci_base_state_machine_get_state(
+         scic_sds_port_get_base_state_machine((SCIC_SDS_PORT_T *)port))
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * This is the default method for a port add phy request.  It will report a
+ * warning and exit.
+ *
+ * @param[in] port This is the SCI_BASE_PORT object which is cast into a
+ *       SCIC_SDS_PORT object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+SCI_STATUS scic_sds_port_default_add_phy_handler(
+   SCI_BASE_PORT_T *port,
+   SCI_BASE_PHY_T  *phy
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger((SCIC_SDS_PORT_T *)port),
+      SCIC_LOG_OBJECT_PORT,
+      "SCIC Port 0x%08x requested to add phy 0x%08x while in invalid state %d\n",
+      port, phy,
+      sci_base_state_machine_get_state(
+         scic_sds_port_get_base_state_machine((SCIC_SDS_PORT_T *)port))
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * This is the default method for a port remove phy request.  It will report a
+ * warning and exit.
+ *
+ * @param[in] port This is the SCI_BASE_PORT object which is cast into a
+ *       SCIC_SDS_PORT object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+SCI_STATUS scic_sds_port_default_remove_phy_handler(
+   SCI_BASE_PORT_T *port,
+   SCI_BASE_PHY_T  *phy
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger((SCIC_SDS_PORT_T *)port),
+      SCIC_LOG_OBJECT_PORT,
+      "SCIC Port 0x%08x requested to remove phy 0x%08x while in invalid state %d\n",
+      port, phy,
+      sci_base_state_machine_get_state(
+         scic_sds_port_get_base_state_machine((SCIC_SDS_PORT_T *)port))
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * This is the default method for a port unsolicited frame request.  It will
+ * report a warning and exit.
+ *
+ * @param[in] port This is the SCI_BASE_PORT object which is cast into a
+ *       SCIC_SDS_PORT object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ *
+ * @todo Is it even possible to receive an unsolicited frame directed to a
+ *       port object?  It seems possible if we implementing virtual functions
+ *       but until then?
+ */
+SCI_STATUS scic_sds_port_default_frame_handler(
+   SCIC_SDS_PORT_T * port,
+   U32               frame_index
+)
+{
+   SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)port;
+
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger(this_port),
+      SCIC_LOG_OBJECT_PORT,
+      "SCIC Port 0x%08x requested to process frame %d while in invalid state %d\n",
+      port, frame_index,
+      sci_base_state_machine_get_state(
+         scic_sds_port_get_base_state_machine(this_port))
+   ));
+
+   scic_sds_controller_release_frame(
+      scic_sds_port_get_controller(this_port), frame_index
+   );
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * This is the default method for a port event request.  It will report a
+ * warning and exit.
+ *
+ * @param[in] port This is the SCI_BASE_PORT object which is cast into a
+ *       SCIC_SDS_PORT object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+SCI_STATUS scic_sds_port_default_event_handler(
+   SCIC_SDS_PORT_T * port,
+   U32               event_code
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger((SCIC_SDS_PORT_T *)port),
+      SCIC_LOG_OBJECT_PORT,
+      "SCIC Port 0x%08x requested to process event 0x%08x while in invalid state %d\n",
+      port, event_code,
+      sci_base_state_machine_get_state(
+         scic_sds_port_get_base_state_machine((SCIC_SDS_PORT_T *)port))
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * This is the default method for a port link up notification.  It will report
+ * a warning and exit.
+ *
+ * @param[in] port This is the SCI_BASE_PORT object which is cast into a
+ *       SCIC_SDS_PORT object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+void scic_sds_port_default_link_up_handler(
+   SCIC_SDS_PORT_T *this_port,
+   SCIC_SDS_PHY_T  *phy
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger(this_port),
+      SCIC_LOG_OBJECT_PORT,
+      "SCIC Port 0x%08x received link_up notification from phy 0x%08x while in invalid state %d\n",
+      this_port, phy,
+      sci_base_state_machine_get_state(
+         scic_sds_port_get_base_state_machine(this_port))
+   ));
+}
+
+/**
+ * This is the default method for a port link down notification.  It will
+ * report a warning and exit.
+ *
+ * @param[in] port This is the SCI_BASE_PORT object which is cast into a
+ *       SCIC_SDS_PORT object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+void scic_sds_port_default_link_down_handler(
+   SCIC_SDS_PORT_T *this_port,
+   SCIC_SDS_PHY_T  *phy
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger(this_port),
+      SCIC_LOG_OBJECT_PORT,
+      "SCIC Port 0x%08x received link down notification from phy 0x%08x while in invalid state %d\n",
+      this_port, phy,
+      sci_base_state_machine_get_state(
+         scic_sds_port_get_base_state_machine(this_port))
+   ));
+}
+
+/**
+ * This is the default method for a port start io request.  It will report a
+ * warning and exit.
+ *
+ * @param[in] port This is the SCI_BASE_PORT object which is cast into a
+ *       SCIC_SDS_PORT object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+SCI_STATUS scic_sds_port_default_start_io_handler(
+   SCIC_SDS_PORT_T          *this_port,
+   SCIC_SDS_REMOTE_DEVICE_T *device,
+   SCIC_SDS_REQUEST_T       *io_request
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger(this_port),
+      SCIC_LOG_OBJECT_PORT,
+      "SCIC Port 0x%08x requested to start io request 0x%08x while in invalid state %d\n",
+      this_port, io_request,
+      sci_base_state_machine_get_state(
+         scic_sds_port_get_base_state_machine(this_port))
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * This is the default method for a port complete io request.  It will report
+ * a warning and exit.
+ *
+ * @param[in] port This is the SCI_BASE_PORT object which is cast into a
+ *       SCIC_SDS_PORT object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+SCI_STATUS scic_sds_port_default_complete_io_handler(
+   SCIC_SDS_PORT_T          *this_port,
+   SCIC_SDS_REMOTE_DEVICE_T *device,
+   SCIC_SDS_REQUEST_T       *io_request
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger(this_port),
+      SCIC_LOG_OBJECT_PORT,
+      "SCIC Port 0x%08x requested to complete io request 0x%08x while in invalid state %d\n",
+      this_port, io_request,
+      sci_base_state_machine_get_state(
+         scic_sds_port_get_base_state_machine(this_port))
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+//****************************************************************************
+//* GENERAL STATE HANDLERS
+//****************************************************************************
+
+/**
+ * This is a general complete io request handler for the SCIC_SDS_PORT object.
+ *
+ * @param[in] port This is the SCIC_SDS_PORT object on which the io request
+ *       count will be decremented.
+ * @param[in] device This is the SCIC_SDS_REMOTE_DEVICE object to which the io
+ *       request is being directed.  This parameter is not required to
+ *       complete this operation.
+ * @param[in] io_request This is the request that is being completed on this
+ *       port object.  This parameter is not required to complete this
+ *       operation.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS
+ */
+static
+SCI_STATUS scic_sds_port_general_complete_io_handler(
+   SCIC_SDS_PORT_T          *port,
+   SCIC_SDS_REMOTE_DEVICE_T *device,
+   SCIC_SDS_REQUEST_T       *io_request
+)
+{
+   SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)port;
+
+   scic_sds_port_decrement_request_count(this_port);
+
+   return SCI_SUCCESS;
+}
+
+//****************************************************************************
+//* STOPPED STATE HANDLERS
+//****************************************************************************
+static
+BOOL scic_sds_port_requires_scheduler_workaround(
+   SCIC_SDS_PORT_T * this_port
+)
+{
+   if (
+         (
+           this_port->owning_controller->logical_port_entries
+         < this_port->owning_controller->task_context_entries
+         )
+      && (
+           this_port->owning_controller->logical_port_entries
+         < this_port->owning_controller->remote_node_entries
+         )
+      )
+   {
+      return TRUE;
+   }
+
+   return FALSE;
+}
+
+
+/**
+ * This method takes the SCIC_SDS_PORT from a stopped state and attempts to
+ * start it.  To start a port it must have no assiged devices and it must have
+ * at least one phy assigned to it.  If those conditions are met then the port
+ * can transition to the ready state.
+ *
+ * @param[in] port This is the SCI_BASE_PORT object which is cast into a
+ *       SCIC_SDS_PORT object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION This SCIC_SDS_PORT
+ *         object could not be started because the port configuration is not
+ *         valid.
+ * @retval SCI_SUCCESS the start request is successful and the SCIC_SDS_PORT
+ *         object has transitioned to the SCI_BASE_PORT_STATE_READY.
+ */
+static
+SCI_STATUS scic_sds_port_stopped_state_start_handler(
+   SCI_BASE_PORT_T *port
+)
+{
+   U32 phy_mask;
+   SCI_STATUS status = SCI_SUCCESS;
+   SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)port;
+
+   if (this_port->assigned_device_count > 0)
+   {
+      /// @todo This is a start failure operation because there are still
+      ///       devices assigned to this port.  There must be no devices
+      ///       assigned to a port on a start operation.
+      return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
+   }
+
+   this_port->timer_handle = scic_cb_timer_create(
+      scic_sds_port_get_controller(this_port),
+      scic_sds_port_timeout_handler,
+      this_port
+   );
+
+   if (this_port->timer_handle == SCI_INVALID_HANDLE)
+   {
+      return SCI_FAILURE_INSUFFICIENT_RESOURCES;
+   }
+
+   if (scic_sds_port_requires_scheduler_workaround(this_port))
+   {
+   if (this_port->reserved_rni == SCU_DUMMY_INDEX)
+   {
+      this_port->reserved_rni =
+         scic_sds_remote_node_table_allocate_remote_node(
+            &this_port->owning_controller->available_remote_nodes, 1
+         );
+
+      if (this_port->reserved_rni != SCU_DUMMY_INDEX)
+      {
+         scic_sds_port_construct_dummy_rnc(
+            this_port,
+            this_port->reserved_rni
+         );
+      }
+      else
+      {
+         status = SCI_FAILURE_INSUFFICIENT_RESOURCES;
+      }
+   }
+
+   if (this_port->reserved_tci == SCU_DUMMY_INDEX)
+   {
+      // Allocate a TCI and remove the sequence nibble
+      this_port->reserved_tci =
+         scic_controller_allocate_io_tag(this_port->owning_controller);
+
+      if (this_port->reserved_tci != SCU_DUMMY_INDEX)
+      {
+         scic_sds_port_construct_dummy_task(this_port, this_port->reserved_tci);
+      }
+      else
+      {
+         status = SCI_FAILURE_INSUFFICIENT_RESOURCES;
+      }
+   }
+   }
+
+   if (status == SCI_SUCCESS)
+   {
+      phy_mask = scic_sds_port_get_phys(this_port);
+
+      // There are one or more phys assigned to this port.  Make sure
+      // the port's phy mask is in fact legal and supported by the
+      // silicon.
+      if (scic_sds_port_is_phy_mask_valid(this_port, phy_mask) == TRUE)
+      {
+         sci_base_state_machine_change_state(
+            scic_sds_port_get_base_state_machine(this_port),
+            SCI_BASE_PORT_STATE_READY
+         );
+      }
+      else
+      {
+         status = SCI_FAILURE;
+      }
+   }
+
+   if (status != SCI_SUCCESS)
+   {
+      scic_sds_port_destroy_dummy_resources(this_port);
+   }
+
+   return status;
+}
+
+/**
+ * This method takes the SCIC_SDS_PORT that is in a stopped state and handles
+ * a stop request.  This function takes no action.
+ *
+ * @param[in] port This is the SCI_BASE_PORT object which is cast into a
+ *       SCIC_SDS_PORT object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS the stop request is successful as the SCIC_SDS_PORT
+ *         object is already stopped.
+ */
+static
+SCI_STATUS scic_sds_port_stopped_state_stop_handler(
+   SCI_BASE_PORT_T *port
+)
+{
+   // We are already stopped so there is nothing to do here
+   return SCI_SUCCESS;
+}
+
+/**
+ * This method takes the SCIC_SDS_PORT that is in a stopped state and handles
+ * the destruct request.  The stopped state is the only state in which the
+ * SCIC_SDS_PORT can be destroyed.  This function causes the port object to
+ * transition to the SCI_BASE_PORT_STATE_FINAL.
+ *
+ * @param[in] port This is the SCI_BASE_PORT object which is cast into a
+ *       SCIC_SDS_PORT object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS
+ */
+static
+SCI_STATUS scic_sds_port_stopped_state_destruct_handler(
+   SCI_BASE_PORT_T *port
+)
+{
+   SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)port;
+
+   sci_base_state_machine_stop(&this_port->parent.state_machine);
+
+   return SCI_SUCCESS;
+}
+
+/**
+ * This method takes the SCIC_SDS_PORT that is in a stopped state and handles
+ * the add phy request.  In MPC mode the only time a phy can be added to a
+ * port is in the SCI_BASE_PORT_STATE_STOPPED.
+ *
+ * @param[in] port This is the SCI_BASE_PORT object which is cast into a
+ *       SCIC_SDS_PORT object.
+ * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
+ *       SCIC_SDS_PHY object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION is returned when the phy
+ *         can not be added to the port.
+ * @retval SCI_SUCCESS if the phy is added to the port.
+ */
+static
+SCI_STATUS scic_sds_port_stopped_state_add_phy_handler(
+   SCI_BASE_PORT_T *port,
+   SCI_BASE_PHY_T  *phy
+)
+{
+   SCIC_SDS_PORT_T * this_port = (SCIC_SDS_PORT_T *)port;
+   SCIC_SDS_PHY_T  * this_phy  = (SCIC_SDS_PHY_T  *)phy;
+   SCI_SAS_ADDRESS_T port_sas_address;
+
+   // Read the port assigned SAS Address if there is one
+   scic_sds_port_get_sas_address(this_port, &port_sas_address);
+
+   if (port_sas_address.high != 0 && port_sas_address.low != 0)
+   {
+      SCI_SAS_ADDRESS_T phy_sas_address;
+
+      // Make sure that the PHY SAS Address matches the SAS Address
+      // for this port.
+      scic_sds_phy_get_sas_address(this_phy, &phy_sas_address);
+
+      if (
+            (port_sas_address.high != phy_sas_address.high)
+         || (port_sas_address.low  != phy_sas_address.low)
+         )
+      {
+         return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
+      }
+   }
+
+   return scic_sds_port_set_phy(this_port, this_phy);
+}
+
+
+/**
+ * This method takes the SCIC_SDS_PORT that is in a stopped state and handles
+ * the remove phy request.  In MPC mode the only time a phy can be removed
+ * from a port is in the SCI_BASE_PORT_STATE_STOPPED.
+ *
+ * @param[in] port This is the SCI_BASE_PORT object which is cast into a
+ *       SCIC_SDS_PORT object.
+ * @param[in] phy This is the SCI_BASE_PHY object which is cast into a
+ *       SCIC_SDS_PHY object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION is returned when the phy
+ *         can not be added to the port.
+ * @retval SCI_SUCCESS if the phy is added to the port.
+ */
+static
+SCI_STATUS scic_sds_port_stopped_state_remove_phy_handler(
+   SCI_BASE_PORT_T *port,
+   SCI_BASE_PHY_T  *phy
+)
+{
+   SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)port;
+   SCIC_SDS_PHY_T  *this_phy  = (SCIC_SDS_PHY_T  *)phy;
+
+   return scic_sds_port_clear_phy(this_port, this_phy);
+}
+
+//****************************************************************************
+//*  READY STATE HANDLERS
+//****************************************************************************
+
+//****************************************************************************
+//*  RESETTING STATE HANDLERS
+//****************************************************************************
+
+//****************************************************************************
+//*  STOPPING STATE HANDLERS
+//****************************************************************************
+
+/**
+ * This method takes the SCIC_SDS_PORT that is in a stopping state and handles
+ * the complete io request. Should the request count reach 0 then the port
+ * object will transition to the stopped state.
+ *
+ * @param[in] port This is the SCIC_SDS_PORT object on which the io request
+ *       count will be decremented.
+ * @param[in] device This is the SCIC_SDS_REMOTE_DEVICE object to which the io
+ *       request is being directed.  This parameter is not required to
+ *       complete this operation.
+ * @param[in] io_request This is the request that is being completed on this
+ *       port object.  This parameter is not required to complete this
+ *       operation.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS
+ */
+static
+SCI_STATUS scic_sds_port_stopping_state_complete_io_handler(
+   SCIC_SDS_PORT_T          *port,
+   SCIC_SDS_REMOTE_DEVICE_T *device,
+   SCIC_SDS_REQUEST_T       *io_request
+)
+{
+   SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)port;
+
+   scic_sds_port_decrement_request_count(this_port);
+
+   if (this_port->started_request_count == 0)
+   {
+      sci_base_state_machine_change_state(
+         scic_sds_port_get_base_state_machine(this_port),
+         SCI_BASE_PORT_STATE_STOPPED
+      );
+   }
+
+   return SCI_SUCCESS;
+}
+
+//****************************************************************************
+//*  RESETTING STATE HANDLERS
+//****************************************************************************
+
+/**
+ * This method will stop a failed port.  This causes a transition to the
+ * stopping state.
+ *
+ * @param[in] port This is the port object which is being requested to stop.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS
+ */
+static
+SCI_STATUS scic_sds_port_reset_state_stop_handler(
+   SCI_BASE_PORT_T *port
+)
+{
+   SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)port;
+
+   sci_base_state_machine_change_state(
+      &this_port->parent.state_machine,
+      SCI_BASE_PORT_STATE_STOPPING
+   );
+
+   return SCI_SUCCESS;
+}
+
+/**
+ * This method will transition a failed port to its ready state.  The port
+ * failed because a hard reset request timed out but at some time later one or
+ * more phys in the port became ready.
+ *
+ * @param[in] port This is the SCI_BASE_PORT object which is cast into a
+ *       SCIC_SDS_PORT object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS
+ */
+static
+void scic_sds_port_reset_state_link_up_handler(
+   SCIC_SDS_PORT_T *this_port,
+   SCIC_SDS_PHY_T  *phy
+)
+{
+   /// @todo We should make sure that the phy that has gone link up is the same
+   ///       one on which we sent the reset.  It is possible that the phy on
+   ///       which we sent the reset is not the one that has gone link up and we
+   ///       want to make sure that phy being reset comes back.  Consider the
+   ///       case where a reset is sent but before the hardware processes the
+   ///       reset it get a link up on the port because of a hot plug event.
+   ///       because of the reset request this phy will go link down almost
+   ///       immediately.
+
+   // In the resetting state we don't notify the user regarding
+   // link up and link down notifications.
+   scic_sds_port_general_link_up_handler(this_port, phy, FALSE, TRUE);
+}
+
+/**
+ * This method process link down notifications that occur during a
+ * port reset operation. Link downs can occur during the reset operation.
+ *
+ * @param[in] port This is the SCI_BASE_PORT object which is cast into a
+ *       SCIC_SDS_PORT object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS
+ */
+static
+void scic_sds_port_reset_state_link_down_handler(
+   SCIC_SDS_PORT_T *this_port,
+   SCIC_SDS_PHY_T  *phy
+)
+{
+   // In the resetting state we don't notify the user regarding
+   // link up and link down notifications.
+   scic_sds_port_deactivate_phy(this_port, phy, FALSE);
+}
+
+// ---------------------------------------------------------------------------
+
+SCIC_SDS_PORT_STATE_HANDLER_T
+   scic_sds_port_state_handler_table[SCI_BASE_PORT_MAX_STATES] =
+{
+   // SCI_BASE_PORT_STATE_STOPPED
+   {
+      {
+         scic_sds_port_stopped_state_start_handler,
+         scic_sds_port_stopped_state_stop_handler,
+         scic_sds_port_stopped_state_destruct_handler,
+         scic_sds_port_default_reset_handler,
+         scic_sds_port_stopped_state_add_phy_handler,
+         scic_sds_port_stopped_state_remove_phy_handler
+      },
+      scic_sds_port_default_frame_handler,
+      scic_sds_port_default_event_handler,
+      scic_sds_port_default_link_up_handler,
+      scic_sds_port_default_link_down_handler,
+      scic_sds_port_default_start_io_handler,
+      scic_sds_port_default_complete_io_handler
+   },
+   // SCI_BASE_PORT_STATE_STOPPING
+   {
+      {
+         scic_sds_port_default_start_handler,
+         scic_sds_port_default_stop_handler,
+         scic_sds_port_default_destruct_handler,
+         scic_sds_port_default_reset_handler,
+         scic_sds_port_default_add_phy_handler,
+         scic_sds_port_default_remove_phy_handler
+      },
+      scic_sds_port_default_frame_handler,
+      scic_sds_port_default_event_handler,
+      scic_sds_port_default_link_up_handler,
+      scic_sds_port_default_link_down_handler,
+      scic_sds_port_default_start_io_handler,
+      scic_sds_port_stopping_state_complete_io_handler
+   },
+   // SCI_BASE_PORT_STATE_READY
+   {
+      {
+         scic_sds_port_default_start_handler,
+         scic_sds_port_default_stop_handler,
+         scic_sds_port_default_destruct_handler,
+         scic_sds_port_default_reset_handler,
+         scic_sds_port_default_add_phy_handler,
+         scic_sds_port_default_remove_phy_handler
+      },
+      scic_sds_port_default_frame_handler,
+      scic_sds_port_default_event_handler,
+      scic_sds_port_default_link_up_handler,
+      scic_sds_port_default_link_down_handler,
+      scic_sds_port_default_start_io_handler,
+      scic_sds_port_general_complete_io_handler
+   },
+   // SCI_BASE_PORT_STATE_RESETTING
+   {
+      {
+         scic_sds_port_default_start_handler,
+         scic_sds_port_reset_state_stop_handler,
+         scic_sds_port_default_destruct_handler,
+         scic_sds_port_default_reset_handler,
+         scic_sds_port_default_add_phy_handler,
+         scic_sds_port_default_remove_phy_handler
+      },
+      scic_sds_port_default_frame_handler,
+      scic_sds_port_default_event_handler,
+      scic_sds_port_reset_state_link_up_handler,
+      scic_sds_port_reset_state_link_down_handler,
+      scic_sds_port_default_start_io_handler,
+      scic_sds_port_general_complete_io_handler
+   },
+   // SCI_BASE_PORT_STATE_FAILED
+   {
+      {
+         scic_sds_port_default_start_handler,
+         scic_sds_port_default_stop_handler,
+         scic_sds_port_default_destruct_handler,
+         scic_sds_port_default_reset_handler,
+         scic_sds_port_default_add_phy_handler,
+         scic_sds_port_default_remove_phy_handler
+      },
+      scic_sds_port_default_frame_handler,
+      scic_sds_port_default_event_handler,
+      scic_sds_port_default_link_up_handler,
+      scic_sds_port_default_link_down_handler,
+      scic_sds_port_default_start_io_handler,
+      scic_sds_port_general_complete_io_handler
+   }
+};
+
+//******************************************************************************
+//*  PORT STATE PRIVATE METHODS
+//******************************************************************************
+
+/**
+ * This method will enable the SCU Port Task Scheduler for this port object
+ * but will leave the port task scheduler in a suspended state.
+ *
+ * @param[in] this_port This is the port object which to suspend.
+ *
+ * @return none
+ */
+static
+void scic_sds_port_enable_port_task_scheduler(
+   SCIC_SDS_PORT_T *this_port
+)
+{
+   U32 pts_control_value;
+
+   pts_control_value = scu_port_task_scheduler_read(this_port, control);
+
+   pts_control_value |= SCU_PTSxCR_GEN_BIT(ENABLE) | SCU_PTSxCR_GEN_BIT(SUSPEND);
+
+   scu_port_task_scheduler_write(this_port, control, pts_control_value);
+}
+
+/**
+ * This method will disable the SCU port task scheduler for this port
+ * object.
+ *
+ * @param[in] this_port This is the port object which to resume.
+ *
+ * @return none
+ */
+static
+void scic_sds_port_disable_port_task_scheduler(
+   SCIC_SDS_PORT_T *this_port
+)
+{
+   U32 pts_control_value;
+
+   pts_control_value = scu_port_task_scheduler_read(this_port, control);
+
+   pts_control_value &= ~(   SCU_PTSxCR_GEN_BIT(ENABLE)
+                           | SCU_PTSxCR_GEN_BIT(SUSPEND) );
+
+   scu_port_task_scheduler_write(this_port, control, pts_control_value);
+}
+
+/**
+ *
+ */
+static
+void scic_sds_port_post_dummy_remote_node(
+      SCIC_SDS_PORT_T *this_port
+)
+{
+   U32 command;
+   SCU_REMOTE_NODE_CONTEXT_T * rnc;
+
+   if (this_port->reserved_rni != SCU_DUMMY_INDEX)
+   {
+   rnc = &(this_port->owning_controller->remote_node_context_table[this_port->reserved_rni]);
+
+   rnc->ssp.is_valid = TRUE;
+
+   command = (
+       (SCU_CONTEXT_COMMAND_POST_RNC_32)
+     | (this_port->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT)
+     | (this_port->reserved_rni)
+   );
+
+   scic_sds_controller_post_request(this_port->owning_controller, command);
+
+   scic_cb_stall_execution(10);
+
+   command = (
+       (SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX_RX)
+     | (this_port->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT)
+     | (this_port->reserved_rni)
+   );
+
+   scic_sds_controller_post_request(this_port->owning_controller, command);
+}
+}
+
+/**
+ *
+ */
+static
+void scic_sds_port_invalidate_dummy_remote_node(
+   SCIC_SDS_PORT_T *this_port
+)
+{
+   U32 command;
+   SCU_REMOTE_NODE_CONTEXT_T * rnc;
+
+   if (this_port->reserved_rni != SCU_DUMMY_INDEX)
+   {
+   rnc = &(this_port->owning_controller->remote_node_context_table[this_port->reserved_rni]);
+
+   rnc->ssp.is_valid = FALSE;
+
+   scic_cb_stall_execution(10);
+
+   command = (
+       (SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE)
+     | (this_port->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT)
+     | (this_port->reserved_rni)
+   );
+
+   scic_sds_controller_post_request(this_port->owning_controller, command);
+}
+}
+
+//******************************************************************************
+//*  PORT STATE METHODS
+//******************************************************************************
+
+/**
+ * This method will perform the actions required by the SCIC_SDS_PORT on
+ * entering the SCI_BASE_PORT_STATE_STOPPED. This function sets the stopped
+ * state handlers for the SCIC_SDS_PORT object and disables the port task
+ * scheduler in the hardware.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_PORT object.
+ *
+ * @return none
+ */
+static
+void scic_sds_port_stopped_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_PORT_T *this_port;
+   this_port = (SCIC_SDS_PORT_T *)object;
+
+   scic_sds_port_set_base_state_handlers(
+      this_port, SCI_BASE_PORT_STATE_STOPPED
+   );
+
+   if (
+         SCI_BASE_PORT_STATE_STOPPING
+      == this_port->parent.state_machine.previous_state_id
+      )
+   {
+      // If we enter this state becasuse of a request to stop
+      // the port then we want to disable the hardwares port
+      // task scheduler.
+      scic_sds_port_disable_port_task_scheduler(this_port);
+   }
+}
+
+/**
+ * This method will perform the actions required by the SCIC_SDS_PORT on
+ * exiting the SCI_BASE_STATE_STOPPED. This function enables the SCU hardware
+ * port task scheduler.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_PORT object.
+ *
+ * @return none
+ */
+static
+void scic_sds_port_stopped_state_exit(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_PORT_T *this_port;
+   this_port = (SCIC_SDS_PORT_T *)object;
+
+   // Enable and suspend the port task scheduler
+   scic_sds_port_enable_port_task_scheduler(this_port);
+}
+
+/**
+ * This method will perform the actions required by the SCIC_SDS_PORT on
+ * entering the SCI_BASE_PORT_STATE_READY. This function sets the ready state
+ * handlers for the SCIC_SDS_PORT object, reports the port object as not ready
+ * and starts the ready substate machine.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_PORT object.
+ *
+ * @return none
+ */
+static
+void scic_sds_port_ready_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_PORT_T *this_port;
+   this_port = (SCIC_SDS_PORT_T *)object;
+
+   // Put the ready state handlers in place though they will not be there long
+   scic_sds_port_set_base_state_handlers(
+      this_port, SCI_BASE_PORT_STATE_READY
+   );
+
+   if (
+          SCI_BASE_PORT_STATE_RESETTING
+      == this_port->parent.state_machine.previous_state_id
+      )
+   {
+      scic_cb_port_hard_reset_complete(
+         scic_sds_port_get_controller(this_port),
+         this_port,
+         SCI_SUCCESS
+      );
+   }
+   else
+   {
+      // Notify the caller that the port is not yet ready
+      scic_cb_port_not_ready(
+         scic_sds_port_get_controller(this_port),
+         this_port,
+         SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS
+      );
+   }
+
+   // Post and suspend the dummy remote node context for this
+   // port.
+   scic_sds_port_post_dummy_remote_node(this_port);
+
+   // Start the ready substate machine
+   sci_base_state_machine_start(
+      scic_sds_port_get_ready_substate_machine(this_port)
+   );
+}
+
+/**
+ * This method will perform the actions required by the SCIC_SDS_PORT on
+ * exiting the SCI_BASE_STATE_READY. This function does nothing.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_PORT object.
+ *
+ * @return none
+ */
+static
+void scic_sds_port_ready_state_exit(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_PORT_T *this_port;
+   this_port = (SCIC_SDS_PORT_T *)object;
+
+   sci_base_state_machine_stop(&this_port->ready_substate_machine);
+
+   scic_cb_stall_execution(10);
+   scic_sds_port_invalidate_dummy_remote_node(this_port);
+}
+
+/**
+ * This method will perform the actions required by the SCIC_SDS_PORT on
+ * entering the SCI_BASE_PORT_STATE_RESETTING. This function sets the
+ * resetting state handlers for the SCIC_SDS_PORT object.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_PORT object.
+ *
+ * @return none
+ */
+static
+void scic_sds_port_resetting_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_PORT_T *this_port;
+   this_port = (SCIC_SDS_PORT_T *)object;
+
+   scic_sds_port_set_base_state_handlers(
+      this_port, SCI_BASE_PORT_STATE_RESETTING
+   );
+}
+
+/**
+ * This method will perform the actions required by the SCIC_SDS_PORT on
+ * exiting the SCI_BASE_STATE_RESETTING. This function does nothing.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_PORT object.
+ *
+ * @return none
+ */
+static
+void scic_sds_port_resetting_state_exit(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_PORT_T *this_port;
+   this_port = (SCIC_SDS_PORT_T *)object;
+
+   scic_cb_timer_stop(
+      scic_sds_port_get_controller(this_port),
+      this_port->timer_handle
+   );
+}
+
+/**
+ * This method will perform the actions required by the SCIC_SDS_PORT on
+ * entering the SCI_BASE_PORT_STATE_STOPPING. This function sets the stopping
+ * state handlers for the SCIC_SDS_PORT object.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_PORT object.
+ *
+ * @return none
+ */
+static
+void scic_sds_port_stopping_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_PORT_T *this_port;
+   this_port = (SCIC_SDS_PORT_T *)object;
+
+   scic_sds_port_set_base_state_handlers(
+      this_port, SCI_BASE_PORT_STATE_STOPPING
+   );
+
+   if (this_port->started_request_count == 0)
+   {
+      sci_base_state_machine_change_state(
+         &this_port->parent.state_machine,
+         SCI_BASE_PORT_STATE_STOPPED
+      );
+   }
+}
+
+/**
+ * This method will perform the actions required by the SCIC_SDS_PORT on
+ * exiting the SCI_BASE_STATE_STOPPING. This function does nothing.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_PORT object.
+ *
+ * @return none
+ */
+static
+void scic_sds_port_stopping_state_exit(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_PORT_T *this_port;
+   this_port = (SCIC_SDS_PORT_T *)object;
+
+   scic_cb_timer_stop(
+      scic_sds_port_get_controller(this_port),
+      this_port->timer_handle
+   );
+
+   scic_cb_timer_destroy(
+      scic_sds_port_get_controller(this_port),
+      this_port->timer_handle
+   );
+   this_port->timer_handle = NULL;
+
+   scic_sds_port_destroy_dummy_resources(this_port);
+}
+
+/**
+ * This method will perform the actions required by the SCIC_SDS_PORT on
+ * entering the SCI_BASE_PORT_STATE_STOPPING. This function sets the stopping
+ * state handlers for the SCIC_SDS_PORT object.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_PORT object.
+ *
+ * @return none
+ */
+static
+void scic_sds_port_failed_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_PORT_T *this_port;
+   this_port = (SCIC_SDS_PORT_T *)object;
+
+   scic_sds_port_set_base_state_handlers(
+      this_port,
+      SCI_BASE_PORT_STATE_FAILED
+   );
+
+   scic_cb_port_hard_reset_complete(
+      scic_sds_port_get_controller(this_port),
+      this_port,
+      SCI_FAILURE_TIMEOUT
+   );
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_BASE_STATE_T scic_sds_port_state_table[SCI_BASE_PORT_MAX_STATES] =
+{
+   {
+      SCI_BASE_PORT_STATE_STOPPED,
+      scic_sds_port_stopped_state_enter,
+      scic_sds_port_stopped_state_exit
+   },
+   {
+      SCI_BASE_PORT_STATE_STOPPING,
+      scic_sds_port_stopping_state_enter,
+      scic_sds_port_stopping_state_exit
+   },
+   {
+      SCI_BASE_PORT_STATE_READY,
+      scic_sds_port_ready_state_enter,
+      scic_sds_port_ready_state_exit
+   },
+   {
+      SCI_BASE_PORT_STATE_RESETTING,
+      scic_sds_port_resetting_state_enter,
+      scic_sds_port_resetting_state_exit
+   },
+   {
+      SCI_BASE_PORT_STATE_FAILED,
+      scic_sds_port_failed_state_enter,
+      NULL
+   }
+};
+
+//******************************************************************************
+//* PORT READY SUB-STATE MACHINE
+//******************************************************************************
+
+//****************************************************************************
+//*  READY SUBSTATE HANDLERS
+//****************************************************************************
+
+/**
+ * This method is the general ready state stop handler for the SCIC_SDS_PORT
+ * object.  This function will transition the ready substate machine to its
+ * final state.
+ *
+ * @param[in] port This is the SCI_BASE_PORT object which is cast into a
+ *       SCIC_SDS_PORT object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS
+ */
+static
+SCI_STATUS scic_sds_port_ready_substate_stop_handler(
+   SCI_BASE_PORT_T *port
+)
+{
+   SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)port;
+
+   sci_base_state_machine_change_state(
+      &this_port->parent.state_machine,
+      SCI_BASE_PORT_STATE_STOPPING
+   );
+
+   return SCI_SUCCESS;
+}
+
+/**
+ * This method is the general ready substate complete io handler for the
+ * SCIC_SDS_PORT object.  This function decrments the outstanding request
+ * count for this port object.
+ *
+ * @param[in] port This is the SCI_BASE_PORT object which is cast into a
+ *       SCIC_SDS_PORT object.
+ * @param[in] device This is the SCI_BASE_REMOTE_DEVICE object which is not
+ *       used in this function.
+ * @param[in] io_request This is the SCI_BASE_REQUEST object which is not used
+ *       in this function.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS
+ */
+static
+SCI_STATUS scic_sds_port_ready_substate_complete_io_handler(
+   SCIC_SDS_PORT_T               *port,
+   struct SCIC_SDS_REMOTE_DEVICE *device,
+   struct SCIC_SDS_REQUEST       *io_request
+)
+{
+   SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)port;
+
+   scic_sds_port_decrement_request_count(this_port);
+
+   return SCI_SUCCESS;
+}
+
+static
+SCI_STATUS scic_sds_port_ready_substate_add_phy_handler(
+   SCI_BASE_PORT_T *port,
+   SCI_BASE_PHY_T  *phy
+)
+{
+   SCIC_SDS_PORT_T * this_port = (SCIC_SDS_PORT_T *)port;
+   SCIC_SDS_PHY_T  * this_phy  = (SCIC_SDS_PHY_T  *)phy;
+   SCI_STATUS        status;
+
+   status = scic_sds_port_set_phy(this_port, this_phy);
+
+   if (status == SCI_SUCCESS)
+   {
+      scic_sds_port_general_link_up_handler(this_port, this_phy, TRUE, FALSE);
+
+      this_port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING;
+
+      sci_base_state_machine_change_state(
+         &this_port->ready_substate_machine,
+         SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING
+      );
+   }
+
+   return status;
+}
+
+static
+SCI_STATUS scic_sds_port_ready_substate_remove_phy_handler(
+   SCI_BASE_PORT_T *port,
+   SCI_BASE_PHY_T  *phy
+)
+{
+   SCIC_SDS_PORT_T * this_port = (SCIC_SDS_PORT_T *)port;
+   SCIC_SDS_PHY_T  * this_phy  = (SCIC_SDS_PHY_T  *)phy;
+   SCI_STATUS        status;
+
+   status = scic_sds_port_clear_phy(this_port, this_phy);
+
+   if (status == SCI_SUCCESS)
+   {
+      scic_sds_port_deactivate_phy(this_port, this_phy, TRUE);
+
+      this_port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING;
+
+      sci_base_state_machine_change_state(
+         &this_port->ready_substate_machine,
+         SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING
+      );
+   }
+
+   return status;
+}
+
+//****************************************************************************
+//*  READY SUBSTATE WAITING HANDLERS
+//****************************************************************************
+
+/**
+ * This method is the ready waiting substate link up handler for the
+ * SCIC_SDS_PORT object.  This methos will report the link up condition for
+ * this port and will transition to the ready operational substate.
+ *
+ * @param[in] this_port This is the SCIC_SDS_PORT object that which has a phy
+ *       that has gone link up.
+ * @param[in] the_phy This is the SCIC_SDS_PHY object that has gone link up.
+ *
+ * @return none
+ */
+static
+void scic_sds_port_ready_waiting_substate_link_up_handler(
+   SCIC_SDS_PORT_T *this_port,
+   SCIC_SDS_PHY_T  *the_phy
+)
+{
+   // Since this is the first phy going link up for the port we can just enable
+   // it and continue.
+   scic_sds_port_activate_phy(this_port, the_phy, TRUE, TRUE);
+
+   sci_base_state_machine_change_state(
+      &this_port->ready_substate_machine,
+      SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL
+   );
+}
+
+/**
+ * This method is the ready waiting substate start io handler for the
+ * SCIC_SDS_PORT object. The port object can not accept new requests so the
+ * request is failed.
+ *
+ * @param[in] port This is the SCI_BASE_PORT object which is cast into a
+ *       SCIC_SDS_PORT object.
+ * @param[in] device This is the SCI_BASE_REMOTE_DEVICE object which is not
+ *       used in this request.
+ * @param[in] io_request This is the SCI_BASE_REQUEST object which is not used
+ *       in this function.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+static
+SCI_STATUS scic_sds_port_ready_waiting_substate_start_io_handler(
+   SCIC_SDS_PORT_T          *port,
+   SCIC_SDS_REMOTE_DEVICE_T *device,
+   SCIC_SDS_REQUEST_T       *io_request
+)
+{
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+//****************************************************************************
+//*  READY SUBSTATE OPERATIONAL HANDLERS
+//****************************************************************************
+
+/**
+ * This method will casue the port to reset.
+ *
+ * @param[in] port This is the SCI_BASE_PORT object which is cast into a
+ *       SCIC_SDS_PORT object.
+ * @param[in] timeout This is the timeout for the reset request to complete.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS
+ */
+static
+SCI_STATUS scic_sds_port_ready_operational_substate_reset_handler(
+   SCI_BASE_PORT_T * port,
+   U32               timeout
+)
+{
+   SCI_STATUS        status = SCI_FAILURE_INVALID_PHY;
+   U32               phy_index;
+   SCIC_SDS_PORT_T * this_port = (SCIC_SDS_PORT_T *)port;
+   SCIC_SDS_PHY_T  * selected_phy = SCI_INVALID_HANDLE;
+
+
+   // Select a phy on which we can send the hard reset request.
+   for (
+         phy_index = 0;
+            (phy_index < SCI_MAX_PHYS)
+         && (selected_phy == SCI_INVALID_HANDLE);
+         phy_index++
+       )
+   {
+      selected_phy = this_port->phy_table[phy_index];
+
+      if (
+            (selected_phy != SCI_INVALID_HANDLE)
+         && !scic_sds_port_active_phy(this_port, selected_phy)
+         )
+      {
+         // We found a phy but it is not ready select different phy
+         selected_phy = SCI_INVALID_HANDLE;
+      }
+   }
+
+   // If we have a phy then go ahead and start the reset procedure
+   if (selected_phy != SCI_INVALID_HANDLE)
+   {
+      status = scic_sds_phy_reset(selected_phy);
+
+      if (status == SCI_SUCCESS)
+      {
+         scic_cb_timer_start(
+            scic_sds_port_get_controller(this_port),
+            this_port->timer_handle,
+            timeout
+         );
+
+         this_port->not_ready_reason = SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED;
+
+         sci_base_state_machine_change_state(
+            &this_port->parent.state_machine,
+            SCI_BASE_PORT_STATE_RESETTING
+         );
+      }
+   }
+
+   return status;
+}
+
+/**
+ * This method is the ready operational substate link up handler for the
+ * SCIC_SDS_PORT object. This function notifies the SCI User that the phy has
+ * gone link up.
+ *
+ * @param[in] this_port This is the SCIC_SDS_PORT object that which has a phy
+ *       that has gone link up.
+ * @param[in] the_phy This is the SCIC_SDS_PHY object that has gone link up.
+ *
+ * @return none
+ */
+static
+void scic_sds_port_ready_operational_substate_link_up_handler(
+   SCIC_SDS_PORT_T *this_port,
+   SCIC_SDS_PHY_T  *the_phy
+)
+{
+   scic_sds_port_general_link_up_handler(this_port, the_phy, TRUE, TRUE);
+}
+
+/**
+ * This method is the ready operational substate link down handler for the
+ * SCIC_SDS_PORT object. This function notifies the SCI User that the phy has
+ * gone link down and if this is the last phy in the port the port will change
+ * state to the ready waiting substate.
+ *
+ * @param[in] this_port This is the SCIC_SDS_PORT object that which has a phy
+ *       that has gone link down.
+ * @param[in] the_phy This is the SCIC_SDS_PHY object that has gone link down.
+ *
+ * @return none
+ */
+static
+void scic_sds_port_ready_operational_substate_link_down_handler(
+   SCIC_SDS_PORT_T *this_port,
+   SCIC_SDS_PHY_T  *the_phy
+)
+{
+   scic_sds_port_deactivate_phy(this_port, the_phy, TRUE);
+
+   // If there are no active phys left in the port, then transition
+   // the port to the WAITING state until such time as a phy goes
+   // link up.
+   if (this_port->active_phy_mask == 0)
+   {
+      sci_base_state_machine_change_state(
+         scic_sds_port_get_ready_substate_machine(this_port),
+         SCIC_SDS_PORT_READY_SUBSTATE_WAITING
+      );
+   }
+}
+
+/**
+ * This method is the ready operational substate start io handler for the
+ * SCIC_SDS_PORT object.  This function incremetns the outstanding request
+ * count for this port object.
+ *
+ * @param[in] port This is the SCI_BASE_PORT object which is cast into a
+ *       SCIC_SDS_PORT object.
+ * @param[in] device This is the SCI_BASE_REMOTE_DEVICE object which is not
+ *       used in this function.
+ * @param[in] io_request This is the SCI_BASE_REQUEST object which is not used
+ *       in this function.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS
+ */
+static
+SCI_STATUS scic_sds_port_ready_operational_substate_start_io_handler(
+   SCIC_SDS_PORT_T          *port,
+   SCIC_SDS_REMOTE_DEVICE_T *device,
+   SCIC_SDS_REQUEST_T       *io_request
+)
+{
+   SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)port;
+
+   scic_sds_port_increment_request_count(this_port);
+
+   return SCI_SUCCESS;
+}
+
+//****************************************************************************
+//*  READY SUBSTATE OPERATIONAL HANDLERS
+//****************************************************************************
+
+/**
+ * This is the default method for a port add phy request.  It will report a
+ * warning and exit.
+ *
+ * @param[in] port This is the SCI_BASE_PORT object which is cast into a
+ *       SCIC_SDS_PORT object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+static
+SCI_STATUS scic_sds_port_ready_configuring_substate_add_phy_handler(
+   SCI_BASE_PORT_T *port,
+   SCI_BASE_PHY_T  *phy
+)
+{
+   SCIC_SDS_PORT_T * this_port = (SCIC_SDS_PORT_T *)port;
+   SCIC_SDS_PHY_T  * this_phy  = (SCIC_SDS_PHY_T  *)phy;
+   SCI_STATUS        status;
+
+   status = scic_sds_port_set_phy(this_port, this_phy);
+
+   if (status == SCI_SUCCESS)
+   {
+      scic_sds_port_general_link_up_handler(this_port, this_phy, TRUE, FALSE);
+
+      // Re-enter the configuring state since this may be the last phy in
+      // the port.
+      sci_base_state_machine_change_state(
+         &this_port->ready_substate_machine,
+         SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING
+      );
+   }
+
+   return status;
+}
+
+/**
+ * This is the default method for a port remove phy request.  It will report a
+ * warning and exit.
+ *
+ * @param[in] port This is the SCI_BASE_PORT object which is cast into a
+ *       SCIC_SDS_PORT object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+static
+SCI_STATUS scic_sds_port_ready_configuring_substate_remove_phy_handler(
+   SCI_BASE_PORT_T *port,
+   SCI_BASE_PHY_T  *phy
+)
+{
+   SCIC_SDS_PORT_T * this_port = (SCIC_SDS_PORT_T *)port;
+   SCIC_SDS_PHY_T  * this_phy  = (SCIC_SDS_PHY_T  *)phy;
+   SCI_STATUS        status;
+
+   status = scic_sds_port_clear_phy(this_port, this_phy);
+
+   if (status == SCI_SUCCESS)
+   {
+      scic_sds_port_deactivate_phy(this_port, this_phy, TRUE);
+
+      // Re-enter the configuring state since this may be the last phy in
+      // the port.
+      sci_base_state_machine_change_state(
+         &this_port->ready_substate_machine,
+         SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING
+      );
+   }
+
+   return status;
+}
+
+/**
+ * This method will decrement the outstanding request count for this port.
+ * If the request count goes to 0 then the port can be reprogrammed with
+ * its new phy data.
+ *
+ * @param[in] port This is the port that is being requested to complete
+ *            the io request.
+ * @param[in] device This is the device on which the io is completing.
+ * @param[in] io_request This is the io request that is completing.
+ */
+static
+SCI_STATUS scic_sds_port_ready_configuring_substate_complete_io_handler(
+   SCIC_SDS_PORT_T          *port,
+   SCIC_SDS_REMOTE_DEVICE_T *device,
+   SCIC_SDS_REQUEST_T       *io_request
+)
+{
+   scic_sds_port_decrement_request_count(port);
+
+   if (port->started_request_count == 0)
+   {
+      sci_base_state_machine_change_state(
+         &port->ready_substate_machine,
+         SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL
+      );
+   }
+
+   return SCI_SUCCESS;
+}
+
+// ---------------------------------------------------------------------------
+
+SCIC_SDS_PORT_STATE_HANDLER_T
+   scic_sds_port_ready_substate_handler_table[SCIC_SDS_PORT_READY_MAX_SUBSTATES] =
+{
+   // SCIC_SDS_PORT_READY_SUBSTATE_WAITING
+   {
+      {
+         scic_sds_port_default_start_handler,
+         scic_sds_port_ready_substate_stop_handler,
+         scic_sds_port_default_destruct_handler,
+         scic_sds_port_default_reset_handler,
+         scic_sds_port_ready_substate_add_phy_handler,
+         scic_sds_port_default_remove_phy_handler
+      },
+      scic_sds_port_default_frame_handler,
+      scic_sds_port_default_event_handler,
+      scic_sds_port_ready_waiting_substate_link_up_handler,
+      scic_sds_port_default_link_down_handler,
+      scic_sds_port_ready_waiting_substate_start_io_handler,
+      scic_sds_port_ready_substate_complete_io_handler,
+   },
+   // SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL
+   {
+      {
+         scic_sds_port_default_start_handler,
+         scic_sds_port_ready_substate_stop_handler,
+         scic_sds_port_default_destruct_handler,
+         scic_sds_port_ready_operational_substate_reset_handler,
+         scic_sds_port_ready_substate_add_phy_handler,
+         scic_sds_port_ready_substate_remove_phy_handler
+      },
+      scic_sds_port_default_frame_handler,
+      scic_sds_port_default_event_handler,
+      scic_sds_port_ready_operational_substate_link_up_handler,
+      scic_sds_port_ready_operational_substate_link_down_handler,
+      scic_sds_port_ready_operational_substate_start_io_handler,
+      scic_sds_port_ready_substate_complete_io_handler
+   },
+   // SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING
+   {
+      {
+         scic_sds_port_default_start_handler,
+         scic_sds_port_ready_substate_stop_handler,
+         scic_sds_port_default_destruct_handler,
+         scic_sds_port_default_reset_handler,
+         scic_sds_port_ready_configuring_substate_add_phy_handler,
+         scic_sds_port_ready_configuring_substate_remove_phy_handler
+      },
+      scic_sds_port_default_frame_handler,
+      scic_sds_port_default_event_handler,
+      scic_sds_port_default_link_up_handler,
+      scic_sds_port_default_link_down_handler,
+      scic_sds_port_default_start_io_handler,
+      scic_sds_port_ready_configuring_substate_complete_io_handler
+   }
+};
+
+/**
+ * This macro sets the port ready substate handlers.
+ */
+#define scic_sds_port_set_ready_state_handlers(port, state_id) \
+   scic_sds_port_set_state_handlers( \
+      port, &scic_sds_port_ready_substate_handler_table[(state_id)] \
+   )
+
+//******************************************************************************
+//*  PORT STATE PRIVATE METHODS
+//******************************************************************************
+
+/**
+ * This method will susped the port task scheduler for this port object.
+ *
+ * @param[in] this_port This is the SCIC_SDS_PORT object to suspend.
+ *
+ * @return none
+ */
+void scic_sds_port_suspend_port_task_scheduler(
+   SCIC_SDS_PORT_T *this_port
+)
+{
+   U32 pts_control_value;
+
+   pts_control_value = scu_port_task_scheduler_read(this_port, control);
+   pts_control_value |= SCU_PTSxCR_GEN_BIT(SUSPEND);
+   scu_port_task_scheduler_write(this_port, control, pts_control_value);
+}
+
+/**
+ * This method will resume the port task scheduler for this port object.
+ *
+ * @param[in] this_port This is the SCIC_SDS_PORT object to resume.
+ *
+ * @return none
+ */
+void scic_sds_port_resume_port_task_scheduler(
+   SCIC_SDS_PORT_T *this_port
+)
+{
+   U32 pts_control_value;
+
+   pts_control_value = scu_port_task_scheduler_read(this_port, control);
+
+   pts_control_value &= ~SCU_PTSxCR_GEN_BIT(SUSPEND);
+
+   scu_port_task_scheduler_write(this_port, control, pts_control_value);
+}
+
+/**
+ * This routine will post the dummy request.  This will prevent the hardware
+ * scheduler from posting new requests to the front of the scheduler queue
+ * causing a starvation problem for currently ongoing requests.
+ *
+ * @parm[in] this_port The port on which the task must be posted.
+ *
+ * @return none
+ */
+static
+void scic_sds_port_post_dummy_request(
+   SCIC_SDS_PORT_T *this_port
+)
+{
+   U32 command;
+   SCU_TASK_CONTEXT_T * task_context;
+
+   if (this_port->reserved_tci != SCU_DUMMY_INDEX)
+   {
+   task_context = scic_sds_controller_get_task_context_buffer(
+                     this_port->owning_controller,
+                     this_port->reserved_tci
+                  );
+
+   task_context->abort = 0;
+
+   command = (
+         (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC)
+      | (this_port->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT)
+      | (this_port->reserved_tci)
+   );
+
+   scic_sds_controller_post_request(this_port->owning_controller, command);
+}
+}
+
+/**
+ * This routine will abort the dummy request.  This will alow the hardware to
+ * power down parts of the silicon to save power.
+ *
+ * @parm[in] this_port The port on which the task must be aborted.
+ *
+ * @return none
+ */
+static
+void scic_sds_port_abort_dummy_request(
+   SCIC_SDS_PORT_T *this_port
+)
+{
+   U32 command;
+   SCU_TASK_CONTEXT_T * task_context;
+
+   if (this_port->reserved_tci != SCU_DUMMY_INDEX)
+   {
+   task_context = scic_sds_controller_get_task_context_buffer(
+                     this_port->owning_controller,
+                     this_port->reserved_tci
+                  );
+
+   task_context->abort = 1;
+
+   command = (
+        (SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT)
+      | (this_port->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT)
+      | (this_port->reserved_tci)
+   );
+
+   scic_sds_controller_post_request(this_port->owning_controller, command);
+}
+}
+
+//******************************************************************************
+//*  PORT READY SUBSTATE METHODS
+//******************************************************************************
+
+/**
+ * This method will perform the actions required by the SCIC_SDS_PORT on
+ * entering the SCIC_SDS_PORT_READY_SUBSTATE_WAITING. This function checks the
+ * port for any ready phys.  If there is at least one phy in a ready state
+ * then the port transitions to the ready operational substate.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_PORT object.
+ *
+ * @return none
+ */
+static
+void scic_sds_port_ready_substate_waiting_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)object;
+
+   scic_sds_port_set_ready_state_handlers(
+      this_port, SCIC_SDS_PORT_READY_SUBSTATE_WAITING
+   );
+
+   scic_sds_port_suspend_port_task_scheduler(this_port);
+
+
+   this_port->not_ready_reason = SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS;
+
+   if (this_port->active_phy_mask != 0)
+   {
+      // At least one of the phys on the port is ready
+      sci_base_state_machine_change_state(
+         &this_port->ready_substate_machine,
+         SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL
+      );
+   }
+}
+
+/**
+ * This method will perform the actions required by the SCIC_SDS_PORT on
+ * exiting the SCIC_SDS_PORT_READY_SUBSTATE_WAITING. This function resume the
+ * PTSG that was suspended at the entry of this state.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_PORT object.
+ *
+ * @return none
+ */
+static
+void scic_sds_port_ready_substate_waiting_exit(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)object;
+   scic_sds_port_resume_port_task_scheduler(this_port);
+}
+
+/**
+ * This method will perform the actions required by the SCIC_SDS_PORT on
+ * entering the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function sets
+ * the state handlers for the port object, notifies the SCI User that the port
+ * is ready, and resumes port operations.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_PORT object.
+ *
+ * @return none
+ */
+static
+void scic_sds_port_ready_substate_operational_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   U32 index;
+   SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)object;
+
+   scic_sds_port_set_ready_state_handlers(
+      this_port, SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL
+   );
+
+   scic_cb_port_ready(
+      scic_sds_port_get_controller(this_port), this_port
+   );
+
+   for (index = 0; index < SCI_MAX_PHYS; index++)
+   {
+      if (this_port->phy_table[index] != NULL)
+      {
+         scic_sds_port_write_phy_assignment(
+            this_port, this_port->phy_table[index]
+         );
+
+         //if the bit at the index location for active phy mask is set and
+         //enabled_phy_mask is not set then resume the phy
+         if ( ( (this_port->active_phy_mask ^ this_port->enabled_phy_mask) & (1 << index) ) != 0)
+         {
+            scic_sds_port_resume_phy (
+               this_port,
+               this_port->phy_table[index]
+            );
+         }
+      }
+   }
+
+   scic_sds_port_update_viit_entry(this_port);
+
+   // Post the dummy task for the port so the hardware can schedule
+   // io correctly
+   scic_sds_port_post_dummy_request(this_port);
+}
+
+/**
+ * This method will perform the actions required by the SCIC_SDS_PORT on
+ * exiting the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function reports
+ * the port not ready and suspends the port task scheduler.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_PORT object.
+ *
+ * @return none
+ */
+static
+void scic_sds_port_ready_substate_operational_exit(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)object;
+
+   // Kill the dummy task for this port if it has not yet posted
+   // the hardware will treat this as a NOP and just return abort
+   // complete.
+   scic_sds_port_abort_dummy_request(this_port);
+
+   scic_cb_port_not_ready(
+      scic_sds_port_get_controller(this_port),
+      this_port,
+      this_port->not_ready_reason
+   );
+}
+
+//******************************************************************************
+//*  PORT READY CONFIGURING METHODS
+//******************************************************************************
+
+/**
+ * This method will perform the actions required by the SCIC_SDS_PORT on
+ * exiting the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function reports
+ * the port not ready and suspends the port task scheduler.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast to a
+ *       SCIC_SDS_PORT object.
+ *
+ * @return none
+ */
+static
+void scic_sds_port_ready_substate_configuring_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)object;
+
+   scic_sds_port_set_ready_state_handlers(
+      this_port, SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING
+   );
+
+   if (this_port->active_phy_mask == 0)
+   {
+      scic_cb_port_not_ready(
+         scic_sds_port_get_controller(this_port),
+         this_port,
+         SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS
+      );
+
+      sci_base_state_machine_change_state(
+         &this_port->ready_substate_machine,
+         SCIC_SDS_PORT_READY_SUBSTATE_WAITING
+      );
+   }
+   //do not wait for IO to go to 0 in this state.
+   else
+   {
+      sci_base_state_machine_change_state(
+         &this_port->ready_substate_machine,
+         SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL
+      );
+   }
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_BASE_STATE_T
+   scic_sds_port_ready_substate_table[SCIC_SDS_PORT_READY_MAX_SUBSTATES] =
+{
+   {
+      SCIC_SDS_PORT_READY_SUBSTATE_WAITING,
+      scic_sds_port_ready_substate_waiting_enter,
+      scic_sds_port_ready_substate_waiting_exit
+   },
+   {
+      SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL,
+      scic_sds_port_ready_substate_operational_enter,
+      scic_sds_port_ready_substate_operational_exit
+   },
+   {
+      SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING,
+      scic_sds_port_ready_substate_configuring_enter,
+      NULL
+   }
+};
diff --git a/sys/dev/disk/isci/scil/scic_sds_port.h b/sys/dev/disk/isci/scil/scic_sds_port.h
new file mode 100644
index 0000000..51431b8
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_sds_port.h
@@ -0,0 +1,595 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_sds_port.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIC_SDS_PORT_H_
+#define _SCIC_SDS_PORT_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+/**
+ * @file
+ *
+ * @brief This file contains the structures, constants and prototypes for the
+ * SCIC_SDS_PORT_T object.
+ */
+
+#include <dev/disk/isci/scil/sci_controller_constants.h>
+#include <dev/disk/isci/scil/intel_sas.h>
+#include <dev/disk/isci/scil/sci_base_port.h>
+#include <dev/disk/isci/scil/sci_base_phy.h>
+#include <dev/disk/isci/scil/scu_registers.h>
+
+#define SCIC_SDS_DUMMY_PORT   0xFF
+
+/**
+ * @enum SCIC_SDS_PORT_READY_SUBSTATES
+ *
+ * This enumeration depicts all of the states for the core port ready substate
+ * machine.
+ */
+enum SCIC_SDS_PORT_READY_SUBSTATES
+{
+   /**
+    * The substate where the port is started and ready but has no active phys.
+    */
+   SCIC_SDS_PORT_READY_SUBSTATE_WAITING,
+
+   /**
+    * The substate where the port is started and ready and there is at least one
+    * phy operational.
+    */
+   SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL,
+
+   /**
+    * The substate where the port is started and there was an add/remove phy
+    * event.  This state is only used in Automatic Port Configuration Mode (APC)
+    */
+   SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING,
+
+   SCIC_SDS_PORT_READY_MAX_SUBSTATES
+};
+
+struct SCIC_SDS_CONTROLLER;
+struct SCIC_SDS_PHY;
+struct SCIC_SDS_REMOTE_DEVICE;
+struct SCIC_SDS_REQUEST;
+
+/**
+ * @struct SCIC_SDS_PORT
+ *
+ * The core port object provides the the abstraction for an SCU port.
+ */
+typedef struct SCIC_SDS_PORT
+{
+   /**
+    * This field is the oommon base port object.
+    */
+   SCI_BASE_PORT_T parent;
+
+   /**
+    * This field is the port index that is reported to the SCI USER.  This allows
+    * the actual hardware physical port to change without the SCI USER getting a
+    * different answer for the get port index.
+    */
+   U8 logical_port_index;
+
+   /**
+    * This field is the port index used to program the SCU hardware.
+    */
+   U8 physical_port_index;
+
+   /**
+    * This field contains the active phy mask for the port.  This mask is used in
+    * conjunction with the phy state to determine which phy to select for some
+    * port operations.
+    */
+   U8 active_phy_mask;
+
+   /**
+    * This field contains the phy mask for the port that are already part of the port.
+   */
+   U8 enabled_phy_mask;
+
+   U16 reserved_rni;
+   U16 reserved_tci;
+
+   /**
+    * This field contains the count of the io requests started on this port
+    * object.  It is used to control controller shutdown.
+    */
+   U32 started_request_count;
+
+   /**
+    * This field contains the number of devices assigned to this port.  It is
+    * used to control port start requests.
+    */
+   U32 assigned_device_count;
+
+   /**
+    * This field contains the reason for the port not going ready.  It is
+    * assigned in the state handlers and used in the state transition.
+    */
+   U32 not_ready_reason;
+
+   /**
+    * This field is the table of phys assigned to the port.
+    */
+   struct SCIC_SDS_PHY *phy_table[SCI_MAX_PHYS];
+
+   /**
+    * This field is a pointer back to the controller that owns this port object.
+    */
+   struct SCIC_SDS_CONTROLLER *owning_controller;
+
+   /**
+    * This field contains the port start/stop timer handle.
+    */
+   void *timer_handle;
+
+   /**
+    * This field points to the current set of state handlers for this port
+    * object.  These state handlers are assigned at each enter state of the state
+    * machine.
+    */
+   struct SCIC_SDS_PORT_STATE_HANDLER *state_handlers;
+
+   /**
+    * This field is the ready substate machine for the port.
+    */
+   SCI_BASE_STATE_MACHINE_T ready_substate_machine;
+
+   #ifdef SCI_LOGGING
+   /**
+    * This field is the ready substate machine logger.  It logs each state
+    * transition request in the ready substate machine.
+    */
+   SCI_BASE_STATE_MACHINE_LOGGER_T ready_substate_machine_logger;
+   #endif
+
+   /// Memory mapped hardware register space
+
+   /**
+    * This field is the pointer to the port task scheduler registers for the SCU
+    * hardware.
+    */
+   SCU_PORT_TASK_SCHEDULER_REGISTERS_T *port_task_scheduler_registers;
+
+   /**
+    * This field is identical for all port objects and points to the port task
+    * scheduler group PE configuration registers.  It is used to assign PEs to a
+    * port.
+    */
+   SCU_PORT_PE_CONFIGURATION_REGISTER_T *port_pe_configuration_register;
+
+   /**
+    * This field is the VIIT register space for ths port object.
+    */
+   SCU_VIIT_ENTRY_T *viit_registers;
+
+} SCIC_SDS_PORT_T;
+
+
+typedef SCI_STATUS (*SCIC_SDS_PORT_EVENT_HANDLER_T)(struct SCIC_SDS_PORT *, U32);
+
+typedef SCI_STATUS (*SCIC_SDS_PORT_FRAME_HANDLER_T)(struct SCIC_SDS_PORT *, U32);
+
+typedef void (*SCIC_SDS_PORT_LINK_HANDLER_T)(struct SCIC_SDS_PORT *, struct SCIC_SDS_PHY *);
+
+typedef SCI_STATUS (*SCIC_SDS_PORT_IO_REQUEST_HANDLER_T)(
+                           struct SCIC_SDS_PORT *,
+                           struct SCIC_SDS_REMOTE_DEVICE *,
+                           struct SCIC_SDS_REQUEST *);
+
+typedef struct SCIC_SDS_PORT_STATE_HANDLER
+{
+   SCI_BASE_PORT_STATE_HANDLER_T parent;
+
+   SCIC_SDS_PORT_FRAME_HANDLER_T frame_handler;
+   SCIC_SDS_PORT_EVENT_HANDLER_T event_handler;
+
+   SCIC_SDS_PORT_LINK_HANDLER_T link_up_handler;
+   SCIC_SDS_PORT_LINK_HANDLER_T link_down_handler;
+
+   SCIC_SDS_PORT_IO_REQUEST_HANDLER_T start_io_handler;
+   SCIC_SDS_PORT_IO_REQUEST_HANDLER_T complete_io_handler;
+
+} SCIC_SDS_PORT_STATE_HANDLER_T;
+
+extern SCI_BASE_STATE_T scic_sds_port_state_table[];
+extern SCI_BASE_STATE_T scic_sds_port_ready_substate_table[];
+
+extern SCIC_SDS_PORT_STATE_HANDLER_T scic_sds_port_state_handler_table[];
+extern SCIC_SDS_PORT_STATE_HANDLER_T scic_sds_port_ready_substate_handler_table[];
+
+/**
+ * Helper macro to get the owning controller of this port
+ */
+#define scic_sds_port_get_controller(this_port) \
+   ((this_port)->owning_controller)
+
+/**
+ * Helper macro to get the base state machine for this port
+ */
+#define scic_sds_port_get_base_state_machine(this_port) \
+   (&(this_port)->parent.state_machine)
+
+/**
+ * This macro will change the state handlers to those of the specified state
+ * id
+ */
+#define scic_sds_port_set_base_state_handlers(this_port, state_id) \
+   scic_sds_port_set_state_handlers( \
+      (this_port), &scic_sds_port_state_handler_table[(state_id)])
+
+/**
+ * Helper macro to get the ready substate machine for this port
+ */
+#define scic_sds_port_get_ready_substate_machine(this_port) \
+   (&(this_port)->ready_substate_machine)
+
+/**
+ * Helper macro to set the port object state handlers
+ */
+#define scic_sds_port_set_state_handlers(this_port, handlers) \
+   ((this_port)->state_handlers = (handlers))
+
+/**
+ * This macro returns the physical port index for this port object
+ */
+#define scic_sds_port_get_index(this_port) \
+   ((this_port)->physical_port_index)
+
+/**
+ * Helper macro to increment the started request count
+ */
+#define scic_sds_port_increment_request_count(this_port) \
+   ((this_port)->started_request_count++)
+
+#ifdef SCIC_DEBUG_ENABLED
+/**
+ * @brief This method decrements the started io request count.  The method
+ *        will not decrment the started io request count below 0 and will
+ *        log a debug message if this is attempted.
+ *
+ * @param[in] this_port
+ */
+void scic_sds_port_decrement_request_count(
+   SCIC_SDS_PORT_T *this_port
+);
+#else
+/**
+ * Helper macro to decrement the started io request count.  The macro will
+ * not decrement the started io request count below 0.
+ */
+#define scic_sds_port_decrement_request_count(this_port) \
+   ( \
+      (this_port)->started_request_count = ( \
+                  ((this_port)->started_request_count == 0) ? \
+                                  (this_port)->started_request_count : \
+                                  ((this_port)->started_request_count - 1) \
+                                              ) \
+    )
+#endif
+
+/**
+ * Helper macro to write the phys port assignment
+ */
+#define scic_sds_port_write_phy_assignment(port, phy) \
+   SCU_PCSPExCR_WRITE( \
+      (port), \
+      (phy)->phy_index, \
+      (port)->physical_port_index \
+   )
+
+/**
+ * Helper macro to read the phys port assignment
+ */
+#define scic_sds_port_read_phy_assignment(port, phy) \
+   SCU_PCSPExCR_READ( \
+      (port), \
+      (phy)->phy_index \
+   )
+
+#define scic_sds_port_active_phy(port, phy) \
+   (((port)->active_phy_mask & (1 << (phy)->phy_index)) != 0)
+
+// ---------------------------------------------------------------------------
+
+U32 scic_sds_port_get_object_size(void);
+
+U32 scic_sds_port_get_min_timer_count(void);
+
+U32 scic_sds_port_get_max_timer_count(void);
+
+// ---------------------------------------------------------------------------
+
+#ifdef SCI_LOGGING
+void scic_sds_port_initialize_state_logging(
+   SCIC_SDS_PORT_T *this_port
+);
+#else
+#define scic_sds_port_initialize_state_logging(x)
+#endif
+
+// ---------------------------------------------------------------------------
+
+void scic_sds_port_construct(
+   SCIC_SDS_PORT_T            *this_port,
+   U8                          port_index,
+   struct SCIC_SDS_CONTROLLER *owning_controller
+);
+
+SCI_STATUS scic_sds_port_initialize(
+   SCIC_SDS_PORT_T *this_port,
+   void *port_task_scheduler_registers,
+   void *port_configuration_regsiter,
+   void *viit_registers
+);
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_sds_port_add_phy(
+   struct SCIC_SDS_PORT * this_port,
+   struct SCIC_SDS_PHY  * the_phy
+);
+
+SCI_STATUS scic_sds_port_remove_phy(
+   struct SCIC_SDS_PORT * this_port,
+   struct SCIC_SDS_PHY  * the_phy
+);
+
+void scic_sds_port_setup_transports(
+   SCIC_SDS_PORT_T * this_port,
+   U32               device_id
+);
+
+void scic_sds_port_activate_phy(
+   SCIC_SDS_PORT_T     *this_port,
+   struct SCIC_SDS_PHY *phy,
+   BOOL                 do_notify_user,
+   BOOL                 do_resume_phy
+);
+
+void scic_sds_port_deactivate_phy(
+   SCIC_SDS_PORT_T     *this_port,
+   struct SCIC_SDS_PHY *phy,
+   BOOL                 do_notify_user
+);
+
+struct SCIC_SDS_PHY * scic_sds_port_get_a_connected_phy(
+   SCIC_SDS_PORT_T * this_port
+);
+
+void scic_sds_port_invalid_link_up(
+   SCIC_SDS_PORT_T *this_port,
+   struct SCIC_SDS_PHY *phy
+);
+
+void scic_sds_port_general_link_up_handler(
+   SCIC_SDS_PORT_T     *this_port,
+   struct SCIC_SDS_PHY *the_phy,
+   BOOL                 do_notify_user,
+   BOOL                 do_resume_phy
+);
+
+BOOL scic_sds_port_link_detected(
+   SCIC_SDS_PORT_T *this_port,
+   struct SCIC_SDS_PHY *phy
+);
+
+void scic_sds_port_link_up(
+   SCIC_SDS_PORT_T *this_port,
+   struct SCIC_SDS_PHY *phy
+);
+
+void scic_sds_port_link_down(
+   SCIC_SDS_PORT_T *this_port,
+   struct SCIC_SDS_PHY *phy
+);
+
+// ---------------------------------------------------------------------------
+
+void scic_sds_port_timeout_handler(
+   void *port
+);
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_sds_port_start_io(
+   SCIC_SDS_PORT_T               *this_port,
+   struct SCIC_SDS_REMOTE_DEVICE *the_device,
+   struct SCIC_SDS_REQUEST       *the_io_request
+);
+
+SCI_STATUS scic_sds_port_complete_io(
+   SCIC_SDS_PORT_T               *this_port,
+   struct SCIC_SDS_REMOTE_DEVICE *the_device,
+   struct SCIC_SDS_REQUEST       *the_io_request
+);
+
+// ---------------------------------------------------------------------------
+
+void scic_sds_port_update_viit_entry(
+   SCIC_SDS_PORT_T *this_port
+);
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_sds_port_default_start_handler(
+   SCI_BASE_PORT_T *port
+);
+
+SCI_STATUS scic_sds_port_default_stop_handler(
+   SCI_BASE_PORT_T *port
+);
+
+SCI_STATUS scic_sds_port_default_destruct_handler(
+   SCI_BASE_PORT_T *port
+);
+
+SCI_STATUS scic_sds_port_default_reset_handler(
+   SCI_BASE_PORT_T * port,
+   U32               timeout
+);
+
+SCI_STATUS scic_sds_port_default_add_phy_handler(
+   SCI_BASE_PORT_T *port,
+   SCI_BASE_PHY_T  *phy
+);
+
+SCI_STATUS scic_sds_port_default_remove_phy_handler(
+   SCI_BASE_PORT_T *port,
+   SCI_BASE_PHY_T  *phy
+);
+
+SCI_STATUS scic_sds_port_default_frame_handler(
+   struct SCIC_SDS_PORT * port,
+   U32                    frame_index
+);
+
+SCI_STATUS scic_sds_port_default_event_handler(
+   struct SCIC_SDS_PORT * port,
+   U32                    event_code
+);
+
+void scic_sds_port_default_link_up_handler(
+   struct SCIC_SDS_PORT *this_port,
+   struct SCIC_SDS_PHY  *phy
+);
+
+void scic_sds_port_default_link_down_handler(
+   struct SCIC_SDS_PORT *this_port,
+   struct SCIC_SDS_PHY  *phy
+);
+
+SCI_STATUS scic_sds_port_default_start_io_handler(
+   struct SCIC_SDS_PORT          *port,
+   struct SCIC_SDS_REMOTE_DEVICE *device,
+   struct SCIC_SDS_REQUEST       *io_request
+);
+
+SCI_STATUS scic_sds_port_default_complete_io_handler(
+   struct SCIC_SDS_PORT          *port,
+   struct SCIC_SDS_REMOTE_DEVICE *device,
+   struct SCIC_SDS_REQUEST       *io_request
+);
+
+SCI_SAS_LINK_RATE scic_sds_port_get_max_allowed_speed(
+   SCIC_SDS_PORT_T * this_port
+);
+
+void scic_sds_port_broadcast_change_received(
+   struct SCIC_SDS_PORT * this_port,
+   struct SCIC_SDS_PHY * this_phy
+);
+
+BOOL scic_sds_port_is_valid_phy_assignment(
+   SCIC_SDS_PORT_T *this_port,
+   U32              phy_index
+);
+
+BOOL scic_sds_port_is_phy_mask_valid(
+   SCIC_SDS_PORT_T * this_port,
+   U32               phy_mask
+);
+
+U32 scic_sds_port_get_phys(
+   SCIC_SDS_PORT_T * this_port
+);
+
+void scic_sds_port_get_sas_address(
+   SCIC_SDS_PORT_T   * this_port,
+   SCI_SAS_ADDRESS_T * sas_address
+);
+
+void scic_sds_port_get_attached_sas_address(
+   SCIC_SDS_PORT_T   * this_port,
+   SCI_SAS_ADDRESS_T * sas_address
+);
+
+void scic_sds_port_get_attached_protocols(
+   SCIC_SDS_PORT_T                            * this_port,
+   SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T * protocols
+);
+
+SCI_STATUS scic_sds_port_set_phy(
+   struct SCIC_SDS_PORT *port,
+   struct SCIC_SDS_PHY  *phy
+);
+
+SCI_STATUS scic_sds_port_clear_phy(
+   struct SCIC_SDS_PORT *port,
+   struct SCIC_SDS_PHY  *phy
+);
+
+void scic_sds_port_suspend_port_task_scheduler(
+   SCIC_SDS_PORT_T *this_port
+);
+
+void scic_sds_port_resume_port_task_scheduler(
+   SCIC_SDS_PORT_T *this_port
+);
+
+void scic_sds_port_release_resource(
+   struct SCIC_SDS_CONTROLLER * controller,
+   struct SCIC_SDS_PORT       * port
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+
+#endif // _SCIC_SDS_PORT_H_
diff --git a/sys/dev/disk/isci/scil/scic_sds_port_configuration_agent.c b/sys/dev/disk/isci/scil/scic_sds_port_configuration_agent.c
new file mode 100644
index 0000000..e9674b4
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_sds_port_configuration_agent.c
@@ -0,0 +1,1132 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_sds_port_configuration_agent.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains the implementation for the public and protected
+ *        methods for the port configuration agent.
+ */
+
+#include <dev/disk/isci/scil/scic_controller.h>
+#include <dev/disk/isci/scil/scic_sds_logger.h>
+#include <dev/disk/isci/scil/scic_sds_controller.h>
+#include <dev/disk/isci/scil/scic_sds_port_configuration_agent.h>
+
+#define SCIC_SDS_MPC_RECONFIGURATION_TIMEOUT    (10)
+#define SCIC_SDS_APC_RECONFIGURATION_TIMEOUT    (10)
+#define SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION  (250)
+
+enum SCIC_SDS_APC_ACTIVITY
+{
+   SCIC_SDS_APC_SKIP_PHY,
+   SCIC_SDS_APC_ADD_PHY,
+   SCIC_SDS_APC_START_TIMER,
+
+   SCIC_SDS_APC_ACTIVITY_MAX
+};
+
+//******************************************************************************
+// General port configuration agent routines
+//******************************************************************************
+
+/**
+ * Compare the two SAS Address and
+ * if SAS Address One is greater than SAS Address Two then return > 0
+ * else if SAS Address One is less than SAS Address Two return < 0
+ * Otherwise they are the same return 0
+ *
+ * @param[in] address_one A SAS Address to be compared.
+ * @param[in] address_two A SAS Address to be compared.
+ *
+ * @return A signed value of x > 0 > y where
+ *         x is returned for Address One > Address Two
+ *         y is returned for Address One < Address Two
+ *         0 is returned ofr Address One = Address Two
+ */
+static
+S32 sci_sas_address_compare(
+   SCI_SAS_ADDRESS_T address_one,
+   SCI_SAS_ADDRESS_T address_two
+)
+{
+   if (address_one.high > address_two.high)
+   {
+      return 1;
+   }
+   else if (address_one.high < address_two.high)
+   {
+      return -1;
+   }
+   else if (address_one.low > address_two.low)
+   {
+      return 1;
+   }
+   else if (address_one.low < address_two.low)
+   {
+      return -1;
+   }
+
+   // The two SAS Address must be identical
+   return 0;
+}
+
+/**
+ * This routine will find a matching port for the phy.  This means that the
+ * port and phy both have the same broadcast sas address and same received
+ * sas address.
+ *
+ * @param[in] controller The controller object used for the port search.
+ * @param[in] phy The phy object to match.
+ *
+ * @return The port address or the SCI_INVALID_HANDLE if there is no matching
+ *         port.
+ *
+ * @retvalue port address if the port can be found to match the phy.
+ * @retvalue SCI_INVALID_HANDLE if there is no matching port for the phy.
+ */
+static
+SCIC_SDS_PORT_T * scic_sds_port_configuration_agent_find_port(
+   SCIC_SDS_CONTROLLER_T * controller,
+   SCIC_SDS_PHY_T        * phy
+)
+{
+   U8 port_index;
+   SCI_PORT_HANDLE_T port_handle;
+   SCI_SAS_ADDRESS_T port_sas_address;
+   SCI_SAS_ADDRESS_T port_attached_device_address;
+   SCI_SAS_ADDRESS_T phy_sas_address;
+   SCI_SAS_ADDRESS_T phy_attached_device_address;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_PORT | SCIC_LOG_OBJECT_PHY,
+      "scic_sds_port_confgiruation_agent_find_port(0x%08x, 0x%08x) enter\n",
+      controller, phy
+   ));
+
+   // Since this phy can be a member of a wide port check to see if one or
+   // more phys match the sent and received SAS address as this phy in which
+   // case it should participate in the same port.
+   scic_sds_phy_get_sas_address(phy, &phy_sas_address);
+   scic_sds_phy_get_attached_sas_address(phy, &phy_attached_device_address);
+
+   for (port_index = 0; port_index < SCI_MAX_PORTS; port_index++)
+   {
+      if (scic_controller_get_port_handle(controller, port_index, &port_handle) == SCI_SUCCESS)
+      {
+         SCIC_SDS_PORT_T * port = (SCIC_SDS_PORT_T *)port_handle;
+
+         scic_sds_port_get_sas_address(port, &port_sas_address);
+         scic_sds_port_get_attached_sas_address(port, &port_attached_device_address);
+
+         if (
+               (sci_sas_address_compare(port_sas_address, phy_sas_address) == 0)
+            && (sci_sas_address_compare(port_attached_device_address, phy_attached_device_address) == 0)
+            )
+         {
+            return port;
+         }
+      }
+   }
+
+   return SCI_INVALID_HANDLE;
+}
+
+/**
+ * This routine will validate the port configuration is correct for the SCU
+ * hardware.  The SCU hardware allows for port configurations as follows.
+ *    LP0 -> (PE0), (PE0, PE1), (PE0, PE1, PE2, PE3)
+ *    LP1 -> (PE1)
+ *    LP2 -> (PE2), (PE2, PE3)
+ *    LP3 -> (PE3)
+ *
+ * @param[in] controller This is the controller object that contains the
+ *            port agent
+ * @param[in] port_agent This is the port configruation agent for
+ *            the controller.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS the port configuration is valid for this
+ *         port configuration agent.
+ * @retval SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION the port configuration
+ *         is not valid for this port configuration agent.
+ */
+static
+SCI_STATUS scic_sds_port_configuration_agent_validate_ports(
+   SCIC_SDS_CONTROLLER_T               * controller,
+   SCIC_SDS_PORT_CONFIGURATION_AGENT_T * port_agent
+)
+{
+#if !defined(ARLINGTON_BUILD)
+   SCI_SAS_ADDRESS_T first_address;
+   SCI_SAS_ADDRESS_T second_address;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_PORT,
+      "scic_sds_port_configuration_agent_validate_ports(0x%08x, 0x%08x) enter\n",
+      controller, port_agent
+   ));
+
+   // Sanity check the max ranges for all the phys the max index
+   // is always equal to the port range index
+   if (
+         (port_agent->phy_valid_port_range[0].max_index != 0)
+      || (port_agent->phy_valid_port_range[1].max_index != 1)
+      || (port_agent->phy_valid_port_range[2].max_index != 2)
+      || (port_agent->phy_valid_port_range[3].max_index != 3)
+      )
+   {
+      return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
+   }
+
+   // This is a request to configure a single x4 port or at least attempt
+   // to make all the phys into a single port
+   if (
+         (port_agent->phy_valid_port_range[0].min_index == 0)
+      && (port_agent->phy_valid_port_range[1].min_index == 0)
+      && (port_agent->phy_valid_port_range[2].min_index == 0)
+      && (port_agent->phy_valid_port_range[3].min_index == 0)
+      )
+   {
+      return SCI_SUCCESS;
+   }
+
+   // This is a degenerate case where phy 1 and phy 2 are assigned
+   // to the same port this is explicitly disallowed by the hardware
+   // unless they are part of the same x4 port and this condition was
+   // already checked above.
+   if (port_agent->phy_valid_port_range[2].min_index == 1)
+   {
+      return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
+   }
+
+   // PE0 and PE3 can never have the same SAS Address unless they
+   // are part of the same x4 wide port and we have already checked
+   // for this condition.
+   scic_sds_phy_get_sas_address(&controller->phy_table[0], &first_address);
+   scic_sds_phy_get_sas_address(&controller->phy_table[3], &second_address);
+
+   if (sci_sas_address_compare(first_address, second_address) == 0)
+   {
+      return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
+   }
+
+   // PE0 and PE1 are configured into a 2x1 ports make sure that the
+   // SAS Address for PE0 and PE2 are different since they can not be
+   // part of the same port.
+   if (
+         (port_agent->phy_valid_port_range[0].min_index == 0)
+      && (port_agent->phy_valid_port_range[1].min_index == 1)
+      )
+   {
+      scic_sds_phy_get_sas_address(&controller->phy_table[0], &first_address);
+      scic_sds_phy_get_sas_address(&controller->phy_table[2], &second_address);
+
+      if (sci_sas_address_compare(first_address, second_address) == 0)
+      {
+         return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
+      }
+   }
+
+   // PE2 and PE3 are configured into a 2x1 ports make sure that the
+   // SAS Address for PE1 and PE3 are different since they can not be
+   // part of the same port.
+   if (
+         (port_agent->phy_valid_port_range[2].min_index == 2)
+      && (port_agent->phy_valid_port_range[3].min_index == 3)
+      )
+   {
+      scic_sds_phy_get_sas_address(&controller->phy_table[1], &first_address);
+      scic_sds_phy_get_sas_address(&controller->phy_table[3], &second_address);
+
+      if (sci_sas_address_compare(first_address, second_address) == 0)
+      {
+         return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
+      }
+   }
+#endif // !defined(ARLINGTON_BUILD)
+
+   return SCI_SUCCESS;
+}
+
+//******************************************************************************
+// Manual port configuration agent routines
+//******************************************************************************
+
+/**
+ * This routine will verify that all of the phys in the same port are using
+ * the same SAS address.
+ *
+ * @param[in] controller This is the controller that contains the PHYs to
+ *            be verified.
+ */
+static
+SCI_STATUS scic_sds_mpc_agent_validate_phy_configuration(
+   SCIC_SDS_CONTROLLER_T               * controller,
+   SCIC_SDS_PORT_CONFIGURATION_AGENT_T * port_agent
+)
+{
+   U32 phy_mask;
+   U32 assigned_phy_mask;
+   SCI_SAS_ADDRESS_T sas_address;
+   SCI_SAS_ADDRESS_T phy_assigned_address;
+   U8 port_index;
+   U8 phy_index;
+
+   assigned_phy_mask = 0;
+   sas_address.high = 0;
+   sas_address.low = 0;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_PORT,
+      "scic_sds_mpc_agent_validate_phy_configuration(0x%08x, 0x%08x) enter\n",
+      controller, port_agent
+   ));
+
+   for (port_index = 0; port_index < SCI_MAX_PORTS; port_index++)
+   {
+      phy_mask = controller->oem_parameters.sds1.ports[port_index].phy_mask;
+
+      if (phy_mask != 0)
+      {
+         // Make sure that one or more of the phys were not already assinged to
+         // a different port.
+         if ((phy_mask & ~assigned_phy_mask) == 0)
+         {
+            return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
+         }
+
+         // Find the starting phy index for this round through the loop
+         for (phy_index = 0; phy_index < SCI_MAX_PHYS; phy_index++)
+         {
+            if ((1 << phy_index) & phy_mask)
+            {
+               scic_sds_phy_get_sas_address(
+                  &controller->phy_table[phy_index], &sas_address
+               );
+
+               // The phy_index can be used as the starting point for the
+               // port range since the hardware starts all logical ports
+               // the same as the PE index.
+               port_agent->phy_valid_port_range[phy_index].min_index = port_index;
+               port_agent->phy_valid_port_range[phy_index].max_index = phy_index;
+
+               if (phy_index != port_index)
+               {
+                  return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
+               }
+
+               break;
+            }
+         }
+
+         // See how many additional phys are being added to this logical port.
+         // Note: We have not moved the current phy_index so we will actually
+         //       compare the startting phy with itself.
+         //       This is expected and required to add the phy to the port.
+         while (phy_index < SCI_MAX_PHYS)
+         {
+            if ((1 << phy_index) & phy_mask)
+            {
+               scic_sds_phy_get_sas_address(
+                  &controller->phy_table[phy_index], &phy_assigned_address
+               );
+
+               if (sci_sas_address_compare(sas_address, phy_assigned_address) != 0)
+               {
+                  // The phy mask specified that this phy is part of the same port
+                  // as the starting phy and it is not so fail this configuration
+                  return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
+               }
+
+               port_agent->phy_valid_port_range[phy_index].min_index = port_index;
+               port_agent->phy_valid_port_range[phy_index].max_index = phy_index;
+
+               scic_sds_port_add_phy(
+                  &controller->port_table[port_index],
+                  &controller->phy_table[phy_index]
+               );
+
+               assigned_phy_mask |= (1 << phy_index);
+            }
+
+            phy_index++;
+         }
+      }
+   }
+
+   return scic_sds_port_configuration_agent_validate_ports(controller, port_agent);
+}
+
+/**
+ * This timer routine is used to allow the SCI User to rediscover or change
+ * device objects before a new series of link up notifications because a
+ * link down has allowed a better port configuration.
+ *
+ * @param[in] controller This is the core controller object which is used
+ *            to obtain the port configuration agent.
+ */
+static
+void scic_sds_mpc_agent_timeout_handler(
+   void * object
+)
+{
+   U8 index;
+   SCIC_SDS_CONTROLLER_T * controller = (SCIC_SDS_CONTROLLER_T *)object;
+   SCIC_SDS_PORT_CONFIGURATION_AGENT_T * port_agent = &controller->port_agent;
+   U16 configure_phy_mask;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_PORT,
+      "scic_sds_mpc_agent_timeout_handler(0x%08x) enter\n",
+      controller
+   ));
+
+   port_agent->timer_pending = FALSE;
+
+   // Find the mask of phys that are reported read but as yet unconfigured into a port
+   configure_phy_mask = ~port_agent->phy_configured_mask & port_agent->phy_ready_mask;
+
+   for (index = 0; index < SCI_MAX_PHYS; index++)
+   {
+      if (configure_phy_mask & (1 << index))
+      {
+         port_agent->link_up_handler(
+                        controller,
+                        port_agent,
+                        scic_sds_phy_get_port(&controller->phy_table[index]),
+                        &controller->phy_table[index]
+                     );
+      }
+   }
+}
+
+/**
+ * This method handles the manual port configuration link up notifications.
+ * Since all ports and phys are associate at initialization time we just turn
+ * around and notifiy the port object that there is a link up.  If this PHY is
+ * not associated with a port there is no action taken.
+ *
+ * @param[in] controller This is the controller object that receives the
+ *            link up notification.
+ * @param[in] port This is the port object associated with the phy.  If the
+ *            is no associated port this is an SCI_INVALID_HANDLE.
+ * @param[in] phy This is the phy object which has gone ready.
+ *
+ * @note Is it possible to get a link up notification from a phy that has
+ *       no assocoated port?
+ */
+static
+void scic_sds_mpc_agent_link_up(
+   SCIC_SDS_CONTROLLER_T               * controller,
+   SCIC_SDS_PORT_CONFIGURATION_AGENT_T * port_agent,
+   SCIC_SDS_PORT_T                     * port,
+   SCIC_SDS_PHY_T                      * phy
+)
+{
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_PORT | SCIC_LOG_OBJECT_PHY,
+      "scic_sds_mpc_agent_link_up(0x%08x, 0x%08x, 0x%08x, 0x%08x) enter\n",
+      controller, port_agent, port, phy
+   ));
+
+   // If the port has an invalid handle then the phy was not assigned to
+   // a port.  This is because the phy was not given the same SAS Address
+   // as the other PHYs in the port.
+   if (port != SCI_INVALID_HANDLE)
+   {
+      port_agent->phy_ready_mask |= (1 << scic_sds_phy_get_index(phy));
+
+      scic_sds_port_link_up(port, phy);
+
+      if ((port->active_phy_mask & (1 << scic_sds_phy_get_index(phy))) != 0)
+      {
+         port_agent->phy_configured_mask |= (1 << scic_sds_phy_get_index(phy));
+      }
+   }
+}
+
+/**
+ * This method handles the manual port configuration link down notifications.
+ * Since all ports and phys are associated at initialization time we just turn
+ * around and notifiy the port object of the link down event.  If this PHY is
+ * not associated with a port there is no action taken.
+ *
+ * @param[in] controller This is the controller object that receives the
+ *            link down notification.
+ * @param[in] port This is the port object associated with the phy.  If the
+ *            is no associated port this is an SCI_INVALID_HANDLE.  The port
+ *            is an invalid handle only if the phy was never port of this
+ *            port.  This happens when the phy is not broadcasting the same
+ *            SAS address as the other phys in the assigned port.
+ * @param[in] phy This is the phy object which has gone link down.
+ *
+ * @note Is it possible to get a link down notification from a phy that has
+ *       no assocoated port?
+ */
+static
+void scic_sds_mpc_agent_link_down(
+   SCIC_SDS_CONTROLLER_T               * controller,
+   SCIC_SDS_PORT_CONFIGURATION_AGENT_T * port_agent,
+   SCIC_SDS_PORT_T                     * port,
+   SCIC_SDS_PHY_T                      * phy
+)
+{
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_PORT | SCIC_LOG_OBJECT_PHY,
+      "scic_sds_mpc_agent_link_down(0x%08x, 0x%08x, 0x%08x, 0x%08x) enter\n",
+      controller, port_agent, port, phy
+   ));
+
+   if (port != SCI_INVALID_HANDLE)
+   {
+      // If we can form a new port from the remainder of the phys then we want
+      // to start the timer to allow the SCI User to cleanup old devices and
+      // rediscover the port before rebuilding the port with the phys that
+      // remain in the ready state.
+      port_agent->phy_ready_mask &= ~(1 << scic_sds_phy_get_index(phy));
+      port_agent->phy_configured_mask &= ~(1 << scic_sds_phy_get_index(phy));
+
+      // Check to see if there are more phys waiting to be configured into a port.
+      // If there are allow the SCI User to tear down this port, if necessary, and
+      // then reconstruc the port after the timeout.
+      if (
+            (port_agent->phy_configured_mask == 0x0000)
+         && (port_agent->phy_ready_mask != 0x0000)
+         && !port_agent->timer_pending
+         )
+      {
+         port_agent->timer_pending = TRUE;
+
+         scic_cb_timer_start(
+            controller,
+            port_agent->timer,
+            SCIC_SDS_MPC_RECONFIGURATION_TIMEOUT
+         );
+      }
+
+      scic_sds_port_link_down(port, phy);
+   }
+}
+
+//******************************************************************************
+// Automatic port configuration agent routines
+//******************************************************************************
+
+/**
+ * This routine will verify that the phys are assigned a valid SAS address for
+ * automatic port configuration mode.
+ */
+static
+SCI_STATUS scic_sds_apc_agent_validate_phy_configuration(
+   SCIC_SDS_CONTROLLER_T               * controller,
+   SCIC_SDS_PORT_CONFIGURATION_AGENT_T * port_agent
+)
+{
+   U8 phy_index;
+   U8 port_index;
+   SCI_SAS_ADDRESS_T sas_address;
+   SCI_SAS_ADDRESS_T phy_assigned_address;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_PORT,
+      "scic_sds_apc_agent_validate_phy_configuration(0x%08x, 0x%08x) enter\n",
+      controller, port_agent
+   ));
+
+   phy_index = 0;
+
+   while (phy_index < SCI_MAX_PHYS)
+   {
+      port_index = phy_index;
+
+      // Get the assigned SAS Address for the first PHY on the controller.
+      scic_sds_phy_get_sas_address(
+         &controller->phy_table[phy_index], &sas_address
+      );
+
+      while (++phy_index < SCI_MAX_PHYS)
+      {
+         scic_sds_phy_get_sas_address(
+            &controller->phy_table[phy_index], &phy_assigned_address
+         );
+
+         // Verify each of the SAS address are all the same for every PHY
+         if (sci_sas_address_compare(sas_address, phy_assigned_address) == 0)
+         {
+            port_agent->phy_valid_port_range[phy_index].min_index = port_index;
+            port_agent->phy_valid_port_range[phy_index].max_index = phy_index;
+         }
+         else
+         {
+            port_agent->phy_valid_port_range[phy_index].min_index = phy_index;
+            port_agent->phy_valid_port_range[phy_index].max_index = phy_index;
+            break;
+         }
+      }
+   }
+
+   return scic_sds_port_configuration_agent_validate_ports(controller, port_agent);
+}
+
+/**
+ * This routine will restart the automatic port configuration timeout
+ * timer for the next time period.  This could be caused by either a
+ * link down event or a link up event where we can not yet tell to which
+ * port a phy belongs.
+ *
+ * @param[in] controller This is the controller that to which the port
+ *            agent is assigned.
+ * @param[in] port_agent This is the port agent that is requesting the
+ *            timer start operation.
+ * @param[in] phy This is the phy that has caused the timer operation to
+ *            be scheduled.
+ * @param[in] timeout This is the timeout in ms.
+ */
+static
+void scic_sds_apc_agent_start_timer(
+   SCIC_SDS_CONTROLLER_T               * controller,
+   SCIC_SDS_PORT_CONFIGURATION_AGENT_T * port_agent,
+   SCIC_SDS_PHY_T                      * phy,
+   U32                                   timeout
+)
+{
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_PORT | SCIC_LOG_OBJECT_PHY,
+      "scic_sds_apc_agent_start_timer(0x%08x, 0x%08x, 0x%08x, 0x%08x) enter\n",
+      controller, port_agent, phy, timeout
+   ));
+
+   if (port_agent->timer_pending)
+   {
+      scic_cb_timer_stop(controller, port_agent->timer);
+   }
+
+   port_agent->timer_pending = TRUE;
+
+   scic_cb_timer_start(controller, port_agent->timer, timeout);
+}
+
+/**
+ * This method handles the automatic port configuration for link up notifications.
+ *
+ * @param[in] controller This is the controller object that receives the
+ *            link up notification.
+ * @param[in] phy This is the phy object which has gone link up.
+ * @param[in] start_timer This tells the routine if it should start the timer for
+ *            any phys that might be added to a port in the future.
+ */
+static
+void scic_sds_apc_agent_configure_ports(
+   SCIC_SDS_CONTROLLER_T               * controller,
+   SCIC_SDS_PORT_CONFIGURATION_AGENT_T * port_agent,
+   SCIC_SDS_PHY_T                      * phy,
+   BOOL                                  start_timer
+)
+{
+   U8 port_index;
+   SCI_STATUS status;
+   SCIC_SDS_PORT_T * port;
+   SCI_PORT_HANDLE_T port_handle;
+   enum SCIC_SDS_APC_ACTIVITY apc_activity = SCIC_SDS_APC_SKIP_PHY;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_PORT | SCIC_LOG_OBJECT_PHY,
+      "scic_sds_apc_agent_configure_ports(0x%08x, 0x%08x, 0x%08x, %d) enter\n",
+      controller, port_agent, phy, start_timer
+   ));
+
+   port = scic_sds_port_configuration_agent_find_port(controller, phy);
+
+   if (port != SCI_INVALID_HANDLE)
+   {
+      if (scic_sds_port_is_valid_phy_assignment(port, phy->phy_index))
+         apc_activity = SCIC_SDS_APC_ADD_PHY;
+      else
+         apc_activity = SCIC_SDS_APC_SKIP_PHY;
+   }
+   else
+   {
+      // There is no matching Port for this PHY so lets search through the
+      // Ports and see if we can add the PHY to its own port or maybe start
+      // the timer and wait to see if a wider port can be made.
+      //
+      // Note the break when we reach the condition of the port id == phy id
+      for (
+             port_index = port_agent->phy_valid_port_range[phy->phy_index].min_index;
+             port_index <= port_agent->phy_valid_port_range[phy->phy_index].max_index;
+             port_index++
+          )
+      {
+         scic_controller_get_port_handle(controller, port_index, &port_handle);
+
+         port = (SCIC_SDS_PORT_T *)port_handle;
+
+         // First we must make sure that this PHY can be added to this Port.
+         if (scic_sds_port_is_valid_phy_assignment(port, phy->phy_index))
+         {
+            // Port contains a PHY with a greater PHY ID than the current
+            // PHY that has gone link up.  This phy can not be part of any
+            // port so skip it and move on.
+            if (port->active_phy_mask > (1 << phy->phy_index))
+            {
+               apc_activity = SCIC_SDS_APC_SKIP_PHY;
+               break;
+            }
+
+            // We have reached the end of our Port list and have not found
+            // any reason why we should not either add the PHY to the port
+            // or wait for more phys to become active.
+            if (port->physical_port_index == phy->phy_index)
+            {
+               // The Port either has no active PHYs.
+               // Consider that if the port had any active PHYs we would have
+               // or active PHYs with
+               // a lower PHY Id than this PHY.
+               if (apc_activity != SCIC_SDS_APC_START_TIMER)
+               {
+                  apc_activity = SCIC_SDS_APC_ADD_PHY;
+               }
+
+               break;
+            }
+
+            // The current Port has no active PHYs and this PHY could be part
+            // of this Port.  Since we dont know as yet setup to start the
+            // timer and see if there is a better configuration.
+            if (port->active_phy_mask == 0)
+            {
+               apc_activity = SCIC_SDS_APC_START_TIMER;
+            }
+         }
+         else if (port->active_phy_mask != 0)
+         {
+            // The Port has an active phy and the current Phy can not
+            // participate in this port so skip the PHY and see if
+            // there is a better configuration.
+            apc_activity = SCIC_SDS_APC_SKIP_PHY;
+         }
+      }
+   }
+
+   // Check to see if the start timer operations should instead map to an
+   // add phy operation.  This is caused because we have been waiting to
+   // add a phy to a port but could not becuase the automatic port
+   // configuration engine had a choice of possible ports for the phy.
+   // Since we have gone through a timeout we are going to restrict the
+   // choice to the smallest possible port.
+   if (
+         (start_timer == FALSE)
+      && (apc_activity == SCIC_SDS_APC_START_TIMER)
+      )
+   {
+      apc_activity = SCIC_SDS_APC_ADD_PHY;
+   }
+
+   switch (apc_activity)
+   {
+   case SCIC_SDS_APC_ADD_PHY:
+      status = scic_sds_port_add_phy(port, phy);
+
+      if (status == SCI_SUCCESS)
+      {
+         port_agent->phy_configured_mask |= (1 << phy->phy_index);
+      }
+      break;
+
+   case SCIC_SDS_APC_START_TIMER:
+      scic_sds_apc_agent_start_timer(
+         controller, port_agent, phy, SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION
+      );
+      break;
+
+   case SCIC_SDS_APC_SKIP_PHY:
+   default:
+      // do nothing the PHY can not be made part of a port at this time.
+      break;
+   }
+}
+
+/**
+ * This method handles the automatic port configuration for link up notifications.
+ *
+ * @param[in] controller This is the controller object that receives the
+ *            link up notification.
+ * @param[in] port This is the port object associated with the phy.  If the
+ *            is no associated port this is an SCI_INVALID_HANDLE.
+ * @param[in] phy This is the phy object which has gone link up.
+ *
+ * @note Is it possible to get a link down notification from a phy that has
+ *       no assocoated port?
+ */
+static
+void scic_sds_apc_agent_link_up(
+   SCIC_SDS_CONTROLLER_T               * controller,
+   SCIC_SDS_PORT_CONFIGURATION_AGENT_T * port_agent,
+   SCIC_SDS_PORT_T                     * port,
+   SCIC_SDS_PHY_T                      * phy
+)
+{
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_PORT | SCIC_LOG_OBJECT_PHY,
+      "scic_sds_apc_agent_link_up(0x%08x, 0x%08x, 0x%08x, 0x%08x) enter\n",
+      controller, port_agent, port, phy
+   ));
+
+   //the phy is not the part of this port, configure the port with this phy
+   if (port == SCI_INVALID_HANDLE)
+   {
+      port_agent->phy_ready_mask |= (1 << scic_sds_phy_get_index(phy));
+
+      scic_sds_apc_agent_start_timer(
+         controller, port_agent, phy, SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION
+      );
+   }
+   else
+   {
+      //the phy is already the part of the port
+
+      //if the PORT'S state is resetting then the link up is from port hard reset
+      //in this case, we need to tell the port that link up is recieved
+      if (  SCI_BASE_PORT_STATE_RESETTING
+            == port->parent.state_machine.current_state_id
+         )
+      {
+         //notify the port that port needs to be ready
+         port_agent->phy_ready_mask |= (1 << scic_sds_phy_get_index(phy));
+         scic_sds_port_link_up(port, phy);
+      }
+      else
+      {
+         ASSERT (0);
+      }
+   }
+}
+
+/**
+ * This method handles the automatic port configuration link down notifications.
+ * If this PHY is * not associated with a port there is no action taken.
+ *
+ * @param[in] controller This is the controller object that receives the
+ *            link down notification.
+ * @param[in] port This is the port object associated with the phy.  If the
+ *            is no associated port this is an SCI_INVALID_HANDLE.
+ * @param[in] phy This is the phy object which has gone link down.
+ *
+ * @note Is it possible to get a link down notification from a phy that has
+ *       no assocoated port?
+ */
+static
+void scic_sds_apc_agent_link_down(
+   SCIC_SDS_CONTROLLER_T               * controller,
+   SCIC_SDS_PORT_CONFIGURATION_AGENT_T * port_agent,
+   SCIC_SDS_PORT_T                     * port,
+   SCIC_SDS_PHY_T                      * phy
+)
+{
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_PORT | SCIC_LOG_OBJECT_PHY,
+      "scic_sds_apc_agent_link_down(0x%08x, 0x%08x, 0x%08x, 0x%08x) enter\n",
+      controller, port_agent, port, phy
+   ));
+
+   port_agent->phy_ready_mask &= ~(1 << scic_sds_phy_get_index(phy));
+
+   if (port != SCI_INVALID_HANDLE)
+   {
+      if (port_agent->phy_configured_mask & (1 << phy->phy_index))
+      {
+         SCI_STATUS status;
+
+         status = scic_sds_port_remove_phy(port, phy);
+
+         if (status == SCI_SUCCESS)
+         {
+            port_agent->phy_configured_mask &= ~(1 << phy->phy_index);
+         }
+      }
+   }
+}
+
+/**
+ * This routine will try to configure the phys into ports when the timer fires.
+ *
+ * @param[in] object This is actually the controller that needs to have the
+ *            pending phys configured.
+ */
+static
+void scic_sds_apc_agent_timeout_handler(
+   void * object
+)
+{
+   U32 index;
+   SCIC_SDS_PORT_CONFIGURATION_AGENT_T * port_agent;
+   SCIC_SDS_CONTROLLER_T * controller = (SCIC_SDS_CONTROLLER_T *)object;
+   U16 configure_phy_mask;
+
+   port_agent = scic_sds_controller_get_port_configuration_agent(controller);
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_PORT,
+      "scic_sds_apc_agent_timeout_handler(0x%08x) enter\n",
+      controller
+   ));
+
+   port_agent->timer_pending = FALSE;
+
+   configure_phy_mask = ~port_agent->phy_configured_mask & port_agent->phy_ready_mask;
+
+   if (configure_phy_mask != 0x00)
+   {
+      for (index = 0; index < SCI_MAX_PHYS; index++)
+      {
+         if (configure_phy_mask & (1 << index))
+         {
+            scic_sds_apc_agent_configure_ports(
+               controller, port_agent, &controller->phy_table[index], FALSE
+            );
+         }
+      }
+
+      //Notify the controller ports are configured.
+      if (
+            (port_agent->phy_ready_mask == port_agent->phy_configured_mask) &&
+            (controller->next_phy_to_start == SCI_MAX_PHYS) &&
+            (controller->phy_startup_timer_pending == FALSE)
+         )
+      {
+         // The controller has successfully finished the start process.
+         // Inform the SCI Core user and transition to the READY state.
+         if (scic_sds_controller_is_start_complete(controller) == TRUE)
+         {
+            scic_sds_controller_port_agent_configured_ports(controller);
+         }
+      }
+   }
+}
+
+//******************************************************************************
+// Public port configuration agent routines
+//******************************************************************************
+
+/**
+ * This method will construct the port configuration agent for operation.
+ * This call is universal for both manual port configuration and automatic
+ * port configuration modes.
+ *
+ * @param[in] port_agent This is the port configuration agent for this
+ *            controller object.
+ */
+void scic_sds_port_configuration_agent_construct(
+   SCIC_SDS_PORT_CONFIGURATION_AGENT_T * port_agent
+)
+{
+   U32 index;
+
+   port_agent->phy_configured_mask = 0x00;
+   port_agent->phy_ready_mask = 0x00;
+
+   port_agent->link_up_handler = NULL;
+   port_agent->link_down_handler = NULL;
+
+   port_agent->timer_pending = FALSE;
+   port_agent->timer = NULL;
+
+   for (index = 0; index < SCI_MAX_PORTS; index++)
+   {
+      port_agent->phy_valid_port_range[index].min_index = 0;
+      port_agent->phy_valid_port_range[index].max_index = 0;
+   }
+}
+
+/**
+ * This method will construct the port configuration agent for this controller.
+ *
+ * @param[in] controller This is the controller object for which the port
+ *            agent is being initialized.
+ *
+ * @param[in] port_agent This is the port configuration agent that is being
+ *            initialized.  The initialization path is handled differntly
+ *            for the automatic port configuration agent and the manual port
+ *            configuration agent.
+ *
+ * @return
+ */
+SCI_STATUS scic_sds_port_configuration_agent_initialize(
+   SCIC_SDS_CONTROLLER_T               * controller,
+   SCIC_SDS_PORT_CONFIGURATION_AGENT_T * port_agent
+)
+{
+   SCI_STATUS status = SCI_SUCCESS;
+   enum SCIC_PORT_CONFIGURATION_MODE mode;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_PORT,
+      "scic_sds_port_configuration_agent_initialize(0x%08x, 0x%08x) enter\n",
+      controller, port_agent
+   ));
+
+   mode = controller->oem_parameters.sds1.controller.mode_type;
+
+   if (mode == SCIC_PORT_MANUAL_CONFIGURATION_MODE)
+   {
+      status = scic_sds_mpc_agent_validate_phy_configuration(controller, port_agent);
+
+      port_agent->link_up_handler = scic_sds_mpc_agent_link_up;
+      port_agent->link_down_handler = scic_sds_mpc_agent_link_down;
+
+      port_agent->timer = scic_cb_timer_create(
+                              controller,
+                              scic_sds_mpc_agent_timeout_handler,
+                              controller
+                          );
+   }
+   else
+   {
+      status = scic_sds_apc_agent_validate_phy_configuration(controller, port_agent);
+
+      port_agent->link_up_handler = scic_sds_apc_agent_link_up;
+      port_agent->link_down_handler = scic_sds_apc_agent_link_down;
+
+      port_agent->timer = scic_cb_timer_create(
+                              controller,
+                              scic_sds_apc_agent_timeout_handler,
+                              controller
+                          );
+   }
+
+   // Make sure we have actually gotten a timer
+   if (status == SCI_SUCCESS && port_agent->timer == NULL)
+   {
+      SCIC_LOG_ERROR((
+         sci_base_object_get_logger(controller),
+         SCIC_LOG_OBJECT_CONTROLLER,
+         "Controller 0x%x automatic port configuration agent could not get timer.\n",
+         controller
+     ));
+
+     status = SCI_FAILURE;
+   }
+
+   return status;
+}
+
+/**
+ * This method will destroy the port configuration agent for this controller.
+ *
+ * @param[in] controller This is the controller object for which the port
+ *            agent is being destroyed.
+ *
+ * @param[in] port_agent This is the port configuration agent that is being
+ *            destroyed.
+ *
+ * @return
+ */
+void scic_sds_port_configuration_agent_destroy(
+   SCIC_SDS_CONTROLLER_T               * controller,
+   SCIC_SDS_PORT_CONFIGURATION_AGENT_T * port_agent
+)
+{
+   if (port_agent->timer_pending == TRUE)
+   {
+      scic_cb_timer_stop(controller, port_agent->timer);
+   }
+
+   scic_cb_timer_destroy(controller, port_agent->timer);
+
+   port_agent->timer_pending = FALSE;
+   port_agent->timer = NULL;
+}
+
+
+/**
+ * @brief This method release resources in for a scic port configuration agent.
+ *
+ * @param[in] controller This parameter specifies the core controller, one of
+ *            its phy's resources are to be released.
+ * @param[in] this_phy This parameter specifies the phy whose resourse is to
+ *            be released.
+ */
+void scic_sds_port_configuration_agent_release_resource(
+   SCIC_SDS_CONTROLLER_T               * controller,
+   SCIC_SDS_PORT_CONFIGURATION_AGENT_T * port_agent
+)
+{
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIC_LOG_OBJECT_PORT,
+      "scic_sds_port_configuration_agent_release_resource(0x%x, 0x%x)\n",
+      controller, port_agent
+   ));
+
+   //Currently, the only resource to be released is a timer.
+   if (port_agent->timer != NULL)
+   {
+      scic_cb_timer_destroy(controller, port_agent->timer);
+      port_agent->timer = NULL;
+   }
+}
diff --git a/sys/dev/disk/isci/scil/scic_sds_port_configuration_agent.h b/sys/dev/disk/isci/scil/scic_sds_port_configuration_agent.h
new file mode 100644
index 0000000..8d5b2b6
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_sds_port_configuration_agent.h
@@ -0,0 +1,128 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_sds_port_configuration_agent.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIC_SDS_PORT_CONFIGURATION_AGENT_H_
+#define _SCIC_SDS_PORT_CONFIGURATION_AGENT_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains the structures, constants and prototypes used for
+ *        the core controller automatic port configuration engine.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/scic_sds_port.h>
+#include <dev/disk/isci/scil/scic_sds_phy.h>
+
+struct SCIC_SDS_CONTROLLER;
+struct SCIC_SDS_PORT_CONFIGURATION_AGENT;
+struct SCIC_SDS_PORT;
+struct SCIC_SDS_PHY;
+
+typedef void (*SCIC_SDS_PORT_CONFIGURATION_AGENT_PHY_HANDLER_T)(
+   struct SCIC_SDS_CONTROLLER *,
+   struct SCIC_SDS_PORT_CONFIGURATION_AGENT *,
+   struct SCIC_SDS_PORT *,
+   struct SCIC_SDS_PHY  *
+);
+
+struct SCIC_SDS_PORT_RANGE
+{
+   U8 min_index;
+   U8 max_index;
+};
+
+typedef struct SCIC_SDS_PORT_CONFIGURATION_AGENT
+{
+   U16 phy_configured_mask;
+   U16 phy_ready_mask;
+
+   struct SCIC_SDS_PORT_RANGE phy_valid_port_range[SCI_MAX_PHYS];
+
+   BOOL timer_pending;
+
+   SCIC_SDS_PORT_CONFIGURATION_AGENT_PHY_HANDLER_T link_up_handler;
+   SCIC_SDS_PORT_CONFIGURATION_AGENT_PHY_HANDLER_T link_down_handler;
+
+   void *timer;
+
+} SCIC_SDS_PORT_CONFIGURATION_AGENT_T;
+
+void scic_sds_port_configuration_agent_construct(
+   SCIC_SDS_PORT_CONFIGURATION_AGENT_T * port_agent
+);
+
+SCI_STATUS scic_sds_port_configuration_agent_initialize(
+   struct SCIC_SDS_CONTROLLER          * controller,
+   SCIC_SDS_PORT_CONFIGURATION_AGENT_T * port_agent
+);
+
+void scic_sds_port_configuration_agent_destroy(
+   struct SCIC_SDS_CONTROLLER          * controller,
+   SCIC_SDS_PORT_CONFIGURATION_AGENT_T * port_agent
+);
+
+void scic_sds_port_configuration_agent_release_resource(
+   struct SCIC_SDS_CONTROLLER          * controller,
+   SCIC_SDS_PORT_CONFIGURATION_AGENT_T * port_agent
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIC_SDS_PORT_CONFIGURATION_AGENT_H_
diff --git a/sys/dev/disk/isci/scil/scic_sds_port_registers.h b/sys/dev/disk/isci/scil/scic_sds_port_registers.h
new file mode 100644
index 0000000..82f8466
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_sds_port_registers.h
@@ -0,0 +1,139 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_sds_port_registers.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIC_SDS_PORT_REGISTERS_H_
+#define _SCIC_SDS_PORT_REGISTERS_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains a set of macros that assist in reading the SCU
+ * hardware registers.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+/**
+ * Macro to read the port task scheduler register associated with this port
+ * object
+ */
+#define scu_port_task_scheduler_read(port, reg) \
+   scu_register_read( \
+      scic_sds_port_get_controller(port), \
+      (port)->port_task_scheduler_registers->reg \
+   )
+
+/**
+ * Macro to write the port task scheduler register associated with this
+ * port object
+ */
+#define scu_port_task_scheduler_write(port, reg, value) \
+   scu_register_write( \
+      scic_sds_port_get_controller(port), \
+      (port)->port_task_scheduler_registers->reg, \
+      (value) \
+   )
+
+#define scu_port_viit_register_write(port, reg, value) \
+   scu_register_write( \
+      scic_sds_port_get_controller(port), \
+      (port)->viit_registers->reg, \
+      (value) \
+   )
+
+//****************************************************************************
+//* Port Task Scheduler registers controlled by the port object
+//****************************************************************************
+
+/**
+ * Macro to read the port task scheduler control register
+ */
+#define SCU_PTSxCR_READ(port) \
+   scu_port_task_scheduler_read(port, control)
+
+/**
+ * Macro to write the port task scheduler control regsister
+ */
+#define SCU_PTSxCR_WRITE(port, value) \
+   scu_port_task_scheduler_write(port, control, value)
+
+//****************************************************************************
+//* Port PE Configuration registers
+//****************************************************************************
+
+/**
+ * Macro to write the PE Port Configuration Register
+ */
+#define SCU_PCSPExCR_WRITE(port, phy_id, value) \
+   scu_register_write( \
+      scic_sds_port_get_controller(port), \
+      (port)->port_pe_configuration_register[phy_id], \
+      (value) \
+   )
+
+/**
+ * Macro to read the PE Port Configuration Regsiter
+ */
+#define SCU_PCSPExCR_READ(port, phy_id) \
+   scu_register_read( \
+      scic_sds_port_get_controller(port), \
+      (port)->port_pe_configuration_register[phy_id] \
+   )
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIC_SDS_PORT_REGISTERS_H_
diff --git a/sys/dev/disk/isci/scil/scic_sds_remote_device.c b/sys/dev/disk/isci/scil/scic_sds_remote_device.c
new file mode 100644
index 0000000..9d47531
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_sds_remote_device.c
@@ -0,0 +1,2725 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_sds_remote_device.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains the implementation of remote device, it's
+ *        methods and state machine.
+ */
+
+#include <dev/disk/isci/scil/intel_sas.h>
+#include <dev/disk/isci/scil/sci_util.h>
+#include <dev/disk/isci/scil/scic_port.h>
+#include <dev/disk/isci/scil/scic_phy.h>
+#include <dev/disk/isci/scil/scic_remote_device.h>
+#include <dev/disk/isci/scil/scic_sds_port.h>
+#include <dev/disk/isci/scil/scic_sds_phy.h>
+#include <dev/disk/isci/scil/scic_sds_remote_device.h>
+#include <dev/disk/isci/scil/scic_sds_request.h>
+#include <dev/disk/isci/scil/scic_sds_controller.h>
+#include <dev/disk/isci/scil/scic_sds_logger.h>
+#include <dev/disk/isci/scil/scic_user_callback.h>
+#include <dev/disk/isci/scil/scic_controller.h>
+#include <dev/disk/isci/scil/scic_sds_logger.h>
+#include <dev/disk/isci/scil/scic_sds_remote_node_context.h>
+#include <dev/disk/isci/scil/scu_event_codes.h>
+
+#define SCIC_SDS_REMOTE_DEVICE_RESET_TIMEOUT  (1000)
+
+//*****************************************************************************
+//*  CORE REMOTE DEVICE PUBLIC METHODS
+//*****************************************************************************
+
+U32 scic_remote_device_get_object_size(void)
+{
+   return   sizeof(SCIC_SDS_REMOTE_DEVICE_T)
+          + sizeof(SCIC_SDS_REMOTE_NODE_CONTEXT_T);
+}
+
+// ---------------------------------------------------------------------------
+
+void scic_remote_device_construct(
+   SCI_PORT_HANDLE_T            port,
+   void                       * remote_device_memory,
+   SCI_REMOTE_DEVICE_HANDLE_T * new_remote_device_handle
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T*)
+                                           remote_device_memory;
+   SCIC_SDS_PORT_T          *the_port    = (SCIC_SDS_PORT_T*) port;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(the_port),
+      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
+      "scic_remote_device_construct(0x%x, 0x%x, 0x%x) enter\n",
+      port, remote_device_memory, new_remote_device_handle
+   ));
+
+   memset(remote_device_memory, 0, sizeof(SCIC_SDS_REMOTE_DEVICE_T));
+
+   *new_remote_device_handle          = this_device;
+   this_device->owning_port           = the_port;
+   this_device->started_request_count = 0;
+   this_device->rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)
+      ((char *)this_device + sizeof(SCIC_SDS_REMOTE_DEVICE_T));
+
+   sci_base_remote_device_construct(
+      &this_device->parent,
+      sci_base_object_get_logger(the_port),
+      scic_sds_remote_device_state_table
+   );
+
+   scic_sds_remote_node_context_construct(
+      this_device,
+      this_device->rnc,
+      SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX
+   );
+
+   sci_object_set_association(this_device->rnc, this_device);
+
+   scic_sds_remote_device_initialize_state_logging(this_device);
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_remote_device_da_construct(
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device
+)
+{
+   SCI_STATUS                status;
+   U16                       remote_node_index;
+   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T*)
+                                           remote_device;
+   SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T  protocols;
+   SCIC_PORT_PROPERTIES_T  properties;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_device->owning_port),
+      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
+      "scic_remote_device_da_construct(0x%x) enter\n",
+      remote_device
+   ));
+
+   // This information is request to determine how many remote node context
+   // entries will be needed to store the remote node.
+   scic_sds_port_get_attached_protocols(this_device->owning_port,&protocols);
+   this_device->target_protocols.u.all = protocols.u.all;
+   this_device->is_direct_attached = TRUE;
+#if !defined(DISABLE_ATAPI)
+   this_device->is_atapi = scic_sds_remote_device_is_atapi(this_device);
+#endif
+
+   scic_port_get_properties(this_device->owning_port, &properties);
+   //Get accurate port width from port's phy mask for a DA device.
+   SCI_GET_BITS_SET_COUNT(properties.phy_mask, this_device->device_port_width);
+
+   status = scic_sds_controller_allocate_remote_node_context(
+               this_device->owning_port->owning_controller,
+               this_device,
+               &remote_node_index
+            );
+
+   if (status == SCI_SUCCESS)
+   {
+      scic_sds_remote_node_context_set_remote_node_index(
+         this_device->rnc, remote_node_index
+      );
+
+      scic_sds_port_get_attached_sas_address(
+         this_device->owning_port, &this_device->device_address
+      );
+
+      if (this_device->target_protocols.u.bits.attached_ssp_target)
+      {
+         this_device->has_ready_substate_machine = FALSE;
+      }
+      else if (this_device->target_protocols.u.bits.attached_stp_target)
+      {
+         this_device->has_ready_substate_machine = TRUE;
+
+         sci_base_state_machine_construct(
+            &this_device->ready_substate_machine,
+            &this_device->parent.parent,
+            scic_sds_stp_remote_device_ready_substate_table,
+            SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
+         );
+      }
+      else if (this_device->target_protocols.u.bits.attached_smp_target)
+      {
+         this_device->has_ready_substate_machine = TRUE;
+
+         //add the SMP ready substate machine construction here
+         sci_base_state_machine_construct(
+            &this_device->ready_substate_machine,
+            &this_device->parent.parent,
+            scic_sds_smp_remote_device_ready_substate_table,
+            SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
+         );
+      }
+
+      this_device->connection_rate = scic_sds_port_get_max_allowed_speed(
+                                        this_device->owning_port
+                                     );
+
+      /// @todo Should I assign the port width by reading all of the phys on the port?
+      this_device->device_port_width = 1;
+   }
+
+   return status;
+}
+
+
+// ---------------------------------------------------------------------------
+
+void scic_sds_remote_device_get_info_from_smp_discover_response(
+   SCIC_SDS_REMOTE_DEVICE_T    * this_device,
+   SMP_RESPONSE_DISCOVER_T     * discover_response
+)
+{
+   // decode discover_response to set sas_address to this_device.
+   this_device->device_address.high =
+      discover_response->attached_sas_address.high;
+
+   this_device->device_address.low =
+      discover_response->attached_sas_address.low;
+
+   this_device->target_protocols.u.all = discover_response->protocols.u.all;
+}
+
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_remote_device_ea_construct(
+   SCI_REMOTE_DEVICE_HANDLE_T    remote_device,
+   SMP_RESPONSE_DISCOVER_T     * discover_response
+)
+{
+   SCI_STATUS status;
+
+   SCIC_SDS_REMOTE_DEVICE_T *this_device;
+   SCIC_SDS_CONTROLLER_T    *the_controller;
+
+   this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_device->owning_port),
+      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
+      "scic_remote_device_ea_sas_construct0x%x, 0x%x) enter\n",
+      remote_device, discover_response
+   ));
+
+   the_controller = scic_sds_port_get_controller(this_device->owning_port);
+
+   scic_sds_remote_device_get_info_from_smp_discover_response(
+      this_device, discover_response
+   );
+
+   status = scic_sds_controller_allocate_remote_node_context(
+               the_controller,
+               this_device,
+               &this_device->rnc->remote_node_index
+            );
+
+   if (status == SCI_SUCCESS)
+   {
+      if (this_device->target_protocols.u.bits.attached_ssp_target)
+      {
+         this_device->has_ready_substate_machine = FALSE;
+      }
+      else if (this_device->target_protocols.u.bits.attached_smp_target)
+      {
+         this_device->has_ready_substate_machine = TRUE;
+
+         //add the SMP ready substate machine construction here
+         sci_base_state_machine_construct(
+            &this_device->ready_substate_machine,
+            &this_device->parent.parent,
+            scic_sds_smp_remote_device_ready_substate_table,
+            SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
+         );
+      }
+      else if (this_device->target_protocols.u.bits.attached_stp_target)
+      {
+         this_device->has_ready_substate_machine = TRUE;
+
+         sci_base_state_machine_construct(
+            &this_device->ready_substate_machine,
+            &this_device->parent.parent,
+            scic_sds_stp_remote_device_ready_substate_table,
+            SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
+         );
+      }
+
+      // For SAS-2 the physical link rate is actually a logical link
+      // rate that incorporates multiplexing.  The SCU doesn't
+      // incorporate multiplexing and for the purposes of the
+      // connection the logical link rate is that same as the
+      // physical.  Furthermore, the SAS-2 and SAS-1.1 fields overlay
+      // one another, so this code works for both situations.
+      this_device->connection_rate = MIN(
+         scic_sds_port_get_max_allowed_speed( this_device->owning_port),
+         discover_response->u2.sas1_1.negotiated_physical_link_rate
+         );
+
+      /// @todo Should I assign the port width by reading all of the phys on the port?
+      this_device->device_port_width = 1;
+   }
+
+   return status;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_remote_device_destruct(
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T *this_device;
+   this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_device),
+      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
+      "scic_remote_device_destruct(0x%x) enter\n",
+      remote_device
+   ));
+
+   return this_device->state_handlers->parent.destruct_handler(&this_device->parent);
+}
+
+// ---------------------------------------------------------------------------
+
+#if !defined(DISABLE_WIDE_PORTED_TARGETS)
+
+SCI_STATUS scic_remote_device_set_port_width(
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
+   U8                          new_port_width
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T *this_device;
+
+   this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_device),
+      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
+      "scic_remote_device_set_port_width(0x%x, 0x%x) enter\n",
+      remote_device, new_port_width
+   ));
+
+   if(new_port_width != 0)
+   {
+      this_device->device_port_width = new_port_width;
+
+      return SCI_SUCCESS;
+   }
+   else
+      return SCI_FAILURE;
+}
+
+// ---------------------------------------------------------------------------
+
+U8 scic_remote_device_get_port_width(
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T *this_device;
+
+   this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_device),
+      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
+      "scic_remote_device_get_port_width(0x%x) enter\n",
+      remote_device
+   ));
+
+   return (U8)this_device->device_port_width;
+}
+
+#endif // !defined(DISABLE_WIDE_PORTED_TARGETS)
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_remote_device_start(
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
+   U32                         timeout
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T *this_device;
+   this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_device),
+      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
+      "scic_remote_device_start(0x%x, 0x%x) enter\n",
+      remote_device, timeout
+   ));
+
+   return this_device->state_handlers->parent.start_handler(&this_device->parent);
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_remote_device_stop(
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
+   U32                         timeout
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T *this_device;
+   this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_device),
+      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
+      "scic_remote_device_stop(0x%x, 0x%x) enter\n",
+      remote_device, timeout
+   ));
+
+   return this_device->state_handlers->parent.stop_handler(&this_device->parent);
+}
+
+/**
+ * This method invokes the remote device reset handler.
+ *
+ * @param[in] this_device The remote device for which the reset is being
+ *       requested.
+ *
+ * @return SCI_STATUS
+ */
+SCI_STATUS scic_remote_device_reset(
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T *this_device;
+   this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_device),
+      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
+      "scic_remote_device_reset(0x%x) enter\n",
+      remote_device
+   ));
+
+   return this_device->state_handlers->parent.reset_handler(&this_device->parent);
+}
+
+/**
+ * This method invokes the remote device reset handler.
+ *
+ * @param[in] this_device The remote device for which the reset is being
+ *       requested.
+ *
+ * @return SCI_STATUS
+ */
+SCI_STATUS scic_remote_device_reset_complete(
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T *this_device;
+   this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_device),
+      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
+      "scic_remote_device_reset_complete(0x%x) enter\n",
+      remote_device
+   ));
+
+   return this_device->state_handlers->parent.reset_complete_handler(&this_device->parent);
+}
+
+/**
+ * This method invokes the remote device reset handler.
+ *
+ * @param[in] this_device The remote device for which the reset is being
+ *       requested.
+ *
+ * @return SCI_STATUS
+ */
+U32 scic_remote_device_get_suggested_reset_timeout(
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T *this_device;
+   this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_device),
+      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
+      "scic_remote_device_get_suggested_reset_timeout(0x%x) enter\n",
+      remote_device
+   ));
+
+   if (this_device->target_protocols.u.bits.attached_stp_target)
+   {
+      return SCIC_SDS_SIGNATURE_FIS_TIMEOUT;
+   }
+
+   return SCIC_SDS_REMOTE_DEVICE_RESET_TIMEOUT;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_remote_device_set_max_connection_rate(
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
+   SCI_SAS_LINK_RATE           connection_rate
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T *this_device;
+   this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_device),
+      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
+      "scic_remote_device_set_max_connection_rate(0x%x, 0x%x) enter\n",
+      remote_device, connection_rate
+   ));
+
+   this_device->connection_rate = connection_rate;
+
+   return SCI_SUCCESS;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_SAS_LINK_RATE scic_remote_device_get_connection_rate(
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T *this_device;
+   this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_device),
+      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
+      "scic_remote_device_get_connection_rate(0x%x) enter\n",
+      remote_device
+   ));
+
+   return this_device->connection_rate;
+}
+
+// ---------------------------------------------------------------------------
+
+void scic_remote_device_get_protocols(
+   SCI_REMOTE_DEVICE_HANDLE_T          remote_device,
+   SMP_DISCOVER_RESPONSE_PROTOCOLS_T * protocols
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)
+                                            remote_device;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_device),
+      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
+      "scic_remote_device_get_protocols(0x%x) enter\n",
+      remote_device
+   ));
+
+   protocols->u.all = this_device->target_protocols.u.all;
+}
+
+// ---------------------------------------------------------------------------
+
+void scic_remote_device_get_sas_address(
+   SCI_REMOTE_DEVICE_HANDLE_T   remote_device,
+   SCI_SAS_ADDRESS_T          * sas_address
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T *this_device;
+   this_device = (SCIC_SDS_REMOTE_DEVICE_T *)remote_device;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_device),
+      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_STP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
+      "scic_remote_device_get_sas_address(0x%x, 0x%x) enter\n",
+      remote_device, sas_address
+   ));
+
+   sas_address->low = this_device->device_address.low;
+   sas_address->high = this_device->device_address.high;
+}
+
+// ---------------------------------------------------------------------------
+#if !defined(DISABLE_ATAPI)
+BOOL scic_remote_device_is_atapi(
+   SCI_REMOTE_DEVICE_HANDLE_T device_handle
+)
+{
+  return ((SCIC_SDS_REMOTE_DEVICE_T *)device_handle)->is_atapi;
+}
+#endif
+
+
+//*****************************************************************************
+//*  SCU DRIVER STANDARD (SDS) REMOTE DEVICE IMPLEMENTATIONS
+//*****************************************************************************
+
+/**
+ * Remote device timer requirements
+ */
+#define SCIC_SDS_REMOTE_DEVICE_MINIMUM_TIMER_COUNT (0)
+#define SCIC_SDS_REMOTE_DEVICE_MAXIMUM_TIMER_COUNT (SCI_MAX_REMOTE_DEVICES)
+
+/**
+ * @brief This method returns the minimum number of timers required for all
+ *        remote devices.
+ *
+ * @return U32
+ */
+U32 scic_sds_remote_device_get_min_timer_count(void)
+{
+   return SCIC_SDS_REMOTE_DEVICE_MINIMUM_TIMER_COUNT;
+}
+
+/**
+ * @brief This method returns the maximum number of timers requried for all
+ *        remote devices.
+ *
+ * @return U32
+ */
+U32 scic_sds_remote_device_get_max_timer_count(void)
+{
+   return SCIC_SDS_REMOTE_DEVICE_MAXIMUM_TIMER_COUNT;
+}
+
+// ---------------------------------------------------------------------------
+
+#ifdef SCI_LOGGING
+/**
+ * This method will enable and turn on state transition logging for the remote
+ * device object.
+ *
+ * @param[in] this_device The device for which state transition logging is to
+ *       be enabled.
+ *
+ * @return Nothing
+ */
+void scic_sds_remote_device_initialize_state_logging(
+   SCIC_SDS_REMOTE_DEVICE_T *this_device
+)
+{
+   sci_base_state_machine_logger_initialize(
+      &this_device->parent.state_machine_logger,
+      &this_device->parent.state_machine,
+      &this_device->parent.parent,
+      scic_cb_logger_log_states,
+      "SCIC_SDS_REMOTE_DEVICE_T", "base state machine",
+      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_STP_REMOTE_TARGET
+   );
+
+   if (this_device->has_ready_substate_machine)
+   {
+      sci_base_state_machine_logger_initialize(
+         &this_device->ready_substate_machine_logger,
+         &this_device->ready_substate_machine,
+         &this_device->parent.parent,
+         scic_cb_logger_log_states,
+         "SCIC_SDS_REMOTE_DEVICE_T", "ready substate machine",
+         SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+         SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
+         SCIC_LOG_OBJECT_STP_REMOTE_TARGET
+      );
+   }
+}
+
+/**
+ * This method will stop the state machine logging for this object and should
+ * be called before the object is destroyed.
+ *
+ * @param[in] this_device The device on which to stop logging state
+ *       transitions.
+ *
+ * @return Nothing
+ */
+void scic_sds_remote_device_deinitialize_state_logging(
+   SCIC_SDS_REMOTE_DEVICE_T *this_device
+)
+{
+   sci_base_state_machine_logger_deinitialize(
+      &this_device->parent.state_machine_logger,
+      &this_device->parent.state_machine
+   );
+
+   if (this_device->has_ready_substate_machine)
+   {
+      sci_base_state_machine_logger_deinitialize(
+         &this_device->ready_substate_machine_logger,
+         &this_device->ready_substate_machine
+      );
+   }
+}
+#endif
+
+/**
+ * This method invokes the remote device suspend state handler.
+ *
+ * @param[in] this_device The remote device for which the suspend is being
+ *       requested.
+ *
+ * @return SCI_STATUS
+ */
+SCI_STATUS scic_sds_remote_device_suspend(
+   SCIC_SDS_REMOTE_DEVICE_T *this_device,
+   U32                       suspend_type
+)
+{
+   return this_device->state_handlers->suspend_handler(this_device, suspend_type);
+}
+
+/**
+ * This method invokes the remote device resume state handler.
+ *
+ * @param[in] this_device The remote device for which the resume is being
+ *       requested.
+ *
+ * @return SCI_STATUS
+ */
+SCI_STATUS scic_sds_remote_device_resume(
+   SCIC_SDS_REMOTE_DEVICE_T *this_device
+)
+{
+   return this_device->state_handlers->resume_handler(this_device);
+}
+
+/**
+ * This method invokes the frame handler for the remote device state machine
+ *
+ * @param[in] this_device The remote device for which the event handling is
+ *       being requested.
+ * @param[in] frame_index This is the frame index that is being processed.
+ *
+ * @return SCI_STATUS
+ */
+SCI_STATUS scic_sds_remote_device_frame_handler(
+   SCIC_SDS_REMOTE_DEVICE_T *this_device,
+   U32                       frame_index
+)
+{
+   return this_device->state_handlers->frame_handler(this_device, frame_index);
+}
+
+/**
+ * This method invokes the remote device event handler.
+ *
+ * @param[in] this_device The remote device for which the event handling is
+ *       being requested.
+ * @param[in] event_code This is the event code that is to be processed.
+ *
+ * @return SCI_STATUS
+ */
+SCI_STATUS scic_sds_remote_device_event_handler(
+   SCIC_SDS_REMOTE_DEVICE_T *this_device,
+   U32                       event_code
+)
+{
+   return this_device->state_handlers->event_handler(this_device, event_code);
+}
+
+/**
+ * This method invokes the remote device start io handler.
+ *
+ * @param[in] controller The controller that is starting the io request.
+ * @param[in] this_device The remote device for which the start io handling is
+ *       being requested.
+ * @param[in] io_request The io request that is being started.
+ *
+ * @return SCI_STATUS
+ */
+SCI_STATUS scic_sds_remote_device_start_io(
+   SCIC_SDS_CONTROLLER_T    *controller,
+   SCIC_SDS_REMOTE_DEVICE_T *this_device,
+   SCIC_SDS_REQUEST_T       *io_request
+)
+{
+   return this_device->state_handlers->parent.start_io_handler(
+                                 &this_device->parent, &io_request->parent);
+}
+
+/**
+ * This method invokes the remote device complete io handler.
+ *
+ * @param[in] controller The controller that is completing the io request.
+ * @param[in] this_device The remote device for which the complete io handling
+ *       is being requested.
+ * @param[in] io_request The io request that is being completed.
+ *
+ * @return SCI_STATUS
+ */
+SCI_STATUS scic_sds_remote_device_complete_io(
+   SCIC_SDS_CONTROLLER_T    *controller,
+   SCIC_SDS_REMOTE_DEVICE_T *this_device,
+   SCIC_SDS_REQUEST_T       *io_request
+)
+{
+   return this_device->state_handlers->parent.complete_io_handler(
+                                 &this_device->parent, &io_request->parent);
+}
+
+/**
+ * This method invokes the remote device start task handler.
+ *
+ * @param[in] controller The controller that is starting the task request.
+ * @param[in] this_device The remote device for which the start task handling
+ *       is being requested.
+ * @param[in] io_request The task request that is being started.
+ *
+ * @return SCI_STATUS
+ */
+SCI_STATUS scic_sds_remote_device_start_task(
+   SCIC_SDS_CONTROLLER_T    *controller,
+   SCIC_SDS_REMOTE_DEVICE_T *this_device,
+   SCIC_SDS_REQUEST_T       *io_request
+)
+{
+   return this_device->state_handlers->parent.start_task_handler(
+                                  &this_device->parent, &io_request->parent);
+}
+
+/**
+ * This method takes the request and bulids an appropriate SCU context for the
+ * request and then requests the controller to post the request.
+ *
+ * @param[in] this_device
+ * @param[in] request
+ *
+ * @return none
+ */
+void scic_sds_remote_device_post_request(
+   SCIC_SDS_REMOTE_DEVICE_T * this_device,
+   U32                        request
+)
+{
+   U32 context;
+
+   context = scic_sds_remote_device_build_command_context(this_device, request);
+
+   scic_sds_controller_post_request(
+      scic_sds_remote_device_get_controller(this_device),
+      context
+   );
+}
+
+#if !defined(DISABLE_ATAPI)
+/**
+ * This method check the signature fis of a stp device to decide whether
+ * a device is atapi or not.
+ *
+ * @param[in] this_device The device to be checked.
+ *
+ * @return TRUE if a device is atapi device. False if a device is not atapi.
+ */
+BOOL scic_sds_remote_device_is_atapi(
+   SCIC_SDS_REMOTE_DEVICE_T * this_device
+)
+{
+   if (!this_device->target_protocols.u.bits.attached_stp_target)
+      return FALSE;
+   else if (this_device->is_direct_attached)
+   {
+      SCIC_SDS_PHY_T * phy;
+      SCIC_SATA_PHY_PROPERTIES_T properties;
+      SATA_FIS_REG_D2H_T * signature_fis;
+      phy = scic_sds_port_get_a_connected_phy(this_device->owning_port);
+      scic_sata_phy_get_properties(phy, &properties);
+
+      //decode the signature fis.
+      signature_fis = &(properties.signature_fis);
+
+      if (   (signature_fis->sector_count  == 0x01)
+          && (signature_fis->lba_low       == 0x01)
+          && (signature_fis->lba_mid       == 0x14)
+          && (signature_fis->lba_high      == 0xEB)
+          && ( (signature_fis->device & 0x5F) == 0x00)
+         )
+      {
+         // An ATA device supporting the PACKET command set.
+         return TRUE;
+      }
+      else
+         return FALSE;
+   }
+   else
+   {
+      //Expander supported ATAPI device is not currently supported.
+      return FALSE;
+   }
+}
+
+#endif // !defined(DISABLE_ATAPI)
+
+//******************************************************************************
+//* REMOTE DEVICE STATE MACHINE
+//******************************************************************************
+
+/**
+ * This method is called once the remote node context is ready to be
+ * freed.  The remote device can now report that its stop operation is
+ * complete.
+ *
+ * @param[in] user_parameter This is cast to a remote device object.
+ *
+ * @return none
+ */
+static
+void scic_sds_cb_remote_device_rnc_destruct_complete(
+   void * user_parameter
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T * this_device;
+   this_device = (SCIC_SDS_REMOTE_DEVICE_T *)user_parameter;
+
+   ASSERT(this_device->started_request_count == 0);
+
+   sci_base_state_machine_change_state(
+      scic_sds_remote_device_get_base_state_machine(this_device),
+      SCI_BASE_REMOTE_DEVICE_STATE_STOPPED
+   );
+}
+
+/**
+ * This method is called once the remote node context has transisitioned to a
+ * ready state.  This is the indication that the remote device object can also
+ * transition to ready.
+ *
+ * @param[in] user_parameter This is cast to a remote device object.
+ *
+ * @return none
+ */
+static
+void scic_sds_remote_device_resume_complete_handler(
+   void * user_parameter
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T * this_device;
+   this_device = (SCIC_SDS_REMOTE_DEVICE_T *)user_parameter;
+
+   if (
+         sci_base_state_machine_get_state(&this_device->parent.state_machine)
+      != SCI_BASE_REMOTE_DEVICE_STATE_READY
+      )
+   {
+      sci_base_state_machine_change_state(
+         &this_device->parent.state_machine,
+         SCI_BASE_REMOTE_DEVICE_STATE_READY
+      );
+   }
+}
+
+/**
+ * This method will perform the STP request start processing common
+ * to IO requests and task requests of all types.
+ *
+ * @param[in] device This parameter specifies the device for which the
+ *            request is being started.
+ * @param[in] request This parameter specifies the request being started.
+ * @param[in] status This parameter specifies the current start operation
+ *            status.
+ *
+ * @return none
+ */
+void scic_sds_remote_device_start_request(
+   SCIC_SDS_REMOTE_DEVICE_T * this_device,
+   SCIC_SDS_REQUEST_T       * the_request,
+   SCI_STATUS                 status
+)
+{
+   // We still have a fault in starting the io complete it on the port
+   if (status == SCI_SUCCESS)
+      scic_sds_remote_device_increment_request_count(this_device);
+   else
+   {
+      this_device->owning_port->state_handlers->complete_io_handler(
+         this_device->owning_port, this_device, the_request
+      );
+   }
+}
+
+
+/**
+ * This method will continue to post tc for a STP request. This method usually
+ * serves as a callback when RNC gets resumed during a task management sequence.
+ *
+ * @param[in] request This parameter specifies the request being continued.
+ *
+ * @return none
+ */
+void scic_sds_remote_device_continue_request(
+   SCIC_SDS_REMOTE_DEVICE_T * this_device
+)
+{
+   // we need to check if this request is still valid to continue.
+   if (this_device->working_request != NULL)
+   {
+      SCIC_SDS_REQUEST_T * this_request = this_device->working_request;
+
+      this_request->owning_controller->state_handlers->parent.continue_io_handler(
+         &this_request->owning_controller->parent,
+         &this_request->target_device->parent,
+         &this_request->parent
+      );
+   }
+}
+
+/**
+ * @brief This method will terminate all of the IO requests in the
+ *        controllers IO request table that were targeted for this
+ *        device.
+ *
+ * @param[in]  this_device This parameter specifies the remote device
+ *             for which to attempt to terminate all requests.
+ *
+ * @return This method returns an indication as to whether all requests
+ *         were successfully terminated.  If a single request fails to
+ *         be terminated, then this method will return the failure.
+ */
+static
+SCI_STATUS scic_sds_remote_device_terminate_requests(
+   SCIC_SDS_REMOTE_DEVICE_T *this_device
+)
+{
+    return scic_sds_terminate_reqests(
+            this_device->owning_port->owning_controller,
+            this_device,
+            NULL);
+}
+
+//*****************************************************************************
+//*  DEFAULT STATE HANDLERS
+//*****************************************************************************
+
+/**
+ * This method is the default start handler.  It logs a warning and returns a
+ * failure.
+ *
+ * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
+ *       SCIC_SDS_REMOTE_DEVICE.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+SCI_STATUS scic_sds_remote_device_default_start_handler(
+   SCI_BASE_REMOTE_DEVICE_T *device
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger((SCIC_SDS_REMOTE_DEVICE_T *)device),
+      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
+      "SCIC Remote Device requested to start while in wrong state %d\n",
+      sci_base_state_machine_get_state(
+         scic_sds_remote_device_get_base_state_machine((SCIC_SDS_REMOTE_DEVICE_T *)device))
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * This method is the default stop handler.  It logs a warning and returns a
+ * failure.
+ *
+ * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
+ *       SCIC_SDS_REMOTE_DEVICE.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+SCI_STATUS scic_sds_remote_device_default_stop_handler(
+   SCI_BASE_REMOTE_DEVICE_T *device
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger((SCIC_SDS_REMOTE_DEVICE_T *)device),
+      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
+      "SCIC Remote Device requested to stop while in wrong state %d\n",
+      sci_base_state_machine_get_state(
+         scic_sds_remote_device_get_base_state_machine((SCIC_SDS_REMOTE_DEVICE_T *)device))
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * This method is the default fail handler.  It logs a warning and returns a
+ * failure.
+ *
+ * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
+ *       SCIC_SDS_REMOTE_DEVICE.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+SCI_STATUS scic_sds_remote_device_default_fail_handler(
+   SCI_BASE_REMOTE_DEVICE_T *device
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger((SCIC_SDS_REMOTE_DEVICE_T *)device),
+      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
+      "SCIC Remote Device requested to fail while in wrong state %d\n",
+      sci_base_state_machine_get_state(
+         scic_sds_remote_device_get_base_state_machine((SCIC_SDS_REMOTE_DEVICE_T *)device))
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * This method is the default destruct handler.  It logs a warning and returns
+ * a failure.
+ *
+ * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
+ *       SCIC_SDS_REMOTE_DEVICE.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+SCI_STATUS scic_sds_remote_device_default_destruct_handler(
+   SCI_BASE_REMOTE_DEVICE_T *device
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger((SCIC_SDS_REMOTE_DEVICE_T *)device),
+      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
+      "SCIC Remote Device requested to destroy while in wrong state %d\n",
+      sci_base_state_machine_get_state(
+         scic_sds_remote_device_get_base_state_machine((SCIC_SDS_REMOTE_DEVICE_T *)device))
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * This method is the default reset handler.  It logs a warning and returns a
+ * failure.
+ *
+ * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
+ *       SCIC_SDS_REMOTE_DEVICE.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+SCI_STATUS scic_sds_remote_device_default_reset_handler(
+   SCI_BASE_REMOTE_DEVICE_T *device
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger((SCIC_SDS_REMOTE_DEVICE_T *)device),
+      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
+      "SCIC Remote Device requested to reset while in wrong state %d\n",
+      sci_base_state_machine_get_state(
+         scic_sds_remote_device_get_base_state_machine((SCIC_SDS_REMOTE_DEVICE_T *)device))
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * This method is the default reset complete handler.  It logs a warning and
+ * returns a failure.
+ *
+ * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
+ *       SCIC_SDS_REMOTE_DEVICE.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+SCI_STATUS scic_sds_remote_device_default_reset_complete_handler(
+   SCI_BASE_REMOTE_DEVICE_T *device
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger((SCIC_SDS_REMOTE_DEVICE_T *)device),
+      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
+      "SCIC Remote Device requested to complete reset while in wrong state %d\n",
+      sci_base_state_machine_get_state(
+         scic_sds_remote_device_get_base_state_machine((SCIC_SDS_REMOTE_DEVICE_T *)device))
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * This method is the default suspend handler.  It logs a warning and returns
+ * a failure.
+ *
+ * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
+ *       SCIC_SDS_REMOTE_DEVICE.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+SCI_STATUS scic_sds_remote_device_default_suspend_handler(
+   SCIC_SDS_REMOTE_DEVICE_T *this_device,
+   U32                       suspend_type
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger(this_device),
+      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
+      "SCIC Remote Device 0x%x requested to suspend %d while in wrong state %d\n",
+      this_device, suspend_type,
+      sci_base_state_machine_get_state(
+         scic_sds_remote_device_get_base_state_machine(this_device))
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * This method is the default resume handler.  It logs a warning and returns a
+ * failure.
+ *
+ * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
+ *       SCIC_SDS_REMOTE_DEVICE.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+SCI_STATUS scic_sds_remote_device_default_resume_handler(
+   SCIC_SDS_REMOTE_DEVICE_T *this_device
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger(this_device),
+      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
+      "SCIC Remote Device requested to resume while in wrong state %d\n",
+      sci_base_state_machine_get_state(
+         scic_sds_remote_device_get_base_state_machine(this_device))
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+#if defined(SCI_LOGGING)
+/**
+ *  This is a private method for emitting log messages related to events reported
+ *  to the remote device from the controller object.
+ *
+ *  @param [in] this_device This is the device object that is receiving the
+ *         event.
+ *  @param [in] event_code The event code to process.
+ *
+ *  @return None
+ */
+static void scic_sds_emit_event_log_message(
+   SCIC_SDS_REMOTE_DEVICE_T * this_device,
+   U32                        event_code,
+   char *                     message_guts,
+   BOOL                       ready_state
+   )
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger(this_device),
+      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
+      "SCIC Remote device 0x%x (state %d) received %s %x while in the %sready %s%d\n",
+      this_device,
+      sci_base_state_machine_get_state(
+               scic_sds_remote_device_get_base_state_machine(this_device)),
+      message_guts, event_code,
+      (ready_state)
+        ? ""
+        : "not ",
+      (this_device->has_ready_substate_machine)
+        ? "substate "
+        : "",
+      (this_device->has_ready_substate_machine)
+        ? sci_base_state_machine_get_state(&this_device->ready_substate_machine)
+        : 0
+   ));
+}
+#else // defined(SCI_LOGGING)
+#define scic_sds_emit_event_log_message(device, event_code, message, state)
+#endif // defined(SCI_LOGGING)
+
+/**
+ * This method is the default event handler.  It will call the RNC state
+ * machine handler for any RNC events otherwise it will log a warning and
+ * returns a failure.
+ *
+ * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
+ *       SCIC_SDS_REMOTE_DEVICE.
+ * @param[in] event_code The event code that the SCIC_SDS_CONTROLLER wants the
+ *       device object to process.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+static
+SCI_STATUS  scic_sds_remote_device_core_event_handler(
+   SCIC_SDS_REMOTE_DEVICE_T *this_device,
+   U32                       event_code,
+   BOOL                      is_ready_state
+)
+{
+   SCI_STATUS status;
+
+   switch (scu_get_event_type(event_code))
+   {
+   case SCU_EVENT_TYPE_RNC_OPS_MISC:
+   case SCU_EVENT_TYPE_RNC_SUSPEND_TX:
+   case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX:
+      status = scic_sds_remote_node_context_event_handler(this_device->rnc, event_code);
+   break;
+   case SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT:
+
+       if( scu_get_event_code(event_code) == SCU_EVENT_IT_NEXUS_TIMEOUT )
+       {
+           status = SCI_SUCCESS;
+
+           // Suspend the associated RNC
+           scic_sds_remote_node_context_suspend( this_device->rnc,
+                                                 SCI_SOFTWARE_SUSPENSION,
+                                                 NULL, NULL );
+
+           scic_sds_emit_event_log_message(
+              this_device, event_code,
+                   (is_ready_state)
+            ? "I_T_Nexus_Timeout event"
+            : "I_T_Nexus_Timeout event in wrong state",
+                   is_ready_state );
+
+           break;
+       }
+       // Else, fall through and treat as unhandled...
+
+   default:
+      scic_sds_emit_event_log_message( this_device, event_code,
+                                       (is_ready_state)
+                                          ? "unexpected event"
+                                          : "unexpected event in wrong state",
+                                       is_ready_state );
+      status = SCI_FAILURE_INVALID_STATE;
+   break;
+   }
+
+   return status;
+}
+/**
+ * This method is the default event handler.  It will call the RNC state
+ * machine handler for any RNC events otherwise it will log a warning and
+ * returns a failure.
+ *
+ * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
+ *       SCIC_SDS_REMOTE_DEVICE.
+ * @param[in] event_code The event code that the SCIC_SDS_CONTROLLER wants the
+ *       device object to process.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+SCI_STATUS  scic_sds_remote_device_default_event_handler(
+   SCIC_SDS_REMOTE_DEVICE_T *this_device,
+   U32                       event_code
+)
+{
+   return scic_sds_remote_device_core_event_handler( this_device,
+                                                     event_code,
+                                                     FALSE );
+}
+
+/**
+ * This method is the default unsolicited frame handler.  It logs a warning,
+ * releases the frame and returns a failure.
+ *
+ * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
+ *       SCIC_SDS_REMOTE_DEVICE.
+ * @param[in] frame_index The frame index for which the SCIC_SDS_CONTROLLER
+ *       wants this device object to process.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+SCI_STATUS scic_sds_remote_device_default_frame_handler(
+   SCIC_SDS_REMOTE_DEVICE_T *this_device,
+   U32                       frame_index
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger(this_device),
+      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
+      "SCIC Remote Device requested to handle frame %x while in wrong state %d\n",
+      frame_index,
+      sci_base_state_machine_get_state(&this_device->parent.state_machine)
+   ));
+
+   // Return the frame back to the controller
+   scic_sds_controller_release_frame(
+      scic_sds_remote_device_get_controller(this_device), frame_index
+   );
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * This method is the default start io handler.  It logs a warning and returns
+ * a failure.
+ *
+ * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
+ *       SCIC_SDS_REMOTE_DEVICE.
+ * @param[in] request The SCI_BASE_REQUEST which is then cast into a
+ *       SCIC_SDS_IO_REQUEST to start.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+SCI_STATUS scic_sds_remote_device_default_start_request_handler(
+   SCI_BASE_REMOTE_DEVICE_T *device,
+   SCI_BASE_REQUEST_T       *request
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger((SCIC_SDS_REMOTE_DEVICE_T *)device),
+      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
+      "SCIC Remote Device requested to start io request %x while in wrong state %d\n",
+      request,
+      sci_base_state_machine_get_state(
+         scic_sds_remote_device_get_base_state_machine((SCIC_SDS_REMOTE_DEVICE_T *)device))
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * This method is the default complete io handler.  It logs a warning and
+ * returns a failure.
+ *
+ * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
+ *       SCIC_SDS_REMOTE_DEVICE.
+ * @param[in] request The SCI_BASE_REQUEST which is then cast into a
+ *       SCIC_SDS_IO_REQUEST to complete.
+ *
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+SCI_STATUS scic_sds_remote_device_default_complete_request_handler(
+   SCI_BASE_REMOTE_DEVICE_T *device,
+   SCI_BASE_REQUEST_T       *request
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger((SCIC_SDS_REMOTE_DEVICE_T *)device),
+      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
+      "SCIC Remote Device requested to complete io_request %x while in wrong state %d\n",
+      request,
+      sci_base_state_machine_get_state(
+         scic_sds_remote_device_get_base_state_machine((SCIC_SDS_REMOTE_DEVICE_T *)device))
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * This method is the default continue io handler.  It logs a warning and
+ * returns a failure.
+ *
+ * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
+ *       SCIC_SDS_REMOTE_DEVICE.
+ * @param[in] request The SCI_BASE_REQUEST which is then cast into a
+ *       SCIC_SDS_IO_REQUEST to continue.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+SCI_STATUS scic_sds_remote_device_default_continue_request_handler(
+   SCI_BASE_REMOTE_DEVICE_T *device,
+   SCI_BASE_REQUEST_T       *request
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger((SCIC_SDS_REMOTE_DEVICE_T *)device),
+      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
+      SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
+      "SCIC Remote Device requested to continue io request %x while in wrong state %d\n",
+      request,
+      sci_base_state_machine_get_state(
+         scic_sds_remote_device_get_base_state_machine((SCIC_SDS_REMOTE_DEVICE_T *)device))
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * This method is the general suspend handler.
+ *
+ * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
+ *       SCIC_SDS_REMOTE_DEVICE.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+static
+SCI_STATUS scic_sds_remote_device_general_suspend_handler(
+   SCIC_SDS_REMOTE_DEVICE_T *this_device,
+   U32                       suspend_type
+)
+{
+    return scic_sds_remote_node_context_suspend(this_device->rnc, suspend_type, NULL, NULL);
+}
+
+/**
+ * This method is the general suspend handler.  It logs a warning and returns
+ * a failure.
+ *
+ * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
+ *       SCIC_SDS_REMOTE_DEVICE.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+static
+SCI_STATUS scic_sds_remote_device_general_resume_handler(
+   SCIC_SDS_REMOTE_DEVICE_T *this_device
+)
+{
+    return scic_sds_remote_node_context_resume(this_device->rnc, NULL, NULL);
+}
+
+//*****************************************************************************
+//*  NORMAL STATE HANDLERS
+//*****************************************************************************
+
+/**
+ * This method is a general ssp frame handler.  In most cases the device
+ * object needs to route the unsolicited frame processing to the io request
+ * object.  This method decodes the tag for the io request object and routes
+ * the unsolicited frame to that object.
+ *
+ * @param[in] device The SCI_BASE_REMOTE_DEVICE which is then cast into a
+ *       SCIC_SDS_REMOTE_DEVICE.
+ * @param[in] frame_index The frame index for which the SCIC_SDS_CONTROLLER
+ *       wants this device object to process.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+SCI_STATUS scic_sds_remote_device_general_frame_handler(
+   SCIC_SDS_REMOTE_DEVICE_T *this_device,
+   U32                       frame_index
+)
+{
+   SCI_STATUS result;
+   SCI_SSP_FRAME_HEADER_T *frame_header;
+   SCIC_SDS_REQUEST_T     *io_request;
+
+   result = scic_sds_unsolicited_frame_control_get_header(
+      &(scic_sds_remote_device_get_controller(this_device)->uf_control),
+      frame_index,
+      (void **)&frame_header
+   );
+
+   if (SCI_SUCCESS == result)
+   {
+      io_request = scic_sds_controller_get_io_request_from_tag(
+         scic_sds_remote_device_get_controller(this_device), frame_header->tag);
+
+      if (  (io_request == SCI_INVALID_HANDLE)
+         || (io_request->target_device != this_device) )
+      {
+         // We could not map this tag to a valid IO request
+         // Just toss the frame and continue
+         scic_sds_controller_release_frame(
+            scic_sds_remote_device_get_controller(this_device), frame_index
+         );
+      }
+      else
+      {
+         // The IO request is now in charge of releasing the frame
+         result = io_request->state_handlers->frame_handler(
+                                                    io_request, frame_index);
+      }
+   }
+
+   return result;
+}
+
+/**
+ *  This is a common method for handling events reported to the remote device
+ *  from the controller object.
+ *
+ *  @param [in] this_device This is the device object that is receiving the
+ *         event.
+ *  @param [in] event_code The event code to process.
+ *
+ *  @return SCI_STATUS
+ */
+SCI_STATUS scic_sds_remote_device_general_event_handler(
+   SCIC_SDS_REMOTE_DEVICE_T * this_device,
+   U32                        event_code
+)
+{
+   return scic_sds_remote_device_core_event_handler( this_device,
+                                                     event_code,
+                                                     TRUE );
+}
+
+//*****************************************************************************
+//*  STOPPED STATE HANDLERS
+//*****************************************************************************
+
+/**
+ * This method takes the SCIC_SDS_REMOTE_DEVICE from a stopped state and
+ * attempts to start it.   The RNC buffer for the device is constructed and
+ * the device state machine is transitioned to the
+ * SCIC_BASE_REMOTE_DEVICE_STATE_STARTING.
+ *
+ * @param[in] device
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS if there is an RNC buffer available to construct the
+ *         remote device.
+ * @retval SCI_FAILURE_INSUFFICIENT_RESOURCES if there is no RNC buffer
+ *         available in which to construct the remote device.
+ */
+static
+SCI_STATUS scic_sds_remote_device_stopped_state_start_handler(
+   SCI_BASE_REMOTE_DEVICE_T *device
+)
+{
+   SCI_STATUS status;
+   SCIC_SDS_REMOTE_DEVICE_T  *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
+
+   status = scic_sds_remote_node_context_resume(
+               this_device->rnc,
+               scic_sds_remote_device_resume_complete_handler,
+               this_device
+            );
+
+   if (status == SCI_SUCCESS)
+   {
+      sci_base_state_machine_change_state(
+         scic_sds_remote_device_get_base_state_machine(this_device),
+         SCI_BASE_REMOTE_DEVICE_STATE_STARTING
+      );
+   }
+
+   return status;
+}
+
+/**
+ * This method will stop a SCIC_SDS_REMOTE_DEVICE that is already in a stopped
+ * state.  This is not considered an error since the device is already
+ * stopped.
+ *
+ * @param[in] this_device The SCI_BASE_REMOTE_DEVICE which is cast into a
+ *       SCIC_SDS_REMOTE_DEVICE.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS
+ */
+static
+SCI_STATUS scic_sds_remote_device_stopped_state_stop_handler(
+   SCI_BASE_REMOTE_DEVICE_T *this_device
+)
+{
+   return SCI_SUCCESS;
+}
+
+/**
+ * This method will destruct a SCIC_SDS_REMOTE_DEVICE that is in a stopped
+ * state.  This is the only state from which a destruct request will succeed.
+ * The RNi for this SCIC_SDS_REMOTE_DEVICE is returned to the free pool and
+ * the device object transitions to the SCI_BASE_REMOTE_DEVICE_STATE_FINAL.
+ *
+ * @param[in] this_device The SCI_BASE_REMOTE_DEVICE which is cast into a
+ *       SCIC_SDS_REMOTE_DEVICE.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS
+ */
+static
+SCI_STATUS scic_sds_remote_device_stopped_state_destruct_handler(
+   SCI_BASE_REMOTE_DEVICE_T *device
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
+
+   SCIC_SDS_CONTROLLER_T * the_controller =
+      scic_sds_remote_device_get_controller(this_device);
+
+   the_controller->remote_device_sequence[this_device->rnc->remote_node_index]++;
+
+   scic_sds_controller_free_remote_node_context(
+      the_controller,
+      this_device,
+      this_device->rnc->remote_node_index
+   );
+
+   scic_sds_remote_node_context_set_remote_node_index(
+      this_device->rnc,
+      SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX
+   );
+
+   sci_base_state_machine_change_state(
+      scic_sds_remote_device_get_base_state_machine(this_device),
+      SCI_BASE_REMOTE_DEVICE_STATE_FINAL
+   );
+
+   scic_sds_remote_device_deinitialize_state_logging(this_device);
+
+   return SCI_SUCCESS;
+}
+
+//*****************************************************************************
+//*  STARTING STATE HANDLERS
+//*****************************************************************************
+
+static
+SCI_STATUS scic_sds_remote_device_starting_state_stop_handler(
+   SCI_BASE_REMOTE_DEVICE_T *device
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
+
+   /*
+    * This device has not yet started so there had better be no IO requests
+    */
+   ASSERT(this_device->started_request_count == 0);
+
+   /*
+    * Destroy the remote node context
+    */
+   scic_sds_remote_node_context_destruct(
+      this_device->rnc,
+      scic_sds_cb_remote_device_rnc_destruct_complete,
+      this_device
+   );
+
+   /*
+    * Transition to the stopping state and wait for the remote node to
+    * complete being posted and invalidated.
+    */
+   sci_base_state_machine_change_state(
+      scic_sds_remote_device_get_base_state_machine(this_device),
+      SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
+   );
+
+   return SCI_SUCCESS;
+}
+
+//*****************************************************************************
+//*  INITIALIZING STATE HANDLERS
+//*****************************************************************************
+
+/* There is nothing to do here for SSP devices */
+
+//*****************************************************************************
+//*  READY STATE HANDLERS
+//*****************************************************************************
+
+/**
+ * This method is the default stop handler for the SCIC_SDS_REMOTE_DEVICE
+ * ready substate machine. It will stop the current substate machine and
+ * transition the base state machine to SCI_BASE_REMOTE_DEVICE_STATE_STOPPING.
+ *
+ * @param[in] device The SCI_BASE_REMOTE_DEVICE object which is cast to a
+ *       SCIC_SDS_REMOTE_DEVICE object.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS
+ */
+SCI_STATUS scic_sds_remote_device_ready_state_stop_handler(
+   SCI_BASE_REMOTE_DEVICE_T *device
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
+   SCI_STATUS                status      = SCI_SUCCESS;
+
+   // Request the parent state machine to transition to the stopping state
+   sci_base_state_machine_change_state(
+      scic_sds_remote_device_get_base_state_machine(this_device),
+      SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
+   );
+
+   if (this_device->started_request_count == 0)
+   {
+      scic_sds_remote_node_context_destruct(
+         this_device->rnc,
+         scic_sds_cb_remote_device_rnc_destruct_complete,
+         this_device
+      );
+   }
+   else
+      status = scic_sds_remote_device_terminate_requests(this_device);
+
+   return status;
+}
+
+/**
+ * This is the ready state device reset handler
+ *
+ * @param[in] device The SCI_BASE_REMOTE_DEVICE object which is cast to a
+ *       SCIC_SDS_REMOTE_DEVICE object.
+ *
+ * @return SCI_STATUS
+ */
+SCI_STATUS scic_sds_remote_device_ready_state_reset_handler(
+   SCI_BASE_REMOTE_DEVICE_T *device
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
+
+   // Request the parent state machine to transition to the stopping state
+   sci_base_state_machine_change_state(
+      scic_sds_remote_device_get_base_state_machine(this_device),
+      SCI_BASE_REMOTE_DEVICE_STATE_RESETTING
+   );
+
+   return SCI_SUCCESS;
+}
+
+/**
+ * This method will attempt to start a task request for this device object.
+ * The remote device object will issue the start request for the task and if
+ * successful it will start the request for the port object then increment its
+ * own requet count.
+ *
+ * @param[in] device The SCI_BASE_REMOTE_DEVICE which is cast to a
+ *       SCIC_SDS_REMOTE_DEVICE for which the request is to be started.
+ * @param[in] request The SCI_BASE_REQUEST which is cast to a
+ *       SCIC_SDS_IO_REQUEST that is to be started.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS if the task request is started for this device object.
+ * @retval SCI_FAILURE_INSUFFICIENT_RESOURCES if the io request object could
+ *         not get the resources to start.
+ */
+static
+SCI_STATUS scic_sds_remote_device_ready_state_start_task_handler(
+   SCI_BASE_REMOTE_DEVICE_T *device,
+   SCI_BASE_REQUEST_T       *request
+)
+{
+   SCI_STATUS result;
+   SCIC_SDS_REMOTE_DEVICE_T *this_device  = (SCIC_SDS_REMOTE_DEVICE_T *)device;
+   SCIC_SDS_REQUEST_T       *task_request = (SCIC_SDS_REQUEST_T       *)request;
+
+   // See if the port is in a state where we can start the IO request
+   result = scic_sds_port_start_io(
+      scic_sds_remote_device_get_port(this_device), this_device, task_request);
+
+   if (result == SCI_SUCCESS)
+   {
+      result = scic_sds_remote_node_context_start_task(
+                  this_device->rnc, task_request
+               );
+
+      if (result == SCI_SUCCESS)
+      {
+         result = scic_sds_request_start(task_request);
+      }
+
+      scic_sds_remote_device_start_request(this_device, task_request, result);
+   }
+
+   return result;
+}
+
+/**
+ * This method will attempt to start an io request for this device object. The
+ * remote device object will issue the start request for the io and if
+ * successful it will start the request for the port object then increment its
+ * own requet count.
+ *
+ * @param[in] device The SCI_BASE_REMOTE_DEVICE which is cast to a
+ *       SCIC_SDS_REMOTE_DEVICE for which the request is to be started.
+ * @param[in] request The SCI_BASE_REQUEST which is cast to a
+ *       SCIC_SDS_IO_REQUEST that is to be started.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS if the io request is started for this device object.
+ * @retval SCI_FAILURE_INSUFFICIENT_RESOURCES if the io request object could
+ *         not get the resources to start.
+ */
+static
+SCI_STATUS scic_sds_remote_device_ready_state_start_io_handler(
+   SCI_BASE_REMOTE_DEVICE_T *device,
+   SCI_BASE_REQUEST_T       *request
+)
+{
+   SCI_STATUS result;
+   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
+   SCIC_SDS_REQUEST_T       *io_request  = (SCIC_SDS_REQUEST_T       *)request;
+
+   // See if the port is in a state where we can start the IO request
+   result = scic_sds_port_start_io(
+      scic_sds_remote_device_get_port(this_device), this_device, io_request);
+
+   if (result == SCI_SUCCESS)
+   {
+      result = scic_sds_remote_node_context_start_io(
+                  this_device->rnc, io_request
+               );
+
+      if (result == SCI_SUCCESS)
+      {
+         result = scic_sds_request_start(io_request);
+      }
+
+      scic_sds_remote_device_start_request(this_device, io_request, result);
+   }
+
+   return result;
+}
+
+/**
+ * This method will complete the request for the remote device object.  The
+ * method will call the completion handler for the request object and if
+ * successful it will complete the request on the port object then decrement
+ * its own started_request_count.
+ *
+ * @param[in] device The SCI_BASE_REMOTE_DEVICE which is cast to a
+ *       SCIC_SDS_REMOTE_DEVICE for which the request is to be completed.
+ * @param[in] request The SCI_BASE_REQUEST which is cast to a
+ *       SCIC_SDS_IO_REQUEST that is to be completed.
+ *
+ * @return SCI_STATUS
+ */
+static
+SCI_STATUS scic_sds_remote_device_ready_state_complete_request_handler(
+   SCI_BASE_REMOTE_DEVICE_T *device,
+   SCI_BASE_REQUEST_T       *request
+)
+{
+   SCI_STATUS result;
+   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
+   SCIC_SDS_REQUEST_T       *the_request = (SCIC_SDS_REQUEST_T       *)request;
+
+   result = scic_sds_request_complete(the_request);
+
+   if (result == SCI_SUCCESS)
+   {
+      // See if the port is in a state where we can start the IO request
+      result = scic_sds_port_complete_io(
+         scic_sds_remote_device_get_port(this_device), this_device, the_request);
+
+      if (result == SCI_SUCCESS)
+      {
+         scic_sds_remote_device_decrement_request_count(this_device);
+      }
+   }
+
+   return result;
+}
+
+//*****************************************************************************
+//*  STOPPING STATE HANDLERS
+//*****************************************************************************
+
+/**
+ * This method will stop a SCIC_SDS_REMOTE_DEVICE that is already in the
+ * SCI_BASE_REMOTE_DEVICE_STATE_STOPPING state. This is not considered an
+ * error since we allow a stop request on a device that is alreay stopping or
+ * stopped.
+ *
+ * @param[in] this_device The SCI_BASE_REMOTE_DEVICE which is cast into a
+ *       SCIC_SDS_REMOTE_DEVICE.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS
+ */
+static
+SCI_STATUS scic_sds_remote_device_stopping_state_stop_handler(
+   SCI_BASE_REMOTE_DEVICE_T *device
+)
+{
+   // All requests should have been terminated, but if there is an
+   // attempt to stop a device already in the stopping state, then
+   // try again to terminate.
+   return scic_sds_remote_device_terminate_requests(
+             (SCIC_SDS_REMOTE_DEVICE_T*)device);
+}
+
+
+/**
+ * This method completes requests for this SCIC_SDS_REMOTE_DEVICE while it is
+ * in the SCI_BASE_REMOTE_DEVICE_STATE_STOPPING state. This method calls the
+ * complete method for the request object and if that is successful the port
+ * object is called to complete the task request. Then the device object
+ * itself completes the task request. If SCIC_SDS_REMOTE_DEVICE
+ * started_request_count goes to 0 and the invalidate RNC request has
+ * completed the device object can transition to the
+ * SCI_BASE_REMOTE_DEVICE_STATE_STOPPED.
+ *
+ * @param[in] device The device object for which the request is completing.
+ * @param[in] request The task request that is being completed.
+ *
+ * @return SCI_STATUS
+ */
+static
+SCI_STATUS scic_sds_remote_device_stopping_state_complete_request_handler(
+   SCI_BASE_REMOTE_DEVICE_T *device,
+   SCI_BASE_REQUEST_T       *request
+)
+{
+   SCI_STATUS                status = SCI_SUCCESS;
+   SCIC_SDS_REQUEST_T       *this_request = (SCIC_SDS_REQUEST_T   *)request;
+   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
+
+   status = scic_sds_request_complete(this_request);
+   if (status == SCI_SUCCESS)
+   {
+      status = scic_sds_port_complete_io(
+                  scic_sds_remote_device_get_port(this_device),
+                  this_device,
+                  this_request
+               );
+
+      if (status == SCI_SUCCESS)
+      {
+         scic_sds_remote_device_decrement_request_count(this_device);
+
+         if (scic_sds_remote_device_get_request_count(this_device) == 0)
+         {
+            scic_sds_remote_node_context_destruct(
+               this_device->rnc,
+               scic_sds_cb_remote_device_rnc_destruct_complete,
+               this_device
+            );
+         }
+      }
+   }
+
+   return status;
+}
+
+//*****************************************************************************
+//*  RESETTING STATE HANDLERS
+//*****************************************************************************
+
+/**
+ * This method will complete the reset operation when the device is in the
+ * resetting state.
+ *
+ * @param[in] device The SCI_BASE_REMOTE_DEVICE which is to be cast into a
+ *       SCIC_SDS_REMOTE_DEVICE object.
+ *
+ * @return SCI_STATUS
+ */
+static
+SCI_STATUS scic_sds_remote_device_resetting_state_reset_complete_handler(
+   SCI_BASE_REMOTE_DEVICE_T * device
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
+
+   sci_base_state_machine_change_state(
+      &this_device->parent.state_machine,
+      SCI_BASE_REMOTE_DEVICE_STATE_READY
+   );
+
+   return SCI_SUCCESS;
+}
+
+/**
+ * This method will stop the remote device while in the resetting state.
+ *
+ * @param[in] device The SCI_BASE_REMOTE_DEVICE which is to be cast into a
+ *       SCIC_SDS_REMOTE_DEVICE object.
+ *
+ * @return SCI_STATUS
+ */
+static
+SCI_STATUS scic_sds_remote_device_resetting_state_stop_handler(
+   SCI_BASE_REMOTE_DEVICE_T * device
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
+
+   sci_base_state_machine_change_state(
+      &this_device->parent.state_machine,
+      SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
+   );
+
+   return SCI_SUCCESS;
+}
+
+/**
+ * This method completes requests for this SCIC_SDS_REMOTE_DEVICE while it is
+ * in the SCI_BASE_REMOTE_DEVICE_STATE_RESETTING state. This method calls the
+ * complete method for the request object and if that is successful the port
+ * object is called to complete the task request. Then the device object
+ * itself completes the task request.
+ *
+ * @param[in] device The device object for which the request is completing.
+ * @param[in] request The task request that is being completed.
+ *
+ * @return SCI_STATUS
+ */
+static
+SCI_STATUS scic_sds_remote_device_resetting_state_complete_request_handler(
+   SCI_BASE_REMOTE_DEVICE_T *device,
+   SCI_BASE_REQUEST_T       *request
+)
+{
+   SCI_STATUS status = SCI_SUCCESS;
+   SCIC_SDS_REQUEST_T       *this_request = (SCIC_SDS_REQUEST_T   *)request;
+   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
+
+   status = scic_sds_request_complete(this_request);
+
+   if (status == SCI_SUCCESS)
+   {
+      status = scic_sds_port_complete_io(
+         scic_sds_remote_device_get_port(this_device), this_device, this_request);
+
+      if (status == SCI_SUCCESS)
+      {
+         scic_sds_remote_device_decrement_request_count(this_device);
+      }
+   }
+
+   return status;
+}
+
+//*****************************************************************************
+//*  FAILED STATE HANDLERS
+//*****************************************************************************
+
+SCIC_SDS_REMOTE_DEVICE_STATE_HANDLER_T
+   scic_sds_remote_device_state_handler_table[SCI_BASE_REMOTE_DEVICE_MAX_STATES] =
+{
+   // SCI_BASE_REMOTE_DEVICE_STATE_INITIAL
+   {
+      {
+         scic_sds_remote_device_default_start_handler,
+         scic_sds_remote_device_default_stop_handler,
+         scic_sds_remote_device_default_fail_handler,
+         scic_sds_remote_device_default_destruct_handler,
+         scic_sds_remote_device_default_reset_handler,
+         scic_sds_remote_device_default_reset_complete_handler,
+         scic_sds_remote_device_default_start_request_handler,
+         scic_sds_remote_device_default_complete_request_handler,
+         scic_sds_remote_device_default_continue_request_handler,
+         scic_sds_remote_device_default_start_request_handler,
+         scic_sds_remote_device_default_complete_request_handler
+      },
+      scic_sds_remote_device_default_suspend_handler,
+      scic_sds_remote_device_default_resume_handler,
+      scic_sds_remote_device_default_event_handler,
+      scic_sds_remote_device_default_frame_handler
+   },
+   // SCI_BASE_REMOTE_DEVICE_STATE_STOPPED
+   {
+      {
+         scic_sds_remote_device_stopped_state_start_handler,
+         scic_sds_remote_device_stopped_state_stop_handler,
+         scic_sds_remote_device_default_fail_handler,
+         scic_sds_remote_device_stopped_state_destruct_handler,
+         scic_sds_remote_device_default_reset_handler,
+         scic_sds_remote_device_default_reset_complete_handler,
+         scic_sds_remote_device_default_start_request_handler,
+         scic_sds_remote_device_default_complete_request_handler,
+         scic_sds_remote_device_default_continue_request_handler,
+         scic_sds_remote_device_default_start_request_handler,
+         scic_sds_remote_device_default_complete_request_handler
+      },
+      scic_sds_remote_device_default_suspend_handler,
+      scic_sds_remote_device_default_resume_handler,
+      scic_sds_remote_device_default_event_handler,
+      scic_sds_remote_device_default_frame_handler
+   },
+   // SCI_BASE_REMOTE_DEVICE_STATE_STARTING
+   {
+      {
+         scic_sds_remote_device_default_start_handler,
+         scic_sds_remote_device_starting_state_stop_handler,
+         scic_sds_remote_device_default_fail_handler,
+         scic_sds_remote_device_default_destruct_handler,
+         scic_sds_remote_device_default_reset_handler,
+         scic_sds_remote_device_default_reset_complete_handler,
+         scic_sds_remote_device_default_start_request_handler,
+         scic_sds_remote_device_default_complete_request_handler,
+         scic_sds_remote_device_default_continue_request_handler,
+         scic_sds_remote_device_default_start_request_handler,
+         scic_sds_remote_device_default_complete_request_handler
+      },
+      scic_sds_remote_device_default_suspend_handler,
+      scic_sds_remote_device_default_resume_handler,
+      scic_sds_remote_device_general_event_handler,
+      scic_sds_remote_device_default_frame_handler
+   },
+   // SCI_BASE_REMOTE_DEVICE_STATE_READY
+   {
+      {
+         scic_sds_remote_device_default_start_handler,
+         scic_sds_remote_device_ready_state_stop_handler,
+         scic_sds_remote_device_default_fail_handler,
+         scic_sds_remote_device_default_destruct_handler,
+         scic_sds_remote_device_ready_state_reset_handler,
+         scic_sds_remote_device_default_reset_complete_handler,
+         scic_sds_remote_device_ready_state_start_io_handler,
+         scic_sds_remote_device_ready_state_complete_request_handler,
+         scic_sds_remote_device_default_continue_request_handler,
+         scic_sds_remote_device_ready_state_start_task_handler,
+         scic_sds_remote_device_ready_state_complete_request_handler
+      },
+      scic_sds_remote_device_general_suspend_handler,
+      scic_sds_remote_device_general_resume_handler,
+      scic_sds_remote_device_general_event_handler,
+      scic_sds_remote_device_general_frame_handler,
+   },
+   // SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
+   {
+      {
+         scic_sds_remote_device_default_start_handler,
+         scic_sds_remote_device_stopping_state_stop_handler,
+         scic_sds_remote_device_default_fail_handler,
+         scic_sds_remote_device_default_destruct_handler,
+         scic_sds_remote_device_default_reset_handler,
+         scic_sds_remote_device_default_reset_complete_handler,
+         scic_sds_remote_device_default_start_request_handler,
+         scic_sds_remote_device_stopping_state_complete_request_handler,
+         scic_sds_remote_device_default_continue_request_handler,
+         scic_sds_remote_device_default_start_request_handler,
+         scic_sds_remote_device_stopping_state_complete_request_handler
+      },
+      scic_sds_remote_device_default_suspend_handler,
+      scic_sds_remote_device_default_resume_handler,
+      scic_sds_remote_device_general_event_handler,
+      scic_sds_remote_device_general_frame_handler
+   },
+   // SCI_BASE_REMOTE_DEVICE_STATE_FAILED
+   {
+      {
+         scic_sds_remote_device_default_start_handler,
+         scic_sds_remote_device_default_stop_handler,
+         scic_sds_remote_device_default_fail_handler,
+         scic_sds_remote_device_default_destruct_handler,
+         scic_sds_remote_device_default_reset_handler,
+         scic_sds_remote_device_default_reset_complete_handler,
+         scic_sds_remote_device_default_start_request_handler,
+         scic_sds_remote_device_default_complete_request_handler,
+         scic_sds_remote_device_default_continue_request_handler,
+         scic_sds_remote_device_default_start_request_handler,
+         scic_sds_remote_device_default_complete_request_handler
+      },
+      scic_sds_remote_device_default_suspend_handler,
+      scic_sds_remote_device_default_resume_handler,
+      scic_sds_remote_device_default_event_handler,
+      scic_sds_remote_device_general_frame_handler
+   },
+   // SCI_BASE_REMOTE_DEVICE_STATE_RESETTING
+   {
+      {
+         scic_sds_remote_device_default_start_handler,
+         scic_sds_remote_device_resetting_state_stop_handler,
+         scic_sds_remote_device_default_fail_handler,
+         scic_sds_remote_device_default_destruct_handler,
+         scic_sds_remote_device_default_reset_handler,
+         scic_sds_remote_device_resetting_state_reset_complete_handler,
+         scic_sds_remote_device_default_start_request_handler,
+         scic_sds_remote_device_resetting_state_complete_request_handler,
+         scic_sds_remote_device_default_continue_request_handler,
+         scic_sds_remote_device_default_start_request_handler,
+         scic_sds_remote_device_resetting_state_complete_request_handler
+      },
+      scic_sds_remote_device_default_suspend_handler,
+      scic_sds_remote_device_default_resume_handler,
+      scic_sds_remote_device_default_event_handler,
+      scic_sds_remote_device_general_frame_handler
+   },
+#if !defined(DISABLE_WIDE_PORTED_TARGETS)
+   // SCI_BASE_REMOTE_DEVICE_STATE_UPDATING_PORT_WIDTH - unused by SCIC
+   {
+      {
+         scic_sds_remote_device_default_start_handler,
+         scic_sds_remote_device_default_stop_handler,
+         scic_sds_remote_device_default_fail_handler,
+         scic_sds_remote_device_default_destruct_handler,
+         scic_sds_remote_device_default_reset_handler,
+         scic_sds_remote_device_default_reset_complete_handler,
+         scic_sds_remote_device_default_start_request_handler,
+         scic_sds_remote_device_default_complete_request_handler,
+         scic_sds_remote_device_default_continue_request_handler,
+         scic_sds_remote_device_default_start_request_handler,
+         scic_sds_remote_device_default_complete_request_handler
+      },
+      scic_sds_remote_device_default_suspend_handler,
+      scic_sds_remote_device_default_resume_handler,
+      scic_sds_remote_device_default_event_handler,
+      scic_sds_remote_device_default_frame_handler
+   },
+#endif
+   // SCI_BASE_REMOTE_DEVICE_STATE_FINAL
+   {
+      {
+         scic_sds_remote_device_default_start_handler,
+         scic_sds_remote_device_default_stop_handler,
+         scic_sds_remote_device_default_fail_handler,
+         scic_sds_remote_device_default_destruct_handler,
+         scic_sds_remote_device_default_reset_handler,
+         scic_sds_remote_device_default_reset_complete_handler,
+         scic_sds_remote_device_default_start_request_handler,
+         scic_sds_remote_device_default_complete_request_handler,
+         scic_sds_remote_device_default_continue_request_handler,
+         scic_sds_remote_device_default_start_request_handler,
+         scic_sds_remote_device_default_complete_request_handler
+      },
+      scic_sds_remote_device_default_suspend_handler,
+      scic_sds_remote_device_default_resume_handler,
+      scic_sds_remote_device_default_event_handler,
+      scic_sds_remote_device_default_frame_handler
+   }
+};
+
+/**
+ * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_INITIAL it
+ * immediatly transitions the remote device object to the stopped state.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT that is cast into a
+ *            SCIC_SDS_REMOTE_DEVICE.
+ *
+ * @return none
+ */
+static
+void scic_sds_remote_device_initial_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object;
+
+   SET_STATE_HANDLER(
+      this_device,
+      scic_sds_remote_device_state_handler_table,
+      SCI_BASE_REMOTE_DEVICE_STATE_INITIAL
+   );
+
+   // Initial state is a transitional state to the stopped state
+   sci_base_state_machine_change_state(
+      scic_sds_remote_device_get_base_state_machine(this_device),
+      SCI_BASE_REMOTE_DEVICE_STATE_STOPPED
+   );
+}
+
+/**
+ * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_INITIAL it
+ * sets the stopped state handlers and if this state is entered from the
+ * SCI_BASE_REMOTE_DEVICE_STATE_STOPPING then the SCI User is informed that
+ * the device stop is complete.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT that is cast into a
+ *       SCIC_SDS_REMOTE_DEVICE.
+ *
+ * @return none
+ */
+static
+void scic_sds_remote_device_stopped_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object;
+
+   SET_STATE_HANDLER(
+      this_device,
+      scic_sds_remote_device_state_handler_table,
+      SCI_BASE_REMOTE_DEVICE_STATE_STOPPED
+   );
+
+   // If we are entering from the stopping state let the SCI User know that
+   // the stop operation has completed.
+   if (this_device->parent.state_machine.previous_state_id
+       == SCI_BASE_REMOTE_DEVICE_STATE_STOPPING)
+   {
+      scic_cb_remote_device_stop_complete(
+         scic_sds_remote_device_get_controller(this_device),
+         this_device,
+         SCI_SUCCESS
+      );
+   }
+
+   scic_sds_controller_remote_device_stopped(
+      scic_sds_remote_device_get_controller(this_device),
+      this_device
+   );
+}
+
+/**
+ * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_STARTING it
+ * sets the starting state handlers, sets the device not ready, and posts the
+ * remote node context to the hardware.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT that is cast into a
+ *       SCIC_SDS_REMOTE_DEVICE.
+ *
+ * @return none
+ */
+static
+void scic_sds_remote_device_starting_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_CONTROLLER_T    * the_controller;
+   SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object;
+
+   the_controller = scic_sds_remote_device_get_controller(this_device);
+
+   SET_STATE_HANDLER(
+      this_device,
+      scic_sds_remote_device_state_handler_table,
+      SCI_BASE_REMOTE_DEVICE_STATE_STARTING
+   );
+
+   scic_cb_remote_device_not_ready(
+      the_controller,
+      this_device,
+      SCIC_REMOTE_DEVICE_NOT_READY_START_REQUESTED
+   );
+}
+
+
+/**
+ * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_READY it sets
+ * the ready state handlers, and starts the ready substate machine.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT that is cast into a
+ *       SCIC_SDS_REMOTE_DEVICE.
+ *
+ * @return none
+ */
+static
+void scic_sds_remote_device_ready_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_CONTROLLER_T    * the_controller;
+   SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object;
+
+   the_controller = scic_sds_remote_device_get_controller(this_device);
+
+   SET_STATE_HANDLER(
+      this_device,
+      scic_sds_remote_device_state_handler_table,
+      SCI_BASE_REMOTE_DEVICE_STATE_READY
+   );
+
+   /// @todo Check the device object for the proper return code for this
+   ///       callback
+   scic_cb_remote_device_start_complete(
+      the_controller, this_device, SCI_SUCCESS
+   );
+
+   scic_sds_controller_remote_device_started(
+      the_controller, this_device
+   );
+
+   if (this_device->has_ready_substate_machine)
+   {
+      sci_base_state_machine_start(&this_device->ready_substate_machine);
+   }
+   else
+   {
+      scic_cb_remote_device_ready(the_controller, this_device);
+   }
+}
+
+/**
+ * This is the exit method for the SCI_BASE_REMOTE_DEVICE_STATE_READY it does
+ * nothing.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT that is cast into a
+ *       SCIC_SDS_REMOTE_DEVICE.
+ *
+ * @return none
+ */
+static
+void scic_sds_remote_device_ready_state_exit(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_CONTROLLER_T    * the_controller;
+   SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object;
+
+   the_controller = scic_sds_remote_device_get_controller(this_device);
+
+   if (this_device->has_ready_substate_machine)
+   {
+      sci_base_state_machine_stop(&this_device->ready_substate_machine);
+   }
+   else
+   {
+      scic_cb_remote_device_not_ready(
+         the_controller,
+         this_device,
+         SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED
+      );
+   }
+}
+
+/**
+ * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_STOPPING it
+ * sets the stopping state handlers and posts an RNC invalidate request to the
+ * SCU hardware.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT that is cast into a
+ *       SCIC_SDS_REMOTE_DEVICE.
+ *
+ * @return none
+ */
+static
+void scic_sds_remote_device_stopping_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object;
+
+   SET_STATE_HANDLER(
+      this_device,
+      scic_sds_remote_device_state_handler_table,
+      SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
+   );
+}
+
+/**
+ * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_FAILED it
+ * sets the stopping state handlers.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT that is cast into a
+ *       SCIC_SDS_REMOTE_DEVICE.
+ *
+ * @return none
+ */
+static
+void scic_sds_remote_device_failed_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object;
+
+   SET_STATE_HANDLER(
+      this_device,
+      scic_sds_remote_device_state_handler_table,
+      SCI_BASE_REMOTE_DEVICE_STATE_FAILED
+   );
+}
+
+/**
+ * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_RESETTING it
+ * sets the resetting state handlers.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT that is cast into a
+ *       SCIC_SDS_REMOTE_DEVICE.
+ *
+ * @return none
+ */
+static
+void scic_sds_remote_device_resetting_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object;
+
+   SET_STATE_HANDLER(
+      this_device,
+      scic_sds_remote_device_state_handler_table,
+      SCI_BASE_REMOTE_DEVICE_STATE_RESETTING
+   );
+
+   scic_sds_remote_node_context_suspend(
+      this_device->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL);
+}
+
+/**
+ * This is the exit method for the SCI_BASE_REMOTE_DEVICE_STATE_RESETTING it
+ * does nothing.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT that is cast into a
+ *       SCIC_SDS_REMOTE_DEVICE.
+ *
+ * @return none
+ */
+static
+void scic_sds_remote_device_resetting_state_exit(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object;
+
+   scic_sds_remote_node_context_resume(this_device->rnc, NULL, NULL);
+}
+
+/**
+ * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_FINAL it sets
+ * the final state handlers.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT that is cast into a
+ *       SCIC_SDS_REMOTE_DEVICE.
+ *
+ * @return none
+ */
+static
+void scic_sds_remote_device_final_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object;
+
+   SET_STATE_HANDLER(
+      this_device,
+      scic_sds_remote_device_state_handler_table,
+      SCI_BASE_REMOTE_DEVICE_STATE_FINAL
+   );
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_BASE_STATE_T
+   scic_sds_remote_device_state_table[SCI_BASE_REMOTE_DEVICE_MAX_STATES] =
+{
+   {
+      SCI_BASE_REMOTE_DEVICE_STATE_INITIAL,
+      scic_sds_remote_device_initial_state_enter,
+      NULL
+   },
+   {
+      SCI_BASE_REMOTE_DEVICE_STATE_STOPPED,
+      scic_sds_remote_device_stopped_state_enter,
+      NULL
+   },
+   {
+      SCI_BASE_REMOTE_DEVICE_STATE_STARTING,
+      scic_sds_remote_device_starting_state_enter,
+      NULL
+   },
+   {
+      SCI_BASE_REMOTE_DEVICE_STATE_READY,
+      scic_sds_remote_device_ready_state_enter,
+      scic_sds_remote_device_ready_state_exit
+   },
+   {
+      SCI_BASE_REMOTE_DEVICE_STATE_STOPPING,
+      scic_sds_remote_device_stopping_state_enter,
+      NULL
+   },
+   {
+      SCI_BASE_REMOTE_DEVICE_STATE_FAILED,
+      scic_sds_remote_device_failed_state_enter,
+      NULL
+   },
+   {
+      SCI_BASE_REMOTE_DEVICE_STATE_RESETTING,
+      scic_sds_remote_device_resetting_state_enter,
+      scic_sds_remote_device_resetting_state_exit
+   },
+#if !defined(DISABLE_WIDE_PORTED_TARGETS)
+   {  //Not used by SCIC
+      SCI_BASE_REMOTE_DEVICE_STATE_UPDATING_PORT_WIDTH,
+      NULL,
+      NULL
+   },
+#endif //#if !defined(DISABLE_WIDE_PORTED_TARGETS)
+   {
+      SCI_BASE_REMOTE_DEVICE_STATE_FINAL,
+      scic_sds_remote_device_final_state_enter,
+      NULL
+   }
+};
diff --git a/sys/dev/disk/isci/scil/scic_sds_remote_device.h b/sys/dev/disk/isci/scil/scic_sds_remote_device.h
new file mode 100644
index 0000000..287ff23
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_sds_remote_device.h
@@ -0,0 +1,646 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_sds_remote_device.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIC_SDS_REMOTE_DEVICE_H_
+#define _SCIC_SDS_REMOTE_DEVICE_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains the structures, constants, and prototypes for the
+ *        SCIC_SDS_REMOTE_DEVICE object.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/intel_sas.h>
+#include <dev/disk/isci/scil/sci_base_remote_device.h>
+#include <dev/disk/isci/scil/sci_base_request.h>
+#include <dev/disk/isci/scil/sci_base_state_machine_logger.h>
+#include <dev/disk/isci/scil/scu_remote_node_context.h>
+#include <dev/disk/isci/scil/scic_sds_remote_node_context.h>
+
+struct SCIC_SDS_CONTROLLER;
+struct SCIC_SDS_PORT;
+struct SCIC_SDS_REQUEST;
+struct SCIC_SDS_REMOTE_DEVICE_STATE_HANDLER;
+
+/**
+ * @enum SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATES
+ *
+ * This is the enumeration of the ready substates for the
+ * SCIC_SDS_REMOTE_DEVICE.
+ */
+enum SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATES
+{
+   /**
+    * This is the initial state for the remote device ready substate.
+    */
+   SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_INITIAL,
+
+   /**
+    * This is the ready operational substate for the remote device.  This is the
+    * normal operational state for a remote device.
+    */
+   SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL,
+
+   /**
+    * This is the suspended state for the remote device.  This is the state that
+    * the device is placed in when a RNC suspend is received by the SCU hardware.
+    */
+   SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_SUSPENDED,
+
+   /**
+    * This is the final state that the device is placed in before a change to the
+    * base state machine.
+    */
+   SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_FINAL,
+
+   SCIC_SDS_SSP_REMOTE_DEVICE_READY_MAX_SUBSTATES
+};
+
+/**
+ * @enum SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATES
+ *
+ * This is the enumeration for the SCIC_SDS_REMOTE_DEVICE ready substates for
+ * the STP remote device.
+ */
+enum SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATES
+{
+   /**
+    * This is the idle substate for the stp remote device.  When there are no
+    * active IO for the device it is is in this state.
+    */
+   SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE,
+
+   /**
+    * This is the command state for for the STP remote device.  This state is
+    * entered when the device is processing a non-NCQ command.  The device object
+    * will fail any new start IO requests until this command is complete.
+    */
+   SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD,
+
+   /**
+    * This is the NCQ state for the STP remote device.  This state is entered
+    * when the device is processing an NCQ reuqest.  It will remain in this state
+    * so long as there is one or more NCQ requests being processed.
+    */
+   SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ,
+
+   /**
+    * This is the NCQ error state for the STP remote device.  This state is
+    * entered when an SDB error FIS is received by the device object while in the
+    * NCQ state.  The device object will only accept a READ LOG command while in
+    * this state.
+    */
+   SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR,
+
+#if !defined(DISABLE_ATAPI)
+   /**
+    * This is the ATAPI error state for the STP ATAPI remote device.  This state is
+    * entered when ATAPI device sends error status FIS without data while the device
+    * object is in CMD state. A suspension event is expected in this state. The device
+    * object will resume right away.
+    */
+   SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR,
+#endif
+
+   /**
+    * This is the READY substate indicates the device is waiting for the RESET task
+    * coming to be recovered from certain hardware specific error.
+    */
+   SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET,
+
+   SCIC_SDS_STP_REMOTE_DEVICE_READY_MAX_SUBSTATES
+};
+
+
+/**
+ * @enum SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATES
+ *
+ * This is the enumeration of the ready substates for the SMP REMOTE DEVICE.
+ */
+
+enum SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATES
+{
+   /**
+    * This is the ready operational substate for the remote device.  This is the
+    * normal operational state for a remote device.
+    */
+   SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE,
+
+   /**
+    * This is the suspended state for the remote device.  This is the state that
+    * the device is placed in when a RNC suspend is received by the SCU hardware.
+    */
+   SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD,
+
+   SCIC_SDS_SMP_REMOTE_DEVICE_READY_MAX_SUBSTATES
+};
+
+
+
+
+/**
+ * @struct SCIC_SDS_REMOTE_DEVICE
+ *
+ * @brief  This structure contains the data for an SCU implementation of
+ *         the SCU Core device data.
+ */
+typedef struct SCIC_SDS_REMOTE_DEVICE
+{
+   /**
+    * This field is the common base for all remote device objects.
+    */
+   SCI_BASE_REMOTE_DEVICE_T parent;
+
+   /**
+    * This field is the programmed device port width.  This value is written to
+    * the RCN data structure to tell the SCU how many open connections this
+    * device can have.
+    */
+   U32 device_port_width;
+
+   /**
+    * This field is the programmed connection rate for this remote device.  It is
+    * used to program the TC with the maximum allowed connection rate.
+    */
+   SCI_SAS_LINK_RATE connection_rate;
+
+   /**
+    * This field contains the allowed target protocols for this remote device.
+    */
+   SMP_DISCOVER_RESPONSE_PROTOCOLS_T target_protocols;
+
+   /**
+    * This field contains the device SAS address.
+    */
+   SCI_SAS_ADDRESS_T device_address;
+
+   /**
+    * This filed is assinged the value of TRUE if the device is directly attached
+    * to the port.
+    */
+   BOOL is_direct_attached;
+
+#if !defined(DISABLE_ATAPI)
+   /**
+    * This filed is assinged the value of TRUE if the device is an ATAPI device.
+    */
+   BOOL is_atapi;
+#endif
+
+   /**
+    * This filed contains a pointer back to the port to which this device is
+    * assigned.
+    */
+   struct SCIC_SDS_PORT *owning_port;
+
+   /**
+    * This field contains the SCU silicon remote node context specific
+    * information.
+    */
+   struct SCIC_SDS_REMOTE_NODE_CONTEXT * rnc;
+
+   /**
+    * This field contains the stated request count for the remote device.  The
+    * device can not reach the SCI_BASE_REMOTE_DEVICE_STATE_STOPPED until all
+    * requests are complete and the rnc_posted value is FALSE.
+    */
+   U32 started_request_count;
+
+   /**
+    * This field contains a pointer to the working request object.  It is only
+    * used only for SATA requests since the unsolicited frames we get from the
+    * hardware have no Tag value to look up the io request object.
+    */
+   struct SCIC_SDS_REQUEST * working_request;
+
+   /**
+    * This field contains the reason for the remote device going not_ready.  It is
+    * assigned in the state handlers and used in the state transition.
+    */
+   U32 not_ready_reason;
+
+   /**
+    * This field is TRUE if this remote device has an initialzied ready substate
+    * machine. SSP devices do not have a ready substate machine and STP devices
+    * have a ready substate machine.
+    */
+   BOOL has_ready_substate_machine;
+
+   /**
+    * This field contains the state machine for the ready substate machine for
+    * this SCIC_SDS_REMOTE_DEVICE object.
+    */
+   SCI_BASE_STATE_MACHINE_T ready_substate_machine;
+
+   /**
+    * This field maintains the set of state handlers for the remote device
+    * object.  These are changed each time the remote device enters a new state.
+    */
+   struct SCIC_SDS_REMOTE_DEVICE_STATE_HANDLER *state_handlers;
+
+   #ifdef SCI_LOGGING
+   /**
+    * This field conatins the ready substate machine logger.  The logger will
+    * emit a message each time the ready substate machine changes state.
+    */
+   SCI_BASE_STATE_MACHINE_LOGGER_T ready_substate_machine_logger;
+   #endif
+
+} SCIC_SDS_REMOTE_DEVICE_T;
+
+
+typedef SCI_STATUS (*SCIC_SDS_REMOTE_DEVICE_HANDLER_T)(
+                                 SCIC_SDS_REMOTE_DEVICE_T *this_device);
+
+typedef SCI_STATUS (*SCIC_SDS_REMOTE_DEVICE_SUSPEND_HANDLER_T)(
+                                 SCIC_SDS_REMOTE_DEVICE_T *this_device,
+                                 U32                       suspend_type);
+
+typedef SCI_STATUS (*SCIC_SDS_REMOTE_DEVICE_RESUME_HANDLER_T)(
+                                 SCIC_SDS_REMOTE_DEVICE_T *this_device);
+
+typedef SCI_STATUS (*SCIC_SDS_REMOTE_DEVICE_FRAME_HANDLER_T)(
+                                  SCIC_SDS_REMOTE_DEVICE_T *this_device,
+                                  U32                       frame_index);
+
+typedef SCI_STATUS (*SCIC_SDS_REMOTE_DEVICE_EVENT_HANDLER_T)(
+                                  SCIC_SDS_REMOTE_DEVICE_T *this_device,
+                                  U32                       event_code);
+
+typedef void (*SCIC_SDS_REMOTE_DEVICE_READY_NOT_READY_HANDLER_T)(
+                                  SCIC_SDS_REMOTE_DEVICE_T *this_device);
+
+/**
+ * @struct SCIC_SDS_REMOTE_DEVICE_STATE_HANDLER
+ * @brief This structure conains the state handlers that are needed to
+ *        process requests for the SCU remote device objects.
+ */
+typedef struct SCIC_SDS_REMOTE_DEVICE_STATE_HANDLER
+{
+   SCI_BASE_REMOTE_DEVICE_STATE_HANDLER_T parent;
+
+   SCIC_SDS_REMOTE_DEVICE_SUSPEND_HANDLER_T suspend_handler;
+   SCIC_SDS_REMOTE_DEVICE_RESUME_HANDLER_T  resume_handler;
+
+   SCIC_SDS_REMOTE_DEVICE_EVENT_HANDLER_T event_handler;
+   SCIC_SDS_REMOTE_DEVICE_FRAME_HANDLER_T frame_handler;
+
+} SCIC_SDS_REMOTE_DEVICE_STATE_HANDLER_T;
+
+
+extern SCI_BASE_STATE_T scic_sds_remote_device_state_table[];
+extern SCI_BASE_STATE_T scic_sds_ssp_remote_device_ready_substate_table[];
+extern SCI_BASE_STATE_T scic_sds_stp_remote_device_ready_substate_table[];
+extern SCI_BASE_STATE_T scic_sds_smp_remote_device_ready_substate_table[];
+
+extern SCIC_SDS_REMOTE_DEVICE_STATE_HANDLER_T
+               scic_sds_remote_device_state_handler_table[];
+extern SCIC_SDS_REMOTE_DEVICE_STATE_HANDLER_T
+               scic_sds_ssp_remote_device_ready_substate_handler_table[];
+extern SCIC_SDS_REMOTE_DEVICE_STATE_HANDLER_T
+               scic_sds_stp_remote_device_ready_substate_handler_table[];
+extern SCIC_SDS_REMOTE_DEVICE_STATE_HANDLER_T
+               scic_sds_smp_remote_device_ready_substate_handler_table[];
+
+/**
+ * This macro incrments the request count for this device
+ */
+#define scic_sds_remote_device_increment_request_count(this_device) \
+   ((this_device)->started_request_count++)
+
+/**
+ * This macro decrements the request count for this device.  This count
+ * will never decrment past 0.
+ */
+#define scic_sds_remote_device_decrement_request_count(this_device) \
+   ((this_device)->started_request_count > 0 ? \
+      (this_device)->started_request_count-- : 0)
+
+/**
+ * This is a helper macro to return the current device request count.
+ */
+#define scic_sds_remote_device_get_request_count(this_device) \
+   ((this_device)->started_request_count)
+
+/**
+ * This macro returns the owning port of this remote device obejct.
+ */
+#define scic_sds_remote_device_get_port(this_device) \
+   ((this_device)->owning_port)
+
+/**
+ * This macro returns the controller object that contains this device
+ * object
+ */
+#define scic_sds_remote_device_get_controller(this_device) \
+   scic_sds_port_get_controller(scic_sds_remote_device_get_port(this_device))
+
+/**
+ * This macro sets the remote device state handlers pointer and is set on
+ * entry to each device state.
+ */
+#define scic_sds_remote_device_set_state_handlers(this_device, handlers) \
+   ((this_device)->state_handlers = (handlers))
+
+/**
+ * This macro returns the base sate machine object for the remote device.
+ */
+#define scic_sds_remote_device_get_base_state_machine(this_device) \
+   (&(this_device)->parent.state_machine)
+
+/**
+ * This macro returns the remote device ready substate machine
+ */
+#define scic_sds_remote_device_get_ready_substate_machine(this_device) \
+   (&(this_device)->ready_substate_machine)
+
+/**
+ * This macro returns the owning port of this device
+ */
+#define scic_sds_remote_device_get_port(this_device) \
+   ((this_device)->owning_port)
+
+/**
+ * This macro returns the remote device sequence value
+ */
+#define scic_sds_remote_device_get_sequence(this_device) \
+   ( \
+      scic_sds_remote_device_get_controller(this_device)->\
+         remote_device_sequence[(this_device)->rnc->remote_node_index] \
+   )
+
+/**
+ * This macro returns the controllers protocol engine group
+ */
+#define scic_sds_remote_device_get_controller_peg(this_device) \
+   ( \
+      scic_sds_controller_get_protocol_engine_group( \
+         scic_sds_port_get_controller( \
+            scic_sds_remote_device_get_port(this_device) \
+         ) \
+      ) \
+   )
+
+/**
+ * This macro returns the port index for the devices owning port
+ */
+#define scic_sds_remote_device_get_port_index(this_device) \
+   (scic_sds_port_get_index(scic_sds_remote_device_get_port(this_device)))
+
+/**
+ * This macro returns the remote node index for this device object
+ */
+#define scic_sds_remote_device_get_index(this_device) \
+   ((this_device)->rnc->remote_node_index)
+
+/**
+ * This macro builds a remote device context for the SCU post request
+ * operation
+ */
+#define scic_sds_remote_device_build_command_context(device, command) \
+   (   (command) \
+     | ((U32)(scic_sds_remote_device_get_controller_peg((device))) << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT)\
+     | ((U32)(scic_sds_remote_device_get_port_index((device))) << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) \
+     | (scic_sds_remote_device_get_index((device))) \
+   )
+
+/**
+ * This macro makes the working request assingment for the remote device
+ * object. To clear the working request use this macro with a NULL request
+ * object.
+ */
+#define scic_sds_remote_device_set_working_request(device, request) \
+   ((device)->working_request = (request))
+
+// ---------------------------------------------------------------------------
+
+U32 scic_sds_remote_device_get_min_timer_count(void);
+
+U32 scic_sds_remote_device_get_max_timer_count(void);
+
+SCI_STATUS scic_sds_remote_device_frame_handler(
+   SCIC_SDS_REMOTE_DEVICE_T *this_device,
+   U32                       frame_index
+);
+
+SCI_STATUS scic_sds_remote_device_event_handler(
+   SCIC_SDS_REMOTE_DEVICE_T *this_device,
+   U32                       event_code
+);
+
+SCI_STATUS scic_sds_remote_device_start_io(
+   struct SCIC_SDS_CONTROLLER *controller,
+   SCIC_SDS_REMOTE_DEVICE_T   *this_device,
+   struct SCIC_SDS_REQUEST    *io_request
+);
+
+SCI_STATUS scic_sds_remote_device_complete_io(
+   struct SCIC_SDS_CONTROLLER *controller,
+   SCIC_SDS_REMOTE_DEVICE_T   *this_device,
+   struct SCIC_SDS_REQUEST    *io_request
+);
+
+SCI_STATUS scic_sds_remote_device_resume(
+   SCIC_SDS_REMOTE_DEVICE_T *this_device
+);
+
+SCI_STATUS scic_sds_remote_device_suspend(
+   SCIC_SDS_REMOTE_DEVICE_T *this_device,
+   U32                       suspend_type
+);
+
+SCI_STATUS scic_sds_remote_device_start_task(
+   struct SCIC_SDS_CONTROLLER  *controller,
+   SCIC_SDS_REMOTE_DEVICE_T    *this_device,
+   struct SCIC_SDS_REQUEST     *io_request
+);
+
+void scic_sds_remote_device_post_request(
+   SCIC_SDS_REMOTE_DEVICE_T * this_device,
+   U32                        request
+);
+
+#if !defined(DISABLE_ATAPI)
+BOOL scic_sds_remote_device_is_atapi(
+   SCIC_SDS_REMOTE_DEVICE_T    *this_device
+);
+#else // !defined(DISABLE_ATAPI)
+#define scic_sds_remote_device_is_atapi(this_device) FALSE
+#endif // !defined(DISABLE_ATAPI)
+
+// ---------------------------------------------------------------------------
+
+#ifdef SCI_LOGGING
+void scic_sds_remote_device_initialize_state_logging(
+   SCIC_SDS_REMOTE_DEVICE_T *this_device
+);
+
+void scic_sds_remote_device_deinitialize_state_logging(
+   SCIC_SDS_REMOTE_DEVICE_T *this_device
+);
+#else // SCI_LOGGING
+#define scic_sds_remote_device_initialize_state_logging(x)
+#define scic_sds_remote_device_deinitialize_state_logging(x)
+#endif // SCI_LOGGING
+
+// ---------------------------------------------------------------------------
+
+void scic_sds_remote_device_start_request(
+   SCIC_SDS_REMOTE_DEVICE_T * this_device,
+   struct SCIC_SDS_REQUEST  * the_request,
+   SCI_STATUS                 status
+);
+
+void scic_sds_remote_device_continue_request(
+   SCIC_SDS_REMOTE_DEVICE_T * this_device
+);
+
+SCI_STATUS scic_sds_remote_device_default_start_handler(
+   SCI_BASE_REMOTE_DEVICE_T *this_device
+);
+
+SCI_STATUS scic_sds_remote_device_default_stop_handler(
+   SCI_BASE_REMOTE_DEVICE_T *this_device
+);
+
+SCI_STATUS scic_sds_remote_device_default_fail_handler(
+   SCI_BASE_REMOTE_DEVICE_T *this_device
+);
+
+SCI_STATUS scic_sds_remote_device_default_destruct_handler(
+   SCI_BASE_REMOTE_DEVICE_T *this_device
+);
+
+SCI_STATUS scic_sds_remote_device_default_reset_handler(
+   SCI_BASE_REMOTE_DEVICE_T *device
+);
+
+SCI_STATUS scic_sds_remote_device_default_reset_complete_handler(
+   SCI_BASE_REMOTE_DEVICE_T *device
+);
+
+SCI_STATUS scic_sds_remote_device_default_start_request_handler(
+   SCI_BASE_REMOTE_DEVICE_T *device,
+   SCI_BASE_REQUEST_T       *request
+);
+
+SCI_STATUS scic_sds_remote_device_default_complete_request_handler(
+   SCI_BASE_REMOTE_DEVICE_T *device,
+   SCI_BASE_REQUEST_T       *request
+);
+
+SCI_STATUS scic_sds_remote_device_default_continue_request_handler(
+   SCI_BASE_REMOTE_DEVICE_T *device,
+   SCI_BASE_REQUEST_T       *request
+);
+
+SCI_STATUS scic_sds_remote_device_default_suspend_handler(
+   SCIC_SDS_REMOTE_DEVICE_T *this_device,
+   U32                       suspend_type
+);
+
+SCI_STATUS scic_sds_remote_device_default_resume_handler(
+   SCIC_SDS_REMOTE_DEVICE_T *this_device
+);
+
+SCI_STATUS  scic_sds_remote_device_default_event_handler(
+   SCIC_SDS_REMOTE_DEVICE_T *this_device,
+   U32                       event_code
+);
+
+SCI_STATUS scic_sds_remote_device_default_frame_handler(
+   SCIC_SDS_REMOTE_DEVICE_T *this_device,
+   U32                       frame_index
+);
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_sds_remote_device_ready_state_stop_handler(
+   SCI_BASE_REMOTE_DEVICE_T *device
+);
+
+SCI_STATUS scic_sds_remote_device_ready_state_reset_handler(
+   SCI_BASE_REMOTE_DEVICE_T *device
+);
+
+SCI_STATUS scic_sds_remote_device_general_frame_handler(
+   SCIC_SDS_REMOTE_DEVICE_T *this_device,
+   U32                       frame_index
+);
+
+SCI_STATUS scic_sds_remote_device_general_event_handler(
+   SCIC_SDS_REMOTE_DEVICE_T *this_device,
+   U32                       event_code
+);
+
+SCI_STATUS scic_sds_ssp_remote_device_ready_suspended_substate_resume_handler(
+   SCIC_SDS_REMOTE_DEVICE_T *this_device
+);
+
+// ---------------------------------------------------------------------------
+
+void scic_sds_remote_device_get_info_from_smp_discover_response(
+   SCIC_SDS_REMOTE_DEVICE_T    * this_device,
+   SMP_RESPONSE_DISCOVER_T     * discover_response
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIC_SDS_REMOTE_DEVICE_H_
diff --git a/sys/dev/disk/isci/scil/scic_sds_remote_node_context.c b/sys/dev/disk/isci/scil/scic_sds_remote_node_context.c
new file mode 100644
index 0000000..2b76b36
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_sds_remote_node_context.c
@@ -0,0 +1,1498 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_sds_remote_node_context.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+* @file
+*
+* @brief This file contains the structures, constants, and prototypes
+*        associated with the remote node context in the silicon.  It
+*        exists to model and manage the remote node context in the silicon.
+*/
+
+#include <dev/disk/isci/scil/sci_util.h>
+#include <dev/disk/isci/scil/scic_sds_logger.h>
+#include <dev/disk/isci/scil/scic_sds_controller.h>
+#include <dev/disk/isci/scil/scic_sds_remote_device.h>
+#include <dev/disk/isci/scil/scic_sds_remote_node_context.h>
+#include <dev/disk/isci/scil/sci_base_state_machine.h>
+#include <dev/disk/isci/scil/scic_remote_device.h>
+#include <dev/disk/isci/scil/scic_sds_port.h>
+#include <dev/disk/isci/scil/scu_event_codes.h>
+#include <dev/disk/isci/scil/scu_task_context.h>
+
+/**
+* @brief
+*/
+   void scic_sds_remote_node_context_construct(
+   SCIC_SDS_REMOTE_DEVICE_T       * device,
+   SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc,
+   U16                              remote_node_index
+      )
+{
+   memset (rnc, 0, sizeof(SCIC_SDS_REMOTE_NODE_CONTEXT_T) );
+
+   rnc->remote_node_index = remote_node_index;
+   rnc->device            = device;
+   rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED;
+
+   rnc->parent.logger = device->parent.parent.logger;
+
+   sci_base_state_machine_construct(
+      &rnc->state_machine,
+      &rnc->parent,
+      scic_sds_remote_node_context_state_table,
+      SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
+         );
+
+   sci_base_state_machine_start(&rnc->state_machine);
+
+   // State logging initialization takes place late for the remote node context
+   // see the resume state handler for the initial state.
+}
+
+/**
+* This method will return TRUE if the RNC is not in the initial state.  In
+* all other states the RNC is considered active and this will return TRUE.
+*
+* @note The destroy request of the state machine drives the RNC back to the
+*       initial state.  If the state machine changes then this routine will
+*       also have to be changed.
+*
+* @param[in] this_rnc The RNC for which the is posted request is being made.
+*
+* @return BOOL
+* @retval TRUE if the state machine is not in the initial state
+* @retval FALSE if the state machine is in the initial state
+*/
+   BOOL scic_sds_remote_node_context_is_initialized(
+   SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
+      )
+{
+   U32 current_state = sci_base_state_machine_get_state(&this_rnc->state_machine);
+
+   if (current_state == SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE)
+   {
+      return FALSE;
+   }
+
+   return TRUE;
+}
+
+/**
+* This method will return TRUE if the remote node context is in a READY state
+* otherwise it will return FALSE
+*
+* @param[in] this_rnc The state of the remote node context object to check.
+*
+* @return BOOL
+* @retval TRUE if the remote node context is in the ready state.
+* @retval FALSE if the remote node context is not in the ready state.
+*/
+   BOOL scic_sds_remote_node_context_is_ready(
+   SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
+      )
+{
+   U32 current_state = sci_base_state_machine_get_state(&this_rnc->state_machine);
+
+   if (current_state == SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE)
+   {
+      return TRUE;
+   }
+
+   return FALSE;
+}
+
+/**
+* This method will construct the RNC buffer for this remote device object.
+*
+* @param[in] this_device The remote device to use to construct the RNC
+*       buffer.
+* @param[in] rnc The buffer into which the remote device data will be copied.
+*
+* @return none
+*/
+   void scic_sds_remote_node_context_construct_buffer(
+   SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
+      )
+{
+   SCU_REMOTE_NODE_CONTEXT_T * rnc;
+   SCIC_SDS_CONTROLLER_T     * the_controller;
+
+   the_controller = scic_sds_remote_device_get_controller(this_rnc->device);
+
+   rnc = scic_sds_controller_get_remote_node_context_buffer(
+      the_controller, this_rnc->remote_node_index);
+
+   memset(
+      rnc,
+      0x00,
+      sizeof(SCU_REMOTE_NODE_CONTEXT_T)
+         * scic_sds_remote_device_node_count(this_rnc->device)
+         );
+
+   rnc->ssp.remote_node_index = this_rnc->remote_node_index;
+   rnc->ssp.remote_node_port_width = this_rnc->device->device_port_width;
+   rnc->ssp.logical_port_index =
+      scic_sds_remote_device_get_port_index(this_rnc->device);
+
+   rnc->ssp.remote_sas_address_hi = SCIC_SWAP_DWORD(this_rnc->device->device_address.high);
+   rnc->ssp.remote_sas_address_lo = SCIC_SWAP_DWORD(this_rnc->device->device_address.low);
+
+   rnc->ssp.nexus_loss_timer_enable = TRUE;
+   rnc->ssp.check_bit               = FALSE;
+   rnc->ssp.is_valid                = FALSE;
+   rnc->ssp.is_remote_node_context  = TRUE;
+   rnc->ssp.function_number         = 0;
+
+   rnc->ssp.arbitration_wait_time = 0;
+
+
+   if (
+      this_rnc->device->target_protocols.u.bits.attached_sata_device
+         || this_rnc->device->target_protocols.u.bits.attached_stp_target
+         )
+   {
+      rnc->ssp.connection_occupancy_timeout =
+         the_controller->user_parameters.sds1.stp_max_occupancy_timeout;
+      rnc->ssp.connection_inactivity_timeout =
+         the_controller->user_parameters.sds1.stp_inactivity_timeout;
+   }
+   else
+   {
+      rnc->ssp.connection_occupancy_timeout  =
+         the_controller->user_parameters.sds1.ssp_max_occupancy_timeout;
+      rnc->ssp.connection_inactivity_timeout =
+         the_controller->user_parameters.sds1.ssp_inactivity_timeout;
+   }
+
+   rnc->ssp.initial_arbitration_wait_time = 0;
+
+   // Open Address Frame Parameters
+   rnc->ssp.oaf_connection_rate = this_rnc->device->connection_rate;
+   rnc->ssp.oaf_features = 0;
+   rnc->ssp.oaf_source_zone_group = 0;
+   rnc->ssp.oaf_more_compatibility_features = 0;
+}
+
+// ---------------------------------------------------------------------------
+
+#ifdef SCI_LOGGING
+/**
+* This method will enable and turn on state transition logging for the remote
+* node context object.
+*
+* @param[in] this_rnc The remote node context for which state transition
+*       logging is to be enabled.
+*
+* @return none
+*/
+   void scic_sds_remote_node_context_initialize_state_logging(
+   SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
+      )
+{
+   sci_base_state_machine_logger_initialize(
+      &this_rnc->state_machine_logger,
+      &this_rnc->state_machine,
+      &this_rnc->parent,
+      scic_cb_logger_log_states,
+      "SCIC_SDS_REMOTE_NODE_CONTEXT_T", "state machine",
+      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+         SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
+         SCIC_LOG_OBJECT_STP_REMOTE_TARGET
+         );
+}
+
+/**
+* This method will stop the state machine logging for this object and should
+* be called before the object is destroyed.
+*
+* @param[in] this_rnc The remote node context on which to stop logging state
+*       transitions.
+*
+* @return none
+*/
+   void scic_sds_remote_node_context_deinitialize_state_logging(
+   SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
+      )
+{
+   sci_base_state_machine_logger_deinitialize(
+      &this_rnc->state_machine_logger,
+      &this_rnc->state_machine
+         );
+}
+#endif
+
+/**
+* This method will setup the remote node context object so it will transition
+* to its ready state.  If the remote node context is already setup to
+* transition to its final state then this function does nothing.
+*
+* @param[in] this_rnc
+* @param[in] the_callback
+* @param[in] callback_parameter
+*
+* @return none
+*/
+static
+void scic_sds_remote_node_context_setup_to_resume(
+   SCIC_SDS_REMOTE_NODE_CONTEXT_T         * this_rnc,
+   SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK   the_callback,
+   void                                   * callback_parameter
+)
+{
+   if (this_rnc->destination_state != SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL)
+   {
+      this_rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY;
+      this_rnc->user_callback     = the_callback;
+      this_rnc->user_cookie       = callback_parameter;
+   }
+}
+
+/**
+* This method will setup the remote node context object so it will
+* transistion to its final state.
+*
+* @param[in] this_rnc
+* @param[in] the_callback
+* @param[in] callback_parameter
+*
+* @return none
+*/
+static
+void scic_sds_remote_node_context_setup_to_destory(
+   SCIC_SDS_REMOTE_NODE_CONTEXT_T         * this_rnc,
+   SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK   the_callback,
+   void                                   * callback_parameter
+)
+{
+   this_rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL;
+   this_rnc->user_callback     = the_callback;
+   this_rnc->user_cookie       = callback_parameter;
+}
+
+/**
+* This method will continue to resume a remote node context.  This is used
+* in the states where a resume is requested while a resume is in progress.
+*
+* @param[in] this_rnc
+* @param[in] the_callback
+* @param[in] callback_parameter
+*/
+static
+SCI_STATUS scic_sds_remote_node_context_continue_to_resume_handler(
+   SCIC_SDS_REMOTE_NODE_CONTEXT_T         * this_rnc,
+   SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK   the_callback,
+   void                                   * callback_parameter
+)
+{
+   if (this_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY)
+   {
+      this_rnc->user_callback = the_callback;
+      this_rnc->user_cookie   = callback_parameter;
+
+      return SCI_SUCCESS;
+   }
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+//******************************************************************************
+//* REMOTE NODE CONTEXT STATE MACHINE
+//******************************************************************************
+
+static
+SCI_STATUS scic_sds_remote_node_context_default_destruct_handler(
+   SCIC_SDS_REMOTE_NODE_CONTEXT_T         * this_rnc,
+   SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK   the_callback,
+   void                                   * callback_parameter
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger(this_rnc->device),
+      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+         SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
+         SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
+      "SCIC Remote Node Context 0x%x requested to stop while in unexpected state %d\n",
+      this_rnc, sci_base_state_machine_get_state(&this_rnc->state_machine)
+         ));
+
+   // We have decided that the destruct request on the remote node context can not fail
+   // since it is either in the initial/destroyed state or is can be destroyed.
+   return SCI_SUCCESS;
+}
+
+static
+SCI_STATUS scic_sds_remote_node_context_default_suspend_handler(
+   SCIC_SDS_REMOTE_NODE_CONTEXT_T         * this_rnc,
+   U32                                      suspend_type,
+   SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK   the_callback,
+   void                                   * callback_parameter
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger(this_rnc->device),
+      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+         SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
+         SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
+      "SCIC Remote Node Context 0x%x requested to suspend while in wrong state %d\n",
+      this_rnc, sci_base_state_machine_get_state(&this_rnc->state_machine)
+         ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+static
+SCI_STATUS scic_sds_remote_node_context_default_resume_handler(
+   SCIC_SDS_REMOTE_NODE_CONTEXT_T         * this_rnc,
+   SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK   the_callback,
+   void                                   * callback_parameter
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger(this_rnc->device),
+      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+         SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
+         SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
+      "SCIC Remote Node Context 0x%x requested to resume while in wrong state %d\n",
+      this_rnc, sci_base_state_machine_get_state(&this_rnc->state_machine)
+         ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+static
+SCI_STATUS scic_sds_remote_node_context_default_start_io_handler(
+   struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
+   struct SCIC_SDS_REQUEST             * the_request
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger(this_rnc->device),
+      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+         SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
+         SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
+      "SCIC Remote Node Context 0x%x requested to start io 0x%x while in wrong state %d\n",
+      this_rnc, the_request, sci_base_state_machine_get_state(&this_rnc->state_machine)
+         ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+static
+SCI_STATUS scic_sds_remote_node_context_default_start_task_handler(
+   struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
+   struct SCIC_SDS_REQUEST             * the_request
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger(this_rnc->device),
+      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+         SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
+         SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
+      "SCIC Remote Node Context 0x%x requested to start task 0x%x while in wrong state %d\n",
+      this_rnc, the_request, sci_base_state_machine_get_state(&this_rnc->state_machine)
+         ));
+
+   return SCI_FAILURE;
+}
+
+static
+SCI_STATUS scic_sds_remote_node_context_default_event_handler(
+   struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
+   U32                                   event_code
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger(this_rnc->device),
+      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+         SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
+         SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
+      "SCIC Remote Node Context 0x%x requested to process event 0x%x while in wrong state %d\n",
+      this_rnc, event_code, sci_base_state_machine_get_state(&this_rnc->state_machine)
+         ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+* This method determines if the task request can be started by the SCU
+* hardware. When the RNC is in the ready state any task can be started.
+*
+* @param[in] this_rnc The rnc for which the task request is targeted.
+* @param[in] the_request The request which is going to be started.
+*
+* @return SCI_STATUS
+* @retval SCI_SUCCESS
+*/
+static
+SCI_STATUS scic_sds_remote_node_context_success_start_task_handler(
+   struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
+   struct SCIC_SDS_REQUEST             * the_request
+)
+{
+   return SCI_SUCCESS;
+}
+
+/**
+* This method handles destruct calls from the various state handlers.  The
+* remote node context can be requested to destroy from any state. If there
+* was a user callback it is always replaced with the request to destroy user
+* callback.
+*
+* @param[in] this_rnc
+* @param[in] the_callback
+* @param[in] callback_parameter
+*
+* @return SCI_STATUS
+*/
+static
+SCI_STATUS scic_sds_remote_node_context_general_destruct_handler(
+   SCIC_SDS_REMOTE_NODE_CONTEXT_T         * this_rnc,
+   SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK   the_callback,
+   void                                   * callback_parameter
+)
+{
+   scic_sds_remote_node_context_setup_to_destory(
+      this_rnc, the_callback, callback_parameter
+         );
+
+   sci_base_state_machine_change_state(
+      &this_rnc->state_machine,
+      SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
+         );
+
+   return SCI_SUCCESS;
+}
+// ---------------------------------------------------------------------------
+static
+SCI_STATUS scic_sds_remote_node_context_reset_required_start_io_handler(
+   struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
+   struct SCIC_SDS_REQUEST             * the_request
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger(this_rnc->device),
+      SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+         SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
+         SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
+      "SCIC Remote Node Context 0x%x requested to start io 0x%x while in wrong state %d\n",
+      this_rnc, the_request, sci_base_state_machine_get_state(&this_rnc->state_machine)
+         ));
+
+   return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED;
+}
+
+// ---------------------------------------------------------------------------
+
+static
+SCI_STATUS scic_sds_remote_node_context_initial_state_resume_handler(
+   SCIC_SDS_REMOTE_NODE_CONTEXT_T         * this_rnc,
+   SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK   the_callback,
+   void                                   * callback_parameter
+)
+{
+   if (this_rnc->remote_node_index != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX)
+   {
+      scic_sds_remote_node_context_setup_to_resume(
+         this_rnc, the_callback, callback_parameter
+            );
+
+      scic_sds_remote_node_context_construct_buffer(this_rnc);
+
+#if defined (SCI_LOGGING)
+      // If a remote node context has a logger already, don't work on its state
+      // logging.
+      if (this_rnc->state_machine.previous_state_id
+             != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE)
+         scic_sds_remote_node_context_initialize_state_logging(this_rnc);
+#endif
+
+      sci_base_state_machine_change_state(
+         &this_rnc->state_machine,
+         SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
+            );
+
+      return SCI_SUCCESS;
+   }
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+// ---------------------------------------------------------------------------
+
+static
+SCI_STATUS scic_sds_remote_node_context_posting_state_event_handler(
+   struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
+   U32                                   event_code
+)
+{
+   SCI_STATUS status;
+
+   switch (scu_get_event_code(event_code))
+   {
+      case SCU_EVENT_POST_RNC_COMPLETE:
+         status = SCI_SUCCESS;
+
+         sci_base_state_machine_change_state(
+            &this_rnc->state_machine,
+            SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
+               );
+         break;
+
+      default:
+         status = SCI_FAILURE;
+         SCIC_LOG_WARNING((
+            sci_base_object_get_logger(this_rnc->device),
+            SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+               SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
+               SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
+            "SCIC Remote Node Context 0x%x requested to process unexpected event 0x%x while in posting state\n",
+            this_rnc, event_code
+               ));
+         break;
+   }
+
+   return status;
+}
+
+// ---------------------------------------------------------------------------
+
+static
+SCI_STATUS scic_sds_remote_node_context_invalidating_state_destruct_handler(
+   SCIC_SDS_REMOTE_NODE_CONTEXT_T         * this_rnc,
+   SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK   the_callback,
+   void                                   * callback_parameter
+)
+{
+   scic_sds_remote_node_context_setup_to_destory(
+      this_rnc, the_callback, callback_parameter
+         );
+
+   return SCI_SUCCESS;
+}
+
+static
+SCI_STATUS scic_sds_remote_node_context_invalidating_state_event_handler(
+   SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
+   U32                              event_code
+)
+{
+   SCI_STATUS status;
+
+   if (scu_get_event_code(event_code) == SCU_EVENT_POST_RNC_INVALIDATE_COMPLETE)
+   {
+      status = SCI_SUCCESS;
+
+      if (this_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL)
+      {
+         sci_base_state_machine_change_state(
+            &this_rnc->state_machine,
+            SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
+               );
+      }
+      else
+      {
+         sci_base_state_machine_change_state(
+            &this_rnc->state_machine,
+            SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
+               );
+      }
+   }
+   else
+   {
+      switch (scu_get_event_type(event_code))
+      {
+         case SCU_EVENT_TYPE_RNC_SUSPEND_TX:
+         case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX:
+            // We really dont care if the hardware is going to suspend
+            // the device since it's being invalidated anyway
+            SCIC_LOG_INFO((
+               sci_base_object_get_logger(this_rnc->device),
+               SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+                  SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
+                  SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
+               "SCIC Remote Node Context 0x%x was suspeneded by hardware while being invalidated.\n",
+               this_rnc
+                  ));
+            status = SCI_SUCCESS;
+            break;
+
+         default:
+            SCIC_LOG_WARNING((
+               sci_base_object_get_logger(this_rnc->device),
+               SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+                  SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
+                  SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
+               "SCIC Remote Node Context 0x%x requested to process event 0x%x while in state %d.\n",
+               this_rnc, event_code, sci_base_state_machine_get_state(&this_rnc->state_machine)
+                  ));
+            status = SCI_FAILURE;
+            break;
+      }
+   }
+
+   return status;
+}
+
+// ---------------------------------------------------------------------------
+
+static
+SCI_STATUS scic_sds_remote_node_context_resuming_state_event_handler(
+   struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
+   U32                                   event_code
+)
+{
+   SCI_STATUS status;
+
+   if (scu_get_event_code(event_code) == SCU_EVENT_POST_RCN_RELEASE)
+   {
+      status = SCI_SUCCESS;
+
+      sci_base_state_machine_change_state(
+         &this_rnc->state_machine,
+         SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
+            );
+   }
+   else
+   {
+      switch (scu_get_event_type(event_code))
+      {
+         case SCU_EVENT_TYPE_RNC_SUSPEND_TX:
+         case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX:
+            // We really dont care if the hardware is going to suspend
+            // the device since it's being resumed anyway
+            SCIC_LOG_INFO((
+               sci_base_object_get_logger(this_rnc->device),
+               SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+                  SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
+                  SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
+               "SCIC Remote Node Context 0x%x was suspeneded by hardware while being resumed.\n",
+               this_rnc
+                  ));
+            status = SCI_SUCCESS;
+            break;
+
+         default:
+            SCIC_LOG_WARNING((
+               sci_base_object_get_logger(this_rnc->device),
+               SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+                  SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
+                  SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
+               "SCIC Remote Node Context 0x%x requested to process event 0x%x while in state %d.\n",
+               this_rnc, event_code, sci_base_state_machine_get_state(&this_rnc->state_machine)
+                  ));
+            status = SCI_FAILURE;
+            break;
+      }
+   }
+
+   return status;
+}
+
+// ---------------------------------------------------------------------------
+
+/**
+* This method will handle the suspend requests from the ready state.
+*
+* @param[in] this_rnc The remote node context object being suspended.
+* @param[in] the_callback The callback when the suspension is complete.
+* @param[in] callback_parameter The parameter that is to be passed into the
+*       callback.
+*
+* @return SCI_SUCCESS
+*/
+static
+SCI_STATUS scic_sds_remote_node_context_ready_state_suspend_handler(
+   SCIC_SDS_REMOTE_NODE_CONTEXT_T         * this_rnc,
+   U32                                      suspend_type,
+   SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK   the_callback,
+   void                                   * callback_parameter
+)
+{
+   this_rnc->user_callback   = the_callback;
+   this_rnc->user_cookie     = callback_parameter;
+   this_rnc->suspension_code = suspend_type;
+
+   if (suspend_type == SCI_SOFTWARE_SUSPENSION)
+   {
+      scic_sds_remote_device_post_request(
+         this_rnc->device,
+         SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX
+            );
+   }
+
+   sci_base_state_machine_change_state(
+      &this_rnc->state_machine,
+      SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE
+         );
+
+   return SCI_SUCCESS;
+}
+
+/**
+* This method determines if the io request can be started by the SCU
+* hardware. When the RNC is in the ready state any io request can be started.
+*
+* @param[in] this_rnc The rnc for which the io request is targeted.
+* @param[in] the_request The request which is going to be started.
+*
+* @return SCI_STATUS
+* @retval SCI_SUCCESS
+*/
+static
+SCI_STATUS scic_sds_remote_node_context_ready_state_start_io_handler(
+   struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
+   struct SCIC_SDS_REQUEST             * the_request
+)
+{
+   return SCI_SUCCESS;
+}
+
+
+static
+SCI_STATUS scic_sds_remote_node_context_ready_state_event_handler(
+   struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
+   U32                                   event_code
+)
+{
+   SCI_STATUS status;
+
+   switch (scu_get_event_type(event_code))
+   {
+      case SCU_EVENT_TL_RNC_SUSPEND_TX:
+         sci_base_state_machine_change_state(
+            &this_rnc->state_machine,
+            SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
+               );
+
+         this_rnc->suspension_code = scu_get_event_specifier(event_code);
+         status = SCI_SUCCESS;
+         break;
+
+      case SCU_EVENT_TL_RNC_SUSPEND_TX_RX:
+         sci_base_state_machine_change_state(
+            &this_rnc->state_machine,
+            SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE
+               );
+
+         this_rnc->suspension_code = scu_get_event_specifier(event_code);
+         status = SCI_SUCCESS;
+         break;
+
+      default:
+         SCIC_LOG_WARNING((
+            sci_base_object_get_logger(this_rnc->device),
+            SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+               SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
+               SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
+            "SCIC Remote Node Context 0x%x requested to process event 0x%x while in state %d.\n",
+            this_rnc, event_code, sci_base_state_machine_get_state(&this_rnc->state_machine)
+               ));
+
+         status = SCI_FAILURE;
+         break;
+   }
+
+   return status;
+}
+
+// ---------------------------------------------------------------------------
+
+static
+SCI_STATUS scic_sds_remote_node_context_tx_suspended_state_resume_handler(
+   SCIC_SDS_REMOTE_NODE_CONTEXT_T         * this_rnc,
+   SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK   the_callback,
+   void                                   * callback_parameter
+)
+{
+   SMP_DISCOVER_RESPONSE_PROTOCOLS_T protocols;
+
+   scic_sds_remote_node_context_setup_to_resume(
+      this_rnc, the_callback, callback_parameter
+         );
+
+   // If this is an expander attached SATA device we must invalidate
+   // and repost the RNC since this is the only way to clear the
+   // TCi to NCQ tag mapping table for the RNi
+   // All other device types we can just resume.
+   scic_remote_device_get_protocols(this_rnc->device, &protocols);
+
+   if (
+      (protocols.u.bits.attached_stp_target == 1)
+         && !(this_rnc->device->is_direct_attached)
+         )
+   {
+      sci_base_state_machine_change_state(
+         &this_rnc->state_machine,
+         SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
+            );
+   }
+   else
+   {
+      sci_base_state_machine_change_state(
+         &this_rnc->state_machine,
+         SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
+            );
+   }
+
+   return SCI_SUCCESS;
+}
+
+/**
+* This method will report a success or failure attempt to start a new task
+* request to the hardware.  Since all task requests are sent on the high
+* priority queue they can be sent when the RCN is in a TX suspend state.
+*
+* @param[in] this_rnc The remote node context which is to receive the task
+*       request.
+* @param[in] the_request The task request to be transmitted to to the remote
+*       target device.
+*
+* @return SCI_STATUS
+* @retval SCI_SUCCESS
+*/
+static
+SCI_STATUS scic_sds_remote_node_context_suspended_start_task_handler(
+   struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
+   struct SCIC_SDS_REQUEST             * the_request
+)
+{
+   scic_sds_remote_node_context_resume(this_rnc, NULL, NULL);
+
+   return SCI_SUCCESS;
+}
+
+// ---------------------------------------------------------------------------
+
+static
+SCI_STATUS scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler(
+   SCIC_SDS_REMOTE_NODE_CONTEXT_T         * this_rnc,
+   SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK   the_callback,
+   void                                   * callback_parameter
+)
+{
+   scic_sds_remote_node_context_setup_to_resume(
+      this_rnc, the_callback, callback_parameter
+         );
+
+   sci_base_state_machine_change_state(
+      &this_rnc->state_machine,
+      SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
+         );
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+// ---------------------------------------------------------------------------
+
+/**
+*
+*/
+static
+SCI_STATUS scic_sds_remote_node_context_await_suspension_state_resume_handler(
+   SCIC_SDS_REMOTE_NODE_CONTEXT_T         * this_rnc,
+   SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK   the_callback,
+   void                                   * callback_parameter
+)
+{
+   scic_sds_remote_node_context_setup_to_resume(
+      this_rnc, the_callback, callback_parameter
+         );
+
+   return SCI_SUCCESS;
+}
+
+/**
+* This method will report a success or failure attempt to start a new task
+* request to the hardware.  Since all task requests are sent on the high
+* priority queue they can be sent when the RCN is in a TX suspend state.
+*
+* @param[in] this_rnc The remote node context which is to receive the task
+*       request.
+* @param[in] the_request The task request to be transmitted to to the remote
+*       target device.
+*
+* @return SCI_STATUS
+* @retval SCI_SUCCESS
+*/
+static
+SCI_STATUS scic_sds_remote_node_context_await_suspension_state_start_task_handler(
+   struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
+   struct SCIC_SDS_REQUEST             * the_request
+)
+{
+   return SCI_SUCCESS;
+}
+
+static
+SCI_STATUS scic_sds_remote_node_context_await_suspension_state_event_handler(
+   struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
+   U32                                   event_code
+)
+{
+   SCI_STATUS status;
+
+   switch (scu_get_event_type(event_code))
+   {
+      case SCU_EVENT_TL_RNC_SUSPEND_TX:
+         sci_base_state_machine_change_state(
+            &this_rnc->state_machine,
+            SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
+               );
+
+         this_rnc->suspension_code = scu_get_event_specifier(event_code);
+         status = SCI_SUCCESS;
+         break;
+
+      case SCU_EVENT_TL_RNC_SUSPEND_TX_RX:
+         sci_base_state_machine_change_state(
+            &this_rnc->state_machine,
+            SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE
+               );
+
+         this_rnc->suspension_code = scu_get_event_specifier(event_code);
+         status = SCI_SUCCESS;
+         break;
+
+      default:
+         SCIC_LOG_WARNING((
+            sci_base_object_get_logger(this_rnc->device),
+            SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
+               SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
+               SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
+            "SCIC Remote Node Context 0x%x requested to process event 0x%x while in state %d.\n",
+            this_rnc, event_code, sci_base_state_machine_get_state(&this_rnc->state_machine)
+               ));
+
+         status = SCI_FAILURE;
+         break;
+   }
+
+   return status;
+}
+
+// ---------------------------------------------------------------------------
+
+   SCIC_SDS_REMOTE_NODE_CONTEXT_HANDLERS
+   scic_sds_remote_node_context_state_handler_table[
+   SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES] =
+{
+   // SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
+   {
+      scic_sds_remote_node_context_default_destruct_handler,
+      scic_sds_remote_node_context_default_suspend_handler,
+      scic_sds_remote_node_context_initial_state_resume_handler,
+      scic_sds_remote_node_context_default_start_io_handler,
+      scic_sds_remote_node_context_default_start_task_handler,
+      scic_sds_remote_node_context_default_event_handler
+   },
+   // SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
+   {
+      scic_sds_remote_node_context_general_destruct_handler,
+      scic_sds_remote_node_context_default_suspend_handler,
+      scic_sds_remote_node_context_continue_to_resume_handler,
+      scic_sds_remote_node_context_default_start_io_handler,
+      scic_sds_remote_node_context_default_start_task_handler,
+      scic_sds_remote_node_context_posting_state_event_handler
+   },
+   // SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
+   {
+      scic_sds_remote_node_context_invalidating_state_destruct_handler,
+      scic_sds_remote_node_context_default_suspend_handler,
+      scic_sds_remote_node_context_continue_to_resume_handler,
+      scic_sds_remote_node_context_default_start_io_handler,
+      scic_sds_remote_node_context_default_start_task_handler,
+      scic_sds_remote_node_context_invalidating_state_event_handler
+   },
+   // SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
+   {
+      scic_sds_remote_node_context_general_destruct_handler,
+      scic_sds_remote_node_context_default_suspend_handler,
+      scic_sds_remote_node_context_continue_to_resume_handler,
+      scic_sds_remote_node_context_default_start_io_handler,
+      scic_sds_remote_node_context_success_start_task_handler,
+      scic_sds_remote_node_context_resuming_state_event_handler
+   },
+   // SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
+   {
+      scic_sds_remote_node_context_general_destruct_handler,
+      scic_sds_remote_node_context_ready_state_suspend_handler,
+      scic_sds_remote_node_context_default_resume_handler,
+      scic_sds_remote_node_context_ready_state_start_io_handler,
+      scic_sds_remote_node_context_success_start_task_handler,
+      scic_sds_remote_node_context_ready_state_event_handler
+   },
+   // SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
+   {
+      scic_sds_remote_node_context_general_destruct_handler,
+      scic_sds_remote_node_context_default_suspend_handler,
+      scic_sds_remote_node_context_tx_suspended_state_resume_handler,
+      scic_sds_remote_node_context_reset_required_start_io_handler,
+      scic_sds_remote_node_context_suspended_start_task_handler,
+      scic_sds_remote_node_context_default_event_handler
+   },
+   // SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE
+   {
+      scic_sds_remote_node_context_general_destruct_handler,
+      scic_sds_remote_node_context_default_suspend_handler,
+      scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler,
+      scic_sds_remote_node_context_reset_required_start_io_handler,
+      scic_sds_remote_node_context_suspended_start_task_handler,
+      scic_sds_remote_node_context_default_event_handler
+   },
+   // SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE
+   {
+      scic_sds_remote_node_context_general_destruct_handler,
+      scic_sds_remote_node_context_default_suspend_handler,
+      scic_sds_remote_node_context_await_suspension_state_resume_handler,
+      scic_sds_remote_node_context_reset_required_start_io_handler,
+      scic_sds_remote_node_context_await_suspension_state_start_task_handler,
+      scic_sds_remote_node_context_await_suspension_state_event_handler
+   }
+};
+
+//*****************************************************************************
+//* REMOTE NODE CONTEXT PRIVATE METHODS
+//*****************************************************************************
+
+/**
+* This method just calls the user callback function and then resets the
+* callback.
+*
+* @param[in out] rnc
+*/
+static
+void scic_sds_remote_node_context_notify_user(
+   SCIC_SDS_REMOTE_NODE_CONTEXT_T *rnc
+)
+{
+   SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK local_user_callback = rnc->user_callback;
+   void * local_user_cookie = rnc->user_cookie;
+
+   //we need to set the user_callback to NULL before it is called, because
+   //the user callback's stack may eventually also set up a new set of
+   //user callback. If we nullify the user_callback after it is called,
+   //we are in the risk to lose the freshly set user callback.
+   rnc->user_callback = NULL;
+   rnc->user_cookie = NULL;
+
+   if (local_user_callback != NULL)
+   {
+      (*local_user_callback)(local_user_cookie);
+   }
+}
+
+/**
+* This method will continue the remote node context state machine by
+* requesting to resume the remote node context state machine from its current
+* state.
+*
+* @param[in] rnc
+*/
+static
+void scic_sds_remote_node_context_continue_state_transitions(
+   SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc
+)
+{
+   if (rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY)
+   {
+      rnc->state_handlers->resume_handler(
+         rnc, rnc->user_callback, rnc->user_cookie
+            );
+   }
+}
+
+/**
+* This method will mark the rnc buffer as being valid and post the request to
+* the hardware.
+*
+* @param[in] this_rnc The remote node context object that is to be
+*            validated.
+*
+* @return none
+*/
+static
+void scic_sds_remote_node_context_validate_context_buffer(
+   SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
+)
+{
+   SCU_REMOTE_NODE_CONTEXT_T *rnc_buffer;
+
+   rnc_buffer = scic_sds_controller_get_remote_node_context_buffer(
+      scic_sds_remote_device_get_controller(this_rnc->device),
+      this_rnc->remote_node_index
+         );
+
+   rnc_buffer->ssp.is_valid = TRUE;
+
+   if (
+      !this_rnc->device->is_direct_attached
+         && this_rnc->device->target_protocols.u.bits.attached_stp_target
+         )
+   {
+      scic_sds_remote_device_post_request(
+         this_rnc->device,
+         SCU_CONTEXT_COMMAND_POST_RNC_96
+            );
+   }
+   else
+   {
+      scic_sds_remote_device_post_request(
+         this_rnc->device,
+         SCU_CONTEXT_COMMAND_POST_RNC_32
+            );
+
+      if (this_rnc->device->is_direct_attached)
+      {
+         scic_sds_port_setup_transports(
+            this_rnc->device->owning_port,
+            this_rnc->remote_node_index
+               );
+      }
+   }
+}
+
+/**
+* This method will update the RNC buffer and post the invalidate request.
+*
+* @param[in] this_rnc The remote node context object that is to be
+*       invalidated.
+*
+* @return none
+*/
+static
+void scic_sds_remote_node_context_invalidate_context_buffer(
+   SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
+)
+{
+   SCU_REMOTE_NODE_CONTEXT_T *rnc_buffer;
+
+   rnc_buffer = scic_sds_controller_get_remote_node_context_buffer(
+      scic_sds_remote_device_get_controller(this_rnc->device),
+      this_rnc->remote_node_index
+         );
+
+   rnc_buffer->ssp.is_valid = FALSE;
+
+   scic_sds_remote_device_post_request(
+      this_rnc->device,
+      SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE
+         );
+}
+
+//*****************************************************************************
+//* REMOTE NODE CONTEXT STATE ENTER AND EXIT METHODS
+//*****************************************************************************
+
+/**
+*
+*
+* @param[in] object
+*/
+static
+void scic_sds_remote_node_context_initial_state_enter(
+   SCI_BASE_OBJECT_T * object
+)
+{
+   SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
+   rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T  *)object;
+
+   SET_STATE_HANDLER(
+      rnc,
+      scic_sds_remote_node_context_state_handler_table,
+      SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
+         );
+
+   // Check to see if we have gotten back to the initial state because someone
+   // requested to destroy the remote node context object.
+   if (
+      rnc->state_machine.previous_state_id
+         == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
+         )
+   {
+      rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED;
+
+      scic_sds_remote_node_context_notify_user(rnc);
+
+      // Since we are destroying the remote node context deinitialize the state logging
+      // should we resume the remote node context the state logging will be reinitialized
+      // on the resume handler.
+      scic_sds_remote_node_context_deinitialize_state_logging(rnc);
+   }
+}
+
+/**
+*
+*
+* @param[in] object
+*/
+static
+void scic_sds_remote_node_context_posting_state_enter(
+   SCI_BASE_OBJECT_T * object
+)
+{
+   SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc;
+   this_rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T  *)object;
+
+   SET_STATE_HANDLER(
+      this_rnc,
+      scic_sds_remote_node_context_state_handler_table,
+      SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
+         );
+
+   scic_sds_remote_node_context_validate_context_buffer(this_rnc);
+}
+
+/**
+*
+*
+* @param[in] object
+*/
+static
+void scic_sds_remote_node_context_invalidating_state_enter(
+   SCI_BASE_OBJECT_T * object
+)
+{
+   SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
+   rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T  *)object;
+
+   SET_STATE_HANDLER(
+      rnc,
+      scic_sds_remote_node_context_state_handler_table,
+      SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
+         );
+
+   scic_sds_remote_node_context_invalidate_context_buffer(rnc);
+}
+
+/**
+*
+*
+* @param[in] object
+*/
+static
+void scic_sds_remote_node_context_resuming_state_enter(
+   SCI_BASE_OBJECT_T * object
+)
+{
+   SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
+   SMP_DISCOVER_RESPONSE_PROTOCOLS_T protocols;
+   rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T  *)object;
+
+   SET_STATE_HANDLER(
+      rnc,
+      scic_sds_remote_node_context_state_handler_table,
+      SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
+         );
+
+   // For direct attached SATA devices we need to clear the TLCR
+   // NCQ to TCi tag mapping on the phy and in cases where we
+   // resume because of a target reset we also need to update
+   // the STPTLDARNI register with the RNi of the device
+   scic_remote_device_get_protocols(rnc->device, &protocols);
+
+   if (
+      (protocols.u.bits.attached_stp_target == 1)
+         && (rnc->device->is_direct_attached)
+         )
+   {
+      scic_sds_port_setup_transports(
+         rnc->device->owning_port, rnc->remote_node_index
+            );
+   }
+
+   scic_sds_remote_device_post_request(
+      rnc->device,
+      SCU_CONTEXT_COMMAND_POST_RNC_RESUME
+         );
+}
+
+/**
+*
+*
+* @param[in] object
+*/
+static
+void scic_sds_remote_node_context_ready_state_enter(
+   SCI_BASE_OBJECT_T * object
+)
+{
+   SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
+   rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T  *)object;
+
+   SET_STATE_HANDLER(
+      rnc,
+      scic_sds_remote_node_context_state_handler_table,
+      SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
+         );
+
+   rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED;
+
+   if (rnc->user_callback != NULL)
+   {
+      scic_sds_remote_node_context_notify_user(rnc);
+   }
+}
+
+/**
+*
+*
+* @param[in] object
+*/
+static
+void scic_sds_remote_node_context_tx_suspended_state_enter(
+   SCI_BASE_OBJECT_T * object
+)
+{
+   SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
+   rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T  *)object;
+
+   SET_STATE_HANDLER(
+      rnc,
+      scic_sds_remote_node_context_state_handler_table,
+      SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
+         );
+
+   scic_sds_remote_node_context_continue_state_transitions(rnc);
+}
+
+/**
+*
+*
+* @param[in] object
+*/
+static
+void scic_sds_remote_node_context_tx_rx_suspended_state_enter(
+   SCI_BASE_OBJECT_T * object
+)
+{
+   SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
+   rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T  *)object;
+
+   SET_STATE_HANDLER(
+      rnc,
+      scic_sds_remote_node_context_state_handler_table,
+      SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE
+         );
+
+   scic_sds_remote_node_context_continue_state_transitions(rnc);
+}
+
+/**
+*
+*
+* @param[in] object
+*/
+static
+void scic_sds_remote_node_context_await_suspension_state_enter(
+   SCI_BASE_OBJECT_T * object
+)
+{
+   SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
+   rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T  *)object;
+
+   SET_STATE_HANDLER(
+      rnc,
+      scic_sds_remote_node_context_state_handler_table,
+      SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE
+         );
+}
+
+// ---------------------------------------------------------------------------
+
+   SCI_BASE_STATE_T
+   scic_sds_remote_node_context_state_table[
+   SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES] =
+{
+   {
+      SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE,
+      scic_sds_remote_node_context_initial_state_enter,
+      NULL
+   },
+   {
+      SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE,
+      scic_sds_remote_node_context_posting_state_enter,
+      NULL
+   },
+   {
+      SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE,
+      scic_sds_remote_node_context_invalidating_state_enter,
+      NULL
+   },
+   {
+      SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE,
+      scic_sds_remote_node_context_resuming_state_enter,
+      NULL
+   },
+   {
+      SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE,
+      scic_sds_remote_node_context_ready_state_enter,
+      NULL
+   },
+   {
+      SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE,
+      scic_sds_remote_node_context_tx_suspended_state_enter,
+      NULL
+   },
+   {
+      SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE,
+      scic_sds_remote_node_context_tx_rx_suspended_state_enter,
+      NULL
+   },
+   {
+      SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE,
+      scic_sds_remote_node_context_await_suspension_state_enter,
+      NULL
+   }
+};
diff --git a/sys/dev/disk/isci/scil/scic_sds_remote_node_context.h b/sys/dev/disk/isci/scil/scic_sds_remote_node_context.h
new file mode 100644
index 0000000..9a290c1
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_sds_remote_node_context.h
@@ -0,0 +1,381 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_sds_remote_node_context.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIC_SDS_REMOTE_NODE_CONTEXT_H_
+#define _SCIC_SDS_REMOTE_NODE_CONTEXT_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains the structures, constants, and prototypes
+ *        associated with the remote node context in the silicon.  It
+ *        exists to model and manage the remote node context in the silicon.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/sci_base_state.h>
+#include <dev/disk/isci/scil/sci_base_state_machine.h>
+#include <dev/disk/isci/scil/sci_base_state_machine_logger.h>
+
+// ---------------------------------------------------------------------------
+
+/**
+ * This constant represents an invalid remote device id, it is used to program
+ * the STPDARNI register so the driver knows when it has received a SIGNATURE
+ * FIS from the SCU.
+ */
+#define SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX    0x0FFF
+
+#define SCU_HARDWARE_SUSPENSION  (0)
+#define SCI_SOFTWARE_SUSPENSION  (1)
+
+struct SCIC_SDS_REQUEST;
+struct SCIC_SDS_REMOTE_DEVICE;
+struct SCIC_SDS_REMOTE_NODE_CONTEXT;
+
+typedef void (*SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK)(void *);
+
+typedef SCI_STATUS (*SCIC_SDS_REMOTE_NODE_CONTEXT_OPERATION)(
+   struct SCIC_SDS_REMOTE_NODE_CONTEXT    * this_rnc,
+   SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK   the_callback,
+   void                                   * callback_parameter
+);
+
+typedef SCI_STATUS (*SCIC_SDS_REMOTE_NODE_CONTEXT_SUSPEND_OPERATION)(
+   struct SCIC_SDS_REMOTE_NODE_CONTEXT    * this_rnc,
+   U32                                      suspension_type,
+   SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK   the_callback,
+   void                                   * callback_parameter
+);
+
+typedef SCI_STATUS (* SCIC_SDS_REMOTE_NODE_CONTEXT_IO_REQUEST)(
+   struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
+   struct SCIC_SDS_REQUEST             * the_request
+);
+
+typedef SCI_STATUS (*SCIC_SDS_REMOTE_NODE_CONTEXT_EVENT_HANDLER)(
+   struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
+   U32                                   event_code
+);
+
+// ---------------------------------------------------------------------------
+
+typedef struct _SCIC_SDS_REMOTE_NODE_CONTEXT_HANDLERS
+{
+   /**
+    * This handle is invoked to stop the RNC.  The callback is invoked when after
+    * the hardware notification that the RNC has been invalidated.
+    */
+   SCIC_SDS_REMOTE_NODE_CONTEXT_OPERATION destruct_handler;
+
+   /**
+    * This handler is invoked when there is a request to suspend  the RNC.  The
+    * callback is invoked after the hardware notification that the remote node is
+    * suspended.
+    */
+   SCIC_SDS_REMOTE_NODE_CONTEXT_SUSPEND_OPERATION suspend_handler;
+
+   /**
+    * This handler is invoked when there is a request to resume the RNC.  The
+    * callback is invoked when after the RNC has reached the ready state.
+    */
+   SCIC_SDS_REMOTE_NODE_CONTEXT_OPERATION resume_handler;
+
+   /**
+    * This handler is invoked when there is a request to start an io request
+    * operation.
+    */
+   SCIC_SDS_REMOTE_NODE_CONTEXT_IO_REQUEST start_io_handler;
+
+   /**
+    * This handler is invoked when there is a request to start a task request
+    * operation.
+    */
+   SCIC_SDS_REMOTE_NODE_CONTEXT_IO_REQUEST start_task_handler;
+
+   /**
+    * This handler is invoked where there is an RNC event that must be processed.
+    */
+   SCIC_SDS_REMOTE_NODE_CONTEXT_EVENT_HANDLER event_handler;
+
+} SCIC_SDS_REMOTE_NODE_CONTEXT_HANDLERS;
+
+// ---------------------------------------------------------------------------
+
+/**
+ * @enum
+ *
+ * This is the enumeration of the remote node context states.
+ */
+typedef enum _SCIS_SDS_REMOTE_NODE_CONTEXT_STATES
+{
+   /**
+    * This state is the initial state for a remote node context.  On a resume
+    * request the remote node context will transition to the posting state.
+    */
+   SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE,
+
+   /**
+    * This is a transition state that posts the RNi to the hardware. Once the RNC
+    * is posted the remote node context will be made ready.
+    */
+   SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE,
+
+   /**
+    * This is a transition state that will post an RNC invalidate to the
+    * hardware.  Once the invalidate is complete the remote node context will
+    * transition to the posting state.
+    */
+   SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE,
+
+   /**
+    * This is a transition state that will post an RNC resume to the hardare.
+    * Once the event notification of resume complete is received the remote node
+    * context will transition to the ready state.
+    */
+   SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE,
+
+   /**
+    * This is the state that the remote node context must be in to accept io
+    * request operations.
+    */
+   SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE,
+
+   /**
+    * This is the state that the remote node context transitions to when it gets
+    * a TX suspend notification from the hardware.
+    */
+   SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE,
+
+   /**
+    * This is the state that the remote node context transitions to when it gets
+    * a TX RX suspend notification from the hardware.
+    */
+   SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE,
+
+   /**
+    * This state is a wait state for the remote node context that waits for a
+    * suspend notification from the hardware.  This state is entered when either
+    * there is a request to supend the remote node context or when there is a TC
+    * completion where the remote node will be suspended by the hardware.
+    */
+   SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE,
+
+   SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES
+
+} SCIS_SDS_REMOTE_NODE_CONTEXT_STATES;
+
+/**
+ * @enum
+ *
+ * This enumeration is used to define the end destination state for the remote
+ * node context.
+ */
+enum SCIC_SDS_REMOTE_NODE_CONTEXT_DESTINATION_STATE
+{
+   SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED,
+   SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY,
+   SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL
+};
+
+/**
+ * @struct SCIC_SDS_REMOTE_NODE_CONTEXT
+ *
+ * @brief  This structure contains the data associated with the remote
+ *         node context object.  The remote node context (RNC) object models
+ *         the the remote device information necessary to manage the
+ *         silicon RNC.
+ */
+typedef struct SCIC_SDS_REMOTE_NODE_CONTEXT
+{
+   /**
+    * This contains the information used to maintain the loggers for the base
+    * state machine.
+    */
+   SCI_BASE_OBJECT_T parent;
+
+   /**
+    * This pointer simply points to the remote device object containing
+    * this RNC.
+    *
+    * @todo Consider making the device pointer the associated object of the
+    *       the parent object.
+    */
+   struct SCIC_SDS_REMOTE_DEVICE * device;
+
+   /**
+    * This field indicates the remote node index (RNI) associated with
+    * this RNC.
+    */
+   U16 remote_node_index;
+
+   /**
+    * This field is the recored suspension code or the reason for the remote node
+    * context suspension.
+    */
+   U32 suspension_code;
+
+   /**
+    * This field is TRUE if the remote node context is resuming from its current
+    * state.  This can cause an automatic resume on receiving a suspension
+    * notification.
+    */
+   enum SCIC_SDS_REMOTE_NODE_CONTEXT_DESTINATION_STATE destination_state;
+
+   /**
+    * This field contains the callback function that the user requested to be
+    * called when the requested state transition is complete.
+    */
+   SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK user_callback;
+
+   /**
+    * This field contains the parameter that is called when the user requested
+    * state transition is completed.
+    */
+   void * user_cookie;
+
+   /**
+    * This field contains the data for the object's state machine.
+    */
+   SCI_BASE_STATE_MACHINE_T state_machine;
+
+   SCIC_SDS_REMOTE_NODE_CONTEXT_HANDLERS * state_handlers;
+
+   #ifdef SCI_LOGGING
+   /**
+    * This field conatins the ready substate machine logger.  The logger will
+    * emit a message each time the ready substate machine changes state.
+    */
+   SCI_BASE_STATE_MACHINE_LOGGER_T state_machine_logger;
+   #endif
+
+} SCIC_SDS_REMOTE_NODE_CONTEXT_T;
+
+// ---------------------------------------------------------------------------
+
+extern SCI_BASE_STATE_T
+   scic_sds_remote_node_context_state_table[
+      SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES];
+
+extern SCIC_SDS_REMOTE_NODE_CONTEXT_HANDLERS
+   scic_sds_remote_node_context_state_handler_table[
+      SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES];
+
+// ---------------------------------------------------------------------------
+
+void scic_sds_remote_node_context_construct(
+   struct SCIC_SDS_REMOTE_DEVICE  * device,
+   SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc,
+   U16                              remote_node_index
+);
+
+void scic_sds_remote_node_context_construct_buffer(
+   SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc
+);
+
+BOOL scic_sds_remote_node_context_is_initialized(
+   SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc
+);
+
+BOOL scic_sds_remote_node_context_is_ready(
+   SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
+);
+
+#define scic_sds_remote_node_context_set_remote_node_index(rnc, rni) \
+   ((rnc)->remote_node_index = (rni))
+
+#define scic_sds_remote_node_context_get_remote_node_index(rcn) \
+   ((rnc)->remote_node_index)
+
+#define scic_sds_remote_node_context_event_handler(rnc, event_code) \
+   ((rnc)->state_handlers->event_handler(rnc, event_code))
+
+#define scic_sds_remote_node_context_resume(rnc, callback, parameter) \
+   ((rnc)->state_handlers->resume_handler(rnc, callback, parameter))
+
+#define scic_sds_remote_node_context_suspend(rnc, suspend_type, callback, parameter) \
+    ((rnc)->state_handlers->suspend_handler(rnc, suspend_type, callback, parameter))
+
+#define scic_sds_remote_node_context_destruct(rnc, callback, parameter) \
+    ((rnc)->state_handlers->destruct_handler(rnc, callback, parameter))
+
+#define scic_sds_remote_node_context_start_io(rnc, request) \
+   ((rnc)->state_handlers->start_io_handler(rnc, request))
+
+#define scic_sds_remote_node_context_start_task(rnc, task) \
+   ((rnc)->state_handlers->start_task_handler(rnc, task))
+
+// ---------------------------------------------------------------------------
+
+#ifdef SCI_LOGGING
+void scic_sds_remote_node_context_initialize_state_logging(
+   SCIC_SDS_REMOTE_NODE_CONTEXT_T *this_rnc
+);
+
+void scic_sds_remote_node_context_deinitialize_state_logging(
+   SCIC_SDS_REMOTE_NODE_CONTEXT_T *this_rnc
+);
+#else // SCI_LOGGING
+#define scic_sds_remote_node_context_initialize_state_logging(x)
+#define scic_sds_remote_node_context_deinitialize_state_logging(x)
+#endif // SCI_LOGGING
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIC_SDS_REMOTE_NODE_CONTEXT_H_
diff --git a/sys/dev/disk/isci/scil/scic_sds_remote_node_table.c b/sys/dev/disk/isci/scil/scic_sds_remote_node_table.c
new file mode 100644
index 0000000..004c6da
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_sds_remote_node_table.c
@@ -0,0 +1,658 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_sds_remote_node_table.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains the implementation of the
+ *        SCIC_SDS_REMOTE_NODE_TABLE public, protected, and private methods.
+ */
+
+#include <dev/disk/isci/scil/scic_sds_remote_node_table.h>
+#include <dev/disk/isci/scil/scic_sds_remote_node_context.h>
+
+/**
+ * This routine will find the bit position in absolute bit terms of the next
+ * available bit for selection.  The absolute bit is index * 32 + bit
+ * position.  If there are available bits in the first U32 then it is just bit
+ * position.
+ *  @param[in] remote_node_table This is the remote node index table from
+ *       which the selection will be made.
+ * @param[in] group_table_index This is the index to the group table from
+ *       which to search for an available selection.
+ *
+ * @return U32 This is the absolute bit position for an available group.
+ */
+static
+U32 scic_sds_remote_node_table_get_group_index(
+   SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
+   U32                        group_table_index
+)
+{
+   U32   dword_index;
+   U32 * group_table;
+   U32   bit_index;
+
+   group_table = remote_node_table->remote_node_groups[group_table_index];
+
+   for (dword_index = 0; dword_index < remote_node_table->group_array_size; dword_index++)
+   {
+      if (group_table[dword_index] != 0)
+      {
+         for (bit_index = 0; bit_index < 32; bit_index++)
+         {
+            if ((group_table[dword_index] & (1 << bit_index)) != 0)
+            {
+               return (dword_index * 32) + bit_index;
+            }
+         }
+      }
+   }
+
+   return SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX;
+}
+
+/**
+ * This method will clear the group index entry in the specified group index
+ * table.
+ *
+ * @param[in out] remote_node_table This the remote node table in which to
+ *       clear the selector.
+ * @param[in] set_index This is the remote node selector in which the change
+ *       will be made.
+ * @param[in] group_index This is the bit index in the table to be modified.
+ *
+ * @return none
+ */
+static
+void scic_sds_remote_node_table_clear_group_index(
+   SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
+   U32                        group_table_index,
+   U32                        group_index
+)
+{
+   U32   dword_index;
+   U32   bit_index;
+   U32 * group_table;
+
+   ASSERT(group_table_index < SCU_STP_REMOTE_NODE_COUNT);
+   ASSERT(group_index < (U32)(remote_node_table->group_array_size * 32));
+
+   dword_index = group_index / 32;
+   bit_index   = group_index % 32;
+   group_table = remote_node_table->remote_node_groups[group_table_index];
+
+   group_table[dword_index] = group_table[dword_index] & ~(1 << bit_index);
+}
+
+/**
+ * This method will set the group index bit entry in the specified gropu index
+ * table.
+ *
+ * @param[in out] remote_node_table This the remote node table in which to set
+ *       the selector.
+ * @param[in] group_table_index This is the remote node selector in which the
+ *       change will be made.
+ * @param[in] group_index This is the bit position in the table to be
+ *       modified.
+ *
+ * @return none
+ */
+static
+void scic_sds_remote_node_table_set_group_index(
+   SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
+   U32                        group_table_index,
+   U32                        group_index
+)
+{
+   U32   dword_index;
+   U32   bit_index;
+   U32 * group_table;
+
+   ASSERT(group_table_index < SCU_STP_REMOTE_NODE_COUNT);
+   ASSERT(group_index < (U32)(remote_node_table->group_array_size * 32));
+
+   dword_index = group_index / 32;
+   bit_index   = group_index % 32;
+   group_table = remote_node_table->remote_node_groups[group_table_index];
+
+   group_table[dword_index] = group_table[dword_index] | (1 << bit_index);
+}
+
+/**
+ * This method will set the remote to available in the remote node allocation
+ * table.
+ *
+ * @param[in out] remote_node_table This is the remote node table in which to
+ *       modify the remote node availability.
+ * @param[in] remote_node_index This is the remote node index that is being
+ *       returned to the table.
+ *
+ * @return none
+ */
+static
+void scic_sds_remote_node_table_set_node_index(
+   SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
+   U32                        remote_node_index
+)
+{
+   U32 dword_location;
+   U32 dword_remainder;
+   U32 slot_normalized;
+   U32 slot_position;
+
+   ASSERT(
+        (remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD)
+      > (remote_node_index / SCU_STP_REMOTE_NODE_COUNT)
+   );
+
+   dword_location  = remote_node_index / SCIC_SDS_REMOTE_NODES_PER_DWORD;
+   dword_remainder = remote_node_index % SCIC_SDS_REMOTE_NODES_PER_DWORD;
+   slot_normalized = (dword_remainder / SCU_STP_REMOTE_NODE_COUNT) * sizeof(U32);
+   slot_position   = remote_node_index % SCU_STP_REMOTE_NODE_COUNT;
+
+   remote_node_table->available_remote_nodes[dword_location] |=
+      1 << (slot_normalized + slot_position);
+}
+
+/**
+ * This method clears the remote node index from the table of available remote
+ * nodes.
+ *
+ * @param[in out] remote_node_table This is the remote node table from which
+ *       to clear the available remote node bit.
+ * @param[in] remote_node_index This is the remote node index which is to be
+ *       cleared from the table.
+ *
+ * @return none
+ */
+static
+void scic_sds_remote_node_table_clear_node_index(
+   SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
+   U32                        remote_node_index
+)
+{
+   U32 dword_location;
+   U32 dword_remainder;
+   U32 slot_position;
+   U32 slot_normalized;
+
+   ASSERT(
+        (remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD)
+      > (remote_node_index / SCU_STP_REMOTE_NODE_COUNT)
+   );
+
+   dword_location  = remote_node_index / SCIC_SDS_REMOTE_NODES_PER_DWORD;
+   dword_remainder = remote_node_index % SCIC_SDS_REMOTE_NODES_PER_DWORD;
+   slot_normalized = (dword_remainder / SCU_STP_REMOTE_NODE_COUNT) * sizeof(U32);
+   slot_position   = remote_node_index % SCU_STP_REMOTE_NODE_COUNT;
+
+   remote_node_table->available_remote_nodes[dword_location] &=
+      ~(1 << (slot_normalized + slot_position));
+}
+
+/**
+ * This method clears the entire table slot at the specified slot index.
+ *
+ * @param[in out] remote_node_table The remote node table from which the slot
+ *       will be cleared.
+ * @param[in] group_index The index for the slot that is to be cleared.
+ *
+ * @return none
+ */
+static
+void scic_sds_remote_node_table_clear_group(
+   SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
+   U32                        group_index
+)
+{
+   U32 dword_location;
+   U32 dword_remainder;
+   U32 dword_value;
+
+   ASSERT(
+        (remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD)
+      > (group_index / SCU_STP_REMOTE_NODE_COUNT)
+   );
+
+   dword_location  = group_index / SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
+   dword_remainder = group_index % SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
+
+   dword_value = remote_node_table->available_remote_nodes[dword_location];
+   dword_value &= ~(SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE << (dword_remainder * 4));
+   remote_node_table->available_remote_nodes[dword_location] = dword_value;
+}
+
+/**
+ * THis method sets an entire remote node group in the remote node table.
+ *
+ * @param[in] remote_node_table
+ * @param[in] group_index
+ */
+static
+void scic_sds_remote_node_table_set_group(
+   SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
+   U32                        group_index
+)
+{
+   U32 dword_location;
+   U32 dword_remainder;
+   U32 dword_value;
+
+   ASSERT(
+        (remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD)
+      > (group_index / SCU_STP_REMOTE_NODE_COUNT)
+   );
+
+   dword_location  = group_index / SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
+   dword_remainder = group_index % SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
+
+   dword_value = remote_node_table->available_remote_nodes[dword_location];
+   dword_value |= (SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE << (dword_remainder * 4));
+   remote_node_table->available_remote_nodes[dword_location] = dword_value;
+}
+
+/**
+ * This method will return the group value for the specified group index.
+ *
+ * @param[in] remote_node_table This is the remote node table that for which
+ *       the group value is to be returned.
+ * @param[in] group_index This is the group index to use to find the group
+ *       value.
+ *
+ * @return The bit values at the specified remote node group index.
+ */
+static
+U8 scic_sds_remote_node_table_get_group_value(
+   SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
+   U32                        group_index
+)
+{
+   U32 dword_location;
+   U32 dword_remainder;
+   U32 dword_value;
+
+   dword_location  = group_index / SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
+   dword_remainder = group_index % SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
+
+   dword_value = remote_node_table->available_remote_nodes[dword_location];
+   dword_value &= (SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE << (dword_remainder * 4));
+   dword_value = dword_value >> (dword_remainder * 4);
+
+   return (U8)dword_value;
+}
+
+/**
+ * This method will initialize the remote node table for use.
+ *
+ * @param[in out] remote_node_table The remote that which is to be
+ *       initialized.
+ * @param[in] remote_node_entries The number of entries to put in the table.
+ *
+ * @return none
+ */
+void scic_sds_remote_node_table_initialize(
+   SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
+   U32                        remote_node_entries
+)
+{
+   U32 index;
+
+   // Initialize the raw data we could improve the speed by only initializing
+   // those entries that we are actually going to be used
+   memset(
+      remote_node_table->available_remote_nodes,
+      0x00,
+      sizeof(remote_node_table->available_remote_nodes)
+   );
+
+   memset(
+      remote_node_table->remote_node_groups,
+      0x00,
+      sizeof(remote_node_table->remote_node_groups)
+   );
+
+   // Initialize the available remote node sets
+   remote_node_table->available_nodes_array_size = (U16)
+        (remote_node_entries / SCIC_SDS_REMOTE_NODES_PER_DWORD)
+      + ((remote_node_entries % SCIC_SDS_REMOTE_NODES_PER_DWORD) != 0);
+
+
+   // Initialize each full DWORD to a FULL SET of remote nodes
+   for (index = 0; index < remote_node_entries; index++)
+   {
+      scic_sds_remote_node_table_set_node_index(remote_node_table, index);
+   }
+
+   remote_node_table->group_array_size = (U16)
+        (remote_node_entries / (SCU_STP_REMOTE_NODE_COUNT * 32))
+      + ((remote_node_entries % (SCU_STP_REMOTE_NODE_COUNT * 32)) != 0);
+
+   for (index = 0; index < (remote_node_entries / SCU_STP_REMOTE_NODE_COUNT); index++)
+   {
+      // These are all guaranteed to be full slot values so fill them in the
+      // available sets of 3 remote nodes
+      scic_sds_remote_node_table_set_group_index(remote_node_table, 2, index);
+   }
+
+   // Now fill in any remainders that we may find
+   if ((remote_node_entries % SCU_STP_REMOTE_NODE_COUNT) == 2)
+   {
+      scic_sds_remote_node_table_set_group_index(remote_node_table, 1, index);
+   }
+   else if ((remote_node_entries % SCU_STP_REMOTE_NODE_COUNT) == 1)
+   {
+      scic_sds_remote_node_table_set_group_index(remote_node_table, 0, index);
+   }
+}
+
+/**
+ * This method will allocate a single RNi from the remote node table.  The
+ * table index will determine from which remote node group table to search.
+ * This search may fail and another group node table can be specified.  The
+ * function is designed to allow a serach of the available single remote node
+ * group up to the triple remote node group.  If an entry is found in the
+ * specified table the remote node is removed and the remote node groups are
+ * updated.
+ *
+ * @param[in out] remote_node_table The remote node table from which to
+ *       allocate a remote node.
+ * @param[in] table_index The group index that is to be used for the search.
+ *
+ * @return The RNi value or an invalid remote node context if an RNi can not
+ *         be found.
+ */
+static
+U16 scic_sds_remote_node_table_allocate_single_remote_node(
+   SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
+   U32                        group_table_index
+)
+{
+   U8  index;
+   U8  group_value;
+   U32 group_index;
+   U16 remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX;
+
+   group_index = scic_sds_remote_node_table_get_group_index(
+                                             remote_node_table, group_table_index);
+
+   // We could not find an available slot in the table selector 0
+   if (group_index != SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX)
+   {
+      group_value = scic_sds_remote_node_table_get_group_value(
+                                    remote_node_table, group_index);
+
+      for (index = 0; index < SCU_STP_REMOTE_NODE_COUNT; index++)
+      {
+         if (((1 << index) & group_value) != 0)
+         {
+            // We have selected a bit now clear it
+            remote_node_index = (U16) (group_index * SCU_STP_REMOTE_NODE_COUNT
+                                       + index);
+
+            scic_sds_remote_node_table_clear_group_index(
+               remote_node_table, group_table_index, group_index
+            );
+
+            scic_sds_remote_node_table_clear_node_index(
+               remote_node_table, remote_node_index
+            );
+
+            if (group_table_index > 0)
+            {
+               scic_sds_remote_node_table_set_group_index(
+                  remote_node_table, group_table_index - 1, group_index
+               );
+            }
+
+            break;
+         }
+      }
+   }
+
+   return remote_node_index;
+}
+
+/**
+ * This method will allocate three consecutive remote node context entries. If
+ * there are no remaining triple entries the function will return a failure.
+ *
+ * @param[in] remote_node_table This is the remote node table from which to
+ *       allocate the remote node entries.
+ * @param[in] group_table_index THis is the group table index which must equal
+ *       two (2) for this operation.
+ *
+ * @return The remote node index that represents three consecutive remote node
+ *         entries or an invalid remote node context if none can be found.
+ */
+static
+U16 scic_sds_remote_node_table_allocate_triple_remote_node(
+   SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
+   U32                        group_table_index
+)
+{
+   U32 group_index;
+   U16 remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX;
+
+   group_index = scic_sds_remote_node_table_get_group_index(
+                                             remote_node_table, group_table_index);
+
+   if (group_index != SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX)
+   {
+      remote_node_index = (U16) group_index * SCU_STP_REMOTE_NODE_COUNT;
+
+      scic_sds_remote_node_table_clear_group_index(
+         remote_node_table, group_table_index, group_index
+      );
+
+      scic_sds_remote_node_table_clear_group(
+         remote_node_table, group_index
+      );
+   }
+
+   return remote_node_index;
+}
+
+/**
+ * This method will allocate a remote node that mataches the remote node count
+ * specified by the caller.  Valid values for remote node count is
+ * SCU_SSP_REMOTE_NODE_COUNT(1) or SCU_STP_REMOTE_NODE_COUNT(3).
+ *
+ * @param[in] remote_node_table This is the remote node table from which the
+ *       remote node allocation is to take place.
+ * @param[in] remote_node_count This is ther remote node count which is one of
+ *       SCU_SSP_REMOTE_NODE_COUNT(1) or SCU_STP_REMOTE_NODE_COUNT(3).
+ *
+ * @return U16 This is the remote node index that is returned or an invalid
+ *         remote node context.
+ */
+U16 scic_sds_remote_node_table_allocate_remote_node(
+   SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
+   U32                        remote_node_count
+)
+{
+   U16 remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX;
+
+   if (remote_node_count == SCU_SSP_REMOTE_NODE_COUNT)
+   {
+      remote_node_index =
+         scic_sds_remote_node_table_allocate_single_remote_node(
+                                                         remote_node_table, 0);
+
+      if (remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX)
+      {
+         remote_node_index =
+            scic_sds_remote_node_table_allocate_single_remote_node(
+                                                         remote_node_table, 1);
+      }
+
+      if (remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX)
+      {
+         remote_node_index =
+            scic_sds_remote_node_table_allocate_single_remote_node(
+                                                         remote_node_table, 2);
+      }
+   }
+   else if (remote_node_count == SCU_STP_REMOTE_NODE_COUNT)
+   {
+      remote_node_index =
+         scic_sds_remote_node_table_allocate_triple_remote_node(
+                                                         remote_node_table, 2);
+   }
+
+   return remote_node_index;
+}
+
+/**
+ * This method will free a single remote node index back to the remote node
+ * table.  This routine will update the remote node groups
+ *
+ * @param[in] remote_node_table
+ * @param[in] remote_node_index
+ */
+static
+void scic_sds_remote_node_table_release_single_remote_node(
+   SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
+   U16                        remote_node_index
+)
+{
+   U32 group_index;
+   U8  group_value;
+
+   group_index = remote_node_index / SCU_STP_REMOTE_NODE_COUNT;
+
+   group_value = scic_sds_remote_node_table_get_group_value(remote_node_table, group_index);
+
+   // Assert that we are not trying to add an entry to a slot that is already
+   // full.
+   ASSERT(group_value != SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE);
+
+   if (group_value == 0x00)
+   {
+      // There are no entries in this slot so it must be added to the single
+      // slot table.
+      scic_sds_remote_node_table_set_group_index(remote_node_table, 0, group_index);
+   }
+   else if ((group_value & (group_value -1)) == 0)
+   {
+      // There is only one entry in this slot so it must be moved from the
+      // single slot table to the dual slot table
+      scic_sds_remote_node_table_clear_group_index(remote_node_table, 0, group_index);
+      scic_sds_remote_node_table_set_group_index(remote_node_table, 1, group_index);
+   }
+   else
+   {
+      // There are two entries in the slot so it must be moved from the dual
+      // slot table to the tripple slot table.
+      scic_sds_remote_node_table_clear_group_index(remote_node_table, 1, group_index);
+      scic_sds_remote_node_table_set_group_index(remote_node_table, 2, group_index);
+   }
+
+   scic_sds_remote_node_table_set_node_index(remote_node_table, remote_node_index);
+}
+
+/**
+ * This method will release a group of three consecutive remote nodes back to
+ * the free remote nodes.
+ *
+ * @param[in] remote_node_table This is the remote node table to which the
+ *       remote node index is to be freed.
+ * @param[in] remote_node_index This is the remote node index which is being
+ *       freed.
+ */
+static
+void scic_sds_remote_node_table_release_triple_remote_node(
+   SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
+   U16                        remote_node_index
+)
+{
+   U32 group_index;
+
+   group_index = remote_node_index / SCU_STP_REMOTE_NODE_COUNT;
+
+   scic_sds_remote_node_table_set_group_index(
+      remote_node_table, 2, group_index
+   );
+
+   scic_sds_remote_node_table_set_group(remote_node_table, group_index);
+}
+
+/**
+ * This method will release the remote node index back into the remote node
+ * table free pool.
+ *
+ * @param[in] remote_node_table The remote node table to which the remote node
+ *       index is to be freed.
+ * @param[in] remote_node_count This is the count of consecutive remote nodes
+ *       that are to be freed.
+ * @param[in] remote_node_index This is the remote node index of the start of
+ *       the number of remote nodes to be freed.
+ */
+void scic_sds_remote_node_table_release_remote_node_index(
+   SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
+   U32                        remote_node_count,
+   U16                        remote_node_index
+)
+{
+   if (remote_node_count == SCU_SSP_REMOTE_NODE_COUNT)
+   {
+      scic_sds_remote_node_table_release_single_remote_node(
+                                       remote_node_table, remote_node_index);
+   }
+   else if (remote_node_count == SCU_STP_REMOTE_NODE_COUNT)
+   {
+      scic_sds_remote_node_table_release_triple_remote_node(
+                                       remote_node_table, remote_node_index);
+   }
+}
diff --git a/sys/dev/disk/isci/scil/scic_sds_remote_node_table.h b/sys/dev/disk/isci/scil/scic_sds_remote_node_table.h
new file mode 100644
index 0000000..da18e71
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_sds_remote_node_table.h
@@ -0,0 +1,190 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_sds_remote_node_table.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIC_SDS_REMOTE_NODE_TABLE_H_
+#define _SCIC_SDS_REMOTE_NODE_TABLE_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains the structures, constants and prototypes used for
+ *        the remote node table.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/sci_controller_constants.h>
+
+/**
+ * Remote node sets are sets of remote node index in the remtoe node table
+ * The SCU hardware requires that STP remote node entries take three
+ * consecutive remote node index so the table is arranged in sets of three.
+ * The bits are used as 0111 0111 to make a byte and the bits define the set
+ * of three remote nodes to use as a sequence.
+ */
+#define SCIC_SDS_REMOTE_NODE_SETS_PER_BYTE 2
+
+/**
+ * Since the remote node table is organized as DWORDS take the remote node
+ * sets in bytes and represent them in DWORDs. The lowest ordered bits are the
+ * ones used in case full DWORD is not being used.
+ *
+ * i.e. 0000 0000 0000 0000 0111 0111 0111 0111 // if only a single WORD is in
+ * use in the DWORD.
+ */
+#define SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD \
+   (sizeof(U32) * SCIC_SDS_REMOTE_NODE_SETS_PER_BYTE)
+/**
+ * This is a count of the numeber of remote nodes that can be represented in
+ * a byte
+ */
+#define SCIC_SDS_REMOTE_NODES_PER_BYTE  \
+   (SCU_STP_REMOTE_NODE_COUNT * SCIC_SDS_REMOTE_NODE_SETS_PER_BYTE)
+
+/**
+ * This is a count of the number of remote nodes that can be represented in a
+ * DWROD
+ */
+#define SCIC_SDS_REMOTE_NODES_PER_DWORD \
+   (sizeof(U32) * SCIC_SDS_REMOTE_NODES_PER_BYTE)
+
+/**
+ * This is the number of bits in a remote node group
+ */
+#define SCIC_SDS_REMOTE_NODES_BITS_PER_GROUP   4
+
+#define SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX      (0xFFFFFFFF)
+#define SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE    (0x07)
+#define SCIC_SDS_REMOTE_NODE_TABLE_EMPTY_SLOT_VALUE   (0x00)
+
+/**
+ * Expander attached sata remote node count
+ */
+#define SCU_STP_REMOTE_NODE_COUNT        3
+
+/**
+ * Expander or direct attached ssp remote node count
+ */
+#define SCU_SSP_REMOTE_NODE_COUNT        1
+
+/**
+ * Direct attached STP remote node count
+ */
+#define SCU_SATA_REMOTE_NODE_COUNT       1
+
+/**
+ * @struct SCIC_REMOTE_NODE_TABLE
+ */
+typedef struct SCIC_REMOTE_NODE_TABLE
+{
+   /**
+    * This field contains the array size in dwords
+    */
+   U16 available_nodes_array_size;
+
+   /**
+    * This field contains the array size of the
+    */
+   U16 group_array_size;
+
+   /**
+    * This field is the array of available remote node entries in bits.
+    * Because of the way STP remote node data is allocated on the SCU hardware
+    * the remote nodes must occupy three consecutive remote node context
+    * entries.  For ease of allocation and de-allocation we have broken the
+    * sets of three into a single nibble.  When the STP RNi is allocated all
+    * of the bits in the nibble are cleared.  This math results in a table size
+    * of MAX_REMOTE_NODES / CONSECUTIVE RNi ENTRIES for STP / 2 entries per byte.
+    */
+   U32 available_remote_nodes[
+        (SCI_MAX_REMOTE_DEVICES / SCIC_SDS_REMOTE_NODES_PER_DWORD)
+      + ((SCI_MAX_REMOTE_DEVICES % SCIC_SDS_REMOTE_NODES_PER_DWORD) != 0)];
+
+   /**
+    * This field is the nibble selector for the above table.  There are three
+    * possible selectors each for fast lookup when trying to find one, two or
+    * three remote node entries.
+    */
+   U32 remote_node_groups[
+      SCU_STP_REMOTE_NODE_COUNT][
+           (SCI_MAX_REMOTE_DEVICES / (32 * SCU_STP_REMOTE_NODE_COUNT))
+         + ((SCI_MAX_REMOTE_DEVICES % (32 * SCU_STP_REMOTE_NODE_COUNT)) != 0)];
+
+} SCIC_REMOTE_NODE_TABLE_T;
+
+// ---------------------------------------------------------------------------
+
+void scic_sds_remote_node_table_initialize(
+   SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
+   U32                        remote_node_entries
+);
+
+U16 scic_sds_remote_node_table_allocate_remote_node(
+   SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
+   U32                        remote_node_count
+);
+
+void scic_sds_remote_node_table_release_remote_node_index(
+   SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
+   U32                        remote_node_count,
+   U16                        remote_node_index
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIC_SDS_REMOTE_NODE_TABLE_H_
diff --git a/sys/dev/disk/isci/scil/scic_sds_request.c b/sys/dev/disk/isci/scil/scic_sds_request.c
new file mode 100644
index 0000000..b34ec6e
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_sds_request.c
@@ -0,0 +1,2888 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_sds_request.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains the implementation for the operations on an
+ *        SCIC_SDS_IO_REQUEST object.
+ */
+
+#include <dev/disk/isci/scil/intel_sat.h>
+#include <dev/disk/isci/scil/intel_sata.h>
+#include <dev/disk/isci/scil/intel_sas.h>
+#include <dev/disk/isci/scil/sci_util.h>
+#include <dev/disk/isci/scil/sci_base_request.h>
+#include <dev/disk/isci/scil/scic_controller.h>
+#include <dev/disk/isci/scil/scic_io_request.h>
+#include <dev/disk/isci/scil/scic_remote_device.h>
+#include <dev/disk/isci/scil/scic_user_callback.h>
+#include <dev/disk/isci/scil/scic_sds_logger.h>
+#include <dev/disk/isci/scil/scic_sds_request.h>
+#include <dev/disk/isci/scil/scic_sds_pci.h>
+#include <dev/disk/isci/scil/scic_sds_stp_request.h>
+#include <dev/disk/isci/scil/scic_sds_controller.h>
+#include <dev/disk/isci/scil/scic_sds_controller_registers.h>
+#include <dev/disk/isci/scil/scic_sds_remote_device.h>
+#include <dev/disk/isci/scil/scic_sds_port.h>
+#include <dev/disk/isci/scil/scic_task_request.h>
+#include <dev/disk/isci/scil/scu_constants.h>
+#include <dev/disk/isci/scil/scu_task_context.h>
+#include <dev/disk/isci/scil/scic_sds_smp_request.h>
+#include <dev/disk/isci/sci_environment.h>
+#include <dev/disk/isci/scil/scic_sds_unsolicited_frame_control.h>
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/scu_completion_codes.h>
+#include <dev/disk/isci/scil/intel_scsi.h>
+
+#if !defined(DISABLE_ATAPI)
+#include <dev/disk/isci/scil/scic_sds_stp_packet_request.h>
+#endif
+
+/**
+* @struct SCI_SINGLE_LEVEL_LUN
+*
+* @brief this struct decribes the single level LUN structure
+*        as per the SAM 4.
+*/
+typedef struct SCI_SINGLE_LEVEL_LUN
+{
+    U8  bus_id              : 6;
+    U8  address_method      : 2;
+    U8  lun_number;
+    U8  second_level_lun[2];
+    U8  third_level_lun[2];
+    U8  forth_level_lun[2];
+
+} SCI_SINGLE_LEVEL_LUN_T;
+
+
+//****************************************************************************
+//* SCIC SDS IO REQUEST CONSTANTS
+//****************************************************************************
+
+/**
+ * We have no timer requirements for IO requests right now
+ */
+#define SCIC_SDS_IO_REQUEST_MINIMUM_TIMER_COUNT (0)
+#define SCIC_SDS_IO_REQUEST_MAXIMUM_TIMER_COUNT (0)
+
+//****************************************************************************
+//* SCIC SDS IO REQUEST MACROS
+//****************************************************************************
+
+/**
+ * This is a helper macro to return the os handle for this request object.
+ */
+#define scic_sds_request_get_user_request(request) \
+   ((request)->user_request)
+
+
+/**
+ * This macro returns the sizeof memory required to store the an SSP IO
+ * request.  This does not include the size of the SGL or SCU Task Context
+ * memory.The sizeof(U32) are needed for DWORD alignment of the command IU
+ * and response IU
+ */
+#define scic_ssp_io_request_get_object_size() \
+   ( \
+       sizeof(SCI_SSP_COMMAND_IU_T) \
+     + sizeof (U32) \
+     + sizeof(SCI_SSP_RESPONSE_IU_T) \
+     + sizeof (U32) \
+   )
+
+/**
+ * This macro returns the address of the ssp command buffer in the io
+ * request memory
+ */
+#define scic_sds_ssp_request_get_command_buffer_unaligned(memory) \
+   ((SCI_SSP_COMMAND_IU_T *)( \
+      ((char *)(memory)) + sizeof(SCIC_SDS_REQUEST_T) \
+   ))
+
+/**
+ * This macro aligns the ssp command buffer in DWORD alignment
+*/
+#define scic_sds_ssp_request_align_command_buffer(address) \
+   ((SCI_SSP_COMMAND_IU_T *)( \
+      (((POINTER_UINT)(address)) + (sizeof(U32) - 1)) \
+         & ~(sizeof(U32)- 1) \
+   ))
+
+/**
+ * This macro returns the DWORD-aligned ssp command buffer
+*/
+#define scic_sds_ssp_request_get_command_buffer(memory) \
+   ((SCI_SSP_COMMAND_IU_T *)  \
+      ((char *)scic_sds_ssp_request_align_command_buffer( \
+         (char *) scic_sds_ssp_request_get_command_buffer_unaligned(memory) \
+   )))
+
+/**
+ * This macro returns the address of the ssp response buffer in the io
+ * request memory
+ */
+#define scic_sds_ssp_request_get_response_buffer_unaligned(memory) \
+   ((SCI_SSP_RESPONSE_IU_T *)( \
+         ((char *)(scic_sds_ssp_request_get_command_buffer(memory))) \
+       + sizeof(SCI_SSP_COMMAND_IU_T) \
+   ))
+
+/**
+ * This macro aligns the ssp response buffer in DWORD-aligned fashion
+ */
+#define scic_sds_ssp_request_align_response_buffer(memory) \
+   ((SCI_SSP_RESPONSE_IU_T *)( \
+      (((POINTER_UINT)(memory)) + (sizeof(U32) - 1)) \
+         & ~(sizeof(U32)- 1) \
+   ))
+
+/**
+ * This macro returns the DWORD-aligned ssp response buffer
+*/
+#define scic_sds_ssp_request_get_response_buffer(memory) \
+   ((SCI_SSP_RESPONSE_IU_T *) \
+      ((char *)scic_sds_ssp_request_align_response_buffer ( \
+         (char *)scic_sds_ssp_request_get_response_buffer_unaligned(memory) \
+   )))
+
+/**
+ * This macro returns the address of the task context buffer in the io
+ * request memory
+ */
+#define scic_sds_ssp_request_get_task_context_buffer_unaligned(memory) \
+   ((SCU_TASK_CONTEXT_T *)( \
+        ((char *)(scic_sds_ssp_request_get_response_buffer(memory))) \
+      + sizeof(SCI_SSP_RESPONSE_IU_T) \
+   ))
+
+/**
+ * This macro returns the aligned task context buffer
+ */
+#define scic_sds_ssp_request_get_task_context_buffer(memory) \
+   ((SCU_TASK_CONTEXT_T *)( \
+      ((char *)scic_sds_request_align_task_context_buffer( \
+         (char *)scic_sds_ssp_request_get_task_context_buffer_unaligned(memory)) \
+    )))
+
+/**
+ * This macro returns the address of the sgl elment pairs in the io request
+ * memory buffer
+ */
+#define scic_sds_ssp_request_get_sgl_element_buffer(memory) \
+   ((SCU_SGL_ELEMENT_PAIR_T *)( \
+        ((char *)(scic_sds_ssp_request_get_task_context_buffer(memory))) \
+      + sizeof(SCU_TASK_CONTEXT_T) \
+    ))
+
+#if !defined(DISABLE_TASK_MANAGEMENT)
+
+/**
+ * This macro returns the sizeof of memory required to store an SSP Task
+ * request.  This does not include the size of the SCU Task Context memory.
+ */
+#define scic_ssp_task_request_get_object_size() \
+   ( \
+       sizeof(SCI_SSP_TASK_IU_T) \
+     + sizeof(SCI_SSP_RESPONSE_IU_T) \
+   )
+
+/**
+ * This macro returns the address of the ssp command buffer in the task
+ * request memory.  Yes its the same as the above macro except for the
+ * name.
+ */
+#define scic_sds_ssp_task_request_get_command_buffer(memory) \
+   ((SCI_SSP_TASK_IU_T *)( \
+        ((char *)(memory)) + sizeof(SCIC_SDS_REQUEST_T) \
+   ))
+
+/**
+ * This macro returns the address of the ssp response buffer in the task
+ * request memory.
+ */
+#define scic_sds_ssp_task_request_get_response_buffer(memory) \
+   ((SCI_SSP_RESPONSE_IU_T *)( \
+        ((char *)(scic_sds_ssp_task_request_get_command_buffer(memory))) \
+      + sizeof(SCI_SSP_TASK_IU_T) \
+   ))
+
+/**
+ * This macro returs the task context buffer for the SSP task request.
+ */
+#define scic_sds_ssp_task_request_get_task_context_buffer(memory) \
+   ((SCU_TASK_CONTEXT_T *)( \
+        ((char *)(scic_sds_ssp_task_request_get_response_buffer(memory))) \
+      + sizeof(SCI_SSP_RESPONSE_IU_T) \
+   ))
+
+#endif // !defined(DISABLE_TASK_MANAGEMENT)
+
+
+//****************************************************************************
+//* SCIC SDS IO REQUEST PRIVATE METHODS
+//****************************************************************************
+
+#ifdef SCI_LOGGING
+/**
+ * This method will initialize state transition logging for the task request
+ * object.
+ *
+ * @param[in] this_request This is the request for which to track state
+ *       transitions.
+ */
+void scic_sds_request_initialize_state_logging(
+   SCIC_SDS_REQUEST_T *this_request
+)
+{
+   sci_base_state_machine_logger_initialize(
+      &this_request->parent.state_machine_logger,
+      &this_request->parent.state_machine,
+      &this_request->parent.parent,
+      scic_cb_logger_log_states,
+      this_request->is_task_management_request ?
+      "SCIC_SDS_IO_REQUEST_T(Task)" : "SCIC_SDS_IO_REQUEST_T(IO)",
+      "base state machine",
+      SCIC_LOG_OBJECT_SMP_IO_REQUEST |
+      SCIC_LOG_OBJECT_STP_IO_REQUEST |
+      SCIC_LOG_OBJECT_SSP_IO_REQUEST
+   );
+
+   if (this_request->has_started_substate_machine)
+   {
+      sci_base_state_machine_logger_initialize(
+         &this_request->started_substate_machine_logger,
+         &this_request->started_substate_machine,
+         &this_request->parent.parent,
+         scic_cb_logger_log_states,
+         "SCIC_SDS_IO_REQUEST_T(Task)", "starting substate machine",
+         SCIC_LOG_OBJECT_SMP_IO_REQUEST |
+         SCIC_LOG_OBJECT_STP_IO_REQUEST |
+         SCIC_LOG_OBJECT_SSP_IO_REQUEST
+     );
+   }
+}
+
+/**
+ * This method will stop the state transition logging for the task request
+ * object.
+ *
+ * @param[in] this_request The task request object on which to stop state
+ *       transition logging.
+ */
+void scic_sds_request_deinitialize_state_logging(
+   SCIC_SDS_REQUEST_T *this_request
+)
+{
+   sci_base_state_machine_logger_deinitialize(
+      &this_request->parent.state_machine_logger,
+      &this_request->parent.state_machine
+   );
+
+   if (this_request->has_started_substate_machine)
+   {
+      sci_base_state_machine_logger_deinitialize(
+         &this_request->started_substate_machine_logger,
+         &this_request->started_substate_machine
+      );
+   }
+}
+#endif // SCI_LOGGING
+
+/**
+ * This method returns the size required to store an SSP IO request object.
+ *
+ * @return U32
+ */
+static
+U32 scic_sds_ssp_request_get_object_size(void)
+{
+   return   sizeof(SCIC_SDS_REQUEST_T)
+          + scic_ssp_io_request_get_object_size()
+          + sizeof(SCU_TASK_CONTEXT_T)
+          + CACHE_LINE_SIZE
+          + sizeof(SCU_SGL_ELEMENT_PAIR_T) * SCU_MAX_SGL_ELEMENT_PAIRS;
+}
+
+/**
+ * @brief This method returns the sgl element pair for the specificed
+ *        sgl_pair index.
+ *
+ * @param[in] this_request This parameter specifies the IO request for which
+ *            to retrieve the Scatter-Gather List element pair.
+ * @param[in] sgl_pair_index This parameter specifies the index into the SGL
+ *            element pair to be retrieved.
+ *
+ * @return This method returns a pointer to an SCU_SGL_ELEMENT_PAIR.
+ */
+SCU_SGL_ELEMENT_PAIR_T *scic_sds_request_get_sgl_element_pair(
+   SCIC_SDS_REQUEST_T *this_request,
+   U32                 sgl_pair_index
+)
+{
+   SCU_TASK_CONTEXT_T *task_context;
+
+   task_context = (SCU_TASK_CONTEXT_T *)this_request->task_context_buffer;
+
+   if (sgl_pair_index == 0)
+   {
+      return &task_context->sgl_pair_ab;
+   }
+   else if (sgl_pair_index == 1)
+   {
+      return &task_context->sgl_pair_cd;
+   }
+
+   return &this_request->sgl_element_pair_buffer[sgl_pair_index - 2];
+}
+
+/**
+ * @brief This function will build the SGL list for an IO request.
+ *
+ * @param[in] this_request This parameter specifies the IO request for which
+ *            to build the Scatter-Gather List.
+ *
+ * @return none
+ */
+void scic_sds_request_build_sgl(
+   SCIC_SDS_REQUEST_T *this_request
+)
+{
+   void                   *os_sge;
+   void                   *os_handle;
+   SCI_PHYSICAL_ADDRESS    physical_address;
+   U32                     sgl_pair_index = 0;
+   SCU_SGL_ELEMENT_PAIR_T *scu_sgl_list   = NULL;
+   SCU_SGL_ELEMENT_PAIR_T *previous_pair  = NULL;
+
+   os_handle = scic_sds_request_get_user_request(this_request);
+   scic_cb_io_request_get_next_sge(os_handle, NULL, &os_sge);
+
+   while (os_sge != NULL)
+   {
+      scu_sgl_list =
+         scic_sds_request_get_sgl_element_pair(this_request, sgl_pair_index);
+
+      SCU_SGL_COPY(os_handle, scu_sgl_list->A, os_sge);
+
+      scic_cb_io_request_get_next_sge(os_handle, os_sge, &os_sge);
+
+      if (os_sge != NULL)
+      {
+         SCU_SGL_COPY(os_handle, scu_sgl_list->B, os_sge);
+
+         scic_cb_io_request_get_next_sge(os_handle, os_sge, &os_sge);
+      }
+      else
+      {
+         SCU_SGL_ZERO(scu_sgl_list->B);
+      }
+
+      if (previous_pair != NULL)
+      {
+         scic_cb_io_request_get_physical_address(
+            scic_sds_request_get_controller(this_request),
+            this_request,
+            scu_sgl_list,
+            &physical_address
+         );
+
+         previous_pair->next_pair_upper =
+            sci_cb_physical_address_upper(physical_address);
+         previous_pair->next_pair_lower =
+            sci_cb_physical_address_lower(physical_address);
+      }
+
+      previous_pair = scu_sgl_list;
+      sgl_pair_index++;
+   }
+
+   if (scu_sgl_list != NULL)
+   {
+      scu_sgl_list->next_pair_upper = 0;
+      scu_sgl_list->next_pair_lower = 0;
+   }
+}
+
+/**
+ * @brief This method initializes common portions of the io request object.
+ *        This includes construction of the SCI_BASE_REQUEST_T parent.
+ *
+ * @param[in] the_controller This parameter specifies the controller for which
+ *            the request is being constructed.
+ * @param[in] the_target This parameter specifies the remote device for which
+ *            the request is being constructed.
+ * @param[in] io_tag This parameter specifies the IO tag to be utilized for
+ *            this request.  This parameter can be set to
+ *            SCI_CONTROLLER_INVALID_IO_TAG.
+ * @param[in] user_io_request_object This parameter specifies the user
+ *            request object for which the request is being constructed.
+ * @param[in] this_request This parameter specifies the request being
+ *            constructed.
+ *
+ * @return none
+ */
+static
+void scic_sds_general_request_construct(
+   SCIC_SDS_CONTROLLER_T    * the_controller,
+   SCIC_SDS_REMOTE_DEVICE_T * the_target,
+   U16                        io_tag,
+   void                     * user_io_request_object,
+   SCIC_SDS_REQUEST_T       * this_request
+)
+{
+   sci_base_request_construct(
+      &this_request->parent,
+      sci_base_object_get_logger(the_controller),
+      scic_sds_request_state_table
+   );
+
+   this_request->io_tag = io_tag;
+   this_request->user_request = user_io_request_object;
+   this_request->owning_controller = the_controller;
+   this_request->target_device = the_target;
+   this_request->has_started_substate_machine = FALSE;
+   this_request->protocol = SCIC_NO_PROTOCOL;
+   this_request->sat_protocol = 0xFF;
+   this_request->saved_rx_frame_index = SCU_INVALID_FRAME_INDEX;
+   this_request->device_sequence = scic_sds_remote_device_get_sequence(the_target);
+
+   this_request->sci_status   = SCI_SUCCESS;
+   this_request->scu_status   = 0;
+   this_request->post_context = 0xFFFFFFFF;
+
+   this_request->is_task_management_request = FALSE;
+
+   if (io_tag == SCI_CONTROLLER_INVALID_IO_TAG)
+   {
+      this_request->was_tag_assigned_by_user = FALSE;
+      this_request->task_context_buffer = NULL;
+   }
+   else
+   {
+      this_request->was_tag_assigned_by_user = TRUE;
+
+      this_request->task_context_buffer =
+         scic_sds_controller_get_task_context_buffer(
+            this_request->owning_controller, io_tag);
+   }
+}
+
+/**
+ * @brief This method build the remainder of the IO request object.
+ *
+ * @pre The scic_sds_general_request_construct() must be called before this
+ *      call is valid.
+ *
+ * @param[in] this_request This parameter specifies the request object being
+ *            constructed.
+ *
+ * @return none
+ */
+void scic_sds_ssp_io_request_assign_buffers(
+   SCIC_SDS_REQUEST_T *this_request
+)
+{
+   this_request->command_buffer =
+      scic_sds_ssp_request_get_command_buffer(this_request);
+   this_request->response_buffer =
+      scic_sds_ssp_request_get_response_buffer(this_request);
+   this_request->sgl_element_pair_buffer =
+      scic_sds_ssp_request_get_sgl_element_buffer(this_request);
+   this_request->sgl_element_pair_buffer =
+      scic_sds_request_align_sgl_element_buffer(this_request->sgl_element_pair_buffer);
+
+   if (this_request->was_tag_assigned_by_user == FALSE)
+   {
+      this_request->task_context_buffer =
+         scic_sds_ssp_request_get_task_context_buffer(this_request);
+   }
+}
+
+/**
+ * @brief This method constructs the SSP Command IU data for this io
+ *        request object.
+ *
+ * @param[in] this_request This parameter specifies the request object for
+ *            which the SSP command information unit is being built.
+ *
+ * @return none
+ */
+static
+void scic_sds_io_request_build_ssp_command_iu(
+   SCIC_SDS_REQUEST_T   *this_request
+)
+{
+   SCI_SINGLE_LEVEL_LUN_T lun;
+   SCI_SSP_COMMAND_IU_T *command_frame;
+   void                 *os_handle;
+   U32  cdb_length;
+   U32 *cdb_buffer;
+
+   command_frame =
+      (SCI_SSP_COMMAND_IU_T *)this_request->command_buffer;
+
+   os_handle = scic_sds_request_get_user_request(this_request);
+
+   ((U32 *)&lun)[0] = 0;
+   ((U32 *)&lun)[1] = 0;
+   lun.lun_number = scic_cb_ssp_io_request_get_lun(os_handle) &0xff;
+   /// @todo Is it ok to leave junk at the end of the cdb buffer?
+   scic_word_copy_with_swap(
+       (U32 *)command_frame->lun,
+       (U32 *)&lun,
+       sizeof(lun));
+
+   ((U32 *)command_frame)[2] = 0;
+
+   cdb_length = scic_cb_ssp_io_request_get_cdb_length(os_handle);
+   cdb_buffer = (U32 *)scic_cb_ssp_io_request_get_cdb_address(os_handle);
+
+   if (cdb_length > 16)
+   {
+      command_frame->additional_cdb_length = cdb_length - 16;
+   }
+
+   /// @todo Is it ok to leave junk at the end of the cdb buffer?
+   scic_word_copy_with_swap(
+      (U32 *)(&command_frame->cdb),
+      (U32 *)(cdb_buffer),
+      (cdb_length + 3) / sizeof(U32)
+   );
+
+   command_frame->enable_first_burst = 0;
+   command_frame->task_priority =
+      scic_cb_ssp_io_request_get_command_priority(os_handle);
+   command_frame->task_attribute =
+      scic_cb_ssp_io_request_get_task_attribute(os_handle);
+}
+
+#if !defined(DISABLE_TASK_MANAGEMENT)
+
+/**
+ * @brief This method constructs the SSP Task IU data for this io request
+ *        object.
+ *
+ * @param[in] this_request
+ *
+ * @return none
+ */
+static
+void scic_sds_task_request_build_ssp_task_iu(
+   SCIC_SDS_REQUEST_T *this_request
+)
+{
+   SCI_SSP_TASK_IU_T *command_frame;
+   void              *os_handle;
+
+   command_frame =
+      (SCI_SSP_TASK_IU_T *)this_request->command_buffer;
+
+   os_handle = scic_sds_request_get_user_request(this_request);
+
+   command_frame->lun_upper = 0;
+   command_frame->lun_lower = scic_cb_ssp_task_request_get_lun(os_handle);
+
+   ((U32 *)command_frame)[2] = 0;
+
+   command_frame->task_function =
+      scic_cb_ssp_task_request_get_function(os_handle);
+   command_frame->task_tag =
+      scic_cb_ssp_task_request_get_io_tag_to_manage(os_handle);
+}
+
+#endif // !defined(DISABLE_TASK_MANAGEMENT)
+
+/**
+ * @brief This method is will fill in the SCU Task Context for any type of
+ *        SSP request.
+ *
+ * @param[in] this_request
+ * @param[in] task_context
+ *
+ * @return none
+ */
+static
+void scu_ssp_reqeust_construct_task_context(
+   SCIC_SDS_REQUEST_T * this_request,
+   SCU_TASK_CONTEXT_T * task_context
+)
+{
+   SCI_PHYSICAL_ADDRESS      physical_address;
+   SCIC_SDS_CONTROLLER_T    *owning_controller;
+   SCIC_SDS_REMOTE_DEVICE_T *target_device;
+   SCIC_SDS_PORT_T          *target_port;
+
+   owning_controller = scic_sds_request_get_controller(this_request);
+   target_device = scic_sds_request_get_device(this_request);
+   target_port = scic_sds_request_get_port(this_request);
+
+   // Fill in the TC with the its required data
+   task_context->abort = 0;
+   task_context->priority = 0;
+   task_context->initiator_request = 1;
+   task_context->connection_rate =
+      scic_remote_device_get_connection_rate(target_device);
+   task_context->protocol_engine_index =
+      scic_sds_controller_get_protocol_engine_group(owning_controller);
+   task_context->logical_port_index =
+      scic_sds_port_get_index(target_port);
+   task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SSP;
+   task_context->valid = SCU_TASK_CONTEXT_VALID;
+   task_context->context_type = SCU_TASK_CONTEXT_TYPE;
+
+   task_context->remote_node_index =
+      scic_sds_remote_device_get_index(this_request->target_device);
+   task_context->command_code = 0;
+
+   task_context->link_layer_control = 0;
+   task_context->do_not_dma_ssp_good_response = 1;
+   task_context->strict_ordering = 0;
+   task_context->control_frame = 0;
+   task_context->timeout_enable = 0;
+   task_context->block_guard_enable = 0;
+
+   task_context->address_modifier = 0;
+
+   //task_context->type.ssp.tag = this_request->io_tag;
+   task_context->task_phase = 0x01;
+
+   if (this_request->was_tag_assigned_by_user)
+   {
+      // Build the task context now since we have already read the data
+      this_request->post_context = (
+           SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC
+         | (
+                scic_sds_controller_get_protocol_engine_group(owning_controller)
+             << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT
+           )
+         | (
+                 scic_sds_port_get_index(target_port)
+              << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT
+           )
+         | scic_sds_io_tag_get_index(this_request->io_tag)
+      );
+   }
+   else
+   {
+      // Build the task context now since we have already read the data
+      this_request->post_context = (
+           SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC
+         | (
+               scic_sds_controller_get_protocol_engine_group(owning_controller)
+            << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT
+           )
+         | (
+                scic_sds_port_get_index(target_port)
+             << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT
+           )
+         // This is not assigned because we have to wait until we get a TCi
+      );
+   }
+
+   // Copy the physical address for the command buffer to the SCU Task Context
+   scic_cb_io_request_get_physical_address(
+      scic_sds_request_get_controller(this_request),
+      this_request,
+      this_request->command_buffer,
+      &physical_address
+   );
+
+   task_context->command_iu_upper =
+      sci_cb_physical_address_upper(physical_address);
+   task_context->command_iu_lower =
+      sci_cb_physical_address_lower(physical_address);
+
+   // Copy the physical address for the response buffer to the SCU Task Context
+   scic_cb_io_request_get_physical_address(
+      scic_sds_request_get_controller(this_request),
+      this_request,
+      this_request->response_buffer,
+      &physical_address
+   );
+
+   task_context->response_iu_upper =
+      sci_cb_physical_address_upper(physical_address);
+   task_context->response_iu_lower =
+      sci_cb_physical_address_lower(physical_address);
+}
+
+/**
+ * @brief This method is will fill in the SCU Task Context for a SSP IO
+ *        request.
+ *
+ * @param[in] this_request
+ *
+ * @return none
+ */
+static
+void scu_ssp_io_request_construct_task_context(
+   SCIC_SDS_REQUEST_T *this_request,
+   SCI_IO_REQUEST_DATA_DIRECTION data_direction,
+   U32 transfer_length_bytes
+)
+{
+   SCU_TASK_CONTEXT_T *task_context;
+
+   task_context = scic_sds_request_get_task_context(this_request);
+
+   scu_ssp_reqeust_construct_task_context(this_request, task_context);
+
+   task_context->ssp_command_iu_length = sizeof(SCI_SSP_COMMAND_IU_T) / sizeof(U32);
+   task_context->type.ssp.frame_type = SCI_SAS_COMMAND_FRAME;
+
+   switch (data_direction)
+   {
+   case SCI_IO_REQUEST_DATA_IN:
+   case SCI_IO_REQUEST_NO_DATA:
+      task_context->task_type = SCU_TASK_TYPE_IOREAD;
+      break;
+   case SCI_IO_REQUEST_DATA_OUT:
+      task_context->task_type = SCU_TASK_TYPE_IOWRITE;
+      break;
+   }
+
+   task_context->transfer_length_bytes = transfer_length_bytes;
+
+   if (task_context->transfer_length_bytes > 0)
+   {
+      scic_sds_request_build_sgl(this_request);
+   }
+}
+
+#if !defined(DISABLE_TASK_MANAGEMENT)
+
+/**
+ * @brief This method will fill in the remainder of the io request object
+ *        for SSP Task requests.
+ *
+ * @param[in] this_request
+ *
+ * @return none
+ */
+void scic_sds_ssp_task_request_assign_buffers(
+   SCIC_SDS_REQUEST_T *this_request
+)
+{
+   // Assign all of the buffer pointers
+   this_request->command_buffer =
+      scic_sds_ssp_task_request_get_command_buffer(this_request);
+   this_request->response_buffer =
+      scic_sds_ssp_task_request_get_response_buffer(this_request);
+   this_request->sgl_element_pair_buffer = NULL;
+
+   if (this_request->was_tag_assigned_by_user == FALSE)
+   {
+      this_request->task_context_buffer =
+         scic_sds_ssp_task_request_get_task_context_buffer(this_request);
+      this_request->task_context_buffer =
+         scic_sds_request_align_task_context_buffer(this_request->task_context_buffer);
+   }
+}
+
+/**
+ * @brief This method will fill in the SCU Task Context for a SSP Task
+ *        request.  The following important settings are utilized:
+ *          -# priority == SCU_TASK_PRIORITY_HIGH.  This ensures that the
+ *             task request is issued ahead of other task destined for the
+ *             same Remote Node.
+ *          -# task_type == SCU_TASK_TYPE_IOREAD.  This simply indicates
+ *             that a normal request type (i.e. non-raw frame) is being
+ *             utilized to perform task management.
+ *          -# control_frame == 1.  This ensures that the proper endianess
+ *             is set so that the bytes are transmitted in the right order
+ *             for a task frame.
+ *
+ * @param[in] this_request This parameter specifies the task request object
+ *            being constructed.
+ *
+ * @return none
+ */
+static
+void scu_ssp_task_request_construct_task_context(
+   SCIC_SDS_REQUEST_T *this_request
+)
+{
+   SCU_TASK_CONTEXT_T *task_context;
+
+   task_context = scic_sds_request_get_task_context(this_request);
+
+   scu_ssp_reqeust_construct_task_context(this_request, task_context);
+
+   task_context->control_frame                = 1;
+   task_context->priority                     = SCU_TASK_PRIORITY_HIGH;
+   task_context->task_type                    = SCU_TASK_TYPE_RAW_FRAME;
+   task_context->transfer_length_bytes        = 0;
+   task_context->type.ssp.frame_type          = SCI_SAS_TASK_FRAME;
+   task_context->ssp_command_iu_length = sizeof(SCI_SSP_TASK_IU_T) / sizeof(U32);
+}
+
+#endif // !defined(DISABLE_TASK_MANAGEMENT)
+
+#if !defined(DISABLE_PASS_THROUGH)
+/**
+ * @brief This method constructs the SSP Command IU data for this
+ *        ssp passthrough comand request object.
+ *
+ * @param[in] this_request This parameter specifies the request object for
+ *            which the SSP command information unit is being built.
+ *
+ * @return SCI_STATUS, returns invalid parameter is cdb > 16
+ */
+static
+SCI_STATUS scic_sds_io_request_build_ssp_command_iu_pass_through(
+   SCIC_SDS_REQUEST_T   *this_request,
+   SCIC_SSP_PASSTHRU_REQUEST_CALLBACKS_T *ssp_passthru_cb
+)
+{
+   SCI_SSP_COMMAND_IU_T *command_frame;
+   U32  cdb_length = 0, additional_cdb_length = 0;
+   U8 *cdb_buffer, *additional_cdb_buffer;
+   U8 *scsi_lun;
+   SCI_STATUS sci_status = SCI_SUCCESS;
+   SCI_SINGLE_LEVEL_LUN_T lun;
+
+   command_frame =
+      (SCI_SSP_COMMAND_IU_T *)this_request->command_buffer;
+
+   //get the lun
+   ssp_passthru_cb->scic_cb_ssp_passthru_get_lun (
+      this_request,
+     &scsi_lun
+   );
+   memset(&lun, 0, sizeof(lun));
+   lun.lun_number = *scsi_lun;
+   scic_word_copy_with_swap(
+       (U32 *)command_frame->lun,
+       (U32 *)&lun,
+       sizeof(lun));
+
+   ((U32 *)command_frame)[2] = 0;
+
+   ssp_passthru_cb->scic_cb_ssp_passthru_get_cdb(
+      this_request,
+     &cdb_length,
+     &cdb_buffer,
+     &additional_cdb_length,
+     &additional_cdb_buffer
+   );
+
+   command_frame->additional_cdb_length = additional_cdb_length;
+
+   // ----------- TODO
+   ///todo: what to do with additional cdb length and buffer as the current command buffer is
+   // 16 bytes in intel_sas.h
+   // ??? see the SAS command IU
+   if (additional_cdb_length > 0)
+   {
+     return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+   }
+
+   /// @todo Is it ok to leave junk at the end of the cdb buffer?
+   scic_word_copy_with_swap(
+      (U32 *)(&command_frame->cdb),
+      (U32 *)(cdb_buffer),
+      (cdb_length + 3) / sizeof(U32)
+   );
+
+   /////-------- End fo TODO
+
+   command_frame->enable_first_burst = 0;
+   command_frame->task_priority = 0;  //todo: check with Richard ????
+
+   //get the task attribute
+   command_frame->task_attribute = ssp_passthru_cb->scic_cb_ssp_passthru_get_task_attribute (
+                                      this_request
+                             );
+
+   return sci_status;
+}
+#endif // !defined(DISABLE_PASS_THROUGH)
+
+//****************************************************************************
+//* SCIC Interface Implementation
+//****************************************************************************
+
+#if !defined(DISABLE_TASK_MANAGEMENT)
+/**
+ * This method returns the size required to store an SSP task request object.
+ *
+ * @return U32
+ */
+static
+U32 scic_sds_ssp_task_request_get_object_size(void)
+{
+   return   sizeof(SCIC_SDS_REQUEST_T)
+          + scic_ssp_task_request_get_object_size()
+          + sizeof(SCU_TASK_CONTEXT_T)
+          + CACHE_LINE_SIZE;
+}
+
+
+U32 scic_task_request_get_object_size(void)
+{
+   U32 ssp_task_request_size;
+   U32 stp_task_request_size;
+
+   ssp_task_request_size = scic_sds_ssp_task_request_get_object_size();
+   stp_task_request_size = scic_sds_stp_task_request_get_object_size();
+
+   return MAX(ssp_task_request_size, stp_task_request_size);
+}
+
+#endif // !defined(DISABLE_TASK_MANAGEMENT)
+
+// ---------------------------------------------------------------------------
+
+U32 scic_io_request_get_object_size(void)
+{
+   U32 ssp_request_size;
+   U32 stp_request_size;
+   U32 smp_request_size;
+
+   ssp_request_size = scic_sds_ssp_request_get_object_size();
+   stp_request_size = scic_sds_stp_request_get_object_size();
+   smp_request_size = scic_sds_smp_request_get_object_size();
+
+   return MAX(ssp_request_size, MAX(stp_request_size, smp_request_size));
+}
+
+// ---------------------------------------------------------------------------
+
+SCIC_TRANSPORT_PROTOCOL scic_io_request_get_protocol(
+   SCI_IO_REQUEST_HANDLE_T  scic_io_request
+)
+{
+   SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T * )scic_io_request;
+   return this_request->protocol;
+}
+
+// ---------------------------------------------------------------------------
+
+U32 scic_sds_request_get_min_timer_count(void)
+{
+   return SCIC_SDS_IO_REQUEST_MINIMUM_TIMER_COUNT;
+}
+
+// ---------------------------------------------------------------------------
+
+U32 scic_sds_request_get_max_timer_count(void)
+{
+   return SCIC_SDS_IO_REQUEST_MAXIMUM_TIMER_COUNT;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_io_request_construct(
+   SCI_CONTROLLER_HANDLE_T      scic_controller,
+   SCI_REMOTE_DEVICE_HANDLE_T   scic_remote_device,
+   U16                          io_tag,
+   void                       * user_io_request_object,
+   void                       * scic_io_request_memory,
+   SCI_IO_REQUEST_HANDLE_T    * new_scic_io_request_handle
+)
+{
+   SCI_STATUS                          status = SCI_SUCCESS;
+   SCIC_SDS_REQUEST_T                * this_request;
+   SMP_DISCOVER_RESPONSE_PROTOCOLS_T   device_protocol;
+
+   this_request = (SCIC_SDS_REQUEST_T * )scic_io_request_memory;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(scic_controller),
+      (SCIC_LOG_OBJECT_SSP_IO_REQUEST
+      |SCIC_LOG_OBJECT_SMP_IO_REQUEST
+      |SCIC_LOG_OBJECT_STP_IO_REQUEST),
+      "scic_io_request_construct(0x%x, 0x%x, 0x02x, 0x%x, 0x%x, 0x%x) enter\n",
+      scic_controller, scic_remote_device,
+      io_tag, user_io_request_object,
+      this_request, new_scic_io_request_handle
+   ));
+
+   // Build the common part of the request
+   scic_sds_general_request_construct(
+      (SCIC_SDS_CONTROLLER_T *)scic_controller,
+      (SCIC_SDS_REMOTE_DEVICE_T *)scic_remote_device,
+      io_tag,
+      user_io_request_object,
+      this_request
+   );
+
+   if (
+         scic_sds_remote_device_get_index((SCIC_SDS_REMOTE_DEVICE_T *)scic_remote_device)
+      == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX
+      )
+   {
+      return SCI_FAILURE_INVALID_REMOTE_DEVICE;
+   }
+
+   scic_remote_device_get_protocols(scic_remote_device, &device_protocol);
+
+   if (device_protocol.u.bits.attached_ssp_target)
+   {
+      scic_sds_ssp_io_request_assign_buffers(this_request);
+   }
+   else if (device_protocol.u.bits.attached_stp_target)
+   {
+      scic_sds_stp_request_assign_buffers(this_request);
+      memset(this_request->command_buffer, 0, sizeof(SATA_FIS_REG_H2D_T));
+   }
+   else if (device_protocol.u.bits.attached_smp_target)
+   {
+      scic_sds_smp_request_assign_buffers(this_request);
+      memset(this_request->command_buffer, 0, sizeof(SMP_REQUEST_T));
+   }
+   else
+   {
+      status = SCI_FAILURE_UNSUPPORTED_PROTOCOL;
+   }
+
+   if (status == SCI_SUCCESS)
+   {
+      memset(
+         this_request->task_context_buffer,
+         0,
+         SCI_FIELD_OFFSET(SCU_TASK_CONTEXT_T, sgl_pair_ab)
+      );
+      *new_scic_io_request_handle = scic_io_request_memory;
+   }
+
+   return status;
+}
+
+// ---------------------------------------------------------------------------
+
+#if !defined(DISABLE_TASK_MANAGEMENT)
+
+SCI_STATUS scic_task_request_construct(
+   SCI_CONTROLLER_HANDLE_T     controller,
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
+   U16                         io_tag,
+   void                       *user_io_request_object,
+   void                       *scic_task_request_memory,
+   SCI_TASK_REQUEST_HANDLE_T  *new_scic_task_request_handle
+)
+{
+   SCI_STATUS           status = SCI_SUCCESS;
+   SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T *)
+                                       scic_task_request_memory;
+   SMP_DISCOVER_RESPONSE_PROTOCOLS_T   device_protocol;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      (SCIC_LOG_OBJECT_SSP_IO_REQUEST
+      |SCIC_LOG_OBJECT_SMP_IO_REQUEST
+      |SCIC_LOG_OBJECT_STP_IO_REQUEST),
+      "scic_task_request_construct(0x%x, 0x%x, 0x02x, 0x%x, 0x%x, 0x%x) enter\n",
+      controller, remote_device,
+      io_tag, user_io_request_object,
+      scic_task_request_memory, new_scic_task_request_handle
+   ));
+
+   // Build the common part of the request
+   scic_sds_general_request_construct(
+      (SCIC_SDS_CONTROLLER_T *)controller,
+      (SCIC_SDS_REMOTE_DEVICE_T *)remote_device,
+      io_tag,
+      user_io_request_object,
+      this_request
+   );
+
+   scic_remote_device_get_protocols(remote_device, &device_protocol);
+
+   if (device_protocol.u.bits.attached_ssp_target)
+   {
+      scic_sds_ssp_task_request_assign_buffers(this_request);
+
+      this_request->has_started_substate_machine = TRUE;
+
+      // Construct the started sub-state machine.
+      sci_base_state_machine_construct(
+         &this_request->started_substate_machine,
+         &this_request->parent.parent,
+         scic_sds_io_request_started_task_mgmt_substate_table,
+         SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION
+      );
+   }
+   else if (device_protocol.u.bits.attached_stp_target)
+   {
+      scic_sds_stp_request_assign_buffers(this_request);
+   }
+   else
+   {
+      status = SCI_FAILURE_UNSUPPORTED_PROTOCOL;
+   }
+
+   if (status == SCI_SUCCESS)
+   {
+      this_request->is_task_management_request = TRUE;
+      memset(this_request->task_context_buffer, 0x00, sizeof(SCU_TASK_CONTEXT_T));
+      *new_scic_task_request_handle            = scic_task_request_memory;
+   }
+
+   return status;
+}
+
+#endif // !defined(DISABLE_TASK_MANAGEMENT)
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_io_request_construct_basic_ssp(
+   SCI_IO_REQUEST_HANDLE_T  scic_io_request
+)
+{
+   void               *os_handle;
+   SCIC_SDS_REQUEST_T *this_request;
+   this_request = (SCIC_SDS_REQUEST_T *)scic_io_request;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_request),
+      SCIC_LOG_OBJECT_SSP_IO_REQUEST,
+      "scic_io_request_construct_basic_ssp(0x%x) enter\n",
+      this_request
+   ));
+
+   this_request->protocol = SCIC_SSP_PROTOCOL;
+
+   os_handle = scic_sds_request_get_user_request(this_request);
+
+   scu_ssp_io_request_construct_task_context(
+      this_request,
+      scic_cb_io_request_get_data_direction(os_handle),
+      scic_cb_io_request_get_transfer_length(os_handle)
+   );
+
+
+   scic_sds_io_request_build_ssp_command_iu(this_request);
+
+   scic_sds_request_initialize_state_logging(this_request);
+
+   sci_base_state_machine_change_state(
+      &this_request->parent.state_machine,
+      SCI_BASE_REQUEST_STATE_CONSTRUCTED
+   );
+
+   return SCI_SUCCESS;
+}
+
+// ---------------------------------------------------------------------------
+
+#if !defined(DISABLE_TASK_MANAGEMENT)
+
+SCI_STATUS scic_task_request_construct_ssp(
+   SCI_TASK_REQUEST_HANDLE_T  scic_task_request
+)
+{
+   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)
+                                      scic_task_request;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_request),
+      SCIC_LOG_OBJECT_SSP_IO_REQUEST,
+      "scic_task_request_construct_ssp(0x%x) enter\n",
+      this_request
+   ));
+
+   // Construct the SSP Task SCU Task Context
+   scu_ssp_task_request_construct_task_context(this_request);
+
+   // Fill in the SSP Task IU
+   scic_sds_task_request_build_ssp_task_iu(this_request);
+
+   scic_sds_request_initialize_state_logging(this_request);
+
+   sci_base_state_machine_change_state(
+      &this_request->parent.state_machine,
+      SCI_BASE_REQUEST_STATE_CONSTRUCTED
+   );
+
+   return SCI_SUCCESS;
+}
+
+#endif // !defined(DISABLE_TASK_MANAGEMENT)
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_io_request_construct_advanced_ssp(
+   SCI_IO_REQUEST_HANDLE_T    scic_io_request,
+   SCIC_IO_SSP_PARAMETERS_T * io_parameters
+)
+{
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(scic_io_request),
+      SCIC_LOG_OBJECT_SSP_IO_REQUEST,
+      "scic_io_request_construct_advanced_ssp(0x%x, 0x%x) enter\n",
+      io_parameters, scic_io_request
+   ));
+
+   /// @todo Implement after 1.1
+   return SCI_FAILURE;
+}
+
+// ---------------------------------------------------------------------------
+
+#if !defined(DISABLE_PASS_THROUGH)
+SCI_STATUS scic_io_request_construct_ssp_pass_through (
+   void                    * scic_io_request,
+   SCIC_SSP_PASSTHRU_REQUEST_CALLBACKS_T *ssp_passthru_cb
+)
+{
+   SCI_STATUS               status = SCI_SUCCESS;
+   SCIC_SDS_REQUEST_T       * this_request;
+
+   this_request = (SCIC_SDS_REQUEST_T * )scic_io_request;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(scic_io_request),
+      SCIC_LOG_OBJECT_STP_IO_REQUEST,
+      "scic_io_request_construct_ssp_pass_through(0x%x) enter\n",
+      scic_io_request
+   ));
+
+   //build the task context from the pass through buffer
+   scu_ssp_io_request_construct_task_context(
+      this_request,
+      ssp_passthru_cb->common_callbacks.scic_cb_passthru_get_data_direction (this_request),
+      ssp_passthru_cb->common_callbacks.scic_cb_passthru_get_transfer_length(this_request)
+   );
+
+   //build the ssp command iu from the pass through buffer
+   status = scic_sds_io_request_build_ssp_command_iu_pass_through (
+               this_request,
+               ssp_passthru_cb
+            );
+   if (status != SCI_SUCCESS)
+   {
+      return status;
+   }
+
+   /* initialize the logging */
+   scic_sds_request_initialize_state_logging(this_request);
+
+   sci_base_state_machine_change_state(
+      &this_request->parent.state_machine,
+      SCI_BASE_REQUEST_STATE_CONSTRUCTED
+   );
+
+   return status;
+}
+#endif // !defined(DISABLE_PASS_THROUGH)
+
+// ---------------------------------------------------------------------------
+
+#if !defined(DISABLE_TASK_MANAGEMENT)
+
+SCI_STATUS scic_task_request_construct_sata(
+   SCI_TASK_REQUEST_HANDLE_T scic_task_request
+)
+{
+   SCI_STATUS           status;
+   SCIC_SDS_REQUEST_T * this_request;
+   U8                   sat_protocol;
+
+   this_request = (SCIC_SDS_REQUEST_T *)scic_task_request;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_request),
+      SCIC_LOG_OBJECT_STP_IO_REQUEST,
+      "scic_task_request_construct_sata(0x%x) enter\n",
+      this_request
+   ));
+
+   sat_protocol =
+      scic_cb_request_get_sat_protocol(this_request->user_request);
+
+   this_request->sat_protocol = sat_protocol;
+
+   switch (sat_protocol)
+   {
+   case SAT_PROTOCOL_ATA_HARD_RESET:
+   case SAT_PROTOCOL_SOFT_RESET:
+      status = scic_sds_stp_soft_reset_request_construct(this_request);
+      break;
+
+   case SAT_PROTOCOL_PIO_DATA_IN:
+      status = scic_sds_stp_pio_request_construct(this_request, sat_protocol, FALSE);
+      break;
+
+   default:
+      SCIC_LOG_ERROR((
+         sci_base_object_get_logger(this_request),
+         SCIC_LOG_OBJECT_STP_IO_REQUEST,
+         "SCIC IO Request 0x%x received un-handled SAT Protocl %d.\n",
+         this_request, sat_protocol
+      ));
+
+      status = SCI_FAILURE;
+      break;
+   }
+
+   if (status == SCI_SUCCESS)
+   {
+      scic_sds_request_initialize_state_logging(this_request);
+
+      sci_base_state_machine_change_state(
+         &this_request->parent.state_machine,
+         SCI_BASE_REQUEST_STATE_CONSTRUCTED
+      );
+   }
+
+   return status;
+}
+
+#endif // !defined(DISABLE_TASK_MANAGEMENT)
+
+// ---------------------------------------------------------------------------
+
+#if !defined(DISABLE_PASS_THROUGH)
+SCI_STATUS scic_io_request_construct_sata_pass_through(
+   SCI_IO_REQUEST_HANDLE_T scic_io_request,
+   SCIC_STP_PASSTHRU_REQUEST_CALLBACKS_T *passthru_cb
+)
+{
+   SCI_STATUS                       status = SCI_SUCCESS;
+   SCIC_SDS_REQUEST_T               * this_request;
+   U8                               sat_protocol;
+   U8                               * reg_fis;
+   U32                              transfer_length;
+   SCI_IO_REQUEST_DATA_DIRECTION    data_direction;
+
+   this_request = (SCIC_SDS_REQUEST_T * )scic_io_request;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(scic_io_request),
+      SCIC_LOG_OBJECT_STP_IO_REQUEST,
+      "scic_io_request_construct_sata_pass_through(0x%x) enter\n",
+      scic_io_request
+   ));
+
+   passthru_cb->scic_cb_stp_passthru_get_register_fis(this_request, &reg_fis);
+
+   if (reg_fis == NULL)
+   {
+      status = SCI_FAILURE_INVALID_PARAMETER_VALUE;
+   }
+
+   if (status == SCI_SUCCESS)
+   {
+      //copy the H2D Reg fis blindly from the request to the SCU command buffer
+      memcpy ((U8 *)this_request->command_buffer, (U8 *)reg_fis, sizeof(SATA_FIS_REG_H2D_T));
+
+      //continue to create the request
+      sat_protocol = passthru_cb->scic_cb_stp_passthru_get_protocol(this_request);
+      transfer_length = passthru_cb->common_callbacks.scic_cb_passthru_get_transfer_length(this_request);
+      data_direction = passthru_cb->common_callbacks.scic_cb_passthru_get_data_direction(this_request);
+
+      status = scic_sds_io_request_construct_sata(
+                  this_request,
+                  sat_protocol,
+                  transfer_length,
+                  data_direction,
+                  TRUE,
+                  TRUE
+               );
+
+      this_request->protocol = SCIC_STP_PROTOCOL;
+   }
+
+   return status;
+}
+#endif // !defined(DISABLE_PASS_THROUGH)
+
+// ---------------------------------------------------------------------------
+
+U16 scic_io_request_get_io_tag(
+   SCI_IO_REQUEST_HANDLE_T  scic_io_request
+)
+{
+   SCIC_SDS_REQUEST_T *this_request;
+   this_request = (SCIC_SDS_REQUEST_T *)scic_io_request;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(scic_io_request),
+      SCIC_LOG_OBJECT_SMP_IO_REQUEST,
+      "scic_io_request_get_io_tag(0x%x) enter\n",
+      scic_io_request
+   ));
+
+   return this_request->io_tag;
+}
+
+// ---------------------------------------------------------------------------
+
+U32 scic_request_get_controller_status(
+   SCI_IO_REQUEST_HANDLE_T  io_request
+)
+{
+   SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T*)io_request;
+   return this_request->scu_status;
+}
+
+U32 scic_request_get_sci_status(
+   SCI_IO_REQUEST_HANDLE_T  io_request
+)
+{
+   SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T*)io_request;
+   return this_request->sci_status;
+}
+
+// ---------------------------------------------------------------------------
+
+void * scic_io_request_get_rx_frame(
+   SCI_IO_REQUEST_HANDLE_T  scic_io_request,
+   U32                      offset
+)
+{
+   void               * frame_buffer = NULL;
+   SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T *)scic_io_request;
+
+   ASSERT(offset < SCU_UNSOLICITED_FRAME_BUFFER_SIZE);
+
+   if (this_request->saved_rx_frame_index != SCU_INVALID_FRAME_INDEX)
+   {
+      scic_sds_unsolicited_frame_control_get_buffer(
+         &(this_request->owning_controller->uf_control),
+         this_request->saved_rx_frame_index,
+         &frame_buffer
+      );
+   }
+
+   return frame_buffer;
+}
+
+void * scic_io_request_get_command_iu_address(
+   SCI_IO_REQUEST_HANDLE_T  scic_io_request
+)
+{
+   SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T *)scic_io_request;
+
+   return this_request->command_buffer;
+}
+
+// ---------------------------------------------------------------------------
+
+void * scic_io_request_get_response_iu_address(
+   SCI_IO_REQUEST_HANDLE_T scic_io_request
+)
+{
+   SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T *)scic_io_request;
+
+   return this_request->response_buffer;
+}
+
+// ---------------------------------------------------------------------------
+#define SCU_TASK_CONTEXT_SRAM 0x200000
+U32 scic_io_request_get_number_of_bytes_transferred (
+   SCI_IO_REQUEST_HANDLE_T  scic_io_request
+)
+{
+   U32 ret_val = 0;
+   SCIC_SDS_REQUEST_T       * scic_sds_request;
+
+   scic_sds_request = (SCIC_SDS_REQUEST_T *) scic_io_request;
+
+   if ( SMU_AMR_READ (scic_sds_request->owning_controller) == 0)
+   {
+      //get the bytes of data from the Address == BAR1 + 20002Ch + (256*TCi) where
+      //   BAR1 is the scu_registers
+      //   0x20002C = 0x200000 + 0x2c
+      //            = start of task context SRAM + offset of (type.ssp.data_offset)
+      //   TCi is the io_tag of SCIC_SDS_REQUEST
+      ret_val =  scic_sds_pci_read_scu_dword(
+                    scic_sds_request->owning_controller,
+                    (
+                       (U8 *) scic_sds_request->owning_controller->scu_registers +
+                          ( SCU_TASK_CONTEXT_SRAM + SCI_FIELD_OFFSET(SCU_TASK_CONTEXT_T, type.ssp.data_offset) ) +
+                       ( ( sizeof (SCU_TASK_CONTEXT_T) ) * scic_sds_io_tag_get_index (scic_sds_request->io_tag))
+                    )
+                 );
+   }
+
+   return ret_val;
+}
+
+//****************************************************************************
+//* SCIC SDS Interface Implementation
+//****************************************************************************
+
+/**
+ * This method invokes the base state start request handler for the
+ * SCIC_SDS_IO_REQUEST_T object.
+ *
+ * @param[in] this_request The SCIC_SDS_IO_REQUEST_T object for which the
+ *       start operation is to be executed.
+ *
+ * @return SCI_STATUS
+ */
+SCI_STATUS scic_sds_request_start(
+   SCIC_SDS_REQUEST_T *this_request
+)
+{
+   if (
+         this_request->device_sequence
+      == scic_sds_remote_device_get_sequence(this_request->target_device)
+      )
+   {
+      return this_request->state_handlers->parent.start_handler(
+                &this_request->parent
+             );
+   }
+
+   return SCI_FAILURE;
+}
+
+/**
+ * This method invokes the base state terminate request handber for the
+ * SCIC_SDS_IO_REQUEST_T object.
+ *
+ * @param[in] this_request The SCIC_SDS_IO_REQUEST_T object for which the
+ *       start operation is to be executed.
+ *
+ * @return SCI_STATUS
+ */
+SCI_STATUS scic_sds_io_request_terminate(
+   SCIC_SDS_REQUEST_T *this_request
+)
+{
+   return this_request->state_handlers->parent.abort_handler(
+                                                      &this_request->parent);
+}
+
+/**
+ * This method invokes the base state request completion handler for the
+ * SCIC_SDS_IO_REQUEST_T object.
+ *
+ * @param[in] this_request The SCIC_SDS_IO_REQUEST_T object for which the
+ *       start operation is to be executed.
+ *
+ * @return SCI_STATUS
+ */
+SCI_STATUS scic_sds_io_request_complete(
+   SCIC_SDS_REQUEST_T *this_request
+)
+{
+   return this_request->state_handlers->parent.complete_handler(
+                                                      &this_request->parent);
+}
+
+/**
+ * This method invokes the core state handler for the SCIC_SDS_IO_REQUEST_T
+ * object.
+ *
+ * @param[in] this_request The SCIC_SDS_IO_REQUEST_T object for which the
+ *       start operation is to be executed.
+ * @param[in] event_code The event code returned by the hardware for the task
+ *       reqeust.
+ *
+ * @return SCI_STATUS
+ */
+SCI_STATUS scic_sds_io_request_event_handler(
+   SCIC_SDS_REQUEST_T * this_request,
+   U32                  event_code
+)
+{
+   return this_request->state_handlers->event_handler(this_request, event_code);
+}
+
+/**
+ * This method invokes the core state frame handler for the
+ * SCIC_SDS_IO_REQUEST_T object.
+ *
+ * @param[in] this_request The SCIC_SDS_IO_REQUEST_T object for which the
+ *       start operation is to be executed.
+ * @param[in] frame_index The frame index returned by the hardware for the
+ *       reqeust object.
+ *
+ * @return SCI_STATUS
+ */
+SCI_STATUS scic_sds_io_request_frame_handler(
+   SCIC_SDS_REQUEST_T * this_request,
+   U32                  frame_index
+)
+{
+   return this_request->state_handlers->frame_handler(this_request, frame_index);
+}
+
+/**
+ * This method invokes the core state task complete handler for the
+ * SCIC_SDS_IO_REQUEST_T object.
+ *
+ * @param[in] this_request The SCIC_SDS_IO_REQUEST_T object for which the task
+ *       start operation is to be executed.
+ *
+ * @return SCI_STATUS
+ */
+SCI_STATUS scic_sds_task_request_complete(
+   SCIC_SDS_REQUEST_T *this_request
+)
+{
+   return this_request->state_handlers->parent.complete_handler(&this_request->parent);
+}
+
+//****************************************************************************
+//* SCIC SDS PROTECTED METHODS
+//****************************************************************************
+
+/**
+ * @brief This method copies response data for requests returning response
+ *        data instead of sense data.
+ *
+ * @param[in]  this_request This parameter specifies the request object for
+ *             which to copy the response data.
+ *
+ * @return none
+ */
+void scic_sds_io_request_copy_response(
+   SCIC_SDS_REQUEST_T *this_request
+)
+{
+   void                  * response_buffer;
+   U32                     user_response_length;
+   U32                     core_response_length;
+   SCI_SSP_RESPONSE_IU_T * ssp_response;
+
+   ssp_response = (SCI_SSP_RESPONSE_IU_T *)this_request->response_buffer;
+
+   response_buffer = scic_cb_ssp_task_request_get_response_data_address(
+                        this_request->user_request
+                     );
+
+   user_response_length = scic_cb_ssp_task_request_get_response_data_length(
+                        this_request->user_request
+                     );
+
+   core_response_length = sci_ssp_get_response_data_length(
+                           ssp_response->response_data_length
+                     );
+
+   user_response_length = MIN(user_response_length, core_response_length);
+
+   memcpy(response_buffer, ssp_response->data, user_response_length);
+}
+
+//******************************************************************************
+//* REQUEST STATE MACHINE
+//******************************************************************************
+
+//*****************************************************************************
+//*  DEFAULT STATE HANDLERS
+//*****************************************************************************
+
+/**
+ * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T
+ * object receives a scic_sds_request_start() request.  The default action is
+ * to log a warning and return a failure status.
+ *
+ * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
+ *       the SCIC_SDS_IO_REQUEST_T object for which the start operation is
+ *       requested.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+SCI_STATUS scic_sds_request_default_start_handler(
+   SCI_BASE_REQUEST_T *request
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger((SCIC_SDS_REQUEST_T *)request),
+      (
+          SCIC_LOG_OBJECT_SSP_IO_REQUEST
+        | SCIC_LOG_OBJECT_STP_IO_REQUEST
+        | SCIC_LOG_OBJECT_SMP_IO_REQUEST
+      ),
+      "SCIC IO Request requested to start while in wrong state %d\n",
+      sci_base_state_machine_get_state(
+         &((SCIC_SDS_REQUEST_T *)request)->parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T
+ * object receives a scic_sds_request_terminate() request.  The default action
+ * is to log a warning and return a failure status.
+ *
+ * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
+ *       the SCIC_SDS_IO_REQUEST_T object for which the start operation is
+ *       requested.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+SCI_STATUS scic_sds_request_default_abort_handler(
+   SCI_BASE_REQUEST_T *request
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger((SCIC_SDS_REQUEST_T *)request),
+      (
+          SCIC_LOG_OBJECT_SSP_IO_REQUEST
+        | SCIC_LOG_OBJECT_STP_IO_REQUEST
+        | SCIC_LOG_OBJECT_SMP_IO_REQUEST
+      ),
+      "SCIC IO Request requested to abort while in wrong state %d\n",
+      sci_base_state_machine_get_state(
+         &((SCIC_SDS_REQUEST_T *)request)->parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T
+ * object receives a scic_sds_request_complete() request.  The default action
+ * is to log a warning and return a failure status.
+ *
+ * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
+ *       the SCIC_SDS_IO_REQUEST_T object for which the start operation is
+ *       requested.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+SCI_STATUS scic_sds_request_default_complete_handler(
+   SCI_BASE_REQUEST_T *request
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger((SCIC_SDS_REQUEST_T *)request),
+      (
+          SCIC_LOG_OBJECT_SSP_IO_REQUEST
+        | SCIC_LOG_OBJECT_STP_IO_REQUEST
+        | SCIC_LOG_OBJECT_SMP_IO_REQUEST
+      ),
+      "SCIC IO Request requested to complete while in wrong state %d\n",
+      sci_base_state_machine_get_state(
+         &((SCIC_SDS_REQUEST_T *)request)->parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T
+ * object receives a scic_sds_request_complete() request.  The default action
+ * is to log a warning and return a failure status.
+ *
+ * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
+ *       the SCIC_SDS_IO_REQUEST_T object for which the start operation is
+ *       requested.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+SCI_STATUS scic_sds_request_default_destruct_handler(
+   SCI_BASE_REQUEST_T *request
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger((SCIC_SDS_REQUEST_T *)request),
+      (
+          SCIC_LOG_OBJECT_SSP_IO_REQUEST
+        | SCIC_LOG_OBJECT_STP_IO_REQUEST
+        | SCIC_LOG_OBJECT_SMP_IO_REQUEST
+      ),
+      "SCIC IO Request requested to destroy while in wrong state %d\n",
+      sci_base_state_machine_get_state(
+         &((SCIC_SDS_REQUEST_T *)request)->parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T
+ * object receives a scic_sds_task_request_complete() request.  The default
+ * action is to log a warning and return a failure status.
+ *
+ * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
+ *       the SCIC_SDS_IO_REQUEST_T object for which the start operation is
+ *       requested.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+SCI_STATUS scic_sds_request_default_tc_completion_handler(
+   SCIC_SDS_REQUEST_T * this_request,
+   U32                  completion_code
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger(this_request),
+      (
+          SCIC_LOG_OBJECT_SSP_IO_REQUEST
+        | SCIC_LOG_OBJECT_STP_IO_REQUEST
+        | SCIC_LOG_OBJECT_SMP_IO_REQUEST
+      ),
+      "SCIC IO Request given task completion notification %x while in wrong state %d\n",
+      completion_code,
+      sci_base_state_machine_get_state(&this_request->parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+
+}
+
+/**
+ * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T
+ * object receives a scic_sds_request_event_handler() request.  The default
+ * action is to log a warning and return a failure status.
+ *
+ * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
+ *       the SCIC_SDS_IO_REQUEST_T object for which the start operation is
+ *       requested.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+SCI_STATUS scic_sds_request_default_event_handler(
+   SCIC_SDS_REQUEST_T * this_request,
+   U32                  event_code
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger(this_request),
+      (
+          SCIC_LOG_OBJECT_SSP_IO_REQUEST
+        | SCIC_LOG_OBJECT_STP_IO_REQUEST
+        | SCIC_LOG_OBJECT_SMP_IO_REQUEST
+      ),
+      "SCIC IO Request given event code notification %x while in wrong state %d\n",
+      event_code,
+      sci_base_state_machine_get_state(&this_request->parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T
+ * object receives a scic_sds_request_event_handler() request.  The default
+ * action is to log a warning and return a failure status.
+ *
+ * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
+ *       the SCIC_SDS_IO_REQUEST_T object for which the start operation is
+ *       requested.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_FAILURE_INVALID_STATE
+ */
+SCI_STATUS scic_sds_request_default_frame_handler(
+   SCIC_SDS_REQUEST_T * this_request,
+   U32                  frame_index
+)
+{
+   SCIC_LOG_WARNING((
+      sci_base_object_get_logger(this_request),
+      (
+          SCIC_LOG_OBJECT_SSP_IO_REQUEST
+        | SCIC_LOG_OBJECT_STP_IO_REQUEST
+        | SCIC_LOG_OBJECT_SMP_IO_REQUEST
+      ),
+      "SCIC IO Request given unexpected frame %x while in state %d\n",
+      frame_index,
+      sci_base_state_machine_get_state(&this_request->parent.state_machine)
+   ));
+
+   scic_sds_controller_release_frame(
+      this_request->owning_controller, frame_index);
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+//*****************************************************************************
+//*  CONSTRUCTED STATE HANDLERS
+//*****************************************************************************
+
+/**
+ * This method implements the action taken when a constructed
+ * SCIC_SDS_IO_REQUEST_T object receives a scic_sds_request_start() request.
+ *
+ * This method will, if necessary, allocate a TCi for the io request object
+ * and then will, if necessary, copy the constructed TC data into the actual
+ * TC buffer.  If everything is successful the post context field is updated
+ * with the TCi so the controller can post the request to the hardware.
+ *
+ * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
+ *       the SCIC_SDS_IO_REQUEST_T object for which the start operation is
+ *       requested.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS
+ * @retval SCI_FAILURE_INSUFFICIENT_RESOURCES
+ */
+static
+SCI_STATUS scic_sds_request_constructed_state_start_handler(
+   SCI_BASE_REQUEST_T *request
+)
+{
+   SCU_TASK_CONTEXT_T *task_context;
+   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)request;
+
+   if (this_request->io_tag == SCI_CONTROLLER_INVALID_IO_TAG)
+   {
+      this_request->io_tag =
+         scic_controller_allocate_io_tag(this_request->owning_controller);
+   }
+
+   // Record the IO Tag in the request
+   if (this_request->io_tag != SCI_CONTROLLER_INVALID_IO_TAG)
+   {
+      task_context = this_request->task_context_buffer;
+
+      task_context->task_index = scic_sds_io_tag_get_index(this_request->io_tag);
+
+      switch (task_context->protocol_type)
+      {
+      case SCU_TASK_CONTEXT_PROTOCOL_SMP:
+      case SCU_TASK_CONTEXT_PROTOCOL_SSP:
+         // SSP/SMP Frame
+         task_context->type.ssp.tag = this_request->io_tag;
+         task_context->type.ssp.target_port_transfer_tag = 0xFFFF;
+         break;
+
+      case SCU_TASK_CONTEXT_PROTOCOL_STP:
+         // STP/SATA Frame
+         //task_context->type.stp.ncq_tag = this_request->ncq_tag;
+         break;
+
+      case SCU_TASK_CONTEXT_PROTOCOL_NONE:
+         /// @todo When do we set no protocol type?
+         break;
+
+      default:
+         // This should never happen since we build the IO requests
+         break;
+      }
+
+      // Check to see if we need to copy the task context buffer
+      // or have been building into the task context buffer
+      if (this_request->was_tag_assigned_by_user == FALSE)
+      {
+         scic_sds_controller_copy_task_context(
+            this_request->owning_controller, this_request
+         );
+      }
+
+      // Add to the post_context the io tag value
+      this_request->post_context |= scic_sds_io_tag_get_index(this_request->io_tag);
+
+      // Everything is good go ahead and change state
+      sci_base_state_machine_change_state(
+         &this_request->parent.state_machine,
+         SCI_BASE_REQUEST_STATE_STARTED
+      );
+
+      return SCI_SUCCESS;
+   }
+
+   return SCI_FAILURE_INSUFFICIENT_RESOURCES;
+}
+
+/**
+ * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T
+ * object receives a scic_sds_request_terminate() request.
+ *
+ * Since the request has not yet been posted to the hardware the request
+ * transitions to the completed state.
+ *
+ * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
+ *       the SCIC_SDS_IO_REQUEST_T object for which the start operation is
+ *       requested.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS
+ */
+static
+SCI_STATUS scic_sds_request_constructed_state_abort_handler(
+   SCI_BASE_REQUEST_T *request
+)
+{
+   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)request;
+
+   // This request has been terminated by the user make sure that the correct
+   // status code is returned
+   scic_sds_request_set_status(
+      this_request,
+      SCU_TASK_DONE_TASK_ABORT,
+      SCI_FAILURE_IO_TERMINATED
+   );
+
+   sci_base_state_machine_change_state(
+      &this_request->parent.state_machine,
+      SCI_BASE_REQUEST_STATE_COMPLETED
+   );
+
+   return SCI_SUCCESS;
+}
+
+//*****************************************************************************
+//*  STARTED STATE HANDLERS
+//*****************************************************************************
+
+/**
+ * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T
+ * object receives a scic_sds_request_terminate() request.
+ *
+ * Since the request has been posted to the hardware the io request state is
+ * changed to the aborting state.
+ *
+ * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
+ *       the SCIC_SDS_IO_REQUEST_T object for which the start operation is
+ *       requested.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS
+ */
+SCI_STATUS scic_sds_request_started_state_abort_handler(
+   SCI_BASE_REQUEST_T *request
+)
+{
+   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)request;
+
+   if (this_request->has_started_substate_machine)
+   {
+      sci_base_state_machine_stop(&this_request->started_substate_machine);
+   }
+
+   sci_base_state_machine_change_state(
+      &this_request->parent.state_machine,
+      SCI_BASE_REQUEST_STATE_ABORTING
+   );
+
+   return SCI_SUCCESS;
+}
+
+/**
+ * @brief This method process TC (task context) completions for normal IO
+ *        request (i.e. Task/Abort Completions of type 0).  This method will
+ *        update the SCIC_SDS_IO_REQUEST_T::status field.
+ *
+ * @param[in] this_request This parameter specifies the request for which
+ *             a completion occurred.
+ * @param[in]  completion_code This parameter specifies the completion code
+ *             recieved from the SCU.
+ *
+ * @return none
+ */
+SCI_STATUS scic_sds_request_started_state_tc_completion_handler(
+   SCIC_SDS_REQUEST_T * this_request,
+   U32                  completion_code
+)
+{
+   U8                      data_present;
+   SCI_SSP_RESPONSE_IU_T * response_buffer;
+
+   /**
+    * @todo Any SDMA return code of other than 0 is bad
+    *       decode 0x003C0000 to determine SDMA status
+    */
+   switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
+   {
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
+      scic_sds_request_set_status(
+         this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
+      );
+      break;
+
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_EARLY_RESP):
+   {
+      // There are times when the SCU hardware will return an early response
+      // because the io request specified more data than is returned by the
+      // target device (mode pages, inquiry data, etc.).  We must check the
+      // response stats to see if this is truly a failed request or a good
+      // request that just got completed early.
+      SCI_SSP_RESPONSE_IU_T *response = (SCI_SSP_RESPONSE_IU_T *)
+                                        this_request->response_buffer;
+      scic_word_copy_with_swap(
+         this_request->response_buffer,
+         this_request->response_buffer,
+         sizeof(SCI_SSP_RESPONSE_IU_T) / sizeof(U32)
+      );
+
+      if (response->status == 0)
+      {
+         scic_sds_request_set_status(
+            this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS_IO_DONE_EARLY
+         );
+      }
+      else
+      {
+         scic_sds_request_set_status(
+            this_request,
+            SCU_TASK_DONE_CHECK_RESPONSE,
+            SCI_FAILURE_IO_RESPONSE_VALID
+         );
+      }
+   }
+   break;
+
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CHECK_RESPONSE):
+      scic_word_copy_with_swap(
+         this_request->response_buffer,
+         this_request->response_buffer,
+         sizeof(SCI_SSP_RESPONSE_IU_T) / sizeof(U32)
+      );
+
+      scic_sds_request_set_status(
+         this_request,
+         SCU_TASK_DONE_CHECK_RESPONSE,
+         SCI_FAILURE_IO_RESPONSE_VALID
+      );
+      break;
+
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_RESP_LEN_ERR):
+      /// @todo With TASK_DONE_RESP_LEN_ERR is the response frame guaranteed
+      ///       to be received before this completion status is posted?
+      response_buffer =
+         (SCI_SSP_RESPONSE_IU_T *)this_request->response_buffer;
+      data_present =
+         response_buffer->data_present & SCI_SSP_RESPONSE_IU_DATA_PRESENT_MASK;
+
+      if ((data_present == 0x01) || (data_present == 0x02))
+      {
+         scic_sds_request_set_status(
+            this_request,
+            SCU_TASK_DONE_CHECK_RESPONSE,
+            SCI_FAILURE_IO_RESPONSE_VALID
+         );
+      }
+      else
+      {
+         scic_sds_request_set_status(
+            this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
+         );
+      }
+      break;
+
+   //only stp device gets suspended.
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_ACK_NAK_TO):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_PERR):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_NAK_ERR):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_DATA_LEN_ERR):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_ABORT_ERR):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_XR_WD_LEN):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_MAX_PLD_ERR):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_RESP):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_SDBFIS):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_REG_ERR):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SDB_ERR):
+      if (this_request->protocol == SCIC_STP_PROTOCOL)
+      {
+         SCIC_LOG_ERROR((
+            sci_base_object_get_logger(this_request),
+            SCIC_LOG_OBJECT_STP_IO_REQUEST,
+            "SCIC IO Request 0x%x returning REMOTE_DEVICE_RESET_REQUIRED for completion code 0x%x\n",
+            this_request, completion_code
+         ));
+         scic_sds_request_set_status(
+            this_request,
+            SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT,
+            SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED
+         );
+      }
+      else
+      {
+         SCIC_LOG_ERROR((
+            sci_base_object_get_logger(this_request),
+            SCIC_LOG_OBJECT_SSP_IO_REQUEST,
+            "SCIC IO Request 0x%x returning CONTROLLER_SPECIFIC_IO_ERR for completion code 0x%x\n",
+            this_request, completion_code
+         ));
+         scic_sds_request_set_status(
+            this_request,
+            SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT,
+            SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
+         );
+      }
+      break;
+
+   //both stp/ssp device gets suspended
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LF_ERR):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_WRONG_DESTINATION):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_1):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_2):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_3):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_BAD_DESTINATION):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_ZONE_VIOLATION):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_STP_RESOURCES_BUSY):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_CONNECTION_RATE_NOT_SUPPORTED):
+      scic_sds_request_set_status(
+         this_request,
+         SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT,
+         SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED
+      );
+     break;
+
+   //neither ssp nor stp gets suspended.
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_NAK_CMD_ERR):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_XR):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_XR_IU_LEN_ERR):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SDMA_ERR):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_OFFSET_ERR):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_EXCESS_DATA):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_RESP_TO_ERR):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_UFI_ERR):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_FRM_TYPE_ERR):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_LL_RX_ERR):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_DATA):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_OPEN_FAIL):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_VIIT_ENTRY_NV):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_IIT_ENTRY_NV):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_RNCNV_OUTBOUND):
+   default:
+      SCIC_LOG_ERROR((
+         sci_base_object_get_logger(this_request),
+         SCIC_LOG_OBJECT_SSP_IO_REQUEST | SCIC_LOG_OBJECT_STP_IO_REQUEST,
+         "SCIC IO Request 0x%x returning CONTROLLER_SPECIFIC_IO_ERR for completion code 0x%x\n",
+         this_request, completion_code
+      ));
+      scic_sds_request_set_status(
+         this_request,
+         SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT,
+         SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
+      );
+      break;
+   }
+
+   /**
+    * @todo This is probably wrong for ACK/NAK timeout conditions
+    */
+
+   // In all cases we will treat this as the completion of the IO request.
+   sci_base_state_machine_change_state(
+      &this_request->parent.state_machine,
+      SCI_BASE_REQUEST_STATE_COMPLETED
+   );
+
+   return SCI_SUCCESS;
+}
+
+/**
+ * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T
+ * object receives a scic_sds_request_frame_handler() request.
+ *
+ * This method first determines the frame type received.  If this is a
+ * response frame then the response data is copied to the io request response
+ * buffer for processing at completion time.
+ *
+ * If the frame type is not a response buffer an error is logged.
+ *
+ * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
+ *       the SCIC_SDS_IO_REQUEST_T object for which the start operation is
+ *       requested.
+ * @param[in] frame_index This is the index of the unsolicited frame to be
+ *       processed.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS
+ * @retval SCI_FAILURE_INVALID_PARAMETER_VALUE
+ */
+static
+SCI_STATUS scic_sds_request_started_state_frame_handler(
+   SCIC_SDS_REQUEST_T * this_request,
+   U32                  frame_index
+)
+{
+   SCI_STATUS status;
+   SCI_SSP_FRAME_HEADER_T *frame_header;
+
+   /// @todo If this is a response frame we must record that we received it
+   status = scic_sds_unsolicited_frame_control_get_header(
+      &(scic_sds_request_get_controller(this_request)->uf_control),
+      frame_index,
+      (void**) &frame_header
+   );
+
+   if (frame_header->frame_type == SCI_SAS_RESPONSE_FRAME)
+   {
+      SCI_SSP_RESPONSE_IU_T *response_buffer;
+
+      status = scic_sds_unsolicited_frame_control_get_buffer(
+         &(scic_sds_request_get_controller(this_request)->uf_control),
+         frame_index,
+         (void**) &response_buffer
+      );
+
+      scic_word_copy_with_swap(
+         this_request->response_buffer,
+         (U32 *)response_buffer,
+         sizeof(SCI_SSP_RESPONSE_IU_T)
+      );
+
+      response_buffer = (SCI_SSP_RESPONSE_IU_T *)this_request->response_buffer;
+
+      if (
+            (response_buffer->data_present == 0x01)
+         || (response_buffer->data_present == 0x02)
+         )
+      {
+         scic_sds_request_set_status(
+            this_request,
+            SCU_TASK_DONE_CHECK_RESPONSE,
+            SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
+         );
+      }
+      else
+      {
+         scic_sds_request_set_status(
+            this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
+         );
+      }
+
+   }
+   else
+   {
+      // This was not a response frame why did it get forwarded?
+      SCIC_LOG_ERROR((
+         sci_base_object_get_logger(this_request),
+         SCIC_LOG_OBJECT_SSP_IO_REQUEST,
+         "SCIC IO Request 0x%x received unexpected frame %d type 0x%02x\n",
+         this_request, frame_index, frame_header->frame_type
+      ));
+   }
+
+   // In any case we are done with this frame buffer return it to the
+   // controller
+   scic_sds_controller_release_frame(
+      this_request->owning_controller, frame_index
+   );
+
+   return SCI_SUCCESS;
+}
+
+//*****************************************************************************
+//*  COMPLETED STATE HANDLERS
+//*****************************************************************************
+
+
+/**
+ * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T
+ * object receives a scic_sds_request_complete() request.
+ *
+ * This method frees up any io request resources that have been allocated and
+ * transitions the request to its final state.
+ *
+ * @todo Consider stopping the state machine instead of transitioning to the
+ *       final state?
+ *
+ * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
+ *       the SCIC_SDS_IO_REQUEST_T object for which the start operation is
+ *       requested.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS
+ */
+static
+SCI_STATUS scic_sds_request_completed_state_complete_handler(
+   SCI_BASE_REQUEST_T *request
+)
+{
+   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)request;
+
+   if (this_request->was_tag_assigned_by_user != TRUE)
+   {
+      scic_controller_free_io_tag(
+         this_request->owning_controller, this_request->io_tag
+      );
+   }
+
+   if (this_request->saved_rx_frame_index != SCU_INVALID_FRAME_INDEX)
+   {
+      scic_sds_controller_release_frame(
+         this_request->owning_controller, this_request->saved_rx_frame_index);
+   }
+
+   sci_base_state_machine_change_state(
+      &this_request->parent.state_machine,
+      SCI_BASE_REQUEST_STATE_FINAL
+   );
+
+   scic_sds_request_deinitialize_state_logging(this_request);
+
+   return SCI_SUCCESS;
+}
+
+//*****************************************************************************
+//*  ABORTING STATE HANDLERS
+//*****************************************************************************
+
+/**
+ * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T
+ * object receives a scic_sds_request_terminate() request.
+ *
+ * This method is the io request aborting state abort handlers.  On receipt of
+ * a multiple terminate requests the io request will transition to the
+ * completed state.  This should not happen in normal operation.
+ *
+ * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
+ *       the SCIC_SDS_IO_REQUEST_T object for which the start operation is
+ *       requested.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS
+ */
+static
+SCI_STATUS scic_sds_request_aborting_state_abort_handler(
+   SCI_BASE_REQUEST_T *request
+)
+{
+   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)request;
+
+   sci_base_state_machine_change_state(
+      &this_request->parent.state_machine,
+      SCI_BASE_REQUEST_STATE_COMPLETED
+   );
+
+   return SCI_SUCCESS;
+}
+
+/**
+ * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T
+ * object receives a scic_sds_request_task_completion() request.
+ *
+ * This method decodes the completion type waiting for the abort task complete
+ * notification. When the abort task complete is received the io request
+ * transitions to the completed state.
+ *
+ * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
+ *       the SCIC_SDS_IO_REQUEST_T object for which the start operation is
+ *       requested.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS
+ */
+static
+SCI_STATUS scic_sds_request_aborting_state_tc_completion_handler(
+   SCIC_SDS_REQUEST_T * this_request,
+   U32                  completion_code
+)
+{
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_request),
+      SCIC_LOG_OBJECT_TASK_MANAGEMENT,
+      "scic_sds_request_aborting_state_tc_completion_handler(0x%x,0x%x) enter\n",
+      this_request, completion_code
+   ));
+
+   switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
+   {
+   case (SCU_TASK_DONE_GOOD << SCU_COMPLETION_TL_STATUS_SHIFT):
+   case (SCU_TASK_DONE_TASK_ABORT << SCU_COMPLETION_TL_STATUS_SHIFT):
+      scic_sds_request_set_status(
+         this_request, SCU_TASK_DONE_TASK_ABORT, SCI_FAILURE_IO_TERMINATED
+      );
+
+      sci_base_state_machine_change_state(
+         &this_request->parent.state_machine,
+         SCI_BASE_REQUEST_STATE_COMPLETED
+      );
+      break;
+
+   default:
+      // Unless we get some strange error wait for the task abort to complete
+      // TODO: Should there be a state change for this completion?
+      break;
+   }
+
+   return SCI_SUCCESS;
+}
+
+/**
+ * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T
+ * object receives a scic_sds_request_frame_handler() request.
+ *
+ * This method discards the unsolicited frame since we are waiting for the
+ * abort task completion.
+ *
+ * @param[in] request This is the SCI_BASE_REQUEST_T object that is cast to
+ *       the SCIC_SDS_IO_REQUEST_T object for which the start operation is
+ *       requested.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS
+ */
+static
+SCI_STATUS scic_sds_request_aborting_state_frame_handler(
+   SCIC_SDS_REQUEST_T * this_request,
+   U32                  frame_index
+)
+{
+   // TODO: Is it even possible to get an unsolicited frame in the aborting state?
+
+   scic_sds_controller_release_frame(
+      this_request->owning_controller, frame_index);
+
+   return SCI_SUCCESS;
+}
+
+// ---------------------------------------------------------------------------
+
+SCIC_SDS_IO_REQUEST_STATE_HANDLER_T
+   scic_sds_request_state_handler_table[SCI_BASE_REQUEST_MAX_STATES] =
+{
+   // SCI_BASE_REQUEST_STATE_INITIAL
+   {
+      {
+         scic_sds_request_default_start_handler,
+         scic_sds_request_default_abort_handler,
+         scic_sds_request_default_complete_handler,
+         scic_sds_request_default_destruct_handler
+      },
+      scic_sds_request_default_tc_completion_handler,
+      scic_sds_request_default_event_handler,
+      scic_sds_request_default_frame_handler
+   },
+   // SCI_BASE_REQUEST_STATE_CONSTRUCTED
+   {
+      {
+         scic_sds_request_constructed_state_start_handler,
+         scic_sds_request_constructed_state_abort_handler,
+         scic_sds_request_default_complete_handler,
+         scic_sds_request_default_destruct_handler
+      },
+      scic_sds_request_default_tc_completion_handler,
+      scic_sds_request_default_event_handler,
+      scic_sds_request_default_frame_handler
+   },
+   // SCI_BASE_REQUEST_STATE_STARTED
+   {
+      {
+         scic_sds_request_default_start_handler,
+         scic_sds_request_started_state_abort_handler,
+         scic_sds_request_default_complete_handler,
+         scic_sds_request_default_destruct_handler
+      },
+      scic_sds_request_started_state_tc_completion_handler,
+      scic_sds_request_default_event_handler,
+      scic_sds_request_started_state_frame_handler
+   },
+   // SCI_BASE_REQUEST_STATE_COMPLETED
+   {
+      {
+         scic_sds_request_default_start_handler,
+         scic_sds_request_default_abort_handler,
+         scic_sds_request_completed_state_complete_handler,
+         scic_sds_request_default_destruct_handler
+      },
+      scic_sds_request_default_tc_completion_handler,
+      scic_sds_request_default_event_handler,
+      scic_sds_request_default_frame_handler
+   },
+   // SCI_BASE_REQUEST_STATE_ABORTING
+   {
+      {
+         scic_sds_request_default_start_handler,
+         scic_sds_request_aborting_state_abort_handler,
+         scic_sds_request_default_complete_handler,
+         scic_sds_request_default_destruct_handler
+      },
+      scic_sds_request_aborting_state_tc_completion_handler,
+      scic_sds_request_default_event_handler,
+      scic_sds_request_aborting_state_frame_handler,
+   },
+   // SCI_BASE_REQUEST_STATE_FINAL
+   {
+      {
+         scic_sds_request_default_start_handler,
+         scic_sds_request_default_abort_handler,
+         scic_sds_request_default_complete_handler,
+         scic_sds_request_default_destruct_handler
+      },
+      scic_sds_request_default_tc_completion_handler,
+      scic_sds_request_default_event_handler,
+      scic_sds_request_default_frame_handler
+   }
+};
+
+/**
+ * This method implements the actions taken when entering the
+ * SCI_BASE_REQUEST_STATE_INITIAL state. This state is entered when the
+ * initial base request is constructed. Entry into the initial state sets all
+ * handlers for the io request object to their default handlers.
+ *
+ * @param[in] object This parameter specifies the base object for which the
+ *       state transition is occurring.
+ *
+ * @return none
+ */
+static
+void scic_sds_request_initial_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
+
+   SET_STATE_HANDLER(
+      this_request,
+      scic_sds_request_state_handler_table,
+      SCI_BASE_REQUEST_STATE_INITIAL
+   );
+}
+
+/**
+ * This method implements the actions taken when entering the
+ * SCI_BASE_REQUEST_STATE_CONSTRUCTED state.
+ * The method sets the state handlers for the the constructed state.
+ *
+ * @param[in] object The io request object that is to enter the constructed
+ *       state.
+ *
+ * @return none
+ */
+static
+void scic_sds_request_constructed_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
+
+   SET_STATE_HANDLER(
+      this_request,
+      scic_sds_request_state_handler_table,
+      SCI_BASE_REQUEST_STATE_CONSTRUCTED
+   );
+}
+
+/**
+ * This method implements the actions taken when entering the
+ * SCI_BASE_REQUEST_STATE_STARTED state. If the io request object type is a
+ * SCSI Task request we must enter the started substate machine.
+ *
+ * @param[in] object This parameter specifies the base object for which the
+ *       state transition is occuring.  This is cast into a
+ *       SCIC_SDS_IO_REQUEST object.
+ *
+ * @return none
+ */
+static
+void scic_sds_request_started_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
+
+   SET_STATE_HANDLER(
+      this_request,
+      scic_sds_request_state_handler_table,
+      SCI_BASE_REQUEST_STATE_STARTED
+   );
+
+   // Most of the request state machines have a started substate machine so
+   // start its execution on the entry to the started state.
+   if (this_request->has_started_substate_machine == TRUE)
+      sci_base_state_machine_start(&this_request->started_substate_machine);
+}
+
+/**
+ * This method implements the actions taken when exiting the
+ * SCI_BASE_REQUEST_STATE_STARTED state. For task requests the action will be
+ * to stop the started substate machine.
+ *
+ * @param[in] object This parameter specifies the base object for which the
+ *       state transition is occuring.  This object is cast into a
+ *       SCIC_SDS_IO_REQUEST object.
+ *
+ * @return none
+ */
+static
+void scic_sds_request_started_state_exit(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
+
+   if (this_request->has_started_substate_machine == TRUE)
+      sci_base_state_machine_stop(&this_request->started_substate_machine);
+}
+
+/**
+ * This method implements the actions taken when entering the
+ * SCI_BASE_REQUEST_STATE_COMPLETED state.  This state is entered when the
+ * SCIC_SDS_IO_REQUEST has completed.  The method will decode the request
+ * completion status and convert it to an SCI_STATUS to return in the
+ * completion callback function.
+ *
+ * @param[in] object This parameter specifies the base object for which the
+ *       state transition is occuring.  This object is cast into a
+ *       SCIC_SDS_IO_REQUEST object.
+ *
+ * @return none
+ */
+static
+void scic_sds_request_completed_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
+
+   SET_STATE_HANDLER(
+      this_request,
+      scic_sds_request_state_handler_table,
+      SCI_BASE_REQUEST_STATE_COMPLETED
+   );
+
+   // Tell the SCI_USER that the IO request is complete
+   if (this_request->is_task_management_request == FALSE)
+   {
+      scic_cb_io_request_complete(
+         scic_sds_request_get_controller(this_request),
+         scic_sds_request_get_device(this_request),
+         this_request,
+         this_request->sci_status
+      );
+   }
+   else
+   {
+      scic_cb_task_request_complete(
+         scic_sds_request_get_controller(this_request),
+         scic_sds_request_get_device(this_request),
+         this_request,
+         this_request->sci_status
+      );
+   }
+}
+
+/**
+ * This method implements the actions taken when entering the
+ * SCI_BASE_REQUEST_STATE_ABORTING state.
+ *
+ * @param[in] object This parameter specifies the base object for which the
+ *       state transition is occuring.  This object is cast into a
+ *       SCIC_SDS_IO_REQUEST object.
+ *
+ * @return none
+ */
+static
+void scic_sds_request_aborting_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
+
+   // Setting the abort bit in the Task Context is required by the silicon.
+   this_request->task_context_buffer->abort = 1;
+
+   SET_STATE_HANDLER(
+      this_request,
+      scic_sds_request_state_handler_table,
+      SCI_BASE_REQUEST_STATE_ABORTING
+   );
+}
+
+/**
+ * This method implements the actions taken when entering the
+ * SCI_BASE_REQUEST_STATE_FINAL state. The only action required is to put the
+ * state handlers in place.
+ *
+ * @param[in] object This parameter specifies the base object for which the
+ *       state transition is occuring.  This is cast into a
+ *       SCIC_SDS_IO_REQUEST object.
+ *
+ * @return none
+ */
+static
+void scic_sds_request_final_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
+
+   SET_STATE_HANDLER(
+      this_request,
+      scic_sds_request_state_handler_table,
+      SCI_BASE_REQUEST_STATE_FINAL
+   );
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_BASE_STATE_T
+   scic_sds_request_state_table[SCI_BASE_REQUEST_MAX_STATES] =
+{
+   {
+      SCI_BASE_REQUEST_STATE_INITIAL,
+      scic_sds_request_initial_state_enter,
+      NULL
+   },
+   {
+      SCI_BASE_REQUEST_STATE_CONSTRUCTED,
+      scic_sds_request_constructed_state_enter,
+      NULL
+   },
+   {
+      SCI_BASE_REQUEST_STATE_STARTED,
+      scic_sds_request_started_state_enter,
+      scic_sds_request_started_state_exit
+   },
+   {
+      SCI_BASE_REQUEST_STATE_COMPLETED,
+      scic_sds_request_completed_state_enter,
+      NULL
+   },
+   {
+      SCI_BASE_REQUEST_STATE_ABORTING,
+      scic_sds_request_aborting_state_enter,
+      NULL
+   },
+   {
+      SCI_BASE_REQUEST_STATE_FINAL,
+      scic_sds_request_final_state_enter,
+      NULL
+   }
+};
diff --git a/sys/dev/disk/isci/scil/scic_sds_request.h b/sys/dev/disk/isci/scil/scic_sds_request.h
new file mode 100644
index 0000000..4fe040a
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_sds_request.h
@@ -0,0 +1,543 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_sds_request.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIC_SDS_IO_REQUEST_H_
+#define _SCIC_SDS_IO_REQUEST_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains the structures, constants and prototypes for the
+ *        SCIC_SDS_IO_REQUEST object.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/scic_io_request.h>
+
+#include <dev/disk/isci/scil/sci_base_request.h>
+#include <dev/disk/isci/scil/sci_base_state_machine_logger.h>
+#include <dev/disk/isci/scil/scu_task_context.h>
+#include <dev/disk/isci/scil/intel_sas.h>
+
+struct SCIC_SDS_CONTROLLER;
+struct SCIC_SDS_REMOTE_DEVICE;
+struct SCIC_SDS_IO_REQUEST_STATE_HANDLER;
+
+/**
+ * @enum _SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATES
+ *
+ * @brief This enumeration depicts all of the substates for a task
+ *        management request to be performed in the STARTED super-state.
+ */
+typedef enum _SCIC_SDS_RAW_REQUEST_STARTED_TASK_MGMT_SUBSTATES
+{
+   /**
+    * The AWAIT_TC_COMPLETION sub-state indicates that the started raw
+    * task management request is waiting for the transmission of the
+    * initial frame (i.e. command, task, etc.).
+    */
+   SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION,
+
+   /**
+    * This sub-state indicates that the started task management request
+    * is waiting for the reception of an unsolicited frame
+    * (i.e. response IU).
+    */
+   SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE,
+
+   SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_MAX_SUBSTATES
+
+} SCIC_SDS_RAW_REQUEST_STARTED_TASK_MGMT_SUBSTATES;
+
+
+/**
+ * @enum _SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATES
+ *
+ * @brief This enumeration depicts all of the substates for a SMP
+ *        request to be performed in the STARTED super-state.
+ */
+typedef enum _SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATES
+{
+   /**
+    * This sub-state indicates that the started task management request
+    * is waiting for the reception of an unsolicited frame
+    * (i.e. response IU).
+    */
+   SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE,
+
+   /**
+    * The AWAIT_TC_COMPLETION sub-state indicates that the started SMP request is
+    * waiting for the transmission of the initial frame (i.e. command, task, etc.).
+    */
+   SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION,
+
+   SCIC_SDS_SMP_REQUEST_STARTED_MAX_SUBSTATES
+
+} SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATES;
+
+/**
+ * @struct SCIC_SDS_IO_REQUEST
+ *
+ * @brief This structure contains or references all of the data necessary
+ *        to process a task management or normal IO request.
+ */
+typedef struct SCIC_SDS_REQUEST
+{
+   /**
+    * This field indictes the parent object of the request.
+    */
+   SCI_BASE_REQUEST_T parent;
+
+   void *user_request;
+
+   /**
+    * This field simply points to the controller to which this IO request
+    * is associated.
+    */
+   struct SCIC_SDS_CONTROLLER    *owning_controller;
+
+   /**
+    * This field simply points to the remote device to which this IO request
+    * is associated.
+    */
+   struct SCIC_SDS_REMOTE_DEVICE *target_device;
+
+   /**
+    * This field is utilized to determine if the SCI user is managing
+    * the IO tag for this request or if the core is managing it.
+    */
+   BOOL was_tag_assigned_by_user;
+
+   /**
+    * This field indicates the IO tag for this request.  The IO tag is
+    * comprised of the task_index and a sequence count. The sequence count
+    * is utilized to help identify tasks from one life to another.
+    */
+   U16 io_tag;
+
+   /**
+   * This field specifies the sat protocol being utilized for this
+   * IO request, such as SAT_PROTOCOL_PIO_DATA_IN, SAT_PROTOCOL_FPDMA etc.
+   */
+   U8 sat_protocol;
+
+   /**
+    * This field specifies the protocol being utilized for this
+    * IO request.
+    */
+   SCIC_TRANSPORT_PROTOCOL protocol;
+
+   /**
+    * This field indicates the completion status taken from the SCUs
+    * completion code.  It indicates the completion result for the SCU hardware.
+    */
+   U32 scu_status;
+
+   /**
+    * This field indicates the completion status returned to the SCI user.  It
+    * indicates the users view of the io request completion.
+    */
+   U32 sci_status;
+
+   /**
+    * This field contains the value to be utilized when posting (e.g. Post_TC,
+    * Post_TC_Abort) this request to the silicon.
+    */
+   U32 post_context;
+
+   void                   *command_buffer;
+   void                   *response_buffer;
+   SCU_TASK_CONTEXT_T     *task_context_buffer;
+   SCU_SGL_ELEMENT_PAIR_T *sgl_element_pair_buffer;
+
+   /**
+    * This field indicates if this request is a task management request or
+    * normal IO request.
+    */
+   BOOL is_task_management_request;
+
+   /**
+    * This field indicates that this request contains an initialized started
+    * substate machine.
+    */
+   BOOL has_started_substate_machine;
+
+   /**
+    * This field is a pointer to the stored rx frame data.  It is used in STP
+    * internal requests and SMP response frames.  If this field is non-NULL the
+    * saved frame must be released on IO request completion.
+    *
+    * @todo In the future do we want to keep a list of RX frame buffers?
+    */
+   U32 saved_rx_frame_index;
+
+   /**
+    * This field specifies the data necessary to manage the sub-state
+    * machine executed while in the SCI_BASE_REQUEST_STATE_STARTED state.
+    */
+   SCI_BASE_STATE_MACHINE_T started_substate_machine;
+
+   /**
+    * This field specifies the current state handlers in place for this
+    * IO Request object.  This field is updated each time the request
+    * changes state.
+    */
+   struct SCIC_SDS_IO_REQUEST_STATE_HANDLER *state_handlers;
+
+   #ifdef SCI_LOGGING
+   /**
+    * This field is the observer of the started subsate machine
+    */
+   SCI_BASE_STATE_MACHINE_LOGGER_T started_substate_machine_logger;
+   #endif
+
+   /**
+    * This field in the recorded device sequence for the io request.  This is
+    * recorded during the build operation and is compared in the start
+    * operation.  If the sequence is different then there was a change of
+    * devices from the build to start operations.
+    */
+   U8  device_sequence;
+
+} SCIC_SDS_REQUEST_T;
+
+
+typedef SCI_STATUS (*SCIC_SDS_IO_REQUEST_FRAME_HANDLER_T)(
+                         SCIC_SDS_REQUEST_T * this_request,
+                         U32                  frame_index);
+
+typedef SCI_STATUS (*SCIC_SDS_IO_REQUEST_EVENT_HANDLER_T)(
+                         SCIC_SDS_REQUEST_T * this_request,
+                         U32                  event_code);
+
+typedef SCI_STATUS (*SCIC_SDS_IO_REQUEST_TASK_COMPLETION_HANDLER_T)(
+                         SCIC_SDS_REQUEST_T * this_request,
+                         U32                  completion_code);
+
+/**
+ * @struct SCIC_SDS_IO_REQUEST_STATE_HANDLER
+ *
+ * @brief This is the SDS core definition of the state handlers.
+ */
+typedef struct SCIC_SDS_IO_REQUEST_STATE_HANDLER
+{
+   SCI_BASE_REQUEST_STATE_HANDLER_T parent;
+
+   SCIC_SDS_IO_REQUEST_TASK_COMPLETION_HANDLER_T  tc_completion_handler;
+   SCIC_SDS_IO_REQUEST_EVENT_HANDLER_T            event_handler;
+   SCIC_SDS_IO_REQUEST_FRAME_HANDLER_T            frame_handler;
+
+} SCIC_SDS_IO_REQUEST_STATE_HANDLER_T;
+
+extern SCI_BASE_STATE_T scic_sds_request_state_table[];
+extern SCIC_SDS_IO_REQUEST_STATE_HANDLER_T
+       scic_sds_request_state_handler_table[];
+
+extern SCI_BASE_STATE_T scic_sds_io_request_started_task_mgmt_substate_table[];
+extern SCIC_SDS_IO_REQUEST_STATE_HANDLER_T
+       scic_sds_ssp_task_request_started_substate_handler_table[];
+
+extern SCI_BASE_STATE_T scic_sds_smp_request_started_substate_table[];
+extern SCIC_SDS_IO_REQUEST_STATE_HANDLER_T
+       scic_sds_smp_request_started_substate_handler_table[];
+
+/**
+ * This macro returns the maximum number of SGL element paris that we will
+ * support in a single IO request.
+ */
+#define SCU_MAX_SGL_ELEMENT_PAIRS ((SCU_IO_REQUEST_SGE_COUNT + 1) / 2)
+
+/**
+ * This macro will return the controller for this io request object
+ */
+#define scic_sds_request_get_controller(this_request) \
+   ((this_request)->owning_controller)
+
+/**
+ * This macro will return the device for this io request object
+ */
+#define scic_sds_request_get_device(this_request) \
+   ((this_request)->target_device)
+
+/**
+ * This macro will return the port for this io request object
+ */
+#define scic_sds_request_get_port(this_request) \
+   scic_sds_remote_device_get_port(scic_sds_request_get_device(this_request))
+
+/**
+ * This macro returns the constructed post context result for the io
+ * request.
+ */
+#define scic_sds_request_get_post_context(this_request) \
+   ((this_request)->post_context)
+
+/**
+ * This is a helper macro to return the os handle for this request object.
+ */
+#define scic_sds_request_get_task_context(request) \
+   ((request)->task_context_buffer)
+
+#define CACHE_LINE_SIZE (64)
+#define scic_sds_request_align_task_context_buffer(address) \
+   ((SCU_TASK_CONTEXT_T *)( \
+       (((POINTER_UINT)(address)) + (CACHE_LINE_SIZE - 1)) \
+     & ~(CACHE_LINE_SIZE - 1) \
+   ))
+
+/**
+ * This macro will align the memory address so that it is correct for the SCU
+ * hardware to DMA the SGL element pairs.
+ */
+#define scic_sds_request_align_sgl_element_buffer(address) \
+   ((SCU_SGL_ELEMENT_PAIR_T *)( \
+     ((char *)(address)) \
+   + ( \
+         ((~(POINTER_UINT)(address)) + 1) \
+       & (sizeof(SCU_SGL_ELEMENT_PAIR_T) - 1) \
+     ) \
+   ))
+
+/**
+ * This macro will set the scu hardware status and sci request completion
+ * status for an io request.
+ */
+#define scic_sds_request_set_status(request, scu_status_code, sci_status_code) \
+{ \
+   (request)->scu_status = (scu_status_code); \
+   (request)->sci_status = (sci_status_code); \
+}
+
+#define scic_sds_request_complete(a_request) \
+   ((a_request)->state_handlers->parent.complete_handler(&(a_request)->parent))
+
+U32 scic_sds_request_get_min_timer_count(void);
+
+U32 scic_sds_request_get_max_timer_count(void);
+
+
+/**
+ * This macro invokes the core state task completion handler for the
+ * SCIC_SDS_IO_REQUEST_T object.
+ */
+#define scic_sds_io_request_tc_completion(this_request, completion_code) \
+{ \
+   if (this_request->parent.state_machine.current_state_id  \
+          == SCI_BASE_REQUEST_STATE_STARTED \
+       && this_request->has_started_substate_machine \
+          == FALSE) \
+      scic_sds_request_started_state_tc_completion_handler(this_request, completion_code); \
+   else \
+      this_request->state_handlers->tc_completion_handler(this_request, completion_code); \
+}
+
+/**
+ * This macro zeros the hardware SGL element data
+ */
+#define SCU_SGL_ZERO(scu_sge) \
+{ \
+   (scu_sge).length = 0; \
+   (scu_sge).address_lower = 0; \
+   (scu_sge).address_upper = 0; \
+   (scu_sge).address_modifier = 0; \
+}
+
+/**
+ * This macro copys the SGL Element data from the host os to the hardware SGL
+ * elment data
+ */
+#define SCU_SGL_COPY(os_handle, scu_sge, os_sge) \
+{ \
+   (scu_sge).length = \
+      scic_cb_sge_get_length_field(os_handle, os_sge); \
+   (scu_sge).address_upper = \
+      sci_cb_physical_address_upper(scic_cb_sge_get_address_field(os_handle, os_sge)); \
+   (scu_sge).address_lower = \
+      sci_cb_physical_address_lower(scic_cb_sge_get_address_field(os_handle, os_sge)); \
+   (scu_sge).address_modifier = 0; \
+}
+
+//*****************************************************************************
+//* CORE REQUEST PROTOTYPES
+//*****************************************************************************
+
+SCU_SGL_ELEMENT_PAIR_T *scic_sds_request_get_sgl_element_pair(
+   SCIC_SDS_REQUEST_T *this_request,
+   U32                 sgl_pair_index
+);
+
+void scic_sds_request_build_sgl(
+   SCIC_SDS_REQUEST_T *this_request
+);
+
+void scic_sds_ssp_io_request_assign_buffers(
+   SCIC_SDS_REQUEST_T *this_request
+);
+
+void scic_sds_ssp_task_request_assign_buffers(
+   SCIC_SDS_REQUEST_T *this_request
+);
+
+void scic_sds_stp_request_assign_buffers(
+   SCIC_SDS_REQUEST_T * this_request
+);
+
+void scic_sds_smp_request_assign_buffers(
+   SCIC_SDS_REQUEST_T * this_request
+);
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_sds_request_start(
+   SCIC_SDS_REQUEST_T *this_request
+);
+
+SCI_STATUS scic_sds_io_request_terminate(
+   SCIC_SDS_REQUEST_T *this_request
+);
+
+SCI_STATUS scic_sds_io_request_complete(
+   SCIC_SDS_REQUEST_T *this_request
+);
+
+void scic_sds_io_request_copy_response(
+   SCIC_SDS_REQUEST_T *this_request
+);
+
+SCI_STATUS scic_sds_io_request_event_handler(
+   SCIC_SDS_REQUEST_T *this_request,
+   U32                    event_code
+);
+
+SCI_STATUS scic_sds_io_request_frame_handler(
+   SCIC_SDS_REQUEST_T *this_request,
+   U32                    frame_index
+);
+
+SCI_STATUS scic_sds_task_request_complete(
+   SCIC_SDS_REQUEST_T *this_request
+);
+
+SCI_STATUS scic_sds_task_request_terminate(
+   SCIC_SDS_REQUEST_T *this_request
+);
+
+#ifdef SCI_LOGGING
+void scic_sds_request_initialize_state_logging(
+   SCIC_SDS_REQUEST_T *this_request
+);
+
+void scic_sds_request_deinitialize_state_logging(
+   SCIC_SDS_REQUEST_T *this_request
+);
+#else // SCI_LOGGING
+#define scic_sds_request_initialize_state_logging(x)
+#define scic_sds_request_deinitialize_state_logging(x)
+#endif // SCI_LOGGING
+
+//*****************************************************************************
+//* DEFAULT STATE HANDLERS
+//*****************************************************************************
+
+SCI_STATUS scic_sds_request_default_start_handler(
+   SCI_BASE_REQUEST_T *this_request
+);
+
+SCI_STATUS scic_sds_request_default_abort_handler(
+   SCI_BASE_REQUEST_T *this_request
+);
+
+SCI_STATUS scic_sds_request_default_complete_handler(
+   SCI_BASE_REQUEST_T *this_request
+);
+
+SCI_STATUS scic_sds_request_default_destruct_handler(
+   SCI_BASE_REQUEST_T *this_request
+);
+
+SCI_STATUS scic_sds_request_default_tc_completion_handler(
+   SCIC_SDS_REQUEST_T * this_request,
+   U32                  completion_code
+);
+
+SCI_STATUS scic_sds_request_default_event_handler(
+   SCIC_SDS_REQUEST_T * this_request,
+   U32                  event_code
+);
+
+SCI_STATUS scic_sds_request_default_frame_handler(
+   SCIC_SDS_REQUEST_T * this_request,
+   U32                  frame_index
+);
+
+//*****************************************************************************
+//* STARTED STATE HANDLERS
+//*****************************************************************************
+
+SCI_STATUS scic_sds_request_started_state_abort_handler(
+   SCI_BASE_REQUEST_T *this_request
+);
+
+SCI_STATUS scic_sds_request_started_state_tc_completion_handler(
+   SCIC_SDS_REQUEST_T * this_request,
+   U32                  completion_code
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIC_SDS_IO_REQUEST_H_
diff --git a/sys/dev/disk/isci/scil/scic_sds_sgpio.c b/sys/dev/disk/isci/scil/scic_sds_sgpio.c
new file mode 100644
index 0000000..629248c
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_sds_sgpio.c
@@ -0,0 +1,297 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_sds_sgpio.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+* @file
+*
+* @brief This file contains the implementation of the SGPIO register inteface
+*        methods.
+*/
+
+#include <dev/disk/isci/scil/scic_sgpio.h>
+#include <dev/disk/isci/scil/scic_sds_controller_registers.h>
+#include <dev/disk/isci/scil/scic_user_callback.h>
+
+/**
+ * @brief Function writes Value to the
+ *        SGPIO Output Data Select Register (SGODSR) for phys specified by
+ *        phy_mask paremeter
+ *
+ * @param[in] SCIC_SDS_CONTROLLER_T controller
+ * @param[in] phy_mask - This field is a bit mask that specifies the phys
+ *                       to be updated.
+ * @param[in] value - Value for write
+ *
+ * @return none
+ */
+static
+void scic_sgpio_write_SGODSR_register(
+   SCIC_SDS_CONTROLLER_T *controller,
+   U32 phy_mask,
+   U32 value
+)
+{
+   U8 phy_index;
+
+   for (phy_index = 0; phy_index < SCI_MAX_PHYS; phy_index++)
+   {
+      if (phy_mask >> phy_index & 1)
+      {
+          scu_sgpio_peg0_register_write(
+             controller, output_data_select[phy_index], value
+          );
+      }
+   }
+}
+
+void scic_sgpio_set_vendor_code(
+   SCI_CONTROLLER_HANDLE_T controller,
+   U8 vendor_specific_sequence
+)
+{
+   SCIC_SDS_CONTROLLER_T * core_controller = (SCIC_SDS_CONTROLLER_T *) controller;
+
+   scu_sgpio_peg0_register_write(
+      core_controller, vendor_specific_code, vendor_specific_sequence);
+}
+
+void scic_sgpio_set_blink_patterns(
+   SCI_CONTROLLER_HANDLE_T controller,
+   U8 pattern_a_low,
+   U8 pattern_a_high,
+   U8 pattern_b_low,
+   U8 pattern_b_high
+)
+{
+   U32 value;
+   SCIC_SDS_CONTROLLER_T * core_controller = (SCIC_SDS_CONTROLLER_T *) controller;
+
+   value = (pattern_b_high << 12) + (pattern_b_low << 8) + (pattern_a_high << 4) + pattern_a_low;
+
+   scu_sgpio_peg0_register_write(
+      core_controller, blink_rate, value);
+}
+
+void scic_sgpio_set_functionality(
+   SCI_CONTROLLER_HANDLE_T controller,
+   BOOL sgpio_mode
+)
+{
+   U32 value = DISABLE_SGPIO_FUNCTIONALITY;
+   SCIC_SDS_CONTROLLER_T * core_controller = (SCIC_SDS_CONTROLLER_T *) controller;
+
+   if(sgpio_mode)
+   {
+      value = ENABLE_SGPIO_FUNCTIONALITY;
+   }
+
+   scu_sgpio_peg0_register_write(
+      core_controller, interface_control, value);
+}
+
+void scic_sgpio_apply_led_blink_pattern(
+   SCI_CONTROLLER_HANDLE_T controller,
+   U32 phy_mask,
+   BOOL error,
+   BOOL locate,
+   BOOL activity,
+   U8 pattern_selection
+)
+{
+   U32 output_value = 0;
+
+   SCIC_SDS_CONTROLLER_T * core_controller = (SCIC_SDS_CONTROLLER_T *) controller;
+
+   // Start with all LEDs turned off
+   output_value = (SGODSR_INVERT_BIT <<  SGODSR_ERROR_LED_SHIFT)
+                     | (SGODSR_INVERT_BIT <<  SGODSR_LOCATE_LED_SHIFT)
+                     | (SGODSR_INVERT_BIT << SGODSR_ACTIVITY_LED_SHIFT);
+
+   if(error)
+   {  //apply pattern to error LED
+      output_value |= pattern_selection << SGODSR_ERROR_LED_SHIFT;
+      output_value &= ~(SGODSR_INVERT_BIT <<  SGODSR_ERROR_LED_SHIFT);
+   }
+   if(locate)
+   {  //apply pattern to locate LED
+      output_value |= pattern_selection << SGODSR_LOCATE_LED_SHIFT;
+      output_value &= ~(SGODSR_INVERT_BIT <<  SGODSR_LOCATE_LED_SHIFT);
+   }
+   if(activity)
+   {  //apply pattern to activity LED
+      output_value |= pattern_selection << SGODSR_ACTIVITY_LED_SHIFT;
+      output_value &= ~(SGODSR_INVERT_BIT << SGODSR_ACTIVITY_LED_SHIFT);
+   }
+
+   scic_sgpio_write_SGODSR_register(core_controller, phy_mask, output_value);
+}
+
+void scic_sgpio_set_led_blink_pattern(
+   SCI_CONTROLLER_HANDLE_T controller,
+   SCI_PORT_HANDLE_T port_handle,
+   BOOL error,
+   BOOL locate,
+   BOOL activity,
+   U8 pattern_selection
+)
+{
+   U32 phy_mask;
+
+   SCIC_SDS_PORT_T * port = (SCIC_SDS_PORT_T *) port_handle;
+
+   phy_mask = scic_sds_port_get_phys(port);
+
+   scic_sgpio_apply_led_blink_pattern(
+           controller, phy_mask, error, locate, activity, pattern_selection);
+}
+
+void scic_sgpio_update_led_state(
+   SCI_CONTROLLER_HANDLE_T controller,
+   U32 phy_mask,
+   BOOL error,
+   BOOL locate,
+   BOOL activity
+)
+{
+   U32 output_value;
+
+   SCIC_SDS_CONTROLLER_T * core_controller = (SCIC_SDS_CONTROLLER_T *) controller;
+
+   // Start with all LEDs turned on
+   output_value = 0x00000000;
+
+   if(!error)
+   {  //turn off error LED
+      output_value |= SGODSR_INVERT_BIT <<  SGODSR_ERROR_LED_SHIFT;
+   }
+   if(!locate)
+   {  //turn off locate LED
+      output_value |= SGODSR_INVERT_BIT <<  SGODSR_LOCATE_LED_SHIFT;
+   }
+   if(!activity)
+   {  //turn off activity LED
+      output_value |= SGODSR_INVERT_BIT <<  SGODSR_ACTIVITY_LED_SHIFT;
+   }
+
+   scic_sgpio_write_SGODSR_register(core_controller, phy_mask, output_value);
+}
+
+void scic_sgpio_set_led_state(
+   SCI_CONTROLLER_HANDLE_T controller,
+   SCI_PORT_HANDLE_T port_handle,
+   BOOL error,
+   BOOL locate,
+   BOOL activity
+)
+{
+   U32 phy_mask;
+
+   SCIC_SDS_PORT_T * port = (SCIC_SDS_PORT_T *) port_handle;
+
+   phy_mask = scic_sds_port_get_phys(port);
+
+   scic_sgpio_update_led_state(controller, phy_mask, error, locate, activity);
+}
+
+void scic_sgpio_set_to_hardware_control(
+   SCI_CONTROLLER_HANDLE_T controller,
+   BOOL is_hardware_controlled
+)
+{
+   SCIC_SDS_CONTROLLER_T * core_controller = (SCIC_SDS_CONTROLLER_T *) controller;
+   U8 i;
+   U32 output_value;
+
+   //turn on hardware control for LED's
+   if(is_hardware_controlled)
+   {
+      output_value = SGPIO_HARDWARE_CONTROL;
+   }
+   else //turn off hardware control
+   {
+      output_value = SGPIO_SOFTWARE_CONTROL;
+   }
+
+   for(i = 0; i < SCI_MAX_PHYS; i++)
+   {
+      scu_sgpio_peg0_register_write(
+         core_controller, output_data_select[i], output_value);
+   }
+}
+
+U32 scic_sgpio_read(
+   SCI_CONTROLLER_HANDLE_T controller
+)
+{
+   //Not supported in the SCU hardware returning 0xFFFFFFFF
+   return 0xffffffff;
+}
+
+void scic_sgpio_hardware_initialize(
+   SCI_CONTROLLER_HANDLE_T controller
+)
+{
+   scic_sgpio_set_functionality(controller, TRUE);
+   scic_sgpio_set_to_hardware_control(controller, TRUE);
+   scic_sgpio_set_vendor_code(controller, 0x00);
+}
+
+void scic_sgpio_initialize(
+   SCI_CONTROLLER_HANDLE_T controller
+)
+{
+   scic_sgpio_set_functionality(controller, TRUE);
+   scic_sgpio_set_to_hardware_control(controller, FALSE);
+   scic_sgpio_set_vendor_code(controller, 0x00);
+}
diff --git a/sys/dev/disk/isci/scil/scic_sds_smp_remote_device.c b/sys/dev/disk/isci/scil/scic_sds_smp_remote_device.c
new file mode 100644
index 0000000..cee3c24
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_sds_smp_remote_device.c
@@ -0,0 +1,369 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_sds_smp_remote_device.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains This file contains the SMP remote device
+ *        object methods and it's state machines.
+ */
+
+#include <dev/disk/isci/scil/scic_user_callback.h>
+#include <dev/disk/isci/scil/scic_sds_logger.h>
+#include <dev/disk/isci/scil/scic_sds_remote_device.h>
+#include <dev/disk/isci/scil/scic_sds_controller.h>
+#include <dev/disk/isci/scil/scic_sds_port.h>
+#include <dev/disk/isci/scil/scic_sds_request.h>
+#include <dev/disk/isci/scil/scu_event_codes.h>
+#include <dev/disk/isci/scil/scu_task_context.h>
+#include <dev/disk/isci/scil/scic_remote_device.h>
+
+//*****************************************************************************
+//*  SMP REMOTE DEVICE READY IDLE SUBSTATE HANDLERS
+//*****************************************************************************
+
+/**
+ * This method will handle the start io operation for a SMP device that is in
+ * the idle state.
+ *
+ * @param [in] device The device the io is sent to.
+ * @param [in] request The io to start.
+ *
+ * @return SCI_STATUS
+ */
+static
+SCI_STATUS scic_sds_smp_remote_device_ready_idle_substate_start_io_handler(
+   SCI_BASE_REMOTE_DEVICE_T * device,
+   SCI_BASE_REQUEST_T       * request
+)
+{
+   SCI_STATUS status;
+   SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
+   SCIC_SDS_REQUEST_T       * io_request  = (SCIC_SDS_REQUEST_T       *)request;
+
+   // Will the port allow the io request to start?
+   status = this_device->owning_port->state_handlers->start_io_handler(
+      this_device->owning_port,
+      this_device,
+      io_request
+   );
+
+   if (status == SCI_SUCCESS)
+   {
+      status =
+         scic_sds_remote_node_context_start_io(this_device->rnc, io_request);
+
+      if (status == SCI_SUCCESS)
+      {
+         status = scic_sds_request_start(io_request);
+      }
+
+      if (status == SCI_SUCCESS)
+      {
+         this_device->working_request = io_request;
+
+         sci_base_state_machine_change_state(
+               &this_device->ready_substate_machine,
+               SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD
+         );
+      }
+
+      scic_sds_remote_device_start_request(this_device, io_request, status);
+   }
+
+   return status;
+}
+
+
+//******************************************************************************
+//* SMP REMOTE DEVICE READY SUBSTATE CMD HANDLERS
+//******************************************************************************
+/**
+ * This device is already handling a command it can not accept new commands
+ * until this one is complete.
+ *
+ * @param[in] device This is the device object that is receiving the IO.
+ *
+ * @param[in] request The io to start.
+ *
+ * @return SCI_STATUS
+ */
+static
+SCI_STATUS scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler(
+   SCI_BASE_REMOTE_DEVICE_T * device,
+   SCI_BASE_REQUEST_T       * request
+)
+{
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+
+/**
+ * @brief this is the complete_io_handler for smp device at ready cmd substate.
+ *
+ * @param[in] device This is the device object that is receiving the IO.
+ * @param[in] request The io to start.
+ *
+ * @return SCI_STATUS
+ */
+static
+SCI_STATUS scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler(
+   SCI_BASE_REMOTE_DEVICE_T * device,
+   SCI_BASE_REQUEST_T       * request
+)
+{
+   SCI_STATUS                 status;
+   SCIC_SDS_REMOTE_DEVICE_T * this_device;
+   SCIC_SDS_REQUEST_T       * the_request;
+
+   this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
+   the_request = (SCIC_SDS_REQUEST_T       *)request;
+
+   status = scic_sds_io_request_complete(the_request);
+
+   if (status == SCI_SUCCESS)
+   {
+      status = scic_sds_port_complete_io(
+         this_device->owning_port, this_device, the_request);
+
+      if (status == SCI_SUCCESS)
+      {
+       scic_sds_remote_device_decrement_request_count(this_device);
+         sci_base_state_machine_change_state(
+            &this_device->ready_substate_machine,
+            SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
+         );
+      }
+      else
+      {
+         SCIC_LOG_ERROR((
+            sci_base_object_get_logger(this_device),
+            SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
+            "SCIC SDS Remote Device 0x%x io request 0x%x could not be completd on the port 0x%x failed with status %d.\n",
+            this_device, the_request, this_device->owning_port, status
+         ));
+      }
+   }
+
+   return status;
+}
+
+/**
+ * @brief This is frame handler for smp device ready cmd substate.
+ *
+ * @param[in] this_device This is the device object that is receiving the frame.
+ * @param[in] frame_index The index for the frame received.
+ *
+ * @return SCI_STATUS
+ */
+static
+SCI_STATUS scic_sds_smp_remote_device_ready_cmd_substate_frame_handler(
+   SCIC_SDS_REMOTE_DEVICE_T * this_device,
+   U32                        frame_index
+)
+{
+   SCI_STATUS status;
+
+   /// The device does not process any UF received from the hardware while
+   /// in this state.  All unsolicited frames are forwarded to the io request
+   /// object.
+   status = scic_sds_io_request_frame_handler(
+      this_device->working_request,
+      frame_index
+   );
+
+   return status;
+}
+
+// ---------------------------------------------------------------------------
+
+SCIC_SDS_REMOTE_DEVICE_STATE_HANDLER_T
+   scic_sds_smp_remote_device_ready_substate_handler_table[
+                              SCIC_SDS_SMP_REMOTE_DEVICE_READY_MAX_SUBSTATES] =
+{
+   // SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
+   {
+      {
+         scic_sds_remote_device_default_start_handler,
+         scic_sds_remote_device_ready_state_stop_handler,
+         scic_sds_remote_device_default_fail_handler,
+         scic_sds_remote_device_default_destruct_handler,
+         scic_sds_remote_device_default_reset_handler,
+         scic_sds_remote_device_default_reset_complete_handler,
+         scic_sds_smp_remote_device_ready_idle_substate_start_io_handler,
+         scic_sds_remote_device_default_complete_request_handler,
+         scic_sds_remote_device_default_continue_request_handler,
+         scic_sds_remote_device_default_start_request_handler,
+         scic_sds_remote_device_default_complete_request_handler
+      },
+      scic_sds_remote_device_default_suspend_handler,
+      scic_sds_remote_device_default_resume_handler,
+      scic_sds_remote_device_general_event_handler,
+      scic_sds_remote_device_default_frame_handler
+   },
+   // SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD
+   {
+      {
+         scic_sds_remote_device_default_start_handler,
+         scic_sds_remote_device_ready_state_stop_handler,
+         scic_sds_remote_device_default_fail_handler,
+         scic_sds_remote_device_default_destruct_handler,
+         scic_sds_remote_device_default_reset_handler,
+         scic_sds_remote_device_default_reset_complete_handler,
+         scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler,
+         scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler,
+         scic_sds_remote_device_default_continue_request_handler,
+         scic_sds_remote_device_default_start_request_handler,
+         scic_sds_remote_device_default_complete_request_handler
+      },
+      scic_sds_remote_device_default_suspend_handler,
+      scic_sds_remote_device_default_resume_handler,
+      scic_sds_remote_device_general_event_handler,
+      scic_sds_smp_remote_device_ready_cmd_substate_frame_handler
+   }
+};
+
+/**
+ * This is the SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE enter method. This
+ * method sets the ready cmd substate handlers and reports the device as ready.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast into a
+ *       SCIC_SDS_REMOTE_DEVICE.
+ *
+ * @return none
+ */
+static
+void scic_sds_smp_remote_device_ready_idle_substate_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object;
+
+   SET_STATE_HANDLER(
+      this_device,
+      scic_sds_smp_remote_device_ready_substate_handler_table,
+      SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
+   );
+
+   scic_cb_remote_device_ready(
+      scic_sds_remote_device_get_controller(this_device), this_device);
+}
+
+/**
+ * This is the SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD enter method. This
+ * method sets the remote device objects ready cmd substate handlers, and notify
+ * core user that the device is not ready.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast into a
+ *       SCIC_SDS_REMOTE_DEVICE.
+ *
+ * @return none
+ */
+static
+void scic_sds_smp_remote_device_ready_cmd_substate_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object;
+
+   ASSERT(this_device->working_request != NULL);
+
+   SET_STATE_HANDLER(
+      this_device,
+      scic_sds_smp_remote_device_ready_substate_handler_table,
+      SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD
+   );
+
+   scic_cb_remote_device_not_ready(
+      scic_sds_remote_device_get_controller(this_device),
+      this_device,
+      SCIC_REMOTE_DEVICE_NOT_READY_SMP_REQUEST_STARTED
+   );
+}
+
+/**
+ * This is the SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_CMD exit method.
+ *
+ * @param[in] object This is the SCI_BASE_OBJECT which is cast into a
+ *       SCIC_SDS_REMOTE_DEVICE.
+ *
+ * @return none
+ */
+static
+void scic_sds_smp_remote_device_ready_cmd_substate_exit(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object;
+
+   this_device->working_request = NULL;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_BASE_STATE_T
+   scic_sds_smp_remote_device_ready_substate_table[
+                     SCIC_SDS_SMP_REMOTE_DEVICE_READY_MAX_SUBSTATES] =
+{
+   {
+      SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE,
+      scic_sds_smp_remote_device_ready_idle_substate_enter,
+      NULL
+   },
+   {
+      SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD,
+      scic_sds_smp_remote_device_ready_cmd_substate_enter,
+      scic_sds_smp_remote_device_ready_cmd_substate_exit
+   }
+};
diff --git a/sys/dev/disk/isci/scil/scic_sds_smp_request.c b/sys/dev/disk/isci/scil/scic_sds_smp_request.c
new file mode 100644
index 0000000..9e93498
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_sds_smp_request.c
@@ -0,0 +1,869 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_sds_smp_request.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+#include <dev/disk/isci/scil/scic_sds_smp_request.h>
+#include <dev/disk/isci/scil/scic_sds_logger.h>
+#include <dev/disk/isci/scil/scic_sds_controller.h>
+#include <dev/disk/isci/scil/scic_sds_remote_device.h>
+#include <dev/disk/isci/scil/scic_remote_device.h>
+#include <dev/disk/isci/scil/sci_util.h>
+#include <dev/disk/isci/sci_environment.h>
+#include <dev/disk/isci/scil/intel_sas.h>
+#include <dev/disk/isci/scil/scic_sds_request.h>
+#include <dev/disk/isci/scil/scic_controller.h>
+#include <dev/disk/isci/scil/scu_completion_codes.h>
+#include <dev/disk/isci/scil/scu_task_context.h>
+#include <dev/disk/isci/scil/sci_base_state_machine.h>
+
+/**
+ * This method return the memory space required for STP PIO requests.
+ *
+ * @return U32
+ */
+U32 scic_sds_smp_request_get_object_size(void)
+{
+   return   sizeof(SCIC_SDS_REQUEST_T)
+          + sizeof(SMP_REQUEST_T)
+          + sizeof(U32)
+          + sizeof(SMP_RESPONSE_T)
+          + sizeof(U32)
+          + sizeof(SCU_TASK_CONTEXT_T)
+          + CACHE_LINE_SIZE;
+}
+
+/**
+ * This macro returns the address of the smp command buffer in the smp request
+ * memory. No need to cast to SMP request type.
+ */
+#define scic_sds_smp_request_get_command_buffer_unaligned(memory) \
+   ( ((char *)(memory)) + sizeof(SCIC_SDS_REQUEST_T) )
+
+/**
+ * This macro aligns the smp command buffer in DWORD alignment
+*/
+#define scic_sds_smp_request_align_command_buffer(address) \
+   ((char *)( \
+      (((POINTER_UINT)(address)) + (sizeof(U32) - 1)) \
+         & ~(sizeof(U32)- 1) \
+   ))
+
+/**
+ * This macro returns the DWORD-aligned smp command buffer
+*/
+#define scic_sds_smp_request_get_command_buffer(memory) \
+   ((char *)  \
+      ((char *)scic_sds_smp_request_align_command_buffer( \
+         (char *) scic_sds_smp_request_get_command_buffer_unaligned(memory) \
+   )))
+
+/**
+ * This macro returns the address of the smp response buffer in the smp request
+ * memory.
+ */
+#define scic_sds_smp_request_get_response_buffer_unaligned(memory) \
+   ( ((char *)(scic_sds_smp_request_get_command_buffer(memory))) \
+      + sizeof(SMP_REQUEST_T) )
+
+/**
+ * This macro aligns the smp command buffer in DWORD alignment
+*/
+#define scic_sds_smp_request_align_response_buffer(address) \
+   ((char *)( \
+      (((POINTER_UINT)(address)) + (sizeof(U32) - 1)) \
+         & ~(sizeof(U32)- 1) \
+   ))
+
+/**
+ * This macro returns the DWORD-aligned smp resposne buffer
+*/
+#define scic_sds_smp_request_get_response_buffer(memory) \
+   ((char *)  \
+      ((char *)scic_sds_smp_request_align_response_buffer( \
+         (char *) scic_sds_smp_request_get_response_buffer_unaligned(memory) \
+   )))
+
+/**
+ * This macro returs the task context buffer for the SMP request.
+ */
+#define scic_sds_smp_request_get_task_context_buffer_unaligned(memory) \
+   ((SCU_TASK_CONTEXT_T *)( \
+        ((char *)(scic_sds_smp_request_get_response_buffer(memory))) \
+      + sizeof(SMP_RESPONSE_T) \
+   ))
+
+/**
+ * This macro returns the dword-aligned smp task context buffer
+ */
+#define scic_sds_smp_request_get_task_context_buffer(memory) \
+   ((SCU_TASK_CONTEXT_T *)( \
+      ((char *)scic_sds_request_align_task_context_buffer( \
+         (char *)scic_sds_smp_request_get_task_context_buffer_unaligned(memory)) \
+   )))
+
+/**
+ * @brief This method build the remainder of the IO request object.
+ *
+ * @pre The scic_sds_general_request_construct() must be called before this
+ *      call is valid.
+ *
+ * @param[in] this_request This parameter specifies the request object being
+ *            constructed.
+ *
+ * @return none
+ */
+
+void scic_sds_smp_request_assign_buffers(
+   SCIC_SDS_REQUEST_T *this_request
+)
+{
+   // Assign all of the buffer pointers
+   this_request->command_buffer =
+      scic_sds_smp_request_get_command_buffer(this_request);
+   this_request->response_buffer =
+      scic_sds_smp_request_get_response_buffer(this_request);
+   this_request->sgl_element_pair_buffer = NULL;
+
+   if (this_request->was_tag_assigned_by_user == FALSE)
+   {
+      this_request->task_context_buffer =
+         scic_sds_smp_request_get_task_context_buffer(this_request);
+   }
+
+}
+/**
+ * @brief This method is called by the SCI user to build an SMP
+ *        IO request.
+ *
+ * @pre
+ *        - The user must have previously called scic_io_request_construct()
+ *          on the supplied IO request.
+ *
+ * @param[in]  scic_io_request This parameter specifies the handle to the
+ *             io request object to be built.
+ *
+ * @return Indicate if the controller successfully built the IO request.
+ * @retval SCI_SUCCESS This value is returned if the IO request was
+ *         successfully built.
+ * @retval SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned if the
+ *         remote_device does not support the SMP protocol.
+ * @retval SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the
+ *         user did not properly set the association between the SCIC IO
+ *         request and the user's IO request.  Please refer to the
+ *         sci_object_set_association() routine for more
+ *         information.
+ */
+SCI_STATUS scic_io_request_construct_smp(
+   SCI_IO_REQUEST_HANDLE_T  scic_smp_request
+)
+{
+   SMP_REQUEST_T smp_request;
+
+   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *) scic_smp_request;
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_request),
+      SCIC_LOG_OBJECT_SMP_IO_REQUEST,
+      "scic_io_request_construct_smp(0x%x) enter\n",
+      this_request
+   ));
+
+   this_request->protocol                     = SCIC_SMP_PROTOCOL;
+   this_request->has_started_substate_machine = TRUE;
+
+   // Construct the started sub-state machine.
+   sci_base_state_machine_construct(
+      &this_request->started_substate_machine,
+      &this_request->parent.parent,
+      scic_sds_smp_request_started_substate_table,
+      SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE
+   );
+
+   // Construct the SMP SCU Task Context
+   memcpy((char *)&smp_request,
+        this_request->command_buffer,
+        sizeof(SMP_REQUEST_T));
+
+   // Look at the SMP requests' header fields; for certain SAS 1.x SMP
+   // functions under SAS 2.0, a zero request length really indicates
+   // a non-zero default length.
+   if( smp_request.header.request_length == 0 )
+   {
+       switch( smp_request.header.function )
+       {
+       case SMP_FUNCTION_DISCOVER:
+       case SMP_FUNCTION_REPORT_PHY_ERROR_LOG:
+       case SMP_FUNCTION_REPORT_PHY_SATA:
+       case SMP_FUNCTION_REPORT_ROUTE_INFORMATION:
+           smp_request.header.request_length = 2;
+           break;
+       case SMP_FUNCTION_CONFIGURE_ROUTE_INFORMATION:
+       case SMP_FUNCTION_PHY_CONTROL:
+       case SMP_FUNCTION_PHY_TEST:
+           smp_request.header.request_length = 9;
+           break;
+       // Default - zero is a valid default for 2.0.
+       }
+   }
+
+   scu_smp_request_construct_task_context(
+      this_request,
+      &smp_request
+   );
+
+   sci_base_state_machine_change_state(
+      &this_request->parent.state_machine,
+      SCI_BASE_REQUEST_STATE_CONSTRUCTED
+   );
+
+   return SCI_SUCCESS;
+}
+
+/**
+ * @brief This method is called by the SCI user to build an SMP pass-through
+ *        IO request.
+ *
+ * @pre
+ *        - The user must have previously called scic_io_request_construct()
+ *          on the supplied IO request.
+ *
+ * @param[in]  scic_smp_request This parameter specifies the handle to the
+ *             io request object to be built.
+ *
+ * @param[in]  passthru_cb This parameter specifies the pointer to the callback
+ *             structure that contains the function pointers
+ *
+ * @return Indicate if the controller successfully built the IO request.
+ */
+SCI_STATUS scic_io_request_construct_smp_pass_through(
+   SCI_IO_REQUEST_HANDLE_T  scic_smp_request,
+   SCIC_SMP_PASSTHRU_REQUEST_CALLBACKS_T *passthru_cb
+)
+{
+   SMP_REQUEST_T smp_request;
+   U8 * request_buffer;
+   U32 request_buffer_length_in_bytes;
+
+   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *) scic_smp_request;
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_request),
+      SCIC_LOG_OBJECT_SMP_IO_REQUEST,
+      "scic_io_request_construct_smp_pass_through(0x%x) enter\n",
+      this_request
+   ));
+
+   this_request->protocol                     = SCIC_SMP_PROTOCOL;
+   this_request->has_started_substate_machine = TRUE;
+
+   // Call the callback function to retrieve the SMP passthrough request
+   request_buffer_length_in_bytes = passthru_cb->scic_cb_smp_passthru_get_request (
+                                       (void *)this_request,
+                                       &request_buffer
+                                    );
+
+   //copy the request to smp request
+   memcpy((char *)&smp_request.request.vendor_specific_request,
+        request_buffer,
+        request_buffer_length_in_bytes);
+
+   //the header length in smp_request is in dwords - the sas spec has similar way,
+   //but the csmi header contains the number of bytes, so we need to convert the
+   //number of bytes to number of dwords
+   smp_request.header.request_length = (U8) (request_buffer_length_in_bytes / sizeof (U32));
+
+   //Grab the other needed fields from the smp request using callbacks
+   smp_request.header.smp_frame_type = passthru_cb->scic_cb_smp_passthru_get_frame_type ((void *)this_request);
+   smp_request.header.function = passthru_cb->scic_cb_smp_passthru_get_function ((void *)this_request);
+   smp_request.header.allocated_response_length = passthru_cb->scic_cb_smp_passthru_get_allocated_response_length((void *)this_request);
+
+   // Construct the started sub-state machine.
+   sci_base_state_machine_construct(
+      &this_request->started_substate_machine,
+      &this_request->parent.parent,
+      scic_sds_smp_request_started_substate_table,
+      SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE
+   );
+
+   // Construct the SMP SCU Task Context
+   scu_smp_request_construct_task_context (this_request, &smp_request);
+
+   sci_base_state_machine_change_state(
+      &this_request->parent.state_machine,
+      SCI_BASE_REQUEST_STATE_CONSTRUCTED
+   );
+
+   return SCI_SUCCESS;
+}
+
+/**
+ * @brief This method will fill in the SCU Task Context for a SMP request. The
+ *        following important settings are utilized:
+ *
+ *          -# task_type == SCU_TASK_TYPE_SMP.  This simply indicates
+ *             that a normal request type (i.e. non-raw frame) is being
+ *             utilized to perform task management.
+ *          -# control_frame == 1.  This ensures that the proper endianess
+ *             is set so that the bytes are transmitted in the right order
+ *             for a smp request frame.
+ *
+ * @param[in] this_request This parameter specifies the smp request object
+ *            being constructed.
+ *
+ * @return none
+ */
+void scu_smp_request_construct_task_context(
+   SCIC_SDS_REQUEST_T *this_request,
+   SMP_REQUEST_T      *smp_request
+)
+{
+   SCI_PHYSICAL_ADDRESS      physical_address;
+   SCIC_SDS_CONTROLLER_T    *owning_controller;
+   SCIC_SDS_REMOTE_DEVICE_T *target_device;
+   SCIC_SDS_PORT_T          *target_port;
+   SCU_TASK_CONTEXT_T *task_context;
+
+   //byte swap the smp request.
+   scic_word_copy_with_swap(
+      this_request->command_buffer,
+      (U32*) smp_request,
+      sizeof(SMP_REQUEST_T)/sizeof(U32)
+   );
+
+   task_context = scic_sds_request_get_task_context(this_request);
+
+   owning_controller = scic_sds_request_get_controller(this_request);
+   target_device = scic_sds_request_get_device(this_request);
+   target_port = scic_sds_request_get_port(this_request);
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_request),
+      SCIC_LOG_OBJECT_SMP_IO_REQUEST,
+      "scu_smp_request_construct_task_context(0x%x) contents\n"
+      "   reqlen=%x; function=%x;\n",
+      this_request,
+      smp_request->header.request_length,
+      smp_request->header.function
+   ));
+
+   // Fill in the TC with the its required data
+   // 00h
+   task_context->priority = 0;
+   task_context->initiator_request = 1;
+   task_context->connection_rate =
+      scic_remote_device_get_connection_rate(target_device);
+   task_context->protocol_engine_index =
+      scic_sds_controller_get_protocol_engine_group(owning_controller);
+   task_context->logical_port_index =
+      scic_sds_port_get_index(target_port);
+   task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SMP;
+   task_context->abort = 0;
+   task_context->valid = SCU_TASK_CONTEXT_VALID;
+   task_context->context_type = SCU_TASK_CONTEXT_TYPE;
+
+   //04h
+   task_context->remote_node_index = this_request->target_device->rnc->remote_node_index;
+   task_context->command_code = 0;
+   task_context->task_type = SCU_TASK_TYPE_SMP_REQUEST;
+
+   //08h
+   task_context->link_layer_control = 0;
+   task_context->do_not_dma_ssp_good_response = 1;
+   task_context->strict_ordering = 0;
+   task_context->control_frame = 1;
+   task_context->timeout_enable = 0;
+   task_context->block_guard_enable = 0;
+
+   //0ch
+   task_context->address_modifier = 0;
+
+   //10h
+   task_context->ssp_command_iu_length = smp_request->header.request_length;
+
+   //14h
+   task_context->transfer_length_bytes = 0;
+
+   //18h ~ 30h, protocol specific
+   // since commandIU has been build by framework at this point, we just
+   // copy the frist DWord from command IU to this location.
+   memcpy((void *)(&task_context->type.smp), this_request->command_buffer, sizeof(U32) );
+
+   //40h
+   // "For SMP you could program it to zero. We would prefer that way so that
+   // done code will be consistent." - Venki
+   task_context->task_phase = 0;
+
+   if (this_request->was_tag_assigned_by_user)
+   {
+      // Build the task context now since we have already read the data
+      this_request->post_context = (
+           SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC
+         | (
+                scic_sds_controller_get_protocol_engine_group(owning_controller)
+             << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT
+           )
+         | (
+                 scic_sds_port_get_index(target_port)
+              << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT
+           )
+         | scic_sds_io_tag_get_index(this_request->io_tag)
+      );
+   }
+   else
+   {
+      // Build the task context now since we have already read the data
+      this_request->post_context = (
+           SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC
+         | (
+               scic_sds_controller_get_protocol_engine_group(owning_controller)
+            << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT
+           )
+         | (
+                scic_sds_port_get_index(target_port)
+             << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT
+           )
+         // This is not assigned because we have to wait until we get a TCi
+      );
+   }
+
+   // Copy the physical address for the command buffer to the SCU Task Context
+   // command buffer should not contain command header.
+   scic_cb_io_request_get_physical_address(
+         scic_sds_request_get_controller(this_request),
+         this_request,
+         ((char *)(this_request->command_buffer) + sizeof(U32)),
+         &physical_address
+      );
+
+   task_context->command_iu_upper =
+      sci_cb_physical_address_upper(physical_address);
+   task_context->command_iu_lower =
+      sci_cb_physical_address_lower(physical_address);
+
+
+   //SMP response comes as UF, so no need to set response IU address.
+   task_context->response_iu_upper = 0;
+   task_context->response_iu_lower = 0;
+}
+
+//******************************************************************************
+//* SMP REQUEST STATE MACHINE
+//******************************************************************************
+
+/**
+ * @brief This method processes an unsolicited frame while the SMP request is
+ *        waiting for a response frame.  It will copy the response data, release
+ *        the unsolicited frame, and transition the request to the
+ *        SCI_BASE_REQUEST_STATE_COMPLETED state.
+ *
+ * @param[in] this_request This parameter specifies the request for which
+ *            the unsolicited frame was received.
+ * @param[in] frame_index This parameter indicates the unsolicited frame
+ *            index that should contain the response.
+ *
+ * @return This method returns an indication of whether the response
+ *         frame was handled successfully or not.
+ * @retval SCI_SUCCESS Currently this value is always returned and indicates
+ *         successful processing of the TC response.
+ */
+static
+SCI_STATUS scic_sds_smp_request_await_response_frame_handler(
+   SCIC_SDS_REQUEST_T * this_request,
+   U32                  frame_index
+)
+{
+   SCI_STATUS              status;
+   void                  * frame_header;
+   SMP_RESPONSE_HEADER_T * this_frame_header;
+   U8                    * user_smp_buffer = this_request->response_buffer;
+
+   // Save off the controller, so that we do not touch the request after it
+   //  is completed.
+   SCIC_SDS_CONTROLLER_T * controller = scic_sds_request_get_controller(this_request);
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_request),
+      SCIC_LOG_OBJECT_SMP_IO_REQUEST,
+      "scic_sds_smp_request_await_response_frame_handler(0x%x, 0x%x) enter\n",
+      this_request, frame_index
+   ));
+
+   status = scic_sds_unsolicited_frame_control_get_header(
+      &(controller->uf_control),
+      frame_index,
+      &frame_header
+   );
+
+   //byte swap the header.
+   scic_word_copy_with_swap(
+      (U32*) user_smp_buffer,
+      frame_header,
+      sizeof(SMP_RESPONSE_HEADER_T)/sizeof(U32)
+   );
+   this_frame_header = (SMP_RESPONSE_HEADER_T*) user_smp_buffer;
+
+   if (this_frame_header->smp_frame_type == SMP_FRAME_TYPE_RESPONSE)
+   {
+      void * smp_response_buffer;
+
+      status = scic_sds_unsolicited_frame_control_get_buffer(
+         &(controller->uf_control),
+         frame_index,
+         &smp_response_buffer
+      );
+
+      scic_word_copy_with_swap(
+         (U32*) (user_smp_buffer + sizeof(SMP_RESPONSE_HEADER_T)),
+         smp_response_buffer,
+         sizeof(SMP_RESPONSE_BODY_T)/sizeof(U32)
+      );
+      if (this_frame_header->function == SMP_FUNCTION_DISCOVER)
+      {
+          SMP_RESPONSE_T * this_smp_response;
+
+          this_smp_response = (SMP_RESPONSE_T *)user_smp_buffer;
+
+          // Some expanders only report an attached SATA device, and
+          // not an STP target.  Since the core depends on the STP
+          // target attribute to correctly build I/O, set the bit now
+          // if necessary.
+          if (this_smp_response->response.discover.protocols.u.bits.attached_sata_device
+           && !this_smp_response->response.discover.protocols.u.bits.attached_stp_target)
+          {
+              this_smp_response->response.discover.protocols.u.bits.attached_stp_target = 1;
+
+              SCIC_LOG_TRACE((
+                  sci_base_object_get_logger(this_request),
+                 SCIC_LOG_OBJECT_SMP_IO_REQUEST,
+                 "scic_sds_smp_request_await_response_frame_handler(0x%x) Found SATA dev, setting STP bit.\n",
+                 this_request
+              ));
+          }
+      }
+
+     //Don't need to copy to user space. User instead will refer to
+     //core request's response buffer.
+
+     //copy the smp response to framework smp request's response buffer.
+     //scic_sds_smp_request_copy_response(this_request);
+
+      scic_sds_request_set_status(
+         this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
+      );
+
+      sci_base_state_machine_change_state(
+         &this_request->started_substate_machine,
+         SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION
+      );
+   }
+   else
+   {
+      // This was not a response frame why did it get forwarded?
+      SCIC_LOG_ERROR((
+         sci_base_object_get_logger(this_request),
+         SCIC_LOG_OBJECT_SMP_IO_REQUEST,
+         "SCIC SMP Request 0x%08x received unexpected frame %d type 0x%02x\n",
+         this_request, frame_index, this_frame_header->smp_frame_type
+      ));
+
+     scic_sds_request_set_status(
+        this_request,
+        SCU_TASK_DONE_SMP_FRM_TYPE_ERR,
+        SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
+     );
+
+     sci_base_state_machine_change_state(
+         &this_request->parent.state_machine,
+         SCI_BASE_REQUEST_STATE_COMPLETED
+      );
+   }
+
+   scic_sds_controller_release_frame(
+      controller, frame_index
+   );
+
+   return SCI_SUCCESS;
+}
+
+
+/**
+ * @brief This method processes an abnormal TC completion while the SMP
+ *        request is waiting for a response frame.  It decides what
+ *        happened to the IO based on TC completion status.
+ *
+ * @param[in] this_request This parameter specifies the request for which
+ *            the TC completion was received.
+ * @param[in] completion_code This parameter indicates the completion status
+ *            information for the TC.
+ *
+ * @return Indicate if the tc completion handler was successful.
+ * @retval SCI_SUCCESS currently this method always returns success.
+ */
+static
+SCI_STATUS scic_sds_smp_request_await_response_tc_completion_handler(
+   SCIC_SDS_REQUEST_T * this_request,
+   U32                  completion_code
+)
+{
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_request),
+      SCIC_LOG_OBJECT_SMP_IO_REQUEST,
+      "scic_sds_smp_request_await_response_tc_completion_handler(0x%x, 0x%x) enter\n",
+      this_request, completion_code
+   ));
+
+   switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
+   {
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
+      //In the AWAIT RESPONSE state, any TC completion is unexpected.
+      //but if the TC has success status, we complete the IO anyway.
+      scic_sds_request_set_status(
+         this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
+      );
+
+      sci_base_state_machine_change_state(
+         &this_request->parent.state_machine,
+         SCI_BASE_REQUEST_STATE_COMPLETED
+      );
+   break;
+
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_RESP_TO_ERR):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_UFI_ERR):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_FRM_TYPE_ERR):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_LL_RX_ERR):
+      //These status has been seen in a specific LSI expander, which sometimes
+      //is not able to send smp response within 2 ms. This causes our hardware
+      //break the connection and set TC completion with one of these SMP_XXX_XX_ERR
+      //status. For these type of error, we ask scic user to retry the request.
+      scic_sds_request_set_status(
+         this_request, SCU_TASK_DONE_SMP_RESP_TO_ERR, SCI_FAILURE_RETRY_REQUIRED
+      );
+
+      sci_base_state_machine_change_state(
+         &this_request->parent.state_machine,
+         SCI_BASE_REQUEST_STATE_COMPLETED
+      );
+   break;
+
+   default:
+      // All other completion status cause the IO to be complete.  If a NAK
+      // was received, then it is up to the user to retry the request.
+      scic_sds_request_set_status(
+         this_request,
+         SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
+         SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
+      );
+
+      sci_base_state_machine_change_state(
+         &this_request->parent.state_machine,
+         SCI_BASE_REQUEST_STATE_COMPLETED
+      );
+   break;
+   }
+
+   return SCI_SUCCESS;
+}
+
+
+/**
+ * @brief This method processes the completions transport layer (TL) status
+ *        to determine if the SMP request was sent successfully. If the SMP
+ *        request was sent successfully, then the state for the SMP request
+ *        transits to waiting for a response frame.
+ *
+ * @param[in] this_request This parameter specifies the request for which
+ *            the TC completion was received.
+ * @param[in] completion_code This parameter indicates the completion status
+ *            information for the TC.
+ *
+ * @return Indicate if the tc completion handler was successful.
+ * @retval SCI_SUCCESS currently this method always returns success.
+ */
+static
+SCI_STATUS scic_sds_smp_request_await_tc_completion_tc_completion_handler(
+   SCIC_SDS_REQUEST_T * this_request,
+   U32                  completion_code
+)
+{
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_request),
+      SCIC_LOG_OBJECT_SMP_IO_REQUEST,
+      "scic_sds_smp_request_await_tc_completion_tc_completion_handler(0x%x, 0x%x) enter\n",
+      this_request, completion_code
+   ));
+
+   switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
+   {
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
+      scic_sds_request_set_status(
+         this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
+      );
+
+      sci_base_state_machine_change_state(
+         &this_request->parent.state_machine,
+         SCI_BASE_REQUEST_STATE_COMPLETED
+      );
+   break;
+
+   default:
+      // All other completion status cause the IO to be complete.  If a NAK
+      // was received, then it is up to the user to retry the request.
+      scic_sds_request_set_status(
+         this_request,
+         SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
+         SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
+      );
+
+      sci_base_state_machine_change_state(
+         &this_request->parent.state_machine,
+         SCI_BASE_REQUEST_STATE_COMPLETED
+      );
+   break;
+   }
+
+   return SCI_SUCCESS;
+}
+
+
+SCIC_SDS_IO_REQUEST_STATE_HANDLER_T
+scic_sds_smp_request_started_substate_handler_table
+[SCIC_SDS_SMP_REQUEST_STARTED_MAX_SUBSTATES] =
+{
+   // SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE
+   {
+      {
+         scic_sds_request_default_start_handler,
+         scic_sds_request_started_state_abort_handler,
+         scic_sds_request_default_complete_handler,
+         scic_sds_request_default_destruct_handler
+      },
+      scic_sds_smp_request_await_response_tc_completion_handler,
+      scic_sds_request_default_event_handler,
+      scic_sds_smp_request_await_response_frame_handler
+   },
+   // SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION
+   {
+      {
+         scic_sds_request_default_start_handler,
+         scic_sds_request_started_state_abort_handler,
+         scic_sds_request_default_complete_handler,
+         scic_sds_request_default_destruct_handler
+      },
+      scic_sds_smp_request_await_tc_completion_tc_completion_handler,
+      scic_sds_request_default_event_handler,
+      scic_sds_request_default_frame_handler
+   }
+};
+
+/**
+ * @brief This method performs the actions required when entering the
+ *        SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_RESPONSE sub-state.
+ *        This includes setting the IO request state handlers for this
+ *        sub-state.
+ *
+ * @param[in]  object This parameter specifies the request object for which
+ *             the sub-state change is occuring.
+ *
+ * @return none.
+ */
+static
+void scic_sds_smp_request_started_await_response_substate_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
+
+   SET_STATE_HANDLER(
+      this_request,
+      scic_sds_smp_request_started_substate_handler_table,
+      SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE
+   );
+}
+
+/**
+ * @brief This method performs the actions required when entering the
+ *        SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION
+ *        sub-state.  This includes setting the SMP request state handlers for
+ *        this sub-state.
+ *
+ * @param[in]  object This parameter specifies the request object for which
+ *             the sub-state change is occuring.
+ *
+ * @return none.
+ */
+static
+void scic_sds_smp_request_started_await_tc_completion_substate_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
+
+   SET_STATE_HANDLER(
+      this_request,
+      scic_sds_smp_request_started_substate_handler_table,
+      SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION
+   );
+}
+
+SCI_BASE_STATE_T scic_sds_smp_request_started_substate_table
+[SCIC_SDS_SMP_REQUEST_STARTED_MAX_SUBSTATES] =
+{
+   {
+      SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE,
+      scic_sds_smp_request_started_await_response_substate_enter,
+      NULL
+   },
+   {
+      SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION,
+      scic_sds_smp_request_started_await_tc_completion_substate_enter,
+      NULL
+   }
+};
diff --git a/sys/dev/disk/isci/scil/scic_sds_smp_request.h b/sys/dev/disk/isci/scil/scic_sds_smp_request.h
new file mode 100644
index 0000000..e7f9911
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_sds_smp_request.h
@@ -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: src/sys/dev/isci/scil/scic_sds_smp_request.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIC_SDS_SMP_REQUEST_T_
+#define _SCIC_SDS_SMP_REQUEST_T_
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/intel_sas.h>
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/scic_sds_request.h>
+
+
+U32 scic_sds_smp_request_get_object_size(void);
+
+void scu_smp_request_construct_task_context(
+   SCIC_SDS_REQUEST_T *this_request,
+   SMP_REQUEST_T      *smp_request
+
+);
+
+void scic_sds_smp_request_copy_response(
+   SCIC_SDS_REQUEST_T * this_request
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIC_SDS_SMP_REQUEST_T_
diff --git a/sys/dev/disk/isci/scil/scic_sds_ssp_request.c b/sys/dev/disk/isci/scil/scic_sds_ssp_request.c
new file mode 100644
index 0000000..027cbeb
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_sds_ssp_request.c
@@ -0,0 +1,337 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_sds_ssp_request.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains the task management substate handlers for the
+ *        SCIC_SDS_IO_REQUEST object.
+ *        This file contains the enter/exit methods associated with each of
+ *        the task management raw request states.  For more information on the
+ *        task management request state machine please refer to
+ *        scic_sds_io_request.h
+ */
+
+#include <dev/disk/isci/scil/intel_sas.h>
+#include <dev/disk/isci/scil/scic_sds_request.h>
+#include <dev/disk/isci/scil/scic_controller.h>
+#include <dev/disk/isci/scil/scic_sds_logger.h>
+#include <dev/disk/isci/scil/scic_sds_controller.h>
+#include <dev/disk/isci/scil/scu_completion_codes.h>
+#include <dev/disk/isci/scil/scu_task_context.h>
+#include <dev/disk/isci/scil/sci_base_state_machine.h>
+
+/**
+ * @brief This method processes the completions transport layer (TL) status
+ *        to determine if the RAW task management frame was sent successfully.
+ *        If the raw frame was sent successfully, then the state for the
+ *        task request transitions to waiting for a response frame.
+ *
+ * @param[in] this_request This parameter specifies the request for which
+ *            the TC completion was received.
+ * @param[in] completion_code This parameter indicates the completion status
+ *            information for the TC.
+ *
+ * @return Indicate if the tc completion handler was successful.
+ * @retval SCI_SUCCESS currently this method always returns success.
+ */
+static
+SCI_STATUS scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler(
+   SCIC_SDS_REQUEST_T * this_request,
+   U32                  completion_code
+)
+{
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_request),
+      SCIC_LOG_OBJECT_TASK_MANAGEMENT,
+      "scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler(0x%x, 0x%x) enter\n",
+      this_request, completion_code
+   ));
+
+   switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
+   {
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
+      scic_sds_request_set_status(
+         this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
+      );
+
+      sci_base_state_machine_change_state(
+         &this_request->started_substate_machine,
+         SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE
+      );
+   break;
+
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_ACK_NAK_TO):
+      // Currently, the decision is to simply allow the task request to
+      // timeout if the task IU wasn't received successfully.
+      // There is a potential for receiving multiple task responses if we
+      // decide to send the task IU again.
+      SCIC_LOG_WARNING((
+         sci_base_object_get_logger(this_request),
+         SCIC_LOG_OBJECT_TASK_MANAGEMENT,
+         "TaskRequest:0x%x CompletionCode:%x - ACK/NAK timeout\n",
+         this_request, completion_code
+      ));
+
+      sci_base_state_machine_change_state(
+         &this_request->started_substate_machine,
+         SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE
+      );
+   break;
+
+   default:
+      // All other completion status cause the IO to be complete.  If a NAK
+      // was received, then it is up to the user to retry the request.
+      scic_sds_request_set_status(
+         this_request,
+         SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
+         SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
+      );
+
+      sci_base_state_machine_change_state(
+         &this_request->parent.state_machine,
+         SCI_BASE_REQUEST_STATE_COMPLETED
+      );
+   break;
+   }
+
+   return SCI_SUCCESS;
+}
+
+/**
+ * @brief This method is responsible for processing a terminate/abort
+ *        request for this TC while the request is waiting for the task
+ *        management response unsolicited frame.
+ *
+ * @param[in] this_request This parameter specifies the request for which
+ *            the termination was requested.
+ *
+ * @return This method returns an indication as to whether the abort
+ *         request was successfully handled.
+ *
+ * @todo need to update to ensure the received UF doesn't cause damage
+ *       to subsequent requests (i.e. put the extended tag in a holding
+ *       pattern for this particular device).
+ */
+static
+SCI_STATUS scic_sds_ssp_task_request_await_tc_response_abort_handler(
+   SCI_BASE_REQUEST_T * request
+)
+{
+   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)request;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_request),
+      SCIC_LOG_OBJECT_TASK_MANAGEMENT,
+      "scic_sds_ssp_task_request_await_tc_response_abort_handler(0x%x) enter\n",
+      this_request
+   ));
+
+   sci_base_state_machine_change_state(
+      &this_request->parent.state_machine,
+      SCI_BASE_REQUEST_STATE_ABORTING
+   );
+
+   sci_base_state_machine_change_state(
+      &this_request->parent.state_machine,
+      SCI_BASE_REQUEST_STATE_COMPLETED
+   );
+
+   return SCI_SUCCESS;
+}
+
+/**
+ * @brief This method processes an unsolicited frame while the task mgmt
+ *        request is waiting for a response frame.  It will copy the
+ *        response data, release the unsolicited frame, and transition
+ *        the request to the SCI_BASE_REQUEST_STATE_COMPLETED state.
+ *
+ * @param[in] this_request This parameter specifies the request for which
+ *            the unsolicited frame was received.
+ * @param[in] frame_index This parameter indicates the unsolicited frame
+ *            index that should contain the response.
+ *
+ * @return This method returns an indication of whether the TC response
+ *         frame was handled successfully or not.
+ * @retval SCI_SUCCESS Currently this value is always returned and indicates
+ *         successful processing of the TC response.
+ *
+ * @todo Should probably update to check frame type and make sure it is
+ *       a response frame.
+ */
+static
+SCI_STATUS scic_sds_ssp_task_request_await_tc_response_frame_handler(
+   SCIC_SDS_REQUEST_T * this_request,
+   U32                  frame_index
+)
+{
+   // Save off the controller, so that we do not touch the request after it
+   //  is completed.
+   SCIC_SDS_CONTROLLER_T * owning_controller = this_request->owning_controller;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_request),
+      SCIC_LOG_OBJECT_TASK_MANAGEMENT,
+      "scic_sds_ssp_task_request_await_tc_response_frame_handler(0x%x, 0x%x) enter\n",
+      this_request, frame_index
+   ));
+
+   scic_sds_io_request_copy_response(this_request);
+
+   sci_base_state_machine_change_state(
+      &this_request->parent.state_machine,
+      SCI_BASE_REQUEST_STATE_COMPLETED
+   );
+
+   scic_sds_controller_release_frame(
+      owning_controller, frame_index
+   );
+
+   return SCI_SUCCESS;
+}
+
+SCIC_SDS_IO_REQUEST_STATE_HANDLER_T
+scic_sds_ssp_task_request_started_substate_handler_table
+[SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_MAX_SUBSTATES] =
+{
+   // SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION
+   {
+      {
+         scic_sds_request_default_start_handler,
+         scic_sds_request_started_state_abort_handler,
+         scic_sds_request_default_complete_handler,
+         scic_sds_request_default_destruct_handler
+      },
+      scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler,
+      scic_sds_request_default_event_handler,
+      scic_sds_request_default_frame_handler
+   },
+   // SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE
+   {
+      {
+         scic_sds_request_default_start_handler,
+         scic_sds_ssp_task_request_await_tc_response_abort_handler,
+         scic_sds_request_default_complete_handler,
+         scic_sds_request_default_destruct_handler
+      },
+      scic_sds_request_default_tc_completion_handler,
+      scic_sds_request_default_event_handler,
+      scic_sds_ssp_task_request_await_tc_response_frame_handler
+   }
+};
+
+/**
+ * @brief This method performs the actions required when entering the
+ *        SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION
+ *        sub-state.  This includes setting the IO request state handlers
+ *        for this sub-state.
+ *
+ * @param[in]  object This parameter specifies the request object for which
+ *             the sub-state change is occuring.
+ *
+ * @return none.
+ */
+static
+void scic_sds_io_request_started_task_mgmt_await_tc_completion_substate_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
+
+   SET_STATE_HANDLER(
+      this_request,
+      scic_sds_ssp_task_request_started_substate_handler_table,
+      SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION
+   );
+}
+
+/**
+ * @brief This method performs the actions required when entering the
+ *        SCIC_SDS_IO_REQUEST_STARTED_SUBSTATE_AWAIT_TC_RESPONSE sub-state.
+ *        This includes setting the IO request state handlers for this
+ *        sub-state.
+ *
+ * @param[in]  object This parameter specifies the request object for which
+ *             the sub-state change is occuring.
+ *
+ * @return none.
+ */
+static
+void scic_sds_io_request_started_task_mgmt_await_task_response_substate_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
+
+   SET_STATE_HANDLER(
+      this_request,
+      scic_sds_ssp_task_request_started_substate_handler_table,
+      SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE
+   );
+}
+
+SCI_BASE_STATE_T scic_sds_io_request_started_task_mgmt_substate_table
+[SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_MAX_SUBSTATES] =
+{
+   {
+      SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION,
+      scic_sds_io_request_started_task_mgmt_await_tc_completion_substate_enter,
+      NULL
+   },
+   {
+      SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE,
+      scic_sds_io_request_started_task_mgmt_await_task_response_substate_enter,
+      NULL
+   }
+};
diff --git a/sys/dev/disk/isci/scil/scic_sds_stp_packet_request.c b/sys/dev/disk/isci/scil/scic_sds_stp_packet_request.c
new file mode 100644
index 0000000..9f77359
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_sds_stp_packet_request.c
@@ -0,0 +1,976 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_sds_stp_packet_request.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+#if !defined(DISABLE_ATAPI)
+
+#include <dev/disk/isci/scil/scic_sds_stp_packet_request.h>
+#include <dev/disk/isci/scil/scic_sds_logger.h>
+#include <dev/disk/isci/scil/scic_sds_controller.h>
+#include <dev/disk/isci/scil/scic_sds_remote_device.h>
+#include <dev/disk/isci/scil/scic_remote_device.h>
+#include <dev/disk/isci/scil/sci_util.h>
+#include <dev/disk/isci/scil/intel_sas.h>
+#include <dev/disk/isci/scil/intel_ata.h>
+#include <dev/disk/isci/scil/intel_sata.h>
+#include <dev/disk/isci/scil/scic_user_callback.h>
+#include <dev/disk/isci/sci_environment.h>
+#include <dev/disk/isci/scil/intel_sat.h>
+#include <dev/disk/isci/scil/scic_sds_request.h>
+#include <dev/disk/isci/scil/scic_controller.h>
+#include <dev/disk/isci/scil/scu_completion_codes.h>
+#include <dev/disk/isci/scil/scu_task_context.h>
+#include <dev/disk/isci/scil/scic_sds_stp_packet_request.h>
+#include <dev/disk/isci/scil/sci_base_state.h>
+
+/**
+ * @brief This method will fill in the SCU Task Context for a PACKET fis. And
+ *           construct the request STARTED sub-state machine for Packet Protocol
+ *           IO.
+ *
+ * @param[in] this_request This parameter specifies the stp packet request object
+ *            being constructed.
+ *
+ * @return none
+ */
+SCI_STATUS scic_sds_stp_packet_request_construct(
+   SCIC_SDS_REQUEST_T *this_request
+)
+{
+   SATA_FIS_REG_H2D_T * h2d_fis =
+      scic_stp_io_request_get_h2d_reg_address(
+         this_request
+      );
+
+   // Work around, we currently only support PACKET DMA protocol, so we
+   // need to make change to Packet Fis features field.
+   h2d_fis->features = h2d_fis->features | ATA_PACKET_FEATURE_DMA;
+
+   scic_sds_stp_non_ncq_request_construct(this_request);
+
+   // Build the Packet Fis task context structure
+   scu_stp_raw_request_construct_task_context(
+      (SCIC_SDS_STP_REQUEST_T*) this_request,
+      this_request->task_context_buffer
+   );
+
+   sci_base_state_machine_construct(
+      &this_request->started_substate_machine,
+      &this_request->parent.parent,
+      scic_sds_stp_packet_request_started_substate_table,
+      SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
+   );
+
+   return SCI_SUCCESS;
+}
+
+
+/**
+ * @brief This method will fill in the SCU Task Context for a Packet request
+ *        command phase in PACKET DMA DATA (IN/OUT) type. The following
+ *        important settings are utilized:
+ *
+ *          -# task_type == SCU_TASK_TYPE_PACKET_DMA.  This simply indicates
+ *             that a normal request type (i.e. non-raw frame) is being
+ *             utilized to perform task management.
+ *          -# control_frame == 1.  This ensures that the proper endianess
+ *             is set so that the bytes are transmitted in the right order
+ *             for a smp request frame.
+ *
+ * @param[in] this_request This parameter specifies the smp request object
+ *            being constructed.
+ * @param[in] task_context The task_context to be reconstruct for packet
+ *            request command phase.
+ * @return none
+ */
+void scu_stp_packet_request_command_phase_construct_task_context(
+   SCIC_SDS_REQUEST_T * this_request,
+   SCU_TASK_CONTEXT_T * task_context
+)
+{
+   void * atapi_cdb;
+   U32 atapi_cdb_length;
+   SCIC_SDS_STP_REQUEST_T * stp_request = (SCIC_SDS_STP_REQUEST_T *)this_request;
+
+   // reference: SSTL 1.13.4.2
+   // task_type, sata_direction
+   if ( scic_cb_io_request_get_data_direction(this_request->user_request)
+           == SCI_IO_REQUEST_DATA_OUT )
+   {
+      task_context->task_type = SCU_TASK_TYPE_PACKET_DMA_OUT;
+      task_context->sata_direction = 0;
+   }
+   else // todo: for NO_DATA command, we need to send out raw frame.
+   {
+      task_context->task_type = SCU_TASK_TYPE_PACKET_DMA_IN;
+      task_context->sata_direction = 1;
+   }
+
+   // sata header
+   memset(&(task_context->type.stp), 0, sizeof(struct STP_TASK_CONTEXT));
+   task_context->type.stp.fis_type = SATA_FIS_TYPE_DATA;
+
+   // Copy in the command IU with CDB so that the commandIU address doesn't
+   // change.
+   memset(this_request->command_buffer, 0, sizeof(SATA_FIS_REG_H2D_T));
+
+   atapi_cdb =
+      scic_cb_stp_packet_io_request_get_cdb_address(this_request->user_request);
+
+   atapi_cdb_length =
+      scic_cb_stp_packet_io_request_get_cdb_length(this_request->user_request);
+
+   memcpy(((U8 *)this_request->command_buffer+sizeof(U32)), atapi_cdb, atapi_cdb_length);
+
+   atapi_cdb_length =
+      MAX(atapi_cdb_length, stp_request->type.packet.device_preferred_cdb_length);
+
+   task_context->ssp_command_iu_length =
+      ((atapi_cdb_length % 4) == 0) ?
+       (atapi_cdb_length / 4) : ((atapi_cdb_length / 4) + 1);
+
+   // task phase is set to TX_CMD
+   task_context->task_phase = 0x1;
+
+   // retry counter
+   task_context->stp_retry_count = 0;
+
+   if (scic_cb_request_is_initial_construction(this_request->user_request))
+   {
+      // data transfer size.
+      task_context->transfer_length_bytes =
+         scic_cb_io_request_get_transfer_length(this_request->user_request);
+
+      // sgls were already built when request was constructed, so don't need to
+      //  to do it here
+   }
+   else
+   {
+      // data transfer size, need to be 4 bytes aligned.
+      task_context->transfer_length_bytes = (SCSI_FIXED_SENSE_DATA_BASE_LENGTH + 2);
+
+      scic_sds_stp_packet_internal_request_sense_build_sgl(this_request);
+   }
+}
+
+/**
+ * @brief This method will fill in the SCU Task Context for a DATA fis
+ *        containing CDB in Raw Frame type. The TC for previous Packet
+ *        fis was already there, we only need to change the H2D fis content.
+ *
+ * @param[in] this_request This parameter specifies the smp request object
+ *            being constructed.
+ * @param[in] task_context The task_context to be reconstruct for packet
+ *            request command phase.
+ * @return none
+ */
+void scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context(
+   SCIC_SDS_REQUEST_T * this_request,
+   SCU_TASK_CONTEXT_T * task_context
+)
+{
+   void * atapi_cdb =
+      scic_cb_stp_packet_io_request_get_cdb_address(this_request->user_request);
+
+   U32 atapi_cdb_length =
+      scic_cb_stp_packet_io_request_get_cdb_length(this_request->user_request);
+
+   memset(this_request->command_buffer, 0, sizeof(SATA_FIS_REG_H2D_T));
+   memcpy( ((U8 *)this_request->command_buffer+sizeof(U32)), atapi_cdb, atapi_cdb_length);
+
+   memset(&(task_context->type.stp), 0, sizeof(struct STP_TASK_CONTEXT));
+   task_context->type.stp.fis_type = SATA_FIS_TYPE_DATA;
+
+   //Note the data send out has to be 4 bytes aligned. Or else out hardware will
+   //patch non-zero bytes and cause the target device unhappy.
+   task_context->transfer_length_bytes = 12;
+}
+
+
+/*
+ *@brief This methods decode the D2H status FIS and retrieve the sense data,
+ *          then pass the sense data to user request.
+ *
+ *@param[in] this_request The request receive D2H status FIS.
+ *@param[in] status_fis The D2H status fis to be processed.
+ *
+ */
+SCI_STATUS scic_sds_stp_packet_request_process_status_fis(
+   SCIC_SDS_REQUEST_T * this_request,
+   SATA_FIS_REG_D2H_T * status_fis
+)
+{
+   SCI_STATUS status = SCI_SUCCESS;
+
+   //TODO: Process the error status fis, retrieve sense data.
+   if (status_fis->status & ATA_STATUS_REG_ERROR_BIT)
+      status = SCI_FAILURE_IO_RESPONSE_VALID;
+
+   return status;
+}
+
+/*
+ *@brief This methods builds sgl for internal REQUEST SENSE stp packet
+ *          command using this request response buffer, only one sge is
+ *          needed.
+ *
+ *@param[in] this_request The request receive request sense data.
+ *
+ */
+void scic_sds_stp_packet_internal_request_sense_build_sgl(
+   SCIC_SDS_REQUEST_T * this_request
+)
+{
+   void                   *sge;
+   SCU_SGL_ELEMENT_PAIR_T *scu_sgl_list   = NULL;
+   SCU_TASK_CONTEXT_T     *task_context;
+   SCI_PHYSICAL_ADDRESS    physical_address;
+
+   SCI_SSP_RESPONSE_IU_T * rsp_iu =
+      (SCI_SSP_RESPONSE_IU_T *)this_request->response_buffer;
+   sge =  (void*)&rsp_iu->data[0];
+
+   task_context = (SCU_TASK_CONTEXT_T *)this_request->task_context_buffer;
+   scu_sgl_list = &task_context->sgl_pair_ab;
+
+   scic_cb_io_request_get_physical_address(
+      scic_sds_request_get_controller(this_request),
+      this_request,
+      ((char *)sge),
+      &physical_address
+   );
+
+   scu_sgl_list->A.address_upper = sci_cb_physical_address_upper(physical_address);
+   scu_sgl_list->A.address_lower = sci_cb_physical_address_lower(physical_address);
+   scu_sgl_list->A.length = task_context->transfer_length_bytes;
+   scu_sgl_list->A.address_modifier = 0;
+
+   SCU_SGL_ZERO(scu_sgl_list->B);
+}
+
+//******************************************************************************
+//* STP PACKET REQUEST STATE MACHINES
+//******************************************************************************
+
+/**
+* @brief This method processes the completions transport layer (TL) status
+*        to determine if the Packet FIS was sent successfully. If the Packet
+*        FIS was sent successfully, then the state for the Packet request
+*        transits to waiting for a PIO SETUP frame.
+*
+* @param[in] this_request This parameter specifies the request for which
+*            the TC completion was received.
+* @param[in] completion_code This parameter indicates the completion status
+*            information for the TC.
+*
+* @return Indicate if the tc completion handler was successful.
+* @retval SCI_SUCCESS currently this method always returns success.
+*/
+static
+SCI_STATUS scic_sds_stp_packet_request_packet_phase_await_tc_completion_tc_completion_handler(
+   SCIC_SDS_REQUEST_T * this_request,
+   U32                  completion_code
+)
+{
+   SCI_STATUS status = SCI_SUCCESS;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_request),
+      SCIC_LOG_OBJECT_STP_IO_REQUEST,
+      "scic_sds_stp_packet_request_packet_phase_await_tc_completion_tc_completion_handler(0x%x, 0x%x) enter\n",
+      this_request, completion_code
+   ));
+
+   switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
+   {
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
+      scic_sds_request_set_status(
+         this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
+      );
+
+      sci_base_state_machine_change_state(
+         &this_request->started_substate_machine,
+         SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE
+      );
+      break;
+
+   default:
+      // All other completion status cause the IO to be complete.  If a NAK
+      // was received, then it is up to the user to retry the request.
+      scic_sds_request_set_status(
+         this_request,
+         SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
+         SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
+      );
+
+      sci_base_state_machine_change_state(
+         &this_request->parent.state_machine,
+         SCI_BASE_REQUEST_STATE_COMPLETED
+      );
+      break;
+   }
+
+   return status;
+}
+
+
+/**
+ * @brief This method processes an unsolicited frame while the Packet request
+ *        is waiting for a PIO SETUP FIS.  It will release
+ *        the unsolicited frame, and transition the request to the
+ *        COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE state.
+ *
+ * @param[in] this_request This parameter specifies the request for which
+ *            the unsolicited frame was received.
+ * @param[in] frame_index This parameter indicates the unsolicited frame
+ *            index that should contain the response.
+ *
+ * @return This method returns an indication of whether the pio setup
+ *         frame was handled successfully or not.
+ * @retval SCI_SUCCESS Currently this value is always returned and indicates
+ *         successful processing of the TC response.
+ *
+ */
+static
+SCI_STATUS scic_sds_stp_packet_request_packet_phase_await_pio_setup_frame_handler(
+   SCIC_SDS_REQUEST_T * request,
+   U32                  frame_index
+)
+{
+   SCI_STATUS               status;
+   SATA_FIS_HEADER_T      * frame_header;
+   U32                    * frame_buffer;
+   SCIC_SDS_STP_REQUEST_T * this_request;
+
+   this_request = (SCIC_SDS_STP_REQUEST_T *)request;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_request),
+      SCIC_LOG_OBJECT_STP_IO_REQUEST,
+      "scic_sds_stp_packet_request_packet_phase_await_pio_setup_frame_handler(0x%x, 0x%x) enter\n",
+      this_request, frame_index
+   ));
+
+   status = scic_sds_unsolicited_frame_control_get_header(
+      &(this_request->parent.owning_controller->uf_control),
+      frame_index,
+      (void**) &frame_header
+   );
+
+   if (status == SCI_SUCCESS)
+   {
+      ASSERT(frame_header->fis_type == SATA_FIS_TYPE_PIO_SETUP);
+
+      // Get from the frame buffer the PIO Setup Data, although we don't need
+      // any info from this pio setup fis.
+      scic_sds_unsolicited_frame_control_get_buffer(
+         &(this_request->parent.owning_controller->uf_control),
+         frame_index,
+         (void**) &frame_buffer
+      );
+
+      // Get the data from the PIO Setup
+      // The SCU Hardware returns first word in the frame_header and the rest
+      // of the data is in the frame buffer so we need to back up one dword
+      this_request->type.packet.device_preferred_cdb_length =
+         (U16)((SATA_FIS_PIO_SETUP_T *)(&frame_buffer[-1]))->transfter_count;
+
+      // Frame has been decoded return it to the controller
+      scic_sds_controller_release_frame(
+         this_request->parent.owning_controller, frame_index
+      );
+
+      sci_base_state_machine_change_state(
+         &this_request->parent.started_substate_machine,
+         SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
+      );
+   }
+   else
+   {
+      SCIC_LOG_ERROR((
+         sci_base_object_get_logger(this_request),
+         SCIC_LOG_OBJECT_STP_IO_REQUEST,
+         "SCIC IO Request 0x%x could not get frame header for frame index %d, status %x\n",
+         this_request, frame_index, status
+      ));
+   }
+
+   return status;
+}
+
+
+/**
+ * @brief This method processes the completions transport layer (TL) status
+ *        to determine if the PACKET command data FIS was sent successfully.
+ *        If successfully, then the state for the packet request
+ *        transits to COMPLETE state. If not successfuly, the request transits
+ *        to COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE.
+ *
+ * @param[in] this_request This parameter specifies the request for which
+ *            the TC completion was received.
+ * @param[in] completion_code This parameter indicates the completion status
+ *            information for the TC.
+ *
+ * @return Indicate if the tc completion handler was successful.
+ * @retval SCI_SUCCESS currently this method always returns success.
+ */
+static
+SCI_STATUS scic_sds_stp_packet_request_command_phase_await_tc_completion_tc_completion_handler(
+   SCIC_SDS_REQUEST_T * this_request,
+   U32                  completion_code
+)
+{
+   SCI_STATUS status = SCI_SUCCESS;
+   U8 sat_packet_protocol = this_request->sat_protocol;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_request),
+      SCIC_LOG_OBJECT_STP_IO_REQUEST,
+      "scic_sds_stp_packet_request_command_phase_await_tc_completion_tc_completion_handler(0x%x, 0x%x) enter\n",
+      this_request, completion_code
+   ));
+
+   switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
+   {
+   case (SCU_TASK_DONE_GOOD << SCU_COMPLETION_TL_STATUS_SHIFT):
+      scic_sds_request_set_status(
+         this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
+      );
+
+      if ( sat_packet_protocol == SAT_PROTOCOL_PACKET_DMA_DATA_IN
+          || sat_packet_protocol == SAT_PROTOCOL_PACKET_DMA_DATA_OUT
+         )
+         sci_base_state_machine_change_state(
+            &this_request->parent.state_machine,
+            SCI_BASE_REQUEST_STATE_COMPLETED
+         );
+      else
+         sci_base_state_machine_change_state(
+            &this_request->started_substate_machine,
+            SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE
+         );
+   break;
+
+   case (SCU_TASK_DONE_UNEXP_FIS << SCU_COMPLETION_TL_STATUS_SHIFT):
+      if (scic_io_request_get_number_of_bytes_transferred(this_request) <
+          scic_cb_io_request_get_transfer_length(this_request->user_request))
+      {
+         scic_sds_request_set_status(
+            this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS_IO_DONE_EARLY
+         );
+
+         sci_base_state_machine_change_state(
+            &this_request->started_substate_machine,
+            SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE
+         );
+
+         //change the device state to ATAPI_ERROR.
+         sci_base_state_machine_change_state(
+            &this_request->target_device->ready_substate_machine,
+            SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR
+         );
+
+         status = this_request->sci_status;
+      }
+   break;
+
+   case (SCU_TASK_DONE_EXCESS_DATA << SCU_COMPLETION_TL_STATUS_SHIFT):
+      //In this case, there is no UF coming after. compelte the IO now.
+      scic_sds_request_set_status(
+         this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
+      );
+
+      sci_base_state_machine_change_state(
+         &this_request->parent.state_machine,
+         SCI_BASE_REQUEST_STATE_COMPLETED
+      );
+
+   break;
+
+   default:
+      if (this_request->sci_status != SCI_SUCCESS)
+      {  //The io status was set already. This means an UF for the status
+         //fis was received already.
+
+         //A device suspension event is expected, we need to have the device
+         //coming out of suspension, then complete the IO.
+         sci_base_state_machine_change_state(
+            &this_request->started_substate_machine,
+            SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE
+         );
+
+         //change the device state to ATAPI_ERROR.
+         sci_base_state_machine_change_state(
+            &this_request->target_device->ready_substate_machine,
+            SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR
+         );
+
+         status = this_request->sci_status;
+      }
+      else
+      {  //If receiving any non-sucess TC status, no UF received yet, then an UF for
+         //the status fis is coming after.
+         scic_sds_request_set_status(
+            this_request,
+            SCU_TASK_DONE_CHECK_RESPONSE,
+            SCI_FAILURE_IO_RESPONSE_VALID
+         );
+
+         sci_base_state_machine_change_state(
+            &this_request->started_substate_machine,
+            SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE
+         );
+      }
+   break;
+   }
+
+   return status;
+}
+
+
+/**
+* @brief This method processes an unsolicited frame.
+*
+* @param[in] this_request This parameter specifies the request for which
+*            the unsolicited frame was received.
+* @param[in] frame_index This parameter indicates the unsolicited frame
+*            index that should contain the response.
+*
+* @return This method returns an indication of whether the UF
+*         frame was handled successfully or not.
+* @retval SCI_SUCCESS Currently this value is always returned and indicates
+*         successful processing of the TC response.
+*
+*/
+static
+SCI_STATUS scic_sds_stp_packet_request_command_phase_common_frame_handler(
+   SCIC_SDS_REQUEST_T * request,
+   U32                  frame_index
+)
+{
+   SCI_STATUS               status;
+   SATA_FIS_HEADER_T      * frame_header;
+   U32                    * frame_buffer;
+   SCIC_SDS_STP_REQUEST_T * this_request;
+
+   this_request = (SCIC_SDS_STP_REQUEST_T *)request;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_request),
+      SCIC_LOG_OBJECT_STP_IO_REQUEST,
+      "scic_sds_stp_packet_request_command_phase_await_d2h_frame_handler(0x%x, 0x%x) enter\n",
+      this_request, frame_index
+   ));
+
+   status = scic_sds_unsolicited_frame_control_get_header(
+      &(this_request->parent.owning_controller->uf_control),
+      frame_index,
+      (void**) &frame_header
+   );
+
+   if (status == SCI_SUCCESS)
+   {
+      ASSERT(frame_header->fis_type == SATA_FIS_TYPE_REGD2H);
+
+      // Get from the frame buffer the PIO Setup Data, although we don't need
+      // any info from this pio setup fis.
+      scic_sds_unsolicited_frame_control_get_buffer(
+         &(this_request->parent.owning_controller->uf_control),
+         frame_index,
+         (void**) &frame_buffer
+      );
+
+      scic_sds_controller_copy_sata_response(
+         &this_request->d2h_reg_fis, (U32 *)frame_header, frame_buffer
+      );
+
+      // Frame has been decoded return it to the controller
+      scic_sds_controller_release_frame(
+         this_request->parent.owning_controller, frame_index
+      );
+   }
+
+   return status;
+}
+
+/**
+* @brief This method processes an unsolicited frame while the packet request is
+*        expecting TC completion. It will process the FIS and construct sense
+*        data.
+*
+* @param[in] this_request This parameter specifies the request for which
+*            the unsolicited frame was received.
+* @param[in] frame_index This parameter indicates the unsolicited frame
+*            index that should contain the response.
+*
+* @return This method returns an indication of whether the UF
+*         frame was handled successfully or not.
+* @retval SCI_SUCCESS Currently this value is always returned and indicates
+*         successful processing of the TC response.
+*
+*/
+static
+SCI_STATUS scic_sds_stp_packet_request_command_phase_await_tc_completion_frame_handler(
+   SCIC_SDS_REQUEST_T * request,
+   U32                  frame_index
+)
+{
+   SCIC_SDS_STP_REQUEST_T * this_request = (SCIC_SDS_STP_REQUEST_T *)request;
+
+   SCI_STATUS status =
+      scic_sds_stp_packet_request_command_phase_common_frame_handler(
+         request, frame_index);
+
+   if (status == SCI_SUCCESS)
+   {
+      // The command has completed with error status from target device.
+      status = scic_sds_stp_packet_request_process_status_fis(
+         request, &this_request->d2h_reg_fis);
+
+      if (status != SCI_SUCCESS)
+      {
+         scic_sds_request_set_status(
+            &this_request->parent,
+            SCU_TASK_DONE_CHECK_RESPONSE,
+            status
+         );
+      }
+      else
+         scic_sds_request_set_status(
+            &this_request->parent, SCU_TASK_DONE_GOOD, SCI_SUCCESS
+         );
+   }
+
+   return status;
+}
+
+
+/**
+* @brief This method processes an unsolicited frame while the packet request is
+*        expecting TC completion. It will process the FIS and construct sense
+*        data.
+*
+* @param[in] this_request This parameter specifies the request for which
+*            the unsolicited frame was received.
+* @param[in] frame_index This parameter indicates the unsolicited frame
+*            index that should contain the response.
+*
+* @return This method returns an indication of whether the UF
+*         frame was handled successfully or not.
+* @retval SCI_SUCCESS Currently this value is always returned and indicates
+*         successful processing of the TC response.
+*
+*/
+static
+SCI_STATUS scic_sds_stp_packet_request_command_phase_await_d2h_fis_frame_handler(
+   SCIC_SDS_REQUEST_T * request,
+   U32                  frame_index
+)
+{
+   SCI_STATUS status =
+      scic_sds_stp_packet_request_command_phase_common_frame_handler(
+         request, frame_index);
+
+   SCIC_SDS_STP_REQUEST_T * this_request = (SCIC_SDS_STP_REQUEST_T *)request;
+
+   if (status == SCI_SUCCESS)
+   {
+       // The command has completed with error status from target device.
+      status = scic_sds_stp_packet_request_process_status_fis(
+         request, &this_request->d2h_reg_fis);
+
+      if (status != SCI_SUCCESS)
+      {
+         scic_sds_request_set_status(
+            request,
+            SCU_TASK_DONE_CHECK_RESPONSE,
+            status
+         );
+      }
+      else
+         scic_sds_request_set_status(
+            request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
+         );
+
+      //Always complete the NON_DATA command right away, no need to delay completion
+      //even an error status fis came from target device.
+      sci_base_state_machine_change_state(
+         &request->parent.state_machine,
+         SCI_BASE_REQUEST_STATE_COMPLETED
+      );
+   }
+
+   return status;
+}
+
+static
+SCI_STATUS scic_sds_stp_packet_request_started_completion_delay_complete_handler(
+   SCI_BASE_REQUEST_T *request
+)
+{
+   SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T *)request;
+
+   sci_base_state_machine_change_state(
+      &this_request->parent.state_machine,
+      SCI_BASE_REQUEST_STATE_COMPLETED
+   );
+
+   return this_request->sci_status;
+}
+
+// ---------------------------------------------------------------------------
+
+SCIC_SDS_IO_REQUEST_STATE_HANDLER_T
+scic_sds_stp_packet_request_started_substate_handler_table
+[SCIC_SDS_STP_PACKET_REQUEST_STARTED_MAX_SUBSTATES] =
+{
+   // SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
+   {
+      {
+         scic_sds_request_default_start_handler,
+         scic_sds_request_started_state_abort_handler,
+         scic_sds_request_default_complete_handler,
+         scic_sds_request_default_destruct_handler
+      },
+      scic_sds_stp_packet_request_packet_phase_await_tc_completion_tc_completion_handler,
+      scic_sds_request_default_event_handler,
+      scic_sds_request_default_frame_handler
+   },
+   // SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE
+   {
+      {
+         scic_sds_request_default_start_handler,
+         scic_sds_request_started_state_abort_handler,
+         scic_sds_request_default_complete_handler,
+         scic_sds_request_default_destruct_handler
+      },
+      scic_sds_request_default_tc_completion_handler,
+      scic_sds_request_default_event_handler,
+      scic_sds_stp_packet_request_packet_phase_await_pio_setup_frame_handler
+   },
+   // SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
+   {
+      {
+         scic_sds_request_default_start_handler,
+         scic_sds_request_started_state_abort_handler,
+         scic_sds_request_default_complete_handler,
+         scic_sds_request_default_destruct_handler
+      },
+      scic_sds_stp_packet_request_command_phase_await_tc_completion_tc_completion_handler,
+      scic_sds_request_default_event_handler,
+      scic_sds_stp_packet_request_command_phase_await_tc_completion_frame_handler
+   },
+   // SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE
+   {
+      {
+         scic_sds_request_default_start_handler,
+         scic_sds_request_started_state_abort_handler,
+         scic_sds_request_default_complete_handler,
+         scic_sds_request_default_destruct_handler
+      },
+      scic_sds_request_default_tc_completion_handler,
+      scic_sds_request_default_event_handler,
+      scic_sds_stp_packet_request_command_phase_await_d2h_fis_frame_handler
+   },
+   // SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE
+   {
+      {
+         scic_sds_request_default_start_handler,
+         scic_sds_request_started_state_abort_handler,
+         scic_sds_stp_packet_request_started_completion_delay_complete_handler,
+         scic_sds_request_default_destruct_handler
+      },
+      scic_sds_request_default_tc_completion_handler,
+      scic_sds_request_default_event_handler,
+      scic_sds_request_default_frame_handler
+   }
+};
+
+/**
+ * @file
+ *
+ * @brief This file contains the Packet IO started substate machine
+ *        for the SCIC_SDS_IO_REQUEST object.
+ */
+static
+void scic_sds_stp_packet_request_started_packet_phase_await_tc_completion_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
+
+   SET_STATE_HANDLER(
+      this_request,
+      scic_sds_stp_packet_request_started_substate_handler_table,
+      SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
+   );
+
+   scic_sds_remote_device_set_working_request(
+      this_request->target_device, this_request
+   );
+}
+
+static
+void scic_sds_stp_packet_request_started_packet_phase_await_pio_setup_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
+
+   SET_STATE_HANDLER(
+      this_request,
+      scic_sds_stp_packet_request_started_substate_handler_table,
+      SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE
+   );
+}
+
+static
+void scic_sds_stp_packet_request_started_command_phase_await_tc_completion_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
+   U8 sat_packet_protocol = this_request->sat_protocol;
+
+   SCU_TASK_CONTEXT_T *task_context;
+   SCI_STATUS status;
+
+   // Recycle the TC and reconstruct it for sending out data fis containing
+   // CDB.
+   task_context = scic_sds_controller_get_task_context_buffer(
+                        this_request->owning_controller, this_request->io_tag);
+
+   if (sat_packet_protocol == SAT_PROTOCOL_PACKET_NON_DATA)
+      scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context(
+         this_request, task_context);
+   else
+      scu_stp_packet_request_command_phase_construct_task_context(
+         this_request, task_context);
+
+   // send the new TC out.
+   status = this_request->owning_controller->state_handlers->parent.continue_io_handler(
+      &this_request->owning_controller->parent,
+      &this_request->target_device->parent,
+      &this_request->parent
+   );
+
+   if (status == SCI_SUCCESS)
+      SET_STATE_HANDLER(
+         this_request,
+         scic_sds_stp_packet_request_started_substate_handler_table,
+         SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
+      );
+}
+
+static
+void scic_sds_stp_packet_request_started_command_phase_await_d2h_fis_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
+
+   SET_STATE_HANDLER(
+      this_request,
+      scic_sds_stp_packet_request_started_substate_handler_table,
+      SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE
+   );
+}
+
+static
+void scic_sds_stp_packet_request_started_completion_delay_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
+
+   SET_STATE_HANDLER(
+      this_request,
+      scic_sds_stp_packet_request_started_substate_handler_table,
+      SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE
+   );
+}
+
+
+// ---------------------------------------------------------------------------
+SCI_BASE_STATE_T
+   scic_sds_stp_packet_request_started_substate_table
+      [SCIC_SDS_STP_PACKET_REQUEST_STARTED_MAX_SUBSTATES] =
+{
+   {
+      SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE,
+      scic_sds_stp_packet_request_started_packet_phase_await_tc_completion_enter,
+      NULL
+   },
+   {
+      SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE,
+      scic_sds_stp_packet_request_started_packet_phase_await_pio_setup_enter,
+      NULL
+   },
+   {
+      SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE,
+      scic_sds_stp_packet_request_started_command_phase_await_tc_completion_enter,
+      NULL
+   },
+   {
+      SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE,
+      scic_sds_stp_packet_request_started_command_phase_await_d2h_fis_enter,
+      NULL
+   },
+   {
+      SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE,
+      scic_sds_stp_packet_request_started_completion_delay_enter,
+      NULL
+   }
+};
+
+#endif //#if !defined(DISABLE_ATAPI)
diff --git a/sys/dev/disk/isci/scil/scic_sds_stp_packet_request.h b/sys/dev/disk/isci/scil/scic_sds_stp_packet_request.h
new file mode 100644
index 0000000..399097c
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_sds_stp_packet_request.h
@@ -0,0 +1,170 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_sds_stp_packet_request.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIC_SDS_STP_PACKET_REQUEST_H_
+#define _SCIC_SDS_STP_PACKET_REQUEST_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/intel_sas.h>
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/scic_sds_stp_request.h>
+
+/**
+ * @file
+ *
+ * @brief This file contains the structures and constants for PACKET protocol
+ *        requests.
+ */
+
+
+/**
+ * @enum
+ *
+ * This is the enumeration of the SATA PIO DATA IN started substate machine.
+ */
+enum _SCIC_SDS_STP_PACKET_REQUEST_STARTED_SUBSTATES
+{
+   /**
+    * While in this state the IO request object is waiting for the TC completion
+    * notification for the H2D Register FIS
+    */
+   SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE,
+
+   /**
+    * While in this state the IO request object is waiting for either a PIO Setup.
+    */
+   SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE,
+
+   /**
+    * While in this state the IO request object is waiting for TC completion for
+    * the Packet DMA DATA fis or Raw Frame.
+    */
+   SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE,
+
+   /**
+    * The non-data IO transit to this state in this state after receiving TC
+    * completion. While in this state IO request object is waiting for D2H status
+    * frame as UF.
+    */
+   SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE,
+
+   /**
+    * The IO transit to this state in this state if the previous TC completion status
+    * is not success and the atapi device is suspended due to target device failed the IO.
+    * While in this state IO request object is waiting for device coming out of the
+    * suspension state then complete the IO.
+    */
+   SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE,
+
+   SCIC_SDS_STP_PACKET_REQUEST_STARTED_MAX_SUBSTATES
+};
+
+
+
+#if !defined(DISABLE_ATAPI)
+extern SCI_BASE_STATE_T scic_sds_stp_packet_request_started_substate_table[];
+extern SCIC_SDS_IO_REQUEST_STATE_HANDLER_T
+	scic_sds_stp_packet_request_started_substate_handler_table[];
+#endif // !defined(DISABLE_ATAPI)
+
+#if !defined(DISABLE_ATAPI)
+SCI_STATUS scic_sds_stp_packet_request_construct(
+   SCIC_SDS_REQUEST_T * this_request
+);
+#else  // !defined(DISABLE_ATAPI)
+#define scic_sds_stp_packet_request_construct(request) SCI_FAILURE
+#endif // !defined(DISABLE_ATAPI)
+
+#if !defined(DISABLE_ATAPI)
+void scu_stp_packet_request_command_phase_construct_task_context(
+   SCIC_SDS_REQUEST_T * this_request,
+   SCU_TASK_CONTEXT_T * task_context
+);
+#else  // !defined(DISABLE_ATAPI)
+#define scu_stp_packet_request_command_phase_construct_task_context(reqeust, tc)
+#endif // !defined(DISABLE_ATAPI)
+
+#if !defined(DISABLE_ATAPI)
+void scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context(
+   SCIC_SDS_REQUEST_T * this_request,
+   SCU_TASK_CONTEXT_T * task_context
+);
+#else  // !defined(DISABLE_ATAPI)
+#define scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context(reqeust, tc)
+#endif // !defined(DISABLE_ATAPI)
+
+#if !defined(DISABLE_ATAPI)
+SCI_STATUS scic_sds_stp_packet_request_process_status_fis(
+   SCIC_SDS_REQUEST_T * this_request,
+   SATA_FIS_REG_D2H_T * status_fis
+);
+#else  // !defined(DISABLE_ATAPI)
+#define scic_sds_stp_packet_request_process_status_fis(reqeust, fis) SCI_FAILURE
+#endif // !defined(DISABLE_ATAPI)
+
+#if !defined(DISABLE_ATAPI)
+void scic_sds_stp_packet_internal_request_sense_build_sgl(
+   SCIC_SDS_REQUEST_T * this_request
+);
+#else  // !defined(DISABLE_ATAPI)
+#define scic_sds_stp_packet_internal_request_sense_build_sgl(request)
+#endif // !defined(DISABLE_ATAPI)
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIC_SDS_STP_PACKET_REQUEST_H_
diff --git a/sys/dev/disk/isci/scil/scic_sds_stp_pio_request.h b/sys/dev/disk/isci/scil/scic_sds_stp_pio_request.h
new file mode 100644
index 0000000..8ac1d2d
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_sds_stp_pio_request.h
@@ -0,0 +1,131 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_sds_stp_pio_request.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIC_SDS_SATA_PIO_REQUEST_H_
+#define _SCIC_SDS_SATA_PIO_REQUEST_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_base_state.h>
+#include <dev/disk/isci/scil/scic_sds_request.h>
+#include <dev/disk/isci/scil/scu_task_context.h>
+
+/**
+ * @file
+ *
+ * @brief This file contains the structures and constants for SATA PIO
+ *        requests.
+ */
+
+
+/**
+ * @enum
+ *
+ * This is the enumeration of the SATA PIO DATA IN started substate machine.
+ */
+enum _SCIC_SDS_STP_REQUEST_STARTED_PIO_SUBSTATES
+{
+   /**
+    * While in this state the IO request object is waiting for the TC completion
+    * notification for the H2D Register FIS
+    */
+   SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE,
+
+   /**
+    * While in this state the IO request object is waiting for either a PIO Setup
+    * FIS or a D2H register FIS.  The type of frame received is based on the
+    * result of the prior frame and line conditions.
+    */
+   SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE,
+
+   /**
+    * While in this state the IO request object is waiting for a DATA frame from
+    * the device.
+    */
+   SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE,
+
+   /**
+    * While in this state the IO request object is waiting to transmit the next data
+    * frame to the device.
+    */
+   SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE,
+
+   SCIC_SDS_STP_REQUEST_STARTED_PIO_MAX_SUBSTATES
+};
+
+
+
+
+// ---------------------------------------------------------------------------
+
+extern SCIC_SDS_IO_REQUEST_STATE_HANDLER_T
+   scic_sds_stp_request_started_pio_substate_handler_table[
+      SCIC_SDS_STP_REQUEST_STARTED_PIO_MAX_SUBSTATES];
+
+extern SCI_BASE_STATE_T
+   scic_sds_stp_request_started_pio_substate_table[
+      SCIC_SDS_STP_REQUEST_STARTED_PIO_MAX_SUBSTATES];
+
+// ---------------------------------------------------------------------------
+
+SCU_SGL_ELEMENT_T * scic_sds_stp_request_pio_get_next_sgl(
+   SCIC_SDS_STP_REQUEST_T * this_request
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif   // _SCIC_SDS_SATA_PIO_REQUEST_H_
diff --git a/sys/dev/disk/isci/scil/scic_sds_stp_remote_device.c b/sys/dev/disk/isci/scil/scic_sds_stp_remote_device.c
new file mode 100644
index 0000000..0a91b43
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_sds_stp_remote_device.c
@@ -0,0 +1,1096 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_sds_stp_remote_device.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains the methods and state machines for SATA/STP
+ *        remote devices.
+ */
+
+#include <dev/disk/isci/scil/intel_sat.h>
+#include <dev/disk/isci/scil/intel_ata.h>
+#include <dev/disk/isci/scil/intel_sata.h>
+#include <dev/disk/isci/scil/scic_remote_device.h>
+#include <dev/disk/isci/scil/scic_user_callback.h>
+#include <dev/disk/isci/scil/scic_sds_logger.h>
+#include <dev/disk/isci/scil/scic_sds_controller.h>
+#include <dev/disk/isci/scil/scic_sds_port.h>
+#include <dev/disk/isci/scil/scic_sds_remote_device.h>
+#include <dev/disk/isci/scil/scic_sds_request.h>
+#include <dev/disk/isci/scil/scu_event_codes.h>
+#include <dev/disk/isci/scil/scu_completion_codes.h>
+#include <dev/disk/isci/scil/sci_base_state.h>
+
+/**
+ * This method will perform the STP request completion processing common
+ * to IO requests and task requests of all types
+ *
+ * @param[in] device This parameter specifies the device for which the
+ *            request is being completed.
+ * @param[in] request This parameter specifies the request being completed.
+ *
+ * @return This method returns an indication as to whether the request
+ *         processing completed successfully.
+ */
+static
+SCI_STATUS scic_sds_stp_remote_device_complete_request(
+   SCI_BASE_REMOTE_DEVICE_T * device,
+   SCI_BASE_REQUEST_T       * request
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
+   SCIC_SDS_REQUEST_T       * the_request = (SCIC_SDS_REQUEST_T *)request;
+   SCI_STATUS                 status;
+
+   status = scic_sds_io_request_complete(the_request);
+
+   if (status == SCI_SUCCESS)
+   {
+      status = scic_sds_port_complete_io(
+                  this_device->owning_port, this_device, the_request
+               );
+
+      if (status == SCI_SUCCESS)
+      {
+         scic_sds_remote_device_decrement_request_count(this_device);
+         if (the_request->sci_status == SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED)
+         {
+            //This request causes hardware error, device needs to be Lun Reset.
+            //So here we force the state machine to IDLE state so the rest IOs
+            //can reach RNC state handler, these IOs will be completed by RNC with
+            //status of "DEVICE_RESET_REQUIRED", instead of "INVALID STATE".
+            sci_base_state_machine_change_state(
+               &this_device->ready_substate_machine,
+               SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET
+            );
+         }
+         else if (scic_sds_remote_device_get_request_count(this_device) == 0)
+         {
+            sci_base_state_machine_change_state(
+               &this_device->ready_substate_machine,
+               SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
+            );
+         }
+      }
+   }
+
+   if (status != SCI_SUCCESS)
+   {
+      SCIC_LOG_ERROR((
+         sci_base_object_get_logger(this_device),
+         SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
+         "Port:0x%x Device:0x%x Request:0x%x Status:0x%x could not complete\n",
+         this_device->owning_port, this_device, the_request, status
+      ));
+   }
+
+   return status;
+}
+
+//*****************************************************************************
+//*  STP REMOTE DEVICE READY COMMON SUBSTATE HANDLERS
+//*****************************************************************************
+
+/**
+ * This is the READY NCQ substate handler to start task management request. In this
+ * routine, we suspend and resume the RNC.
+ *
+ * @param[in] device The target device a task management request towards to.
+ * @param[in] request The task request.
+ *
+ * @return SCI_STATUS Always return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS status
+ *     to let controller_start_task_handler know that the controller can't post TC for
+ *     task request yet, instead, when RNC gets resumed, a controller_continue_task
+ *     callback will be called.
+ */
+static
+SCI_STATUS scic_sds_stp_remote_device_ready_substate_start_request_handler(
+   SCI_BASE_REMOTE_DEVICE_T * device,
+   SCI_BASE_REQUEST_T       * request
+)
+{
+   SCI_STATUS status;
+   SCIC_SDS_REMOTE_DEVICE_T * this_device  = (SCIC_SDS_REMOTE_DEVICE_T *)device;
+   SCIC_SDS_REQUEST_T       * this_request = (SCIC_SDS_REQUEST_T       *)request;
+
+   // Will the port allow the io request to start?
+   status = this_device->owning_port->state_handlers->start_io_handler(
+      this_device->owning_port,
+      this_device,
+      this_request
+   );
+
+   if (SCI_SUCCESS == status)
+   {
+      status =
+         scic_sds_remote_node_context_start_task(this_device->rnc, this_request);
+
+      if (SCI_SUCCESS == status)
+      {
+         status = this_request->state_handlers->parent.start_handler(request);
+      }
+
+      if (status == SCI_SUCCESS)
+      {
+         /// @note If the remote device state is not IDLE this will replace
+         ///       the request that probably resulted in the task management
+         ///       request.
+         this_device->working_request = this_request;
+
+         sci_base_state_machine_change_state(
+            &this_device->ready_substate_machine,
+            SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD
+         );
+
+         //The remote node context must cleanup the TCi to NCQ mapping table.
+         //The only way to do this correctly is to either write to the TLCR
+         //register or to invalidate and repost the RNC. In either case the
+         //remote node context state machine will take the correct action when
+         //the remote node context is suspended and later resumed.
+         scic_sds_remote_node_context_suspend(
+            this_device->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL);
+
+         scic_sds_remote_node_context_resume(
+            this_device->rnc,
+            (SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK)
+                scic_sds_remote_device_continue_request,
+            this_device);
+      }
+
+      scic_sds_remote_device_start_request(this_device,this_request,status);
+
+      //We need to let the controller start request handler know that it can't
+      //post TC yet. We will provide a callback function to post TC when RNC gets
+      //resumed.
+      return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS;
+   }
+
+   return status;
+}
+
+//*****************************************************************************
+//*  STP REMOTE DEVICE READY IDLE SUBSTATE HANDLERS
+//*****************************************************************************
+
+/**
+ * This method will handle the start io operation for a sata device that is in
+ * the command idle state.
+ *    - Evalute the type of IO request to be started
+ *    - If its an NCQ request change to NCQ substate
+ *    - If its any other command change to the CMD substate
+ *
+ * @note If this is a softreset we may want to have a different substate.
+ *
+ * @param [in] device
+ * @param [in] request
+ *
+ * @return SCI_STATUS
+ */
+static
+SCI_STATUS scic_sds_stp_remote_device_ready_idle_substate_start_io_handler(
+   SCI_BASE_REMOTE_DEVICE_T * device,
+   SCI_BASE_REQUEST_T       * request
+)
+{
+   SCI_STATUS status;
+   SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
+   SCIC_SDS_REQUEST_T       * io_request  = (SCIC_SDS_REQUEST_T       *)request;
+
+
+   // Will the port allow the io request to start?
+   status = this_device->owning_port->state_handlers->start_io_handler(
+      this_device->owning_port,
+      this_device,
+      io_request
+   );
+
+   if (status == SCI_SUCCESS)
+   {
+      status =
+         scic_sds_remote_node_context_start_io(this_device->rnc, io_request);
+
+      if (status == SCI_SUCCESS)
+      {
+         status = io_request->state_handlers->parent.start_handler(request);
+      }
+
+      if (status == SCI_SUCCESS)
+      {
+         if (io_request->sat_protocol == SAT_PROTOCOL_FPDMA)
+         {
+            sci_base_state_machine_change_state(
+               &this_device->ready_substate_machine,
+               SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ
+            );
+         }
+         else
+         {
+            this_device->working_request = io_request;
+
+            sci_base_state_machine_change_state(
+               &this_device->ready_substate_machine,
+               SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD
+            );
+         }
+      }
+
+      scic_sds_remote_device_start_request(this_device, io_request, status);
+   }
+
+   return status;
+}
+
+
+/**
+ * This method will handle the event for a sata device that is in
+ * the idle state. We pick up suspension events to handle specifically
+ * to this state. We resume the RNC right away.
+ *
+ * @param [in] device The device received event.
+ * @param [in] event_code The event code.
+ *
+ * @return SCI_STATUS
+ */
+static
+SCI_STATUS scic_sds_stp_remote_device_ready_idle_substate_event_handler(
+   SCIC_SDS_REMOTE_DEVICE_T * this_device,
+   U32                        event_code
+)
+{
+   SCI_STATUS status;
+
+   status = scic_sds_remote_device_general_event_handler(this_device, event_code);
+
+   if (status == SCI_SUCCESS)
+   {
+      if ((scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX
+          || scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX)
+          && (this_device->rnc->destination_state != SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY))
+      {
+         status = scic_sds_remote_node_context_resume(
+                  this_device->rnc, NULL, NULL);
+      }
+   }
+
+   return status;
+}
+
+
+//*****************************************************************************
+//*  STP REMOTE DEVICE READY NCQ SUBSTATE HANDLERS
+//*****************************************************************************
+
+/**
+ *
+ */
+static
+SCI_STATUS scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler(
+   SCI_BASE_REMOTE_DEVICE_T * device,
+   SCI_BASE_REQUEST_T       * request
+)
+{
+   SCI_STATUS status;
+   SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
+   SCIC_SDS_REQUEST_T       * io_request  = (SCIC_SDS_REQUEST_T       *)request;
+
+   if (io_request->sat_protocol == SAT_PROTOCOL_FPDMA)
+   {
+      status = this_device->owning_port->state_handlers->start_io_handler(
+         this_device->owning_port,
+         this_device,
+         io_request
+      );
+
+      if (status == SCI_SUCCESS)
+      {
+         status = scic_sds_remote_node_context_start_io(this_device->rnc, io_request);
+
+         if (status == SCI_SUCCESS)
+         {
+            status = io_request->state_handlers->parent.start_handler(request);
+         }
+
+         scic_sds_remote_device_start_request(this_device, io_request, status);
+      }
+   }
+   else
+   {
+      status = SCI_FAILURE_INVALID_STATE;
+   }
+
+   return status;
+}
+
+/**
+ *  This method will handle events received while the STP device is in the
+ *  ready command substate.
+ *
+ *  @param [in] this_device This is the device object that is receiving the
+ *         event.
+ *  @param [in] event_code The event code to process.
+ *
+ *  @return SCI_STATUS
+ */
+static
+SCI_STATUS scic_sds_stp_remote_device_ready_ncq_substate_event_handler(
+   SCIC_SDS_REMOTE_DEVICE_T * this_device,
+   U32                        event_code
+)
+{
+   SCI_STATUS status;
+
+   status = scic_sds_remote_device_general_event_handler(this_device, event_code);
+
+   switch (scu_get_event_code(event_code))
+   {
+   case SCU_EVENT_TL_RNC_SUSPEND_TX:
+   case SCU_EVENT_TL_RNC_SUSPEND_TX_RX:
+      /// @todo We need to decode and understand why the hardware suspended the device.
+      ///       The suspension reason was probably due to an SDB error FIS received.
+      break;
+
+   case SCU_EVENT_TL_RNC_SUSPEND_TX_DONE_DATA_LEN_ERR:
+   case SCU_EVENT_TL_RNC_SUSPEND_TX_DONE_OFFSET_ERR:
+   case SCU_EVENT_TL_RNC_SUSPEND_TX_DONE_DMASETUP_DIERR:
+   case SCU_EVENT_TL_RNC_SUSPEND_TX_DONE_XFERCNT_ERR:
+   case SCU_EVENT_TL_RNC_SUSPEND_TX_RX_DONE_PLD_LEN_ERR:
+      this_device->not_ready_reason =
+         SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED;
+
+      sci_base_state_machine_change_state(
+         &this_device->ready_substate_machine,
+         SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR
+      );
+
+      // We have a notification that the driver requested a suspend operation
+      // this should not happen.
+      SCIC_LOG_WARNING((
+         sci_base_object_get_logger(this_device),
+         SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
+         "SCIC Remote device 0x%x received driver suspend event %x while in ncq ready substate %d\n",
+         this_device, event_code, sci_base_state_machine_get_state(&this_device->ready_substate_machine)
+      ));
+
+      // Since we didnt expect to get here start the device again.
+      status = scic_sds_remote_device_resume(this_device);
+      break;
+
+   case SCU_EVENT_POST_RCN_RELEASE:
+      /// @todo Do we need to store the suspend state on the device?
+      SCIC_LOG_INFO((
+         sci_base_object_get_logger(this_device),
+         SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
+         "SCIC Remote device 0x%x received driver release event %x while in the ready substate %d\n",
+         this_device, event_code, sci_base_state_machine_get_state(&this_device->ready_substate_machine)
+      ));
+      break;
+
+   default:
+      // Some other event just log it and continue
+      SCIC_LOG_WARNING((
+         sci_base_object_get_logger(this_device),
+         SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
+         "SCIC Remote device 0x%x received driver unexpected event %x while in the ready substate %d\n",
+         this_device, event_code, sci_base_state_machine_get_state(&this_device->ready_substate_machine)
+      ));
+
+      status = SCI_FAILURE_INVALID_STATE;
+      break;
+   }
+
+   return status;
+}
+
+/**
+ *
+ *
+ * @param[in] this_device
+ * @param[in] frame_index
+ *
+ * @return SCI_STATUS
+ */
+static
+SCI_STATUS scic_sds_stp_remote_device_ready_ncq_substate_frame_handler(
+   SCIC_SDS_REMOTE_DEVICE_T * this_device,
+   U32                        frame_index
+)
+{
+   SCI_STATUS           status;
+   SATA_FIS_HEADER_T  * frame_header;
+
+   status = scic_sds_unsolicited_frame_control_get_header(
+      &(scic_sds_remote_device_get_controller(this_device)->uf_control),
+      frame_index,
+      (void **)&frame_header
+   );
+
+   if (status == SCI_SUCCESS)
+   {
+      if (
+            (frame_header->fis_type == SATA_FIS_TYPE_SETDEVBITS)
+         && (frame_header->status & ATA_STATUS_REG_ERROR_BIT)
+         )
+      {
+         this_device->not_ready_reason =
+            SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED;
+
+         /** @todo Check sactive and complete associated IO if any. */
+
+         sci_base_state_machine_change_state(
+            &this_device->ready_substate_machine,
+            SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR
+         );
+      }
+      else if (
+            (frame_header->fis_type == SATA_FIS_TYPE_REGD2H)
+         && (frame_header->status & ATA_STATUS_REG_ERROR_BIT)
+         )
+      {
+         // Some devices return D2H FIS when an NCQ error is detected.
+         // Treat this like an SDB error FIS ready reason.
+         this_device->not_ready_reason =
+            SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED;
+
+         sci_base_state_machine_change_state(
+            &this_device->ready_substate_machine,
+            SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR
+         );
+      }
+      else
+      {
+         status = SCI_FAILURE;
+      }
+
+      scic_sds_controller_release_frame(
+         scic_sds_remote_device_get_controller(this_device), frame_index
+      );
+   }
+
+   return status;
+}
+
+//*****************************************************************************
+//*  STP REMOTE DEVICE READY CMD SUBSTATE HANDLERS
+//*****************************************************************************
+
+/**
+ * This device is already handling a command it can not accept new commands
+ * until this one is complete.
+ *
+ * @param[in] device
+ * @param[in] request
+ *
+ * @return SCI_STATUS
+ */
+static
+SCI_STATUS scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler(
+   SCI_BASE_REMOTE_DEVICE_T * device,
+   SCI_BASE_REQUEST_T       * request
+)
+{
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+static
+SCI_STATUS scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler(
+   SCIC_SDS_REMOTE_DEVICE_T * this_device,
+   U32                        suspend_type
+)
+{
+   SCI_STATUS status;
+
+   status = scic_sds_remote_node_context_suspend(
+      this_device->rnc, suspend_type, NULL, NULL
+   );
+
+   return status;
+}
+
+/**
+ *
+ *
+ * @param[in] this_device
+ * @param[in] frame_index
+ *
+ * @return SCI_STATUS
+ */
+static
+SCI_STATUS scic_sds_stp_remote_device_ready_cmd_substate_frame_handler(
+   SCIC_SDS_REMOTE_DEVICE_T * this_device,
+   U32                        frame_index
+)
+{
+   SCI_STATUS status;
+
+   /// The device doe not process any UF received from the hardware while
+   /// in this state.  All unsolicited frames are forwarded to the io request
+   /// object.
+   status = scic_sds_io_request_frame_handler(
+      this_device->working_request,
+      frame_index
+   );
+
+   return status;
+}
+
+
+//*****************************************************************************
+//*  STP REMOTE DEVICE READY NCQ SUBSTATE HANDLERS
+//*****************************************************************************
+
+
+//*****************************************************************************
+//*  STP REMOTE DEVICE READY AWAIT RESET SUBSTATE HANDLERS
+//*****************************************************************************
+static
+SCI_STATUS scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler(
+   SCI_BASE_REMOTE_DEVICE_T * device,
+   SCI_BASE_REQUEST_T       * request
+)
+{
+   return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED;
+}
+
+
+
+/**
+ * This method will perform the STP request (both io or task) completion
+ * processing for await reset state.
+ *
+ * @param[in] device This parameter specifies the device for which the
+ *            request is being completed.
+ * @param[in] request This parameter specifies the request being completed.
+ *
+ * @return This method returns an indication as to whether the request
+ *         processing completed successfully.
+ */
+static
+SCI_STATUS scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler(
+   SCI_BASE_REMOTE_DEVICE_T * device,
+   SCI_BASE_REQUEST_T       * request
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
+   SCIC_SDS_REQUEST_T       * the_request = (SCIC_SDS_REQUEST_T *)request;
+   SCI_STATUS                 status;
+
+   status = scic_sds_io_request_complete(the_request);
+
+   if (status == SCI_SUCCESS)
+   {
+      status = scic_sds_port_complete_io(
+                  this_device->owning_port, this_device, the_request
+               );
+
+      if (status == SCI_SUCCESS)
+         scic_sds_remote_device_decrement_request_count(this_device);
+   }
+
+   if (status != SCI_SUCCESS)
+   {
+      SCIC_LOG_ERROR((
+         sci_base_object_get_logger(this_device),
+         SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
+         "Port:0x%x Device:0x%x Request:0x%x Status:0x%x could not complete\n",
+         this_device->owning_port, this_device, the_request, status
+      ));
+   }
+
+   return status;
+}
+
+#if !defined(DISABLE_ATAPI)
+//*****************************************************************************
+//*  STP REMOTE DEVICE READY ATAPI ERROR SUBSTATE HANDLERS
+//*****************************************************************************
+
+/**
+ * This method will handle the event for a ATAPI device that is in
+ * the ATAPI ERROR state. We pick up suspension events to handle specifically
+ * to this state. We resume the RNC right away. We then complete the outstanding
+ * IO to this device.
+ *
+ * @param [in] device The device received event.
+ * @param [in] event_code The event code.
+ *
+ * @return SCI_STATUS
+ */
+static
+SCI_STATUS scic_sds_stp_remote_device_ready_atapi_error_substate_event_handler(
+   SCIC_SDS_REMOTE_DEVICE_T * this_device,
+   U32                        event_code
+)
+{
+   SCI_STATUS status;
+
+   status = scic_sds_remote_device_general_event_handler(this_device, event_code);
+
+   if (status == SCI_SUCCESS)
+   {
+      if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX
+          || scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX)
+      {
+         status = scic_sds_remote_node_context_resume(
+                     this_device->rnc,
+                     (SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK)
+                        this_device->working_request->state_handlers->parent.complete_handler,
+                     (void *)this_device->working_request
+                  );
+      }
+   }
+
+   return status;
+}
+#endif // !defined(DISABLE_ATAPI)
+
+// ---------------------------------------------------------------------------
+
+SCIC_SDS_REMOTE_DEVICE_STATE_HANDLER_T
+   scic_sds_stp_remote_device_ready_substate_handler_table[
+                              SCIC_SDS_STP_REMOTE_DEVICE_READY_MAX_SUBSTATES] =
+{
+   // SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
+   {
+      {
+         scic_sds_remote_device_default_start_handler,
+         scic_sds_remote_device_ready_state_stop_handler,
+         scic_sds_remote_device_default_fail_handler,
+         scic_sds_remote_device_default_destruct_handler,
+         scic_sds_remote_device_ready_state_reset_handler,
+         scic_sds_remote_device_default_reset_complete_handler,
+         scic_sds_stp_remote_device_ready_idle_substate_start_io_handler,
+         scic_sds_remote_device_default_complete_request_handler,
+         scic_sds_remote_device_default_continue_request_handler,
+         scic_sds_stp_remote_device_ready_substate_start_request_handler,
+         scic_sds_remote_device_default_complete_request_handler
+      },
+      scic_sds_remote_device_default_suspend_handler,
+      scic_sds_remote_device_default_resume_handler,
+      scic_sds_stp_remote_device_ready_idle_substate_event_handler,
+      scic_sds_remote_device_default_frame_handler
+   },
+   // SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD
+   {
+      {
+         scic_sds_remote_device_default_start_handler,
+         scic_sds_remote_device_ready_state_stop_handler,
+         scic_sds_remote_device_default_fail_handler,
+         scic_sds_remote_device_default_destruct_handler,
+         scic_sds_remote_device_ready_state_reset_handler,
+         scic_sds_remote_device_default_reset_complete_handler,
+         scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler,
+         scic_sds_stp_remote_device_complete_request,
+         scic_sds_remote_device_default_continue_request_handler,
+         scic_sds_stp_remote_device_ready_substate_start_request_handler,
+         scic_sds_stp_remote_device_complete_request,
+      },
+      scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler,
+      scic_sds_remote_device_default_resume_handler,
+      scic_sds_remote_device_general_event_handler,
+      scic_sds_stp_remote_device_ready_cmd_substate_frame_handler
+   },
+   // SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ
+   {
+      {
+         scic_sds_remote_device_default_start_handler,
+         scic_sds_remote_device_ready_state_stop_handler,
+         scic_sds_remote_device_default_fail_handler,
+         scic_sds_remote_device_default_destruct_handler,
+         scic_sds_remote_device_ready_state_reset_handler,
+         scic_sds_remote_device_default_reset_complete_handler,
+         scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler,
+         scic_sds_stp_remote_device_complete_request,
+         scic_sds_remote_device_default_continue_request_handler,
+         scic_sds_stp_remote_device_ready_substate_start_request_handler,
+         scic_sds_stp_remote_device_complete_request
+      },
+      scic_sds_remote_device_default_suspend_handler,
+      scic_sds_remote_device_default_resume_handler,
+      scic_sds_stp_remote_device_ready_ncq_substate_event_handler,
+      scic_sds_stp_remote_device_ready_ncq_substate_frame_handler
+   },
+   // SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR
+   {
+      {
+         scic_sds_remote_device_default_start_handler,
+         scic_sds_remote_device_ready_state_stop_handler,
+         scic_sds_remote_device_default_fail_handler,
+         scic_sds_remote_device_default_destruct_handler,
+         scic_sds_remote_device_ready_state_reset_handler,
+         scic_sds_remote_device_default_reset_complete_handler,
+         scic_sds_remote_device_default_start_request_handler,
+         scic_sds_stp_remote_device_complete_request,
+         scic_sds_remote_device_default_continue_request_handler,
+         scic_sds_stp_remote_device_ready_substate_start_request_handler,
+         scic_sds_stp_remote_device_complete_request
+      },
+      scic_sds_remote_device_default_suspend_handler,
+      scic_sds_remote_device_default_resume_handler,
+      scic_sds_remote_device_general_event_handler,
+      scic_sds_remote_device_general_frame_handler
+   },
+#if !defined(DISABLE_ATAPI)
+   // SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR
+   {
+      {
+         scic_sds_remote_device_default_start_handler,
+         scic_sds_remote_device_ready_state_stop_handler,
+         scic_sds_remote_device_default_fail_handler,
+         scic_sds_remote_device_default_destruct_handler,
+         scic_sds_remote_device_ready_state_reset_handler,
+         scic_sds_remote_device_default_reset_complete_handler,
+         scic_sds_remote_device_default_start_request_handler,
+         scic_sds_stp_remote_device_complete_request,
+         scic_sds_remote_device_default_continue_request_handler,
+         scic_sds_stp_remote_device_ready_substate_start_request_handler,
+         scic_sds_stp_remote_device_complete_request
+      },
+      scic_sds_remote_device_default_suspend_handler,
+      scic_sds_remote_device_default_resume_handler,
+      scic_sds_stp_remote_device_ready_atapi_error_substate_event_handler,
+      scic_sds_remote_device_general_frame_handler
+   },
+#endif
+   // SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET
+   {
+      {
+         scic_sds_remote_device_default_start_handler,
+         scic_sds_remote_device_ready_state_stop_handler,
+         scic_sds_remote_device_default_fail_handler,
+         scic_sds_remote_device_default_destruct_handler,
+         scic_sds_remote_device_ready_state_reset_handler,
+         scic_sds_remote_device_default_reset_complete_handler,
+         scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler,
+         scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler,
+         scic_sds_remote_device_default_continue_request_handler,
+         scic_sds_stp_remote_device_ready_substate_start_request_handler,
+         scic_sds_stp_remote_device_complete_request
+      },
+      scic_sds_remote_device_default_suspend_handler,
+      scic_sds_remote_device_default_resume_handler,
+      scic_sds_remote_device_general_event_handler,
+      scic_sds_remote_device_general_frame_handler
+   }
+};
+
+//*****************************************************************************
+//*  STP REMOTE DEVICE READY SUBSTATE PRIVATE METHODS
+//*****************************************************************************
+
+static
+void scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(
+   void * user_cookie
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T * this_device;
+   this_device = (SCIC_SDS_REMOTE_DEVICE_T *)user_cookie;
+
+   // For NCQ operation we do not issue a
+   // scic_cb_remote_device_not_ready().  As a result, avoid sending
+   // the ready notification.
+   if (this_device->ready_substate_machine.previous_state_id
+       != SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ)
+   {
+      scic_cb_remote_device_ready(
+         scic_sds_remote_device_get_controller(this_device), this_device
+      );
+   }
+}
+
+//*****************************************************************************
+//*  STP REMOTE DEVICE READY IDLE SUBSTATE
+//*****************************************************************************
+
+/**
+ *
+ * @param[in] device This is the SCI base object which is cast into a
+ *       SCIC_SDS_REMOTE_DEVICE object.
+ *
+ * @return none
+ */
+static
+void scic_sds_stp_remote_device_ready_idle_substate_enter(
+   SCI_BASE_OBJECT_T * device
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T * this_device;
+
+   this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
+
+   SET_STATE_HANDLER(
+      this_device,
+      scic_sds_stp_remote_device_ready_substate_handler_table,
+      SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
+   );
+
+   this_device->working_request = NULL;
+
+   if (scic_sds_remote_node_context_is_ready(this_device->rnc))
+   {
+      // Since the RNC is ready, it's alright to finish completion
+      // processing (e.g. signal the remote device is ready).
+      scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(
+         this_device
+      );
+   }
+   else
+   {
+      scic_sds_remote_node_context_resume(
+         this_device->rnc,
+         scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler,
+         this_device
+      );
+   }
+}
+
+//*****************************************************************************
+//*  STP REMOTE DEVICE READY CMD SUBSTATE
+//*****************************************************************************
+
+/**
+ *
+ *
+ * @param[in] device This is the SCI base object which is cast into a
+ *       SCIC_SDS_REMOTE_DEVICE object.
+ *
+ * @return none
+ */
+static
+void scic_sds_stp_remote_device_ready_cmd_substate_enter(
+   SCI_BASE_OBJECT_T * device
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T * this_device;
+
+   this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
+
+   ASSERT(this_device->working_request != NULL);
+
+   SET_STATE_HANDLER(
+      this_device,
+      scic_sds_stp_remote_device_ready_substate_handler_table,
+      SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD
+   );
+
+   scic_cb_remote_device_not_ready(
+      scic_sds_remote_device_get_controller(this_device),
+      this_device,
+      SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED
+   );
+}
+
+//*****************************************************************************
+//*  STP REMOTE DEVICE READY NCQ SUBSTATE
+//*****************************************************************************
+
+/**
+ *
+ *
+ * @param[in] device This is the SCI base object which is cast into a
+ *       SCIC_SDS_REMOTE_DEVICE object.
+ *
+ * @return none
+ */
+static
+void scic_sds_stp_remote_device_ready_ncq_substate_enter(
+   SCI_BASE_OBJECT_T * device
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T * this_device;
+
+   this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
+
+   SET_STATE_HANDLER(
+      this_device,
+      scic_sds_stp_remote_device_ready_substate_handler_table,
+      SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ
+   );
+}
+
+//*****************************************************************************
+//*  STP REMOTE DEVICE READY NCQ ERROR SUBSTATE
+//*****************************************************************************
+
+/**
+ *
+ *
+ * @param[in] device This is the SCI base object which is cast into a
+ *       SCIC_SDS_REMOTE_DEVICE object.
+ *
+ * @return none
+ */
+static
+void scic_sds_stp_remote_device_ready_ncq_error_substate_enter(
+   SCI_BASE_OBJECT_T * device
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T * this_device;
+
+   this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
+
+   SET_STATE_HANDLER(
+      this_device,
+      scic_sds_stp_remote_device_ready_substate_handler_table,
+      SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR
+   );
+
+   if(this_device->not_ready_reason ==
+         SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED)
+   {
+      scic_cb_remote_device_not_ready(
+         scic_sds_remote_device_get_controller(this_device),
+         this_device,
+         this_device->not_ready_reason
+      );
+   }
+}
+
+//*****************************************************************************
+//*  STP REMOTE DEVICE READY AWAIT RESET SUBSTATE
+//*****************************************************************************
+
+/**
+ * @brief The enter routine to READY AWAIT RESET substate.
+ *
+ * @param[in] device This is the SCI base object which is cast into a
+ *       SCIC_SDS_REMOTE_DEVICE object.
+ *
+ * @return none
+ */
+static
+void scic_sds_stp_remote_device_ready_await_reset_substate_enter(
+   SCI_BASE_OBJECT_T * device
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T * this_device;
+
+   this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
+
+   SET_STATE_HANDLER(
+      this_device,
+      scic_sds_stp_remote_device_ready_substate_handler_table,
+      SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET
+   );
+}
+
+#if !defined(DISABLE_ATAPI)
+//*****************************************************************************
+//*  STP REMOTE DEVICE READY ATAPI ERROR SUBSTATE
+//*****************************************************************************
+
+/**
+ * @brief The enter routine to READY ATAPI ERROR substate.
+ *
+ * @param[in] device This is the SCI base object which is cast into a
+ *       SCIC_SDS_REMOTE_DEVICE object.
+ *
+ * @return none
+ */
+static
+void scic_sds_stp_remote_device_ready_atapi_error_substate_enter(
+   SCI_BASE_OBJECT_T * device
+)
+{
+   SCIC_SDS_REMOTE_DEVICE_T * this_device;
+
+   this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
+
+   SET_STATE_HANDLER(
+      this_device,
+      scic_sds_stp_remote_device_ready_substate_handler_table,
+      SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR
+   );
+}
+#endif // !defined(DISABLE_ATAPI)
+
+// ---------------------------------------------------------------------------
+
+SCI_BASE_STATE_T
+   scic_sds_stp_remote_device_ready_substate_table[
+      SCIC_SDS_STP_REMOTE_DEVICE_READY_MAX_SUBSTATES] =
+{
+   {
+      SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE,
+      scic_sds_stp_remote_device_ready_idle_substate_enter,
+      NULL
+   },
+   {
+      SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD,
+      scic_sds_stp_remote_device_ready_cmd_substate_enter,
+      NULL
+   },
+   {
+      SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ,
+      scic_sds_stp_remote_device_ready_ncq_substate_enter,
+      NULL
+   },
+   {
+      SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR,
+      scic_sds_stp_remote_device_ready_ncq_error_substate_enter,
+      NULL
+   },
+#if !defined(DISABLE_ATAPI)
+   {
+      SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR,
+      scic_sds_stp_remote_device_ready_atapi_error_substate_enter,
+      NULL
+   },
+#endif
+   {
+      SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET,
+      scic_sds_stp_remote_device_ready_await_reset_substate_enter,
+      NULL
+   }
+};
diff --git a/sys/dev/disk/isci/scil/scic_sds_stp_request.c b/sys/dev/disk/isci/scil/scic_sds_stp_request.c
new file mode 100644
index 0000000..435c8ab
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_sds_stp_request.c
@@ -0,0 +1,2578 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_sds_stp_request.c,v 1.2 2012/02/07 17:45:11 jimharris Exp $
+ */
+
+#include <dev/disk/isci/scil/intel_sat.h>
+#include <dev/disk/isci/scil/intel_sata.h>
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/scic_remote_device.h>
+#include <dev/disk/isci/scil/scic_user_callback.h>
+#include <dev/disk/isci/scil/scic_sds_controller.h>
+#include <dev/disk/isci/scil/scic_sds_remote_device.h>
+#include <dev/disk/isci/scil/scic_sds_stp_request.h>
+#include <dev/disk/isci/scil/scic_sds_stp_pio_request.h>
+#include <dev/disk/isci/scil/scic_sds_logger.h>
+#include <dev/disk/isci/sci_environment.h>
+#include <dev/disk/isci/scil/sci_base_state_machine.h>
+#include <dev/disk/isci/scil/scu_task_context.h>
+#include <dev/disk/isci/scil/intel_ata.h>
+#include <dev/disk/isci/scil/sci_util.h>
+#include <dev/disk/isci/scil/scic_sds_logger.h>
+#include <dev/disk/isci/scil/scic_sds_request.h>
+#include <dev/disk/isci/scil/scic_sds_stp_request.h>
+#include <dev/disk/isci/scil/scu_completion_codes.h>
+#include <dev/disk/isci/scil/scu_event_codes.h>
+#include <dev/disk/isci/scil/sci_base_state.h>
+#include <dev/disk/isci/scil/scic_sds_unsolicited_frame_control.h>
+#include <dev/disk/isci/scil/scic_io_request.h>
+
+#if !defined(DISABLE_ATAPI)
+#include <dev/disk/isci/scil/scic_sds_stp_packet_request.h>
+#endif
+
+/**
+ * This macro returns the address of the stp h2d reg fis buffer in the io
+ * request memory
+ */
+#define scic_sds_stp_request_get_h2d_reg_buffer_unaligned(memory) \
+   ((SATA_FIS_REG_H2D_T *)( \
+      ((char *)(memory)) + sizeof(SCIC_SDS_STP_REQUEST_T) \
+   ))
+
+/**
+ * This macro aligns the stp command buffer in DWORD alignment
+*/
+#define scic_sds_stp_request_align_h2d_reg_buffer(address) \
+   ((SATA_FIS_REG_H2D_T *)( \
+      (((POINTER_UINT)(address)) + (sizeof(U32) - 1)) \
+         & ~(sizeof(U32)- 1) \
+      ))
+
+/**
+ * This macro returns the DWORD-aligned stp command buffer
+*/
+#define scic_sds_stp_request_get_h2d_reg_buffer(memory) \
+   ((SATA_FIS_REG_H2D_T *)  \
+       ((char *)scic_sds_stp_request_align_h2d_reg_buffer( \
+       (char *) scic_sds_stp_request_get_h2d_reg_buffer_unaligned(memory) \
+   )))
+
+/**
+ * This macro returns the address of the stp response buffer in the io
+ * request memory
+ */
+#define scic_sds_stp_request_get_response_buffer_unaligned(memory) \
+   ((SATA_FIS_REG_D2H_T *)( \
+         ((char *)(scic_sds_stp_request_get_h2d_reg_buffer(memory))) \
+       + sizeof(SATA_FIS_REG_H2D_T) \
+   ))
+
+
+/**
+ * This macro aligns the stp response buffer in DWORD alignment
+*/
+#define scic_sds_stp_request_align_response_buffer(address) \
+   ((SATA_FIS_REG_D2H_T *)( \
+      (((POINTER_UINT)(address)) + (sizeof(U32) - 1)) \
+         & ~(sizeof(U32)- 1) \
+   ))
+
+/**
+ * This macro returns the DWORD-aligned stp response buffer
+*/
+#define scic_sds_stp_request_get_response_buffer(memory) \
+   ((SATA_FIS_REG_D2H_T *)  \
+      ((char *)scic_sds_stp_request_align_response_buffer( \
+         (char *)scic_sds_stp_request_get_response_buffer_unaligned(memory) \
+   )))
+
+
+/**
+ * This macro returns the address of the task context buffer in the io
+ * request memory
+ */
+#define scic_sds_stp_request_get_task_context_buffer_unaligned(memory) \
+   ((SCU_TASK_CONTEXT_T *)( \
+        ((char *)(scic_sds_stp_request_get_response_buffer(memory))) \
+      + sizeof(SCI_SSP_RESPONSE_IU_T) \
+   ))
+
+/**
+ * This macro returns the aligned task context buffer
+ */
+#define scic_sds_stp_request_get_task_context_buffer(memory) \
+   ((SCU_TASK_CONTEXT_T *)( \
+      ((char *)scic_sds_request_align_task_context_buffer( \
+         (char *)scic_sds_stp_request_get_task_context_buffer_unaligned(memory)) \
+    )))
+
+/**
+ * This macro returns the address of the sgl elment pairs in the io request
+ * memory buffer
+ */
+#define scic_sds_stp_request_get_sgl_element_buffer(memory) \
+   ((SCU_SGL_ELEMENT_PAIR_T *)( \
+        ((char *)(scic_sds_stp_request_get_task_context_buffer(memory))) \
+      + sizeof(SCU_TASK_CONTEXT_T) \
+    ))
+
+
+/**
+ * This method return the memory space commonly required for STP IO and
+ * task requests.
+ *
+ * @return U32
+ */
+static
+U32 scic_sds_stp_common_request_get_object_size(void)
+{
+   return   sizeof(SCIC_SDS_STP_REQUEST_T)
+          + sizeof(SATA_FIS_REG_H2D_T)
+          + sizeof(U32)
+          + sizeof(SATA_FIS_REG_D2H_T)
+          + sizeof(U32)
+          + sizeof(SCU_TASK_CONTEXT_T)
+          + CACHE_LINE_SIZE;
+}
+
+
+/**
+ * This method return the memory space required for STP PIO requests.
+ *
+ * @return U32
+ */
+U32 scic_sds_stp_request_get_object_size(void)
+{
+   return   scic_sds_stp_common_request_get_object_size()
+          + sizeof(SCU_SGL_ELEMENT_PAIR_T) * SCU_MAX_SGL_ELEMENT_PAIRS;
+}
+
+
+/**
+ * This method return the memory space required for STP task requests.
+ *
+ * @return U32
+ */
+U32 scic_sds_stp_task_request_get_object_size(void)
+{
+   return scic_sds_stp_common_request_get_object_size();
+}
+
+
+/**
+ *
+ *
+ * @param[in] this_request
+ */
+void scic_sds_stp_request_assign_buffers(
+   SCIC_SDS_REQUEST_T * request
+)
+{
+   SCIC_SDS_STP_REQUEST_T * this_request = (SCIC_SDS_STP_REQUEST_T *)request;
+
+   this_request->parent.command_buffer =
+      scic_sds_stp_request_get_h2d_reg_buffer(this_request);
+   this_request->parent.response_buffer =
+      scic_sds_stp_request_get_response_buffer(this_request);
+   this_request->parent.sgl_element_pair_buffer =
+      scic_sds_stp_request_get_sgl_element_buffer(this_request);
+   this_request->parent.sgl_element_pair_buffer =
+      scic_sds_request_align_sgl_element_buffer(this_request->parent.sgl_element_pair_buffer);
+
+   if (this_request->parent.was_tag_assigned_by_user == FALSE)
+   {
+      this_request->parent.task_context_buffer =
+         scic_sds_stp_request_get_task_context_buffer(this_request);
+   }
+}
+
+/**
+ * @brief This method is will fill in the SCU Task Context for any type of
+ *        SATA request.  This is called from the various SATA constructors.
+ *
+ * @pre The general io request construction is complete.
+ * @pre The buffer assignment for the command buffer is complete.
+ *
+ * @param[in] this_request The general IO request object which is to be used
+ *       in constructing the SCU task context.
+ * @param[in] task_context The buffer pointer for the SCU task context which
+ *       is being constructed.
+ *
+ * @return none
+ *
+ * @todo Revisit task context construction to determine what is common for
+ *       SSP/SMP/STP task context structures.
+ */
+void scu_sata_reqeust_construct_task_context(
+   SCIC_SDS_REQUEST_T * this_request,
+   SCU_TASK_CONTEXT_T * task_context
+)
+{
+   SCI_PHYSICAL_ADDRESS      physical_address;
+   SCIC_SDS_CONTROLLER_T    *owning_controller;
+   SCIC_SDS_REMOTE_DEVICE_T *target_device;
+   SCIC_SDS_PORT_T          *target_port;
+
+   owning_controller = scic_sds_request_get_controller(this_request);
+   target_device = scic_sds_request_get_device(this_request);
+   target_port = scic_sds_request_get_port(this_request);
+
+   // Fill in the TC with the its required data
+   task_context->abort = 0;
+   task_context->priority = SCU_TASK_PRIORITY_NORMAL;
+   task_context->initiator_request = 1;
+   task_context->connection_rate =
+      scic_remote_device_get_connection_rate(target_device);
+   task_context->protocol_engine_index =
+      scic_sds_controller_get_protocol_engine_group(owning_controller);
+   task_context->logical_port_index =
+      scic_sds_port_get_index(target_port);
+   task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_STP;
+   task_context->valid = SCU_TASK_CONTEXT_VALID;
+   task_context->context_type = SCU_TASK_CONTEXT_TYPE;
+
+   task_context->remote_node_index =
+      scic_sds_remote_device_get_index(this_request->target_device);
+   task_context->command_code = 0;
+
+   task_context->link_layer_control = 0;
+   task_context->do_not_dma_ssp_good_response = 1;
+   task_context->strict_ordering = 0;
+   task_context->control_frame = 0;
+   task_context->timeout_enable = 0;
+   task_context->block_guard_enable = 0;
+
+   task_context->address_modifier = 0;
+   task_context->task_phase = 0x01;
+
+   task_context->ssp_command_iu_length =
+      (sizeof(SATA_FIS_REG_H2D_T) - sizeof(U32)) / sizeof(U32);
+
+   // Set the first word of the H2D REG FIS
+   task_context->type.words[0] = *(U32 *)this_request->command_buffer;
+
+   if (this_request->was_tag_assigned_by_user)
+   {
+      // Build the task context now since we have already read the data
+      this_request->post_context = (
+           SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC
+         | (
+                scic_sds_controller_get_protocol_engine_group(owning_controller)
+             << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT
+           )
+         | (
+                 scic_sds_port_get_index(target_port)
+              << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT
+           )
+         | scic_sds_io_tag_get_index(this_request->io_tag)
+      );
+   }
+   else
+   {
+      // Build the task context now since we have already read the data
+      this_request->post_context = (
+           SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC
+         | (
+               scic_sds_controller_get_protocol_engine_group(owning_controller)
+            << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT
+           )
+         | (
+                scic_sds_port_get_index(target_port)
+             << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT
+           )
+         // This is not assigned because we have to wait until we get a TCi
+      );
+   }
+
+   // Copy the physical address for the command buffer to the SCU Task Context
+   // We must offset the command buffer by 4 bytes because the first 4 bytes are
+   // transfered in the body of the TC
+   scic_cb_io_request_get_physical_address(
+      scic_sds_request_get_controller(this_request),
+      this_request,
+      ((char *)this_request->command_buffer) + sizeof(U32),
+      &physical_address
+   );
+
+   task_context->command_iu_upper =
+      sci_cb_physical_address_upper(physical_address);
+   task_context->command_iu_lower =
+      sci_cb_physical_address_lower(physical_address);
+
+   // SATA Requests do not have a response buffer
+   task_context->response_iu_upper = 0;
+   task_context->response_iu_lower = 0;
+}
+
+/**
+ * This method will perform any general sata request construction.
+ *
+ * @todo What part of SATA IO request construction is general?
+ *
+ * @param[in] this_request
+ *
+ * @return none
+ */
+void scic_sds_stp_non_ncq_request_construct(
+   SCIC_SDS_REQUEST_T * this_request
+)
+{
+   this_request->has_started_substate_machine = TRUE;
+}
+
+/**
+ * This method will perform request construction common to all types of
+ * STP requests that are optimized by the silicon (i.e. UDMA, NCQ).
+ *
+ * @param[in,out] this_request This parameter specifies the request to be
+ *                constructed as an optimized request.
+ * @param[in] optimized_task_type This parameter specifies whether the
+ *            request is to be an UDMA request or a NCQ request.
+ *            - A value of 0 indicates UDMA.
+ *            - A value of 1 indicates NCQ.
+ *
+ * @return This method returns an indication as to whether the construction
+ *         was successful.
+ */
+static
+void scic_sds_stp_optimized_request_construct(
+   SCIC_SDS_REQUEST_T * this_request,
+   U8                   optimized_task_type,
+   U32                  transfer_length,
+   SCI_IO_REQUEST_DATA_DIRECTION data_direction
+)
+{
+   SCU_TASK_CONTEXT_T * task_context = this_request->task_context_buffer;
+
+   // Build the STP task context structure
+   scu_sata_reqeust_construct_task_context(this_request, task_context);
+
+   // Copy over the number of bytes to be transfered
+   task_context->transfer_length_bytes = transfer_length;
+
+   if ( data_direction == SCI_IO_REQUEST_DATA_OUT )
+   {
+      // The difference between the DMA IN and DMA OUT request task type
+      // values are consistent with the difference between FPDMA READ
+      // and FPDMA WRITE values.  Add the supplied task type parameter
+      // to this difference to set the task type properly for this
+      // DATA OUT (WRITE) case.
+      task_context->task_type = optimized_task_type + (SCU_TASK_TYPE_DMA_OUT
+                                                     - SCU_TASK_TYPE_DMA_IN);
+   }
+   else
+   {
+      // For the DATA IN (READ) case, simply save the supplied
+      // optimized task type.
+      task_context->task_type = optimized_task_type;
+   }
+}
+
+/**
+ * This method performs the operations common to all SATA/STP requests
+ * utilizing the raw frame method.
+ *
+ * @param[in] this_request This parameter specifies the STP request object
+ *            for which to construct a RAW command frame task context.
+ * @param[in] task_context This parameter specifies the SCU specific
+ *            task context buffer to construct.
+ *
+ * @return none
+ */
+void scu_stp_raw_request_construct_task_context(
+   SCIC_SDS_STP_REQUEST_T * this_request,
+   SCU_TASK_CONTEXT_T     * task_context
+)
+{
+   scu_sata_reqeust_construct_task_context(&this_request->parent, task_context);
+
+   task_context->control_frame         = 0;
+   task_context->priority              = SCU_TASK_PRIORITY_NORMAL;
+   task_context->task_type             = SCU_TASK_TYPE_SATA_RAW_FRAME;
+   task_context->type.stp.fis_type     = SATA_FIS_TYPE_REGH2D;
+   task_context->transfer_length_bytes = sizeof(SATA_FIS_REG_H2D_T) - sizeof(U32);
+}
+
+/**
+ * This method will construct the STP Non-data request and its associated
+ * TC data.  A non-data request essentially behaves like a 0 length read
+ * request in the SCU.
+ *
+ * @param[in] this_request This parameter specifies the core request
+ *            object to construction into an STP/SATA non-data request.
+ *
+ * @return This method currently always returns SCI_SUCCESS
+ */
+SCI_STATUS scic_sds_stp_non_data_request_construct(
+   SCIC_SDS_REQUEST_T * this_request
+)
+{
+   scic_sds_stp_non_ncq_request_construct(this_request);
+
+   // Build the STP task context structure
+   scu_stp_raw_request_construct_task_context(
+      (SCIC_SDS_STP_REQUEST_T*) this_request,
+      this_request->task_context_buffer
+   );
+
+   sci_base_state_machine_construct(
+      &this_request->started_substate_machine,
+      &this_request->parent.parent,
+      scic_sds_stp_request_started_non_data_substate_table,
+      SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE
+   );
+
+   return SCI_SUCCESS;
+}
+
+
+SCI_STATUS scic_sds_stp_soft_reset_request_construct(
+   SCIC_SDS_REQUEST_T * this_request
+)
+{
+   scic_sds_stp_non_ncq_request_construct(this_request);
+
+   // Build the STP task context structure
+   scu_stp_raw_request_construct_task_context(
+      (SCIC_SDS_STP_REQUEST_T*) this_request,
+      this_request->task_context_buffer
+   );
+
+   sci_base_state_machine_construct(
+      &this_request->started_substate_machine,
+      &this_request->parent.parent,
+      scic_sds_stp_request_started_soft_reset_substate_table,
+      SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE
+   );
+
+   return SCI_SUCCESS;
+}
+
+/**
+ * @brief This method constructs the SATA request object.
+ *
+ * @param[in] this_request
+ * @param[in] sat_protocol
+ * @param[in] transfer_length
+ * @param[in] data_direction
+ * @param[in] copy_rx_frame
+ * @param[in] do_translate_sgl This parameter specifies whether SGL
+ *            translation should be performed or if the user is handling
+ *            it.
+ *
+ * @return SCI_STATUS
+ */
+SCI_STATUS scic_sds_io_request_construct_sata(
+   SCIC_SDS_REQUEST_T          * this_request,
+   U8                            sat_protocol,
+   U32                           transfer_length,
+   SCI_IO_REQUEST_DATA_DIRECTION data_direction,
+   BOOL                          copy_rx_frame,
+   BOOL                          do_translate_sgl
+)
+{
+   SCI_STATUS  status = SCI_SUCCESS;
+
+   this_request->protocol = SCIC_STP_PROTOCOL;
+
+   this_request->sat_protocol = sat_protocol;
+
+   switch (sat_protocol)
+   {
+   case SAT_PROTOCOL_FPDMA:
+      scic_sds_stp_optimized_request_construct(
+         this_request,
+         SCU_TASK_TYPE_FPDMAQ_READ,
+         transfer_length,
+         data_direction
+      );
+
+      // Copy over the SGL elements
+      if (do_translate_sgl == TRUE)
+         scic_sds_request_build_sgl(this_request);
+   break;
+
+   case SAT_PROTOCOL_UDMA_DATA_IN:
+   case SAT_PROTOCOL_UDMA_DATA_OUT:
+      scic_sds_stp_non_ncq_request_construct(this_request);
+
+      scic_sds_stp_optimized_request_construct(
+         this_request, SCU_TASK_TYPE_DMA_IN, transfer_length, data_direction
+      );
+
+      // Copy over the SGL elements
+      if (do_translate_sgl == TRUE)
+         scic_sds_request_build_sgl(this_request);
+
+      sci_base_state_machine_construct(
+         &this_request->started_substate_machine,
+         &this_request->parent.parent,
+         scic_sds_stp_request_started_udma_substate_table,
+         SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE
+      );
+   break;
+
+   case SAT_PROTOCOL_PIO_DATA_IN:
+   case SAT_PROTOCOL_PIO_DATA_OUT:
+      status = scic_sds_stp_pio_request_construct(
+                  this_request, sat_protocol, copy_rx_frame);
+   break;
+
+   case SAT_PROTOCOL_ATA_HARD_RESET:
+   case SAT_PROTOCOL_SOFT_RESET:
+      status = scic_sds_stp_soft_reset_request_construct(this_request);
+   break;
+
+   case SAT_PROTOCOL_NON_DATA:
+      status = scic_sds_stp_non_data_request_construct(this_request);
+   break;
+
+#if !defined(DISABLE_ATAPI)
+   case SAT_PROTOCOL_PACKET_NON_DATA:
+   case SAT_PROTOCOL_PACKET_DMA_DATA_IN:
+   case SAT_PROTOCOL_PACKET_DMA_DATA_OUT:
+   case SAT_PROTOCOL_PACKET_PIO_DATA_IN:
+   case SAT_PROTOCOL_PACKET_PIO_DATA_OUT:
+      status = scic_sds_stp_packet_request_construct(this_request);
+      if (do_translate_sgl == TRUE)
+         scic_sds_request_build_sgl(this_request);
+   break;
+#endif
+
+   case SAT_PROTOCOL_DMA_QUEUED:
+   case SAT_PROTOCOL_DMA:
+   case SAT_PROTOCOL_DEVICE_DIAGNOSTIC:
+   case SAT_PROTOCOL_DEVICE_RESET:
+   case SAT_PROTOCOL_RETURN_RESPONSE_INFO:
+   default:
+      SCIC_LOG_ERROR((
+         sci_base_object_get_logger(this_request),
+         SCIC_LOG_OBJECT_STP_IO_REQUEST,
+         "SCIC IO Request 0x%x received un-handled SAT Protocol %d.\n",
+         this_request, sat_protocol
+      ));
+
+      status = SCI_FAILURE;
+   break;
+   }
+
+   if (status == SCI_SUCCESS)
+   {
+      scic_sds_request_initialize_state_logging(this_request);
+
+      sci_base_state_machine_change_state(
+         &this_request->parent.state_machine,
+         SCI_BASE_REQUEST_STATE_CONSTRUCTED
+      );
+   }
+
+   return status;
+}
+
+//****************************************************************************
+//* SCIC Interface Implementation
+//****************************************************************************
+
+void scic_stp_io_request_set_ncq_tag(
+   SCI_IO_REQUEST_HANDLE_T  scic_io_request,
+   U16                      ncq_tag
+)
+{
+   /**
+    * @note This could be made to return an error to the user if the user
+    *       attempts to set the NCQ tag in the wrong state.
+    */
+   SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T *)scic_io_request;
+   this_request->task_context_buffer->type.stp.ncq_tag = ncq_tag;
+}
+
+// ---------------------------------------------------------------------------
+
+void * scic_stp_io_request_get_h2d_reg_address(
+   SCI_IO_REQUEST_HANDLE_T  scic_io_request
+)
+{
+   SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T *)scic_io_request;
+
+   return this_request->command_buffer;
+}
+
+// ---------------------------------------------------------------------------
+
+void * scic_stp_io_request_get_d2h_reg_address(
+   SCI_IO_REQUEST_HANDLE_T  scic_io_request
+)
+{
+   SCIC_SDS_STP_REQUEST_T * this_request = (SCIC_SDS_STP_REQUEST_T *)scic_io_request;
+
+   return &this_request->d2h_reg_fis;
+}
+
+/**
+ * Get the next SGL element from the request.
+ *    - Check on which SGL element pair we are working
+ *    - if working on SLG pair element A
+ *       - advance to element B
+ *    - else
+ *       - check to see if there are more SGL element pairs
+ *           for this IO request
+ *       - if there are more SGL element pairs
+ *          - advance to the next pair and return element A
+ *
+ * @param[in] this_request
+ *
+ * @return SCU_SGL_ELEMENT_T*
+ */
+SCU_SGL_ELEMENT_T * scic_sds_stp_request_pio_get_next_sgl(
+   SCIC_SDS_STP_REQUEST_T * this_request
+)
+{
+   SCU_SGL_ELEMENT_T * current_sgl;
+
+   if (this_request->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A)
+   {
+      if (
+            (this_request->type.pio.request_current.sgl_pair->B.address_lower == 0)
+         && (this_request->type.pio.request_current.sgl_pair->B.address_upper == 0)
+         )
+      {
+         current_sgl = NULL;
+      }
+      else
+      {
+         this_request->type.pio.request_current.sgl_set = SCU_SGL_ELEMENT_PAIR_B;
+         current_sgl = &(this_request->type.pio.request_current.sgl_pair->B);
+      }
+   }
+   else
+   {
+      if (
+            (this_request->type.pio.request_current.sgl_pair->next_pair_lower == 0)
+         && (this_request->type.pio.request_current.sgl_pair->next_pair_upper == 0)
+         )
+      {
+         current_sgl = NULL;
+      }
+      else
+      {
+         this_request->type.pio.request_current.sgl_pair =
+            scic_sds_request_get_sgl_element_pair(
+               &(this_request->parent),
+               ++this_request->type.pio.sgl_pair_index
+            );
+
+         this_request->type.pio.request_current.sgl_set = SCU_SGL_ELEMENT_PAIR_A;
+
+         current_sgl = &(this_request->type.pio.request_current.sgl_pair->A);
+      }
+   }
+
+   return current_sgl;
+}
+
+/**
+ * This method will construct the SATA PIO request.
+ *
+ * @param[in] scic_io_request The core request object which is cast to a SATA
+ *            PIO request object.
+ *
+ * @return This method returns an indication as to whether the construction
+ *         was successful.
+ * @retval SCI_SUCCESS Currently this method always returns this value.
+ */
+SCI_STATUS scic_sds_stp_pio_request_construct(
+   SCIC_SDS_REQUEST_T  * scic_io_request,
+   U8                    sat_protocol,
+   BOOL                  copy_rx_frame
+)
+{
+   SCIC_SDS_STP_REQUEST_T * this_request;
+
+   this_request = (SCIC_SDS_STP_REQUEST_T *)scic_io_request;
+
+   scic_sds_stp_non_ncq_request_construct(&this_request->parent);
+
+   scu_stp_raw_request_construct_task_context(
+      this_request, this_request->parent.task_context_buffer
+   );
+
+   this_request->type.pio.current_transfer_bytes = 0;
+   this_request->type.pio.ending_error = 0;
+   this_request->type.pio.ending_status = 0;
+
+   this_request->type.pio.request_current.sgl_offset = 0;
+   this_request->type.pio.request_current.sgl_set = SCU_SGL_ELEMENT_PAIR_A;
+   this_request->type.pio.sat_protocol = sat_protocol;
+   this_request->type.pio.sgl_pair_index = 0;
+
+   if ((copy_rx_frame) || (sat_protocol == SAT_PROTOCOL_PIO_DATA_OUT))
+   {
+      scic_sds_request_build_sgl(&this_request->parent);
+      // Since the IO request copy of the TC contains the same data as
+      // the actual TC this pointer is vaild for either.
+      this_request->type.pio.request_current.sgl_pair =
+         &this_request->parent.task_context_buffer->sgl_pair_ab;
+   }
+   else
+   {
+      // The user does not want the data copied to the SGL buffer location
+      this_request->type.pio.request_current.sgl_pair = NULL;
+   }
+
+   sci_base_state_machine_construct(
+      &this_request->parent.started_substate_machine,
+      &this_request->parent.parent.parent,
+      scic_sds_stp_request_started_pio_substate_table,
+      SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE
+   );
+
+   return SCI_SUCCESS;
+}
+
+//******************************************************************************
+//* STP NON-DATA STATE MACHINE
+//******************************************************************************
+
+/**
+ * This method processes a TC completion.  The expected TC completion is
+ * for the transmission of the H2D register FIS containing the SATA/STP
+ * non-data request.
+ *
+ * @param[in] this_request
+ * @param[in] completion_code
+ *
+ * @return This method always successfully processes the TC completion.
+ * @retval SCI_SUCCESS This value is always returned.
+ */
+static
+SCI_STATUS scic_sds_stp_request_non_data_await_h2d_tc_completion_handler(
+   SCIC_SDS_REQUEST_T * this_request,
+   U32                  completion_code
+)
+{
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_request),
+      SCIC_LOG_OBJECT_STP_IO_REQUEST,
+      "scic_sds_stp_request_non_data_await_h2d_tc_completion_handler(0x%x, 0x%x) enter\n",
+      this_request, completion_code
+   ));
+
+   switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
+   {
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
+      scic_sds_request_set_status(
+         this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
+      );
+
+      sci_base_state_machine_change_state(
+         &this_request->started_substate_machine,
+         SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE
+      );
+      break;
+
+   default:
+      // All other completion status cause the IO to be complete.  If a NAK
+      // was received, then it is up to the user to retry the request.
+      scic_sds_request_set_status(
+         this_request,
+         SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
+         SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
+      );
+
+      sci_base_state_machine_change_state(
+         &this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED
+      );
+      break;
+   }
+
+   return SCI_SUCCESS;
+}
+
+/**
+ * This method processes frames received from the target while waiting
+ * for a device to host register FIS.  If a non-register FIS is received
+ * during this time, it is treated as a protocol violation from an
+ * IO perspective.
+ *
+ * @param[in] request This parameter specifies the request for which a
+ *            frame has been received.
+ * @param[in] frame_index This parameter specifies the index of the frame
+ *            that has been received.
+ *
+ * @return Indicate if the received frame was processed successfully.
+ */
+static
+SCI_STATUS scic_sds_stp_request_non_data_await_d2h_frame_handler(
+   SCIC_SDS_REQUEST_T * request,
+   U32                  frame_index
+)
+{
+   SCI_STATUS               status;
+   SATA_FIS_HEADER_T      * frame_header;
+   U32                    * frame_buffer;
+   SCIC_SDS_STP_REQUEST_T * this_request = (SCIC_SDS_STP_REQUEST_T *)request;
+
+   // Save off the controller, so that we do not touch the request after it
+   //  is completed.
+   SCIC_SDS_CONTROLLER_T  * owning_controller = this_request->parent.owning_controller;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_request),
+      SCIC_LOG_OBJECT_STP_IO_REQUEST,
+      "scic_sds_stp_request_non_data_await_d2h_frame_handler(0x%x, 0x%x) enter\n",
+      this_request, frame_index
+   ));
+
+   status = scic_sds_unsolicited_frame_control_get_header(
+               &(owning_controller->uf_control),
+               frame_index,
+               (void**) &frame_header
+            );
+
+   if (status == SCI_SUCCESS)
+   {
+      switch (frame_header->fis_type)
+      {
+      case SATA_FIS_TYPE_REGD2H:
+         scic_sds_unsolicited_frame_control_get_buffer(
+            &(owning_controller->uf_control),
+            frame_index,
+            (void**) &frame_buffer
+         );
+
+         scic_sds_controller_copy_sata_response(
+            &this_request->d2h_reg_fis, (U32 *)frame_header, frame_buffer
+         );
+
+         // The command has completed with error
+         scic_sds_request_set_status(
+            &this_request->parent,
+            SCU_TASK_DONE_CHECK_RESPONSE,
+            SCI_FAILURE_IO_RESPONSE_VALID
+         );
+         break;
+
+      default:
+         SCIC_LOG_WARNING((
+            sci_base_object_get_logger(this_request),
+            SCIC_LOG_OBJECT_STP_IO_REQUEST,
+            "IO Request:0x%x Frame Id:%d protocol violation occurred\n",
+            this_request, frame_index
+         ));
+
+         scic_sds_request_set_status(
+            &this_request->parent,
+            SCU_TASK_DONE_UNEXP_FIS,
+            SCI_FAILURE_PROTOCOL_VIOLATION
+         );
+         break;
+      }
+
+      sci_base_state_machine_change_state(
+         &this_request->parent.parent.state_machine,
+         SCI_BASE_REQUEST_STATE_COMPLETED
+      );
+
+      // Frame has been decoded return it to the controller
+      scic_sds_controller_release_frame(
+         owning_controller, frame_index
+      );
+   }
+   else
+   {
+      SCIC_LOG_ERROR((
+         sci_base_object_get_logger(this_request),
+         SCIC_LOG_OBJECT_STP_IO_REQUEST,
+         "SCIC IO Request 0x%x could not get frame header for frame index %d, status %x\n",
+         this_request, frame_index, status
+      ));
+   }
+
+   return status;
+}
+
+// ---------------------------------------------------------------------------
+
+SCIC_SDS_IO_REQUEST_STATE_HANDLER_T
+   scic_sds_stp_request_started_non_data_substate_handler_table
+      [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_MAX_SUBSTATES] =
+{
+   // SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE
+   {
+      {
+         scic_sds_request_default_start_handler,
+         scic_sds_request_started_state_abort_handler,
+         scic_sds_request_default_complete_handler,
+         scic_sds_request_default_destruct_handler
+      },
+      scic_sds_stp_request_non_data_await_h2d_tc_completion_handler,
+      scic_sds_request_default_event_handler,
+      scic_sds_request_default_frame_handler
+   },
+   // SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE
+   {
+      {
+         scic_sds_request_default_start_handler,
+         scic_sds_request_started_state_abort_handler,
+         scic_sds_request_default_complete_handler,
+         scic_sds_request_default_destruct_handler
+      },
+      scic_sds_request_default_tc_completion_handler,
+      scic_sds_request_default_event_handler,
+      scic_sds_stp_request_non_data_await_d2h_frame_handler
+   }
+};
+
+static
+void scic_sds_stp_request_started_non_data_await_h2d_completion_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
+
+   SET_STATE_HANDLER(
+      this_request,
+      scic_sds_stp_request_started_non_data_substate_handler_table,
+      SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE
+   );
+
+   scic_sds_remote_device_set_working_request(
+      this_request->target_device, this_request
+   );
+}
+
+static
+void scic_sds_stp_request_started_non_data_await_d2h_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
+
+   SET_STATE_HANDLER(
+      this_request,
+      scic_sds_stp_request_started_non_data_substate_handler_table,
+      SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE
+   );
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_BASE_STATE_T scic_sds_stp_request_started_non_data_substate_table
+[SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_MAX_SUBSTATES] =
+{
+   {
+      SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE,
+      scic_sds_stp_request_started_non_data_await_h2d_completion_enter,
+      NULL
+   },
+   {
+      SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE,
+      scic_sds_stp_request_started_non_data_await_d2h_enter,
+      NULL
+   }
+};
+
+//******************************************************************************
+//* STP PIO STATE MACHINE
+//******************************************************************************
+
+#define SCU_MAX_FRAME_BUFFER_SIZE  0x400  // 1K is the maximum SCU frame data payload
+
+/**
+ * This function will transmit DATA_FIS from (current sgl + offset) for input parameter length.
+ * current sgl and offset is alreay stored in the IO request
+ *
+ * @param[in] this_request
+ * @param[in] length
+ *
+ * @return SCI_STATUS
+ */
+static
+SCI_STATUS scic_sds_stp_request_pio_data_out_trasmit_data_frame (
+   SCIC_SDS_REQUEST_T * this_request,
+   U32                  length
+)
+{
+   SCI_STATUS status = SCI_SUCCESS;
+   SCU_SGL_ELEMENT_T *  current_sgl;
+   SCIC_SDS_STP_REQUEST_T * this_sds_stp_request = (SCIC_SDS_STP_REQUEST_T *)this_request;
+
+   // Recycle the TC and reconstruct it for sending out DATA FIS containing
+   // for the data from current_sgl+offset for the input length
+   SCU_TASK_CONTEXT_T * task_context = scic_sds_controller_get_task_context_buffer(
+                                          this_request->owning_controller,
+                                          this_request->io_tag
+                                       );
+
+   if (this_sds_stp_request->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A)
+   {
+      current_sgl = &(this_sds_stp_request->type.pio.request_current.sgl_pair->A);
+   }
+   else
+   {
+      current_sgl = &(this_sds_stp_request->type.pio.request_current.sgl_pair->B);
+   }
+
+   //update the TC
+   task_context->command_iu_upper = current_sgl->address_upper;
+   task_context->command_iu_lower = current_sgl->address_lower;
+   task_context->transfer_length_bytes = length;
+   task_context->type.stp.fis_type = SATA_FIS_TYPE_DATA;
+
+   // send the new TC out.
+   status = this_request->owning_controller->state_handlers->parent.continue_io_handler(
+      &this_request->owning_controller->parent,
+      &this_request->target_device->parent,
+      &this_request->parent
+   );
+
+   return status;
+
+}
+
+/**
+ *
+ *
+ * @param[in] this_request
+ *
+ * @return SCI_STATUS
+ */
+static
+SCI_STATUS scic_sds_stp_request_pio_data_out_transmit_data(
+   SCIC_SDS_REQUEST_T * this_sds_request
+)
+{
+
+   SCU_SGL_ELEMENT_T *  current_sgl;
+   U32                  sgl_offset;
+   U32                  remaining_bytes_in_current_sgl = 0;
+   SCI_STATUS           status = SCI_SUCCESS;
+
+   SCIC_SDS_STP_REQUEST_T * this_sds_stp_request = (SCIC_SDS_STP_REQUEST_T *)this_sds_request;
+
+   sgl_offset = this_sds_stp_request->type.pio.request_current.sgl_offset;
+
+   if (this_sds_stp_request->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A)
+   {
+      current_sgl = &(this_sds_stp_request->type.pio.request_current.sgl_pair->A);
+      remaining_bytes_in_current_sgl = this_sds_stp_request->type.pio.request_current.sgl_pair->A.length - sgl_offset;
+   }
+   else
+   {
+      current_sgl = &(this_sds_stp_request->type.pio.request_current.sgl_pair->B);
+      remaining_bytes_in_current_sgl = this_sds_stp_request->type.pio.request_current.sgl_pair->B.length - sgl_offset;
+   }
+
+
+   if (this_sds_stp_request->type.pio.pio_transfer_bytes > 0)
+   {
+      if (this_sds_stp_request->type.pio.pio_transfer_bytes >= remaining_bytes_in_current_sgl )
+      {
+         //recycle the TC and send the H2D Data FIS from (current sgl + sgl_offset) and length = remaining_bytes_in_current_sgl
+         status = scic_sds_stp_request_pio_data_out_trasmit_data_frame (this_sds_request, remaining_bytes_in_current_sgl);
+         if (status == SCI_SUCCESS)
+         {
+            this_sds_stp_request->type.pio.pio_transfer_bytes -= remaining_bytes_in_current_sgl;
+            sgl_offset = 0;
+         }
+      }
+      else if (this_sds_stp_request->type.pio.pio_transfer_bytes < remaining_bytes_in_current_sgl )
+      {
+         //recycle the TC and send the H2D Data FIS from (current sgl + sgl_offset) and length = type.pio.pio_transfer_bytes
+         scic_sds_stp_request_pio_data_out_trasmit_data_frame (this_sds_request, this_sds_stp_request->type.pio.pio_transfer_bytes);
+
+         if (status == SCI_SUCCESS)
+         {
+            //Sgl offset will be adjusted and saved for future
+            sgl_offset += this_sds_stp_request->type.pio.pio_transfer_bytes;
+            current_sgl->address_lower += this_sds_stp_request->type.pio.pio_transfer_bytes;
+            this_sds_stp_request->type.pio.pio_transfer_bytes = 0;
+         }
+      }
+   }
+
+   if (status == SCI_SUCCESS)
+   {
+      this_sds_stp_request->type.pio.request_current.sgl_offset = sgl_offset;
+   }
+
+   return status;
+}
+
+/**
+ * Copy the data from the buffer for the length specified to the IO reqeust
+ * SGL specified data region.
+ *
+ * @param[in] this_request The request that is used for the SGL processing.
+ * @param[in] data_buffer The buffer of data to be copied.
+ * @param[in] length  The length of the data transfer.
+ *
+ * @return SCI_STATUS
+ */
+static
+SCI_STATUS scic_sds_stp_request_pio_data_in_copy_data_buffer(
+   SCIC_SDS_STP_REQUEST_T * this_request,
+   U8                     * data_buffer,
+   U32                      length
+)
+{
+   SCI_STATUS          status;
+   SCU_SGL_ELEMENT_T * current_sgl;
+   U32                 sgl_offset;
+   U32                 data_offset;
+   U8                * source_address;
+
+   // Initial setup to get the current working SGL and the offset within the buffer
+   current_sgl =
+      (this_request->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) ?
+         &(this_request->type.pio.request_current.sgl_pair->A) :
+         &(this_request->type.pio.request_current.sgl_pair->B) ;
+
+   sgl_offset = this_request->type.pio.request_current.sgl_offset;
+
+   source_address = data_buffer;
+   data_offset = this_request->type.pio.current_transfer_bytes;
+   status = SCI_SUCCESS;
+
+   // While we are still doing Ok and there is more data to transfer
+   while (
+            (length > 0)
+         && (status == SCI_SUCCESS)
+         )
+   {
+      if (current_sgl->length == sgl_offset)
+      {
+         // This SGL has been exauhasted so we need to get the next SGL
+         current_sgl = scic_sds_stp_request_pio_get_next_sgl(this_request);
+
+         if (current_sgl == NULL)
+            status = SCI_FAILURE;
+         else
+            sgl_offset = 0;
+      }
+      else
+      {
+#ifdef ENABLE_OSSL_COPY_BUFFER
+         scic_cb_io_request_copy_buffer(this_request, data_buffer, data_offset, length);
+         length = 0;
+#else
+         U8 * destination_address;
+         U32  copy_length;
+
+         destination_address = (U8 *)scic_cb_io_request_get_virtual_address_from_sgl(
+            this_request,
+            data_offset
+         );
+
+         copy_length = MIN(length, current_sgl->length - sgl_offset);
+
+         memcpy(destination_address, source_address, copy_length);
+
+         length -= copy_length;
+         sgl_offset += copy_length;
+         data_offset += copy_length;
+#endif
+      }
+   }
+
+   this_request->type.pio.request_current.sgl_offset = sgl_offset;
+
+   return status;
+}
+
+/**
+ * Copy the data buffer to the io request data region.
+ *
+ * @param[in] this_request The PIO DATA IN request that is to receive the
+ *       data.
+ * @param[in] data_buffer The buffer to copy from.
+ *
+ * @return SCI_STATUS
+ */
+static
+SCI_STATUS scic_sds_stp_request_pio_data_in_copy_data(
+   SCIC_SDS_STP_REQUEST_T * this_request,
+   U8                     * data_buffer
+)
+{
+   SCI_STATUS status;
+
+   // If there is less than 1K remaining in the transfer request
+   // copy just the data for the transfer
+   if (this_request->type.pio.pio_transfer_bytes < SCU_MAX_FRAME_BUFFER_SIZE)
+   {
+      status = scic_sds_stp_request_pio_data_in_copy_data_buffer(
+         this_request,data_buffer,this_request->type.pio.pio_transfer_bytes);
+
+      if (status == SCI_SUCCESS)
+      {
+         // All data for this PIO request has now been copied, so we don't
+         //  technically need to update current_transfer_bytes here - just
+         //  doing it for completeness.
+         this_request->type.pio.current_transfer_bytes += this_request->type.pio.pio_transfer_bytes;
+         this_request->type.pio.pio_transfer_bytes = 0;
+      }
+   }
+   else
+   {
+      // We are transfering the whole frame so copy
+      status = scic_sds_stp_request_pio_data_in_copy_data_buffer(
+         this_request, data_buffer, SCU_MAX_FRAME_BUFFER_SIZE);
+
+      if (status == SCI_SUCCESS)
+      {
+         this_request->type.pio.pio_transfer_bytes -= SCU_MAX_FRAME_BUFFER_SIZE;
+         this_request->type.pio.current_transfer_bytes += SCU_MAX_FRAME_BUFFER_SIZE;
+      }
+   }
+
+   return status;
+}
+
+/**
+ *
+ *
+ * @param[in] this_request
+ * @param[in] completion_code
+ *
+ * @return SCI_STATUS
+ */
+static
+SCI_STATUS scic_sds_stp_request_pio_await_h2d_completion_tc_completion_handler(
+   SCIC_SDS_REQUEST_T * this_request,
+   U32                  completion_code
+)
+{
+   SCI_STATUS status = SCI_SUCCESS;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_request),
+      SCIC_LOG_OBJECT_STP_IO_REQUEST,
+      "scic_sds_stp_request_pio_data_in_await_h2d_completion_tc_completion_handler(0x%x, 0x%x) enter\n",
+      this_request, completion_code
+   ));
+
+   switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
+   {
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
+      scic_sds_request_set_status(
+         this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
+      );
+
+      sci_base_state_machine_change_state(
+         &this_request->started_substate_machine,
+         SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE
+      );
+      break;
+
+   default:
+      // All other completion status cause the IO to be complete.  If a NAK
+      // was received, then it is up to the user to retry the request.
+      scic_sds_request_set_status(
+         this_request,
+         SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
+         SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
+      );
+
+      sci_base_state_machine_change_state(
+         &this_request->parent.state_machine,
+         SCI_BASE_REQUEST_STATE_COMPLETED
+      );
+      break;
+   }
+
+   return status;
+}
+
+/**
+ *
+ *
+ * @param[in] this_request
+ * @param[in] frame_index
+ *
+ * @return SCI_STATUS
+ */
+static
+SCI_STATUS scic_sds_stp_request_pio_await_frame_frame_handler(
+   SCIC_SDS_REQUEST_T * request,
+   U32                  frame_index
+)
+{
+   SCI_STATUS               status;
+   SATA_FIS_HEADER_T      * frame_header;
+   U32                    * frame_buffer;
+   SCIC_SDS_STP_REQUEST_T * this_request;
+   SCIC_SDS_CONTROLLER_T  * owning_controller;
+
+   this_request = (SCIC_SDS_STP_REQUEST_T *)request;
+
+   // Save off the controller, so that we do not touch the request after it
+   //  is completed.
+   owning_controller = this_request->parent.owning_controller;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_request),
+      SCIC_LOG_OBJECT_STP_IO_REQUEST,
+      "scic_sds_stp_request_pio_data_in_await_frame_frame_handler(0x%x, 0x%x) enter\n",
+      this_request, frame_index
+   ));
+
+   status = scic_sds_unsolicited_frame_control_get_header(
+      &(owning_controller->uf_control),
+      frame_index,
+      (void**) &frame_header
+   );
+
+   if (status == SCI_SUCCESS)
+   {
+      switch (frame_header->fis_type)
+      {
+      case SATA_FIS_TYPE_PIO_SETUP:
+         // Get from the frame buffer the PIO Setup Data
+         scic_sds_unsolicited_frame_control_get_buffer(
+            &(owning_controller->uf_control),
+            frame_index,
+            (void**) &frame_buffer
+         );
+
+         // Get the data from the PIO Setup
+         // The SCU Hardware returns first word in the frame_header and the rest
+         // of the data is in the frame buffer so we need to back up one dword
+         this_request->type.pio.pio_transfer_bytes =
+            (U16)((SATA_FIS_PIO_SETUP_T *)(&frame_buffer[-1]))->transfter_count;
+         this_request->type.pio.ending_status =
+            (U8)((SATA_FIS_PIO_SETUP_T *)(&frame_buffer[-1]))->ending_status;
+
+         scic_sds_controller_copy_sata_response(
+            &this_request->d2h_reg_fis, (U32 *)frame_header, frame_buffer
+         );
+
+         this_request->d2h_reg_fis.status =
+            this_request->type.pio.ending_status;
+
+         //The next state is dependent on whether the request was PIO Data-in or Data out
+         if (this_request->type.pio.sat_protocol == SAT_PROTOCOL_PIO_DATA_IN)
+         {
+         sci_base_state_machine_change_state(
+            &this_request->parent.started_substate_machine,
+            SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE
+            );
+         }
+         else if (this_request->type.pio.sat_protocol == SAT_PROTOCOL_PIO_DATA_OUT)
+         {
+            //Transmit data
+            status = scic_sds_stp_request_pio_data_out_transmit_data ( request);
+            if (status == SCI_SUCCESS)
+            {
+               sci_base_state_machine_change_state(
+                  &this_request->parent.started_substate_machine,
+                  SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE
+               );
+            }
+         }
+      break;
+
+      case SATA_FIS_TYPE_SETDEVBITS:
+         sci_base_state_machine_change_state(
+            &this_request->parent.started_substate_machine,
+            SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE
+            );
+      break;
+
+      case SATA_FIS_TYPE_REGD2H:
+         if ( (frame_header->status & ATA_STATUS_REG_BSY_BIT) == 0)
+         {
+            scic_sds_unsolicited_frame_control_get_buffer(
+               &(owning_controller->uf_control),
+               frame_index,
+               (void**) &frame_buffer
+            );
+
+            scic_sds_controller_copy_sata_response(
+               &this_request->d2h_reg_fis, (U32 *)frame_header, frame_buffer);
+
+            scic_sds_request_set_status(
+               &this_request->parent,
+               SCU_TASK_DONE_CHECK_RESPONSE,
+               SCI_FAILURE_IO_RESPONSE_VALID
+            );
+
+            sci_base_state_machine_change_state(
+               &this_request->parent.parent.state_machine,
+               SCI_BASE_REQUEST_STATE_COMPLETED
+            );
+         }
+         else
+         {
+            // Now why is the drive sending a D2H Register FIS when it is still busy?
+            // Do nothing since we are still in the right state.
+            SCIC_LOG_INFO((
+               sci_base_object_get_logger(this_request),
+               SCIC_LOG_OBJECT_STP_IO_REQUEST,
+               "SCIC PIO Request 0x%x received D2H Register FIS with BSY status 0x%x\n",
+               this_request, frame_header->status
+            ));
+         }
+         break;
+
+         default:
+         break;
+         }
+
+      // Frame is decoded return it to the controller
+      scic_sds_controller_release_frame(
+         owning_controller,
+         frame_index
+      );
+   }
+   else
+   {
+      SCIC_LOG_ERROR((
+         sci_base_object_get_logger(this_request),
+         SCIC_LOG_OBJECT_STP_IO_REQUEST,
+         "SCIC IO Request 0x%x could not get frame header for frame index %d, status %x\n",
+         this_request, frame_index, status
+      ));
+   }
+
+   return status;
+}
+
+/**
+ *
+ *
+ * @param[in] this_request
+ * @param[in] frame_index
+ *
+ * @return SCI_STATUS
+ */
+static
+SCI_STATUS scic_sds_stp_request_pio_data_in_await_data_frame_handler(
+   SCIC_SDS_REQUEST_T * request,
+   U32                  frame_index
+)
+{
+   SCI_STATUS               status;
+   SATA_FIS_HEADER_T      * frame_header;
+   SATA_FIS_DATA_T        * frame_buffer;
+   SCIC_SDS_STP_REQUEST_T * this_request;
+   SCIC_SDS_CONTROLLER_T  * owning_controller;
+
+   this_request = (SCIC_SDS_STP_REQUEST_T *)request;
+
+   // Save off the controller, so that we do not touch the request after it
+   //  is completed.
+   owning_controller = this_request->parent.owning_controller;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_request),
+      SCIC_LOG_OBJECT_STP_IO_REQUEST,
+      "scic_sds_stp_request_pio_data_in_await_data_frame_handler(0x%x, 0x%x) enter\n",
+      this_request, frame_index
+   ));
+
+   status = scic_sds_unsolicited_frame_control_get_header(
+      &(owning_controller->uf_control),
+      frame_index,
+      (void**) &frame_header
+   );
+
+   if (status == SCI_SUCCESS)
+   {
+      if (frame_header->fis_type == SATA_FIS_TYPE_DATA)
+      {
+         if (this_request->type.pio.request_current.sgl_pair == NULL)
+         {
+            this_request->parent.saved_rx_frame_index = frame_index;
+            this_request->type.pio.pio_transfer_bytes = 0;
+         }
+         else
+         {
+            status = scic_sds_unsolicited_frame_control_get_buffer(
+               &(owning_controller->uf_control),
+               frame_index,
+               (void**) &frame_buffer
+            );
+
+            status = scic_sds_stp_request_pio_data_in_copy_data(this_request, (U8 *)frame_buffer);
+
+            // Frame is decoded return it to the controller
+            scic_sds_controller_release_frame(
+               owning_controller,
+               frame_index
+            );
+         }
+
+         // Check for the end of the transfer, are there more bytes remaining
+         // for this data transfer
+         if (
+               (status == SCI_SUCCESS)
+            && (this_request->type.pio.pio_transfer_bytes == 0)
+            )
+         {
+            if ((this_request->type.pio.ending_status & ATA_STATUS_REG_BSY_BIT) == 0)
+            {
+               scic_sds_request_set_status(
+                  &this_request->parent,
+                  SCU_TASK_DONE_CHECK_RESPONSE,
+                  SCI_FAILURE_IO_RESPONSE_VALID
+               );
+
+               sci_base_state_machine_change_state(
+                  &this_request->parent.parent.state_machine,
+                  SCI_BASE_REQUEST_STATE_COMPLETED
+               );
+            }
+            else
+            {
+               sci_base_state_machine_change_state(
+                  &this_request->parent.started_substate_machine,
+                  SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE
+               );
+            }
+         }
+      }
+      else
+      {
+         SCIC_LOG_ERROR((
+            sci_base_object_get_logger(this_request),
+            SCIC_LOG_OBJECT_STP_IO_REQUEST,
+            "SCIC PIO Request 0x%x received frame %d with fis type 0x%02x when expecting a data fis.\n",
+            this_request, frame_index, frame_header->fis_type
+         ));
+
+         scic_sds_request_set_status(
+            &this_request->parent,
+            SCU_TASK_DONE_GOOD,
+            SCI_FAILURE_IO_REQUIRES_SCSI_ABORT
+         );
+
+         sci_base_state_machine_change_state(
+            &this_request->parent.parent.state_machine,
+            SCI_BASE_REQUEST_STATE_COMPLETED
+         );
+
+         // Frame is decoded return it to the controller
+         scic_sds_controller_release_frame(
+            owning_controller,
+            frame_index
+         );
+      }
+   }
+   else
+   {
+      SCIC_LOG_ERROR((
+         sci_base_object_get_logger(this_request),
+         SCIC_LOG_OBJECT_STP_IO_REQUEST,
+         "SCIC IO Request 0x%x could not get frame header for frame index %d, status %x\n",
+         this_request, frame_index, status
+      ));
+   }
+
+   return status;
+}
+
+
+/**
+ *
+ *
+ * @param[in] this_request
+ * @param[in] completion_code
+ *
+ * @return SCI_STATUS
+ */
+static
+SCI_STATUS scic_sds_stp_request_pio_data_out_await_data_transmit_completion_tc_completion_handler(
+
+   SCIC_SDS_REQUEST_T * this_request,
+   U32                  completion_code
+)
+{
+   SCI_STATUS  status                     = SCI_SUCCESS;
+   BOOL        all_frames_transferred     = FALSE;
+
+   SCIC_SDS_STP_REQUEST_T *this_scic_sds_stp_request = (SCIC_SDS_STP_REQUEST_T *) this_request;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_request),
+      SCIC_LOG_OBJECT_STP_IO_REQUEST,
+      "scic_sds_stp_request_pio_data_in_await_h2d_completion_tc_completion_handler(0x%x, 0x%x) enter\n",
+      this_request, completion_code
+   ));
+
+   switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
+   {
+      case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
+         //Transmit data
+         if (this_scic_sds_stp_request->type.pio.pio_transfer_bytes != 0)
+         {
+            status = scic_sds_stp_request_pio_data_out_transmit_data ( this_request);
+            if (status == SCI_SUCCESS)
+            {
+               if (this_scic_sds_stp_request->type.pio.pio_transfer_bytes == 0)
+               all_frames_transferred = TRUE;
+            }
+         }
+         else if (this_scic_sds_stp_request->type.pio.pio_transfer_bytes == 0)
+         {
+            //this will happen if the all data is written at the first time after the pio setup fis is recieved
+            all_frames_transferred  = TRUE;
+         }
+
+         //all data transferred.
+         if (all_frames_transferred)
+         {
+            //Change the state to SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_FRAME_SUBSTATE
+            //and wait for PIO_SETUP fis / or D2H REg fis.
+            sci_base_state_machine_change_state(
+               &this_request->started_substate_machine,
+               SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE
+            );
+         }
+         break;
+
+      default:
+         // All other completion status cause the IO to be complete.  If a NAK
+         // was received, then it is up to the user to retry the request.
+         scic_sds_request_set_status(
+            this_request,
+            SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
+            SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
+         );
+
+         sci_base_state_machine_change_state(
+            &this_request->parent.state_machine,
+            SCI_BASE_REQUEST_STATE_COMPLETED
+         );
+         break;
+   }
+
+   return status;
+}
+
+/**
+ * This method will handle any link layer events while waiting for the data
+ * frame.
+ *
+ * @param[in] request This is the request which is receiving the event.
+ * @param[in] event_code This is the event code that the request on which the
+ *       request is expected to take action.
+ *
+ * @return SCI_STATUS
+ * @retval SCI_SUCCESS
+ * @retval SCI_FAILURE
+ */
+static
+SCI_STATUS scic_sds_stp_request_pio_data_in_await_data_event_handler(
+   SCIC_SDS_REQUEST_T * request,
+   U32                  event_code
+)
+{
+   SCI_STATUS status;
+
+   switch (scu_get_event_specifier(event_code))
+   {
+   case SCU_TASK_DONE_CRC_ERR << SCU_EVENT_SPECIFIC_CODE_SHIFT:
+      // We are waiting for data and the SCU has R_ERR the data frame.
+      // Go back to waiting for the D2H Register FIS
+      sci_base_state_machine_change_state(
+         &request->started_substate_machine,
+         SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE
+      );
+
+      status = SCI_SUCCESS;
+      break;
+
+   default:
+      SCIC_LOG_ERROR((
+         sci_base_object_get_logger(request),
+         SCIC_LOG_OBJECT_STP_IO_REQUEST,
+         "SCIC PIO Request 0x%x received unexpected event 0x%08x\n",
+         request, event_code
+      ));
+
+      /// @todo Should we fail the PIO request when we get an unexpected event?
+      status = SCI_FAILURE;
+      break;
+   }
+
+   return status;
+}
+
+// ---------------------------------------------------------------------------
+
+SCIC_SDS_IO_REQUEST_STATE_HANDLER_T
+   scic_sds_stp_request_started_pio_substate_handler_table
+      [SCIC_SDS_STP_REQUEST_STARTED_PIO_MAX_SUBSTATES] =
+{
+   // SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE
+   {
+      {
+         scic_sds_request_default_start_handler,
+         scic_sds_request_started_state_abort_handler,
+         scic_sds_request_default_complete_handler,
+         scic_sds_request_default_destruct_handler
+      },
+      scic_sds_stp_request_pio_await_h2d_completion_tc_completion_handler,
+      scic_sds_request_default_event_handler,
+      scic_sds_request_default_frame_handler
+   },
+   // SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE
+   {
+      {
+         scic_sds_request_default_start_handler,
+         //scic_sds_stp_pio_request_data_in_await_frame_abort_handler,
+         scic_sds_request_started_state_abort_handler,
+         scic_sds_request_default_complete_handler,
+         scic_sds_request_default_destruct_handler
+      },
+      scic_sds_request_default_tc_completion_handler,
+      scic_sds_request_default_event_handler,
+      scic_sds_stp_request_pio_await_frame_frame_handler
+   },
+   // SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE
+   {
+      {
+         scic_sds_request_default_start_handler,
+         //scic_sds_stp_pio_request_data_in_await_data_abort_handler,
+         scic_sds_request_started_state_abort_handler,
+         scic_sds_request_default_complete_handler,
+         scic_sds_request_default_destruct_handler
+      },
+      scic_sds_request_default_tc_completion_handler,
+      scic_sds_stp_request_pio_data_in_await_data_event_handler,
+      scic_sds_stp_request_pio_data_in_await_data_frame_handler
+   },
+   //SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE
+   {
+      {
+         scic_sds_request_default_start_handler,
+         scic_sds_request_started_state_abort_handler,
+         scic_sds_request_default_complete_handler,
+         scic_sds_request_default_destruct_handler
+      },
+      scic_sds_stp_request_pio_data_out_await_data_transmit_completion_tc_completion_handler,
+      scic_sds_request_default_event_handler,
+      scic_sds_request_default_frame_handler
+   }
+};
+
+static
+void scic_sds_stp_request_started_pio_await_h2d_completion_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
+
+   SET_STATE_HANDLER(
+      this_request,
+      scic_sds_stp_request_started_pio_substate_handler_table,
+      SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE
+   );
+
+   scic_sds_remote_device_set_working_request(
+      this_request->target_device, this_request);
+}
+
+static
+void scic_sds_stp_request_started_pio_await_frame_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
+
+   SET_STATE_HANDLER(
+      this_request,
+      scic_sds_stp_request_started_pio_substate_handler_table,
+      SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE
+   );
+}
+
+static
+void scic_sds_stp_request_started_pio_data_in_await_data_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
+
+   SET_STATE_HANDLER(
+      this_request,
+      scic_sds_stp_request_started_pio_substate_handler_table,
+      SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE
+   );
+}
+
+static
+void scic_sds_stp_request_started_pio_data_out_transmit_data_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
+
+   SET_STATE_HANDLER(
+      this_request,
+      scic_sds_stp_request_started_pio_substate_handler_table,
+      SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE
+   );
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_BASE_STATE_T
+   scic_sds_stp_request_started_pio_substate_table
+      [SCIC_SDS_STP_REQUEST_STARTED_PIO_MAX_SUBSTATES] =
+{
+   {
+      SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE,
+      scic_sds_stp_request_started_pio_await_h2d_completion_enter,
+      NULL
+   },
+   {
+      SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE,
+      scic_sds_stp_request_started_pio_await_frame_enter,
+      NULL
+   },
+   {
+      SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE,
+      scic_sds_stp_request_started_pio_data_in_await_data_enter,
+      NULL
+   },
+   {
+      SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE,
+      scic_sds_stp_request_started_pio_data_out_transmit_data_enter,
+      NULL
+   }
+};
+
+//******************************************************************************
+//* UDMA REQUEST STATE MACHINE
+//******************************************************************************
+
+static
+void scic_sds_stp_request_udma_complete_request(
+   SCIC_SDS_REQUEST_T * this_request,
+   U32                  scu_status,
+   SCI_STATUS           sci_status
+)
+{
+   scic_sds_request_set_status(
+      this_request, scu_status, sci_status
+   );
+
+   sci_base_state_machine_change_state(
+      &this_request->parent.state_machine,
+      SCI_BASE_REQUEST_STATE_COMPLETED
+   );
+}
+
+/**
+ *
+ *
+ * @param[in] this_request
+ * @param[in] frame_index
+ *
+ * @return SCI_STATUS
+ */
+static
+SCI_STATUS scic_sds_stp_request_udma_general_frame_handler(
+   SCIC_SDS_REQUEST_T * this_request,
+   U32                  frame_index
+)
+{
+   SCI_STATUS          status;
+   SATA_FIS_HEADER_T * frame_header;
+   U32               * frame_buffer;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_request),
+      SCIC_LOG_OBJECT_STP_IO_REQUEST,
+      "scic_sds_stp_pio_request_data_in_await_frame_frame_handler(0x%x, 0x%x) enter\n",
+      this_request, frame_index
+   ));
+
+   status = scic_sds_unsolicited_frame_control_get_header(
+      &this_request->owning_controller->uf_control,
+      frame_index,
+      (void**) &frame_header
+   );
+
+   if (
+         (status == SCI_SUCCESS)
+      && (frame_header->fis_type == SATA_FIS_TYPE_REGD2H)
+      )
+   {
+      scic_sds_unsolicited_frame_control_get_buffer(
+         &this_request->owning_controller->uf_control,
+         frame_index,
+         (void**) &frame_buffer
+      );
+
+      scic_sds_controller_copy_sata_response(
+         &((SCIC_SDS_STP_REQUEST_T *)this_request)->d2h_reg_fis,
+         (U32 *)frame_header,
+         frame_buffer
+      );
+   }
+
+   scic_sds_controller_release_frame(
+      this_request->owning_controller, frame_index);
+
+   return status;
+}
+
+/**
+ * @brief This method process TC completions while in the state where
+ *        we are waiting for TC completions.
+ *
+ * @param[in] this_request
+ * @param[in] completion_code
+ *
+ * @return SCI_STATUS
+ */
+static
+SCI_STATUS scic_sds_stp_request_udma_await_tc_completion_tc_completion_handler(
+   SCIC_SDS_REQUEST_T * request,
+   U32                  completion_code
+)
+{
+   SCI_STATUS               status = SCI_SUCCESS;
+   SCIC_SDS_STP_REQUEST_T * this_request = (SCIC_SDS_STP_REQUEST_T *)request;
+
+   switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
+   {
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
+      scic_sds_stp_request_udma_complete_request(
+         &this_request->parent, SCU_TASK_DONE_GOOD, SCI_SUCCESS
+      );
+   break;
+
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_FIS):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_REG_ERR):
+      // We must check ther response buffer to see if the D2H Register FIS was
+      // received before we got the TC completion.
+      if (this_request->d2h_reg_fis.fis_type == SATA_FIS_TYPE_REGD2H)
+      {
+         scic_sds_remote_device_suspend(
+            this_request->parent.target_device,
+            SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code))
+         );
+
+         scic_sds_stp_request_udma_complete_request(
+            &this_request->parent,
+            SCU_TASK_DONE_CHECK_RESPONSE,
+            SCI_FAILURE_IO_RESPONSE_VALID
+         );
+      }
+      else
+      {
+         // If we have an error completion status for the TC then we can expect a
+         // D2H register FIS from the device so we must change state to wait for it
+         sci_base_state_machine_change_state(
+            &this_request->parent.started_substate_machine,
+            SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE
+         );
+      }
+   break;
+
+   /// @todo Check to see if any of these completion status need to wait for
+   ///       the device to host register fis.
+   /// @todo We can retry the command for SCU_TASK_DONE_CMD_LL_R_ERR - this comes only for B0
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_INV_FIS_LEN):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_MAX_PLD_ERR):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_R_ERR):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CMD_LL_R_ERR):
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CRC_ERR):
+      scic_sds_remote_device_suspend(
+         this_request->parent.target_device,
+         SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code))
+      );
+      // Fall through to the default case
+   default:
+      // All other completion status cause the IO to be complete.
+      SCIC_LOG_ERROR((
+         sci_base_object_get_logger(&this_request->parent),
+         SCIC_LOG_OBJECT_STP_IO_REQUEST,
+         "SCIC IO Request 0x%x returning CONTROLLER_SPECIFIC_IO_ERR for completion code 0x%x\n",
+         &this_request->parent, completion_code
+      ));
+      scic_sds_stp_request_udma_complete_request(
+         &this_request->parent,
+         SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
+         SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
+      );
+      break;
+   }
+
+   return status;
+}
+
+static
+SCI_STATUS scic_sds_stp_request_udma_await_d2h_reg_fis_frame_handler(
+   SCIC_SDS_REQUEST_T * this_request,
+   U32                  frame_index
+)
+{
+   SCI_STATUS status;
+
+   // Use the general frame handler to copy the resposne data
+   status = scic_sds_stp_request_udma_general_frame_handler(this_request, frame_index);
+
+   if (status == SCI_SUCCESS)
+   {
+      scic_sds_stp_request_udma_complete_request(
+         this_request,
+         SCU_TASK_DONE_CHECK_RESPONSE,
+         SCI_FAILURE_IO_RESPONSE_VALID
+      );
+   }
+
+   return status;
+}
+
+// ---------------------------------------------------------------------------
+
+SCIC_SDS_IO_REQUEST_STATE_HANDLER_T
+   scic_sds_stp_request_started_udma_substate_handler_table
+      [SCIC_SDS_STP_REQUEST_STARTED_UDMA_MAX_SUBSTATES] =
+{
+   // SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE
+   {
+      {
+         scic_sds_request_default_start_handler,
+         scic_sds_request_started_state_abort_handler,
+         scic_sds_request_default_complete_handler,
+         scic_sds_request_default_destruct_handler
+      },
+      scic_sds_stp_request_udma_await_tc_completion_tc_completion_handler,
+      scic_sds_request_default_event_handler,
+      scic_sds_stp_request_udma_general_frame_handler
+   },
+   // SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE
+   {
+      {
+         scic_sds_request_default_start_handler,
+         scic_sds_request_started_state_abort_handler,
+         scic_sds_request_default_complete_handler,
+         scic_sds_request_default_destruct_handler
+      },
+      scic_sds_request_default_tc_completion_handler,
+      scic_sds_request_default_event_handler,
+      scic_sds_stp_request_udma_await_d2h_reg_fis_frame_handler
+   }
+};
+
+/**
+ *
+ *
+ * @param[in] object
+ */
+static
+void scic_sds_stp_request_started_udma_await_tc_completion_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
+
+   SET_STATE_HANDLER(
+      this_request,
+      scic_sds_stp_request_started_udma_substate_handler_table,
+      SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE
+   );
+}
+
+/**
+ * This state is entered when there is an TC completion failure.  The hardware
+ * received an unexpected condition while processing the IO request and now
+ * will UF the D2H register FIS to complete the IO.
+ *
+ * @param[in] object
+ */
+static
+void scic_sds_stp_request_started_udma_await_d2h_reg_fis_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
+
+   SET_STATE_HANDLER(
+      this_request,
+      scic_sds_stp_request_started_udma_substate_handler_table,
+      SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE
+   );
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_BASE_STATE_T
+   scic_sds_stp_request_started_udma_substate_table
+      [SCIC_SDS_STP_REQUEST_STARTED_UDMA_MAX_SUBSTATES] =
+{
+   {
+      SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE,
+      scic_sds_stp_request_started_udma_await_tc_completion_enter,
+      NULL
+   },
+   {
+      SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE,
+      scic_sds_stp_request_started_udma_await_d2h_reg_fis_enter,
+      NULL
+   }
+};
+
+//******************************************************************************
+//* STP SOFT RESET STATE MACHINE
+//******************************************************************************
+
+/**
+ * This method processes a TC completion.  The expected TC completion is
+ * for the transmission of the H2D register FIS containing the SATA/STP
+ * non-data request.
+ *
+ * @param[in] this_request
+ * @param[in] completion_code
+ *
+ * @return This method always successfully processes the TC completion.
+ * @retval SCI_SUCCESS This value is always returned.
+ */
+static
+SCI_STATUS scic_sds_stp_request_soft_reset_await_h2d_asserted_tc_completion_handler(
+   SCIC_SDS_REQUEST_T * this_request,
+   U32                  completion_code
+)
+{
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_request),
+      SCIC_LOG_OBJECT_STP_IO_REQUEST,
+      "scic_sds_stp_request_soft_reset_await_h2d_tc_completion_handler(0x%x, 0x%x) enter\n",
+      this_request, completion_code
+   ));
+
+   switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
+   {
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
+      scic_sds_request_set_status(
+         this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
+      );
+
+      sci_base_state_machine_change_state(
+         &this_request->started_substate_machine,
+         SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE
+      );
+      break;
+
+   default:
+      // All other completion status cause the IO to be complete.  If a NAK
+      // was received, then it is up to the user to retry the request.
+      scic_sds_request_set_status(
+         this_request,
+         SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
+         SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
+      );
+
+      sci_base_state_machine_change_state(
+         &this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED
+      );
+      break;
+   }
+
+   return SCI_SUCCESS;
+}
+
+/**
+ * This method processes a TC completion.  The expected TC completion is
+ * for the transmission of the H2D register FIS containing the SATA/STP
+ * non-data request.
+ *
+ * @param[in] this_request
+ * @param[in] completion_code
+ *
+ * @return This method always successfully processes the TC completion.
+ * @retval SCI_SUCCESS This value is always returned.
+ */
+static
+SCI_STATUS scic_sds_stp_request_soft_reset_await_h2d_diagnostic_tc_completion_handler(
+   SCIC_SDS_REQUEST_T * this_request,
+   U32                  completion_code
+)
+{
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_request),
+      SCIC_LOG_OBJECT_STP_IO_REQUEST,
+      "scic_sds_stp_request_soft_reset_await_h2d_tc_completion_handler(0x%x, 0x%x) enter\n",
+      this_request, completion_code
+   ));
+
+   switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
+   {
+   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
+      scic_sds_request_set_status(
+         this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
+      );
+
+      sci_base_state_machine_change_state(
+         &this_request->started_substate_machine,
+         SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE
+      );
+      break;
+
+   default:
+      // All other completion status cause the IO to be complete.  If a NAK
+      // was received, then it is up to the user to retry the request.
+      scic_sds_request_set_status(
+         this_request,
+         SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
+         SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
+      );
+
+      sci_base_state_machine_change_state(
+         &this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED
+      );
+      break;
+   }
+
+   return SCI_SUCCESS;
+}
+
+/**
+ * This method processes frames received from the target while waiting
+ * for a device to host register FIS.  If a non-register FIS is received
+ * during this time, it is treated as a protocol violation from an
+ * IO perspective.
+ *
+ * @param[in] request This parameter specifies the request for which a
+ *            frame has been received.
+ * @param[in] frame_index This parameter specifies the index of the frame
+ *            that has been received.
+ *
+ * @return Indicate if the received frame was processed successfully.
+ */
+static
+SCI_STATUS scic_sds_stp_request_soft_reset_await_d2h_frame_handler(
+   SCIC_SDS_REQUEST_T * request,
+   U32                  frame_index
+)
+{
+   SCI_STATUS               status;
+   SATA_FIS_HEADER_T      * frame_header;
+   U32                    * frame_buffer;
+   SCIC_SDS_STP_REQUEST_T * this_request = (SCIC_SDS_STP_REQUEST_T *)request;
+
+   // Save off the controller, so that we do not touch the request after it
+   //  is completed.
+   SCIC_SDS_CONTROLLER_T  * owning_controller = this_request->parent.owning_controller;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(this_request),
+      SCIC_LOG_OBJECT_STP_IO_REQUEST,
+      "scic_sds_stp_request_soft_reset_await_d2h_frame_handler(0x%x, 0x%x) enter\n",
+      this_request, frame_index
+   ));
+
+   status = scic_sds_unsolicited_frame_control_get_header(
+               &(owning_controller->uf_control),
+               frame_index,
+               (void**) &frame_header
+            );
+
+   if (status == SCI_SUCCESS)
+   {
+      switch (frame_header->fis_type)
+      {
+      case SATA_FIS_TYPE_REGD2H:
+         scic_sds_unsolicited_frame_control_get_buffer(
+            &(owning_controller->uf_control),
+            frame_index,
+            (void**) &frame_buffer
+         );
+
+         scic_sds_controller_copy_sata_response(
+            &this_request->d2h_reg_fis, (U32 *)frame_header, frame_buffer
+         );
+
+         // The command has completed with error
+         scic_sds_request_set_status(
+            &this_request->parent,
+            SCU_TASK_DONE_CHECK_RESPONSE,
+            SCI_FAILURE_IO_RESPONSE_VALID
+         );
+         break;
+
+      default:
+         SCIC_LOG_WARNING((
+            sci_base_object_get_logger(this_request),
+            SCIC_LOG_OBJECT_STP_IO_REQUEST,
+            "IO Request:0x%x Frame Id:%d protocol violation occurred\n",
+            this_request, frame_index
+         ));
+
+         scic_sds_request_set_status(
+            &this_request->parent,
+            SCU_TASK_DONE_UNEXP_FIS,
+            SCI_FAILURE_PROTOCOL_VIOLATION
+         );
+         break;
+      }
+
+      sci_base_state_machine_change_state(
+         &this_request->parent.parent.state_machine,
+         SCI_BASE_REQUEST_STATE_COMPLETED
+      );
+
+      // Frame has been decoded return it to the controller
+      scic_sds_controller_release_frame(
+         owning_controller, frame_index
+      );
+   }
+   else
+   {
+      SCIC_LOG_ERROR((
+         sci_base_object_get_logger(this_request),
+         SCIC_LOG_OBJECT_STP_IO_REQUEST,
+         "SCIC IO Request 0x%x could not get frame header for frame index %d, status %x\n",
+         this_request, frame_index, status
+      ));
+   }
+
+   return status;
+}
+
+// ---------------------------------------------------------------------------
+
+SCIC_SDS_IO_REQUEST_STATE_HANDLER_T
+   scic_sds_stp_request_started_soft_reset_substate_handler_table
+      [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_MAX_SUBSTATES] =
+{
+   // SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE
+   {
+      {
+         scic_sds_request_default_start_handler,
+         scic_sds_request_started_state_abort_handler,
+         scic_sds_request_default_complete_handler,
+         scic_sds_request_default_destruct_handler
+      },
+      scic_sds_stp_request_soft_reset_await_h2d_asserted_tc_completion_handler,
+      scic_sds_request_default_event_handler,
+      scic_sds_request_default_frame_handler
+   },
+   // SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE
+   {
+      {
+         scic_sds_request_default_start_handler,
+         scic_sds_request_started_state_abort_handler,
+         scic_sds_request_default_complete_handler,
+         scic_sds_request_default_destruct_handler
+      },
+      scic_sds_stp_request_soft_reset_await_h2d_diagnostic_tc_completion_handler,
+      scic_sds_request_default_event_handler,
+      scic_sds_request_default_frame_handler
+   },
+   // SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE
+   {
+      {
+         scic_sds_request_default_start_handler,
+         scic_sds_request_started_state_abort_handler,
+         scic_sds_request_default_complete_handler,
+         scic_sds_request_default_destruct_handler
+      },
+      scic_sds_request_default_tc_completion_handler,
+      scic_sds_request_default_event_handler,
+      scic_sds_stp_request_soft_reset_await_d2h_frame_handler
+   }
+};
+
+static
+void scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completion_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
+
+   SET_STATE_HANDLER(
+      this_request,
+      scic_sds_stp_request_started_soft_reset_substate_handler_table,
+      SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE
+   );
+
+   scic_sds_remote_device_set_working_request(
+      this_request->target_device, this_request
+   );
+}
+
+static
+void scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCI_STATUS status;
+   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
+   SATA_FIS_REG_H2D_T *h2d_fis;
+   SCU_TASK_CONTEXT_T *task_context;
+
+   // Clear the SRST bit
+   h2d_fis = scic_stp_io_request_get_h2d_reg_address(this_request);
+   h2d_fis->control = 0;
+
+   // Clear the TC control bit
+   task_context = scic_sds_controller_get_task_context_buffer(
+                        this_request->owning_controller, this_request->io_tag);
+   task_context->control_frame = 0;
+
+   status = this_request->owning_controller->state_handlers->parent.continue_io_handler(
+      &this_request->owning_controller->parent,
+      &this_request->target_device->parent,
+      &this_request->parent
+   );
+
+   if (status == SCI_SUCCESS)
+   {
+      SET_STATE_HANDLER(
+         this_request,
+         scic_sds_stp_request_started_soft_reset_substate_handler_table,
+         SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE
+      );
+   }
+}
+
+static
+void scic_sds_stp_request_started_soft_reset_await_d2h_response_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
+
+   SET_STATE_HANDLER(
+      this_request,
+      scic_sds_stp_request_started_soft_reset_substate_handler_table,
+      SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE
+   );
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_BASE_STATE_T
+   scic_sds_stp_request_started_soft_reset_substate_table
+      [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_MAX_SUBSTATES] =
+{
+   {
+      SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE,
+      scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completion_enter,
+      NULL
+   },
+   {
+      SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE,
+      scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter,
+      NULL
+   },
+   {
+      SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE,
+      scic_sds_stp_request_started_soft_reset_await_d2h_response_enter,
+      NULL
+   }
+};
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_io_request_construct_basic_sata(
+   SCI_IO_REQUEST_HANDLE_T  scic_io_request
+)
+{
+   SCI_STATUS           status;
+   SCIC_SDS_REQUEST_T * request = (SCIC_SDS_REQUEST_T *)scic_io_request;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(scic_io_request),
+      SCIC_LOG_OBJECT_STP_IO_REQUEST,
+      "scic_io_request_construct_basic_sata(0x%x) enter\n",
+      scic_io_request
+   ));
+
+   status = scic_sds_io_request_construct_sata(
+               request,
+               scic_cb_request_get_sat_protocol(request->user_request),
+               scic_cb_io_request_get_transfer_length(request->user_request),
+               scic_cb_io_request_get_data_direction(request->user_request),
+               scic_cb_io_request_do_copy_rx_frames(request->user_request),
+               TRUE
+            );
+
+   return status;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scic_io_request_construct_advanced_sata(
+   SCI_IO_REQUEST_HANDLE_T     scic_io_request,
+   SCIC_IO_SATA_PARAMETERS_T * io_parameters
+)
+{
+   SCI_STATUS           status;
+   SCIC_SDS_REQUEST_T * request = (SCIC_SDS_REQUEST_T *)scic_io_request;
+
+   SCIC_LOG_TRACE((
+      sci_base_object_get_logger(scic_io_request),
+      SCIC_LOG_OBJECT_STP_IO_REQUEST,
+      "scic_io_request_construct_basic_sata(0x%x) enter\n",
+      scic_io_request
+   ));
+
+   status = scic_sds_io_request_construct_sata(
+               request,
+               scic_cb_request_get_sat_protocol(request->user_request),
+               scic_sds_request_get_sgl_element_pair(request, 0)->A.length,
+               scic_cb_io_request_get_data_direction(request->user_request),
+               scic_cb_io_request_do_copy_rx_frames(request->user_request),
+               io_parameters->do_translate_sgl
+            );
+
+   return status;
+}
diff --git a/sys/dev/disk/isci/scil/scic_sds_stp_request.h b/sys/dev/disk/isci/scil/scic_sds_stp_request.h
new file mode 100644
index 0000000..59fcdee
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_sds_stp_request.h
@@ -0,0 +1,280 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_sds_stp_request.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIC_SDS_STP_REQUEST_T_
+#define _SCIC_SDS_STP_REQUEST_T_
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/intel_sata.h>
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/scic_sds_request.h>
+
+/**
+ * @struct
+ *
+ * @brief This structure represents the additional information that is
+ *        required to handle SATA PIO requests.
+ */
+typedef struct SCIC_SDS_STP_REQUEST
+{
+   SCIC_SDS_REQUEST_T parent;
+
+   SATA_FIS_REG_D2H_T d2h_reg_fis;
+
+   union
+   {
+      U32 ncq;
+
+      U32 udma;
+
+      struct
+      {
+         /**
+          * Total transfer for the entire PIO request recorded at request constuction
+          * time.
+          *
+          * @todo Should we just decrement this value for each byte of data transitted
+          *       or received to elemenate the current_transfer_bytes field?
+          */
+         U32 total_transfer_bytes;
+
+         /**
+          * Total number of bytes received/transmitted in data frames since the start
+          * of the IO request.  At the end of the IO request this should equal the
+          * total_transfer_bytes.
+          */
+         U32 current_transfer_bytes;
+
+         /**
+          * The number of bytes requested in the in the PIO setup.
+          */
+         U32 pio_transfer_bytes;
+
+         /**
+          * PIO Setup ending status value to tell us if we need to wait for another FIS
+          * or if the transfer is complete. On the receipt of a D2H FIS this will be
+          * the status field of that FIS.
+          */
+         U8  ending_status;
+
+         /**
+          * On receipt of a D2H FIS this will be the ending error field if the
+          * ending_status has the SATA_STATUS_ERR bit set.
+          */
+         U8  ending_error;
+
+         /**
+          * Protocol Type. This is filled in by core during IO Request construction type.
+          */
+         U8  sat_protocol;
+
+         /**
+         * This field keeps track of sgl pair to be retrieved from OS memory for processing.
+         */
+         U8  sgl_pair_index;
+
+         struct
+         {
+            SCU_SGL_ELEMENT_PAIR_T * sgl_pair;
+            U8                       sgl_set;
+            U32                      sgl_offset;
+         } request_current;
+      } pio;
+
+      struct
+      {
+         /**
+          * The number of bytes requested in the PIO setup before CDB data frame.
+          */
+         U32 device_preferred_cdb_length;
+      } packet;
+   } type;
+
+} SCIC_SDS_STP_REQUEST_T;
+
+/**
+ * @enum SCIC_SDS_STP_REQUEST_STARTED_UDMA_SUBSTATES
+ *
+ * @brief This enumeration depicts the various sub-states associated with
+ *        a SATA/STP UDMA protocol operation.
+ */
+enum SCIC_SDS_STP_REQUEST_STARTED_UDMA_SUBSTATES
+{
+   SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE,
+   SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE,
+
+   SCIC_SDS_STP_REQUEST_STARTED_UDMA_MAX_SUBSTATES
+};
+
+/**
+ * @enum SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_SUBSTATES
+ *
+ * @brief This enumeration depicts the various sub-states associated with
+ *        a SATA/STP non-data protocol operation.
+ */
+enum SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_SUBSTATES
+{
+   SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE,
+   SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE,
+   SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_MAX_SUBSTATES
+};
+
+/**
+ * @enum SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_SUBSTATES
+ *
+ * @brief THis enumeration depicts the various sub-states associated with a
+ *        SATA/STP soft reset operation.
+ */
+enum SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_SUBSTATES
+{
+   SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE,
+   SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE,
+   SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE,
+
+   SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_MAX_SUBSTATES
+};
+
+extern SCIC_SDS_IO_REQUEST_STATE_HANDLER_T
+   scic_sds_stp_request_started_udma_substate_handler_table
+      [SCIC_SDS_STP_REQUEST_STARTED_UDMA_MAX_SUBSTATES];
+
+extern SCI_BASE_STATE_T
+   scic_sds_stp_request_started_udma_substate_table
+      [SCIC_SDS_STP_REQUEST_STARTED_UDMA_MAX_SUBSTATES];
+
+extern SCIC_SDS_IO_REQUEST_STATE_HANDLER_T
+   scic_sds_stp_request_started_non_data_substate_handler_table
+      [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_MAX_SUBSTATES];
+
+extern SCI_BASE_STATE_T
+   scic_sds_stp_request_started_non_data_substate_table
+      [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_MAX_SUBSTATES];
+
+
+extern SCIC_SDS_IO_REQUEST_STATE_HANDLER_T
+   scic_sds_stp_request_started_soft_reset_substate_handler_table
+      [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_MAX_SUBSTATES];
+
+extern SCI_BASE_STATE_T
+   scic_sds_stp_request_started_soft_reset_substate_table
+      [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_MAX_SUBSTATES];
+
+// ---------------------------------------------------------------------------
+
+U32 scic_sds_stp_request_get_object_size(void);
+
+U32 scic_sds_stp_task_request_get_object_size(void);
+
+void scu_sata_reqeust_construct_task_context(
+   SCIC_SDS_REQUEST_T * this_request,
+   SCU_TASK_CONTEXT_T * task_context
+);
+
+void scic_sds_stp_non_ncq_request_construct(
+   SCIC_SDS_REQUEST_T *this_request
+);
+
+SCI_STATUS scic_sds_stp_pio_request_construct(
+   SCIC_SDS_REQUEST_T  * scic_io_request,
+   U8                    sat_protocol,
+   BOOL                  copy_rx_frame
+);
+
+SCI_STATUS scic_sds_stp_pio_request_construct_pass_through (
+   SCIC_SDS_REQUEST_T  * scic_io_request,
+   SCIC_STP_PASSTHRU_REQUEST_CALLBACKS_T *passthru_cb
+);
+
+SCI_STATUS scic_sds_stp_udma_request_construct(
+   SCIC_SDS_REQUEST_T * this_request,
+   U32 transfer_length,
+   SCI_IO_REQUEST_DATA_DIRECTION data_direction
+);
+
+SCI_STATUS scic_sds_stp_non_data_request_construct(
+   SCIC_SDS_REQUEST_T * this_request
+);
+
+SCI_STATUS scic_sds_stp_soft_reset_request_construct(
+   SCIC_SDS_REQUEST_T * this_request
+);
+
+SCI_STATUS scic_sds_stp_ncq_request_construct(
+   SCIC_SDS_REQUEST_T * this_request,
+   U32 transfer_length,
+   SCI_IO_REQUEST_DATA_DIRECTION data_direction
+);
+
+void scu_stp_raw_request_construct_task_context(
+   SCIC_SDS_STP_REQUEST_T * this_request,
+   SCU_TASK_CONTEXT_T     * task_context
+
+);
+
+SCI_STATUS scic_sds_io_request_construct_sata(
+   SCIC_SDS_REQUEST_T          * this_request,
+   U8                            sat_protocol,
+   U32                           transfer_length,
+   SCI_IO_REQUEST_DATA_DIRECTION data_direction,
+   BOOL                          copy_rx_frame,
+   BOOL                          do_translate_sgl
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIC_SDS_STP_REQUEST_T_
diff --git a/sys/dev/disk/isci/scil/scic_sds_unsolicited_frame_control.c b/sys/dev/disk/isci/scil/scic_sds_unsolicited_frame_control.c
new file mode 100644
index 0000000..e2d6135
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_sds_unsolicited_frame_control.c
@@ -0,0 +1,400 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_sds_unsolicited_frame_control.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains the implementation of the
+ *        SCIC_SDS_UNSOLICITED_FRAME_CONTROL object and it's public,
+ *        protected, and private methods.
+ */
+
+#include <dev/disk/isci/scil/scic_sds_unsolicited_frame_control.h>
+#include <dev/disk/isci/scil/scu_registers.h>
+#include <dev/disk/isci/scil/scic_sds_controller.h>
+#include <dev/disk/isci/scil/scic_user_callback.h>
+#include <dev/disk/isci/scil/sci_util.h>
+
+/**
+ * @brief The UF buffer address table size must be programmed to a power
+ *        of 2.  Find the first power of 2 that is equal to or greater then
+ *        the number of unsolicited frame buffers to be utilized.
+ *
+ * @param[in,out] uf_control This parameter specifies the UF control
+ *                object for which to update the address table count.
+ *
+ * @return none
+ */
+void scic_sds_unsolicited_frame_control_set_address_table_count(
+   SCIC_SDS_UNSOLICITED_FRAME_CONTROL_T *uf_control
+)
+{
+   uf_control->address_table.count = SCU_MIN_UF_TABLE_ENTRIES;
+   while (
+            (uf_control->address_table.count < uf_control->buffers.count)
+         && (uf_control->address_table.count < SCU_ABSOLUTE_MAX_UNSOLICITED_FRAMES)
+         )
+   {
+      uf_control->address_table.count <<= 1;
+   }
+}
+
+/**
+ * @brief This method will program the unsolicited frames (UFs) into
+ *        the UF address table and construct the UF frame structure
+ *        being modeled in the core.  It will handle the case where
+ *        some of the UFs are not being used and thus should have
+ *        entries programmed to zero in the address table.
+ *
+ * @param[in,out] uf_control This parameter specifies the unsolicted
+ *                frame control object for which to construct the
+ *                unsolicited frames objects.
+ * @param[in]     uf_buffer_phys_address This parameter specifies the
+ *                physical address for the first unsolicited frame
+ *                buffer.
+ * @param[in]     uf_buffer_virt_address This parameter specifies the
+ *                virtual address for the first unsolicited frame
+ *                buffer.
+ * @param[in]     unused_uf_header_entries This parameter specifies
+ *                the number of unused UF headers.  This value can
+ *                be non-zero when there are a non-power of 2 number
+ *                of unsolicited frames being supported.
+ * @param[in]     used_uf_header_entries This parameter specifies
+ *                the number of actually utilized UF headers.
+ *
+ * @return none
+ */
+static
+void scic_sds_unsolicited_frame_control_construct_frames(
+   SCIC_SDS_UNSOLICITED_FRAME_CONTROL_T *uf_control,
+   SCI_PHYSICAL_ADDRESS                  uf_buffer_phys_address,
+   POINTER_UINT                          uf_buffer_virt_address,
+   U32                                   unused_uf_header_entries,
+   U32                                   used_uf_header_entries
+)
+{
+   U32                           index;
+   SCIC_SDS_UNSOLICITED_FRAME_T *uf;
+
+   // Program the unused buffers into the UF address table and the
+   // controller's array of UFs.
+   for (index = 0; index < unused_uf_header_entries; index++)
+   {
+      uf = &uf_control->buffers.array[index];
+
+      sci_cb_make_physical_address(
+         uf_control->address_table.array[index], 0, 0
+      );
+      uf->buffer = NULL;
+      uf->header = &uf_control->headers.array[index];
+      uf->state  = UNSOLICITED_FRAME_EMPTY;
+   }
+
+   // Program the actual used UF buffers into the UF address table and
+   // the controller's array of UFs.
+   for (index = unused_uf_header_entries;
+        index < unused_uf_header_entries + used_uf_header_entries;
+        index++)
+   {
+      uf = &uf_control->buffers.array[index];
+
+      uf_control->address_table.array[index] = uf_buffer_phys_address;
+
+      uf->buffer = (void*) uf_buffer_virt_address;
+      uf->header = &uf_control->headers.array[index];
+      uf->state  = UNSOLICITED_FRAME_EMPTY;
+
+      // Increment the address of the physical and virtual memory pointers
+      // Everything is aligned on 1k boundary with an increment of 1k
+      uf_buffer_virt_address += SCU_UNSOLICITED_FRAME_BUFFER_SIZE;
+      sci_physical_address_add(
+         uf_buffer_phys_address, SCU_UNSOLICITED_FRAME_BUFFER_SIZE
+      );
+   }
+}
+
+/**
+ * @brief This method constructs the various members of the unsolicted
+ *        frame control object (buffers, headers, address, table, etc).
+ *
+ * @param[in,out] uf_control This parameter specifies the unsolicited
+ *                frame control object to construct.
+ * @param[in]     mde This parameter specifies the memory descriptor
+ *                from which to derive all of the address information
+ *                needed to get the unsolicited frame functionality
+ *                working.
+ * @param[in]     controller This parameter specifies the controller
+ *                object associated with the uf_control being constructed.
+ *
+ * @return none
+ */
+void scic_sds_unsolicited_frame_control_construct(
+   SCIC_SDS_UNSOLICITED_FRAME_CONTROL_T *uf_control,
+   SCI_PHYSICAL_MEMORY_DESCRIPTOR_T     *mde,
+   SCIC_SDS_CONTROLLER_T                *controller
+)
+{
+   U32  unused_uf_header_entries;
+   U32  used_uf_header_entries;
+   U32  used_uf_buffer_bytes;
+   U32  unused_uf_header_bytes;
+   U32  used_uf_header_bytes;
+   SCI_PHYSICAL_ADDRESS  uf_buffer_phys_address;
+
+   // Prepare all of the memory sizes for the UF headers, UF address
+   // table, and UF buffers themselves.
+   used_uf_buffer_bytes     = uf_control->buffers.count
+                              * SCU_UNSOLICITED_FRAME_BUFFER_SIZE;
+   unused_uf_header_entries = uf_control->address_table.count
+                              - uf_control->buffers.count;
+   used_uf_header_entries   = uf_control->buffers.count;
+   unused_uf_header_bytes   = unused_uf_header_entries
+                              * sizeof(SCU_UNSOLICITED_FRAME_HEADER_T);
+   used_uf_header_bytes     = used_uf_header_entries
+                              * sizeof(SCU_UNSOLICITED_FRAME_HEADER_T);
+
+   // The Unsolicited Frame buffers are set at the start of the UF
+   // memory descriptor entry.  The headers and address table will be
+   // placed after the buffers.
+   uf_buffer_phys_address = mde->physical_address;
+
+   // Program the location of the UF header table into the SCU.
+   // Notes:
+   // - The address must align on a 64-byte boundary. Guaranteed to be
+   //   on 64-byte boundary already 1KB boundary for unsolicited frames.
+   // - Program unused header entries to overlap with the last
+   //   unsolicited frame.  The silicon will never DMA to these unused
+   //   headers, since we program the UF address table pointers to
+   //   NULL.
+   uf_control->headers.physical_address = uf_buffer_phys_address;
+   sci_physical_address_add(
+      uf_control->headers.physical_address, used_uf_buffer_bytes);
+   sci_physical_address_subtract(
+      uf_control->headers.physical_address, unused_uf_header_bytes);
+
+   uf_control->headers.array = (SCU_UNSOLICITED_FRAME_HEADER_T*)
+      ((U8 *)mde->virtual_address + used_uf_buffer_bytes - unused_uf_header_bytes);
+
+   // Program the location of the UF address table into the SCU.
+   // Notes:
+   // - The address must align on a 64-bit boundary. Guaranteed to be on 64
+   //   byte boundary already due to above programming headers being on a
+   //   64-bit boundary and headers are on a 64-bytes in size.
+   uf_control->address_table.physical_address = uf_buffer_phys_address;
+   sci_physical_address_add(
+      uf_control->address_table.physical_address, used_uf_buffer_bytes);
+   sci_physical_address_add(
+      uf_control->address_table.physical_address, used_uf_header_bytes);
+
+   uf_control->address_table.array = (SCI_PHYSICAL_ADDRESS*)
+      ((U8 *)mde->virtual_address + used_uf_buffer_bytes + used_uf_header_bytes);
+
+   uf_control->get = 0;
+
+   // UF buffer requirements are:
+   // - The last entry in the UF queue is not NULL.
+   // - There is a power of 2 number of entries (NULL or not-NULL)
+   //   programmed into the queue.
+   // - Aligned on a 1KB boundary.
+
+   // If the user provided less then the maximum amount of memory,
+   // then be sure that we programm the first entries in the UF
+   // address table to NULL.
+   scic_sds_unsolicited_frame_control_construct_frames(
+      uf_control,
+      uf_buffer_phys_address,
+      (POINTER_UINT) mde->virtual_address,
+      unused_uf_header_entries,
+      used_uf_header_entries
+   );
+}
+
+/**
+ * @brief This method returns the frame header for the specified frame
+ *        index.
+ *
+ * @param[in] uf_control
+ * @param[in] frame_index
+ * @param[out] frame_header
+ *
+ * @return SCI_STATUS
+ */
+SCI_STATUS scic_sds_unsolicited_frame_control_get_header(
+   SCIC_SDS_UNSOLICITED_FRAME_CONTROL_T *uf_control,
+   U32                                   frame_index,
+   void                                **frame_header
+)
+{
+   if (frame_index < uf_control->address_table.count)
+   {
+      // Skip the first word in the frame since this is a controll word used
+      // by the hardware.
+      *frame_header = &uf_control->buffers.array[frame_index].header->data;
+
+      return SCI_SUCCESS;
+   }
+
+   return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+}
+
+/**
+ * @brief This method returns the frame buffer for the specified frame
+ *        index.
+ *
+ * @param[in] uf_control
+ * @param[in] frame_index
+ * @param[out] frame_buffer
+ *
+ * @return SCI_STATUS
+ */
+SCI_STATUS scic_sds_unsolicited_frame_control_get_buffer(
+   SCIC_SDS_UNSOLICITED_FRAME_CONTROL_T *uf_control,
+   U32                                   frame_index,
+   void                                **frame_buffer
+)
+{
+   if (frame_index < uf_control->address_table.count)
+   {
+      *frame_buffer = uf_control->buffers.array[frame_index].buffer;
+
+      return SCI_SUCCESS;
+   }
+
+   return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+}
+
+/**
+ * @brief This method releases the frame once this is done the frame is
+ *        available for re-use by the hardware.  The data contained in the
+ *        frame header and frame buffer is no longer valid.
+ *
+ * @param[in] uf_control This parameter specifies the UF control object
+ * @param[in] frame_index This parameter specifies the frame index to
+ *            attempt to release.
+ *
+ * @return This method returns an indication to the caller as to whether
+ *         the unsolicited frame get pointer should be updated.
+ * @retval TRUE This value indicates the unsolicited frame get pointer
+ *         should be updated (i.e. write SCU_UFQGP_WRITE).
+ * @retval FALSE This value indicates the get pointer should not be
+ *         updated.
+ */
+BOOL scic_sds_unsolicited_frame_control_release_frame(
+   SCIC_SDS_UNSOLICITED_FRAME_CONTROL_T *uf_control,
+   U32                                   frame_index
+)
+{
+   U32 frame_get;
+   U32 frame_cycle;
+
+   frame_get   = uf_control->get & (uf_control->address_table.count - 1);
+   frame_cycle = uf_control->get & uf_control->address_table.count;
+
+   // In the event there are NULL entries in the UF table, we need to
+   // advance the get pointer in order to find out if this frame should
+   // be released (i.e. update the get pointer).
+   while (
+            (
+               (sci_cb_physical_address_lower(
+                   uf_control->address_table.array[frame_get]) == 0)
+            && (sci_cb_physical_address_upper(
+                   uf_control->address_table.array[frame_get]) == 0)
+            )
+         && (frame_get < uf_control->address_table.count)
+         )
+   {
+      frame_get++;
+   }
+
+   // The table has a NULL entry as it's last element.  This is
+   // illegal.
+   ASSERT(frame_get < uf_control->address_table.count);
+
+   if (frame_index < uf_control->address_table.count)
+   {
+      uf_control->buffers.array[frame_index].state = UNSOLICITED_FRAME_RELEASED;
+
+      // The frame index is equal to the current get pointer so we
+      // can now free up all of the frame entries that
+      if (frame_get == frame_index)
+      {
+         while (
+                  uf_control->buffers.array[frame_get].state
+               == UNSOLICITED_FRAME_RELEASED
+               )
+         {
+            uf_control->buffers.array[frame_get].state = UNSOLICITED_FRAME_EMPTY;
+
+            INCREMENT_QUEUE_GET(
+               frame_get,
+               frame_cycle,
+               uf_control->address_table.count - 1,
+               uf_control->address_table.count
+            );
+         }
+
+         uf_control->get =
+                  (SCU_UFQGP_GEN_BIT(ENABLE_BIT) | frame_cycle | frame_get);
+
+         return TRUE;
+      }
+      else
+      {
+         // Frames remain in use until we advance the get pointer
+         // so there is nothing we can do here
+      }
+   }
+
+   return FALSE;
+}
diff --git a/sys/dev/disk/isci/scil/scic_sds_unsolicited_frame_control.h b/sys/dev/disk/isci/scil/scic_sds_unsolicited_frame_control.h
new file mode 100644
index 0000000..3b5e588
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_sds_unsolicited_frame_control.h
@@ -0,0 +1,305 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_sds_unsolicited_frame_control.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+/**
+ * @file
+ *
+ * @brief This file contains all of the unsolicited frame related
+ *        management for the address table, the headers, and actual
+ *        payload buffers.
+ */
+
+#ifndef _SCIC_SDS_UNSOLICITED_FRAME_CONTROL_H_
+#define _SCIC_SDS_UNSOLICITED_FRAME_CONTROL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/types.h>
+#include <dev/disk/isci/scil/scu_unsolicited_frame.h>
+#include <dev/disk/isci/scil/sci_memory_descriptor_list.h>
+#include <dev/disk/isci/scil/scu_constants.h>
+#include <dev/disk/isci/scil/sci_status.h>
+
+/**
+ * @enum UNSOLICITED_FRAME_STATE
+ *
+ * This enumeration represents the current unsolicited frame state.  The
+ * controller object can not updtate the hardware unsolicited frame put
+ * pointer unless it has already processed the priror unsolicited frames.
+ */
+enum UNSOLICITED_FRAME_STATE
+{
+   /**
+    * This state is when the frame is empty and not in use.  It is
+    * different from the released state in that the hardware could DMA
+    * data to this frame buffer.
+    */
+   UNSOLICITED_FRAME_EMPTY,
+
+   /**
+    * This state is set when the frame buffer is in use by by some
+    * object in the system.
+    */
+   UNSOLICITED_FRAME_IN_USE,
+
+   /**
+    * This state is set when the frame is returned to the free pool
+    * but one or more frames prior to this one are still in use.
+    * Once all of the frame before this one are freed it will go to
+    * the empty state.
+    */
+   UNSOLICITED_FRAME_RELEASED,
+
+   UNSOLICITED_FRAME_MAX_STATES
+};
+
+/**
+ * @struct SCIC_SDS_UNSOLICITED_FRAME
+ *
+ * This is the unsolicited frame data structure it acts as the container for
+ * the current frame state, frame header and frame buffer.
+ */
+typedef struct SCIC_SDS_UNSOLICITED_FRAME
+{
+   /**
+    * This field contains the current frame state
+    */
+   enum UNSOLICITED_FRAME_STATE state;
+
+   /**
+    * This field points to the frame header data.
+    */
+   SCU_UNSOLICITED_FRAME_HEADER_T *header;
+
+   /**
+    * This field points to the frame buffer data.
+    */
+   void *buffer;
+
+} SCIC_SDS_UNSOLICITED_FRAME_T;
+
+/**
+ * @struct SCIC_SDS_UF_HEADER_ARRAY
+ *
+ * This structure contains all of the unsolicited frame header
+ * information.
+ */
+typedef struct SCIC_SDS_UF_HEADER_ARRAY
+{
+   /**
+    * This field is represents a virtual pointer to the start
+    * address of the UF address table.  The table contains
+    * 64-bit pointers as required by the hardware.
+    */
+   SCU_UNSOLICITED_FRAME_HEADER_T *array;
+
+   /**
+    * This field specifies the physical address location for the UF
+    * buffer array.
+    */
+   SCI_PHYSICAL_ADDRESS physical_address;
+
+} SCIC_SDS_UF_HEADER_ARRAY_T;
+
+// Determine the size of the unsolicited frame array including
+// unused buffers.
+#if SCU_UNSOLICITED_FRAME_COUNT <= SCU_MIN_UF_TABLE_ENTRIES
+#define SCU_UNSOLICITED_FRAME_CONTROL_ARRAY_SIZE SCU_MIN_UF_TABLE_ENTRIES
+#else
+#define SCU_UNSOLICITED_FRAME_CONTROL_ARRAY_SIZE SCU_MAX_UNSOLICITED_FRAMES
+#endif // SCU_UNSOLICITED_FRAME_COUNT <= SCU_MIN_UF_TABLE_ENTRIES
+
+/**
+ * @struct SCIC_SDS_UF_BUFFER_ARRAY
+ *
+ * This structure contains all of the unsolicited frame buffer (actual
+ * payload) information.
+ */
+typedef struct SCIC_SDS_UF_BUFFER_ARRAY
+{
+   /**
+    * This field is the minimum number of unsolicited frames supported by the
+    * hardware and the number of unsolicited frames requested by the software.
+    */
+   U32 count;
+
+   /**
+    * This field is the SCIC_UNSOLICITED_FRAME data its used to manage
+    * the data for the unsolicited frame requests.  It also represents
+    * the virtual address location that corresponds to the
+    * physical_address field.
+    */
+   SCIC_SDS_UNSOLICITED_FRAME_T array[SCU_UNSOLICITED_FRAME_CONTROL_ARRAY_SIZE];
+
+   /**
+    * This field specifies the physical address location for the UF
+    * buffer array.
+    */
+   SCI_PHYSICAL_ADDRESS physical_address;
+
+} SCIC_SDS_UF_BUFFER_ARRAY_T;
+
+/**
+ * @struct SCIC_SDS_UF_ADDRESS_TABLE_ARRAY
+ *
+ * This object maintains all of the unsolicited frame address
+ * table specific data.  The address table is a collection of
+ * 64-bit pointers that point to 1KB buffers into which
+ * the silicon will DMA unsolicited frames.
+ */
+typedef struct SCIC_SDS_UF_ADDRESS_TABLE_ARRAY
+{
+   /**
+    * This field specifies the actual programmed size of the
+    * unsolicited frame buffer address table.  The size of the table
+    * can be larger than the actual number of UF buffers, but it must
+    * be a power of 2 and the last entry in the table is not allowed
+    * to be NULL.
+    */
+   U32 count;
+
+   /**
+    * This field represents a virtual pointer that refers to the
+    * starting address of the UF address table.
+    * 64-bit pointers are required by the hardware.
+    */
+   SCI_PHYSICAL_ADDRESS * array;
+
+   /**
+    * This field specifies the physical address location for the UF
+    * address table.
+    */
+   SCI_PHYSICAL_ADDRESS physical_address;
+
+} SCIC_SDS_UF_ADDRESS_TABLE_ARRAY_T;
+
+/**
+ * @struct SCIC_SDS_UNSOLICITED_FRAME_CONTROL
+ *
+ * This object contains all of the data necessary to handle
+ * unsolicited frames.
+ */
+typedef struct SCIC_SDS_UNSOLICITED_FRAME_CONTROL
+{
+   /**
+    * This field is the software copy of the unsolicited frame queue
+    * get pointer.  The controller object writes this value to the
+    * hardware to let the hardware put more unsolicited frame entries.
+    */
+   U32 get;
+
+   /**
+    * This field contains all of the unsolicited frame header
+    * specific fields.
+    */
+   SCIC_SDS_UF_HEADER_ARRAY_T headers;
+
+   /**
+    * This field contains all of the unsolicited frame buffer
+    * specific fields.
+    */
+   SCIC_SDS_UF_BUFFER_ARRAY_T buffers;
+
+   /**
+    * This field contains all of the unsolicited frame address table
+    * specific fields.
+    */
+   SCIC_SDS_UF_ADDRESS_TABLE_ARRAY_T address_table;
+
+} SCIC_SDS_UNSOLICITED_FRAME_CONTROL_T;
+
+void scic_sds_unsolicited_frame_control_set_address_table_count(
+   SCIC_SDS_UNSOLICITED_FRAME_CONTROL_T *uf_control
+);
+
+struct SCIC_SDS_CONTROLLER;
+void scic_sds_unsolicited_frame_control_construct(
+   SCIC_SDS_UNSOLICITED_FRAME_CONTROL_T *uf_control,
+   SCI_PHYSICAL_MEMORY_DESCRIPTOR_T     *mde,
+   struct SCIC_SDS_CONTROLLER           *this_controller
+);
+
+SCI_STATUS scic_sds_unsolicited_frame_control_get_header(
+   SCIC_SDS_UNSOLICITED_FRAME_CONTROL_T *uf_control,
+   U32                                   frame_index,
+   void                                **frame_header
+);
+
+SCI_STATUS scic_sds_unsolicited_frame_control_get_buffer(
+   SCIC_SDS_UNSOLICITED_FRAME_CONTROL_T *uf_control,
+   U32                                   frame_index,
+   void                                **frame_buffer
+);
+
+BOOL scic_sds_unsolicited_frame_control_release_frame(
+   SCIC_SDS_UNSOLICITED_FRAME_CONTROL_T *uf_control,
+   U32                                   frame_index
+);
+
+/**
+ * This macro simply calculates the size of the memory descriptor
+ * entry that relates to unsolicited frames and the surrounding
+ * silicon memory required to utilize it.
+ */
+#define scic_sds_unsolicited_frame_control_get_mde_size(uf_control) \
+   ( ((uf_control).buffers.count * SCU_UNSOLICITED_FRAME_BUFFER_SIZE) \
+   + ((uf_control).address_table.count * sizeof(SCI_PHYSICAL_ADDRESS)) \
+   + ((uf_control).buffers.count * sizeof(SCU_UNSOLICITED_FRAME_HEADER_T)) )
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIC_SDS_UNSOLICITED_FRAME_CONTROL_H_
diff --git a/sys/dev/disk/isci/scil/scic_sgpio.h b/sys/dev/disk/isci/scil/scic_sgpio.h
new file mode 100644
index 0000000..90bc1a7
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_sgpio.h
@@ -0,0 +1,299 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_sgpio.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIC_SGPIO_H_
+#define _SCIC_SGPIO_H_
+
+/**
+* @file
+*
+* @brief This file contains all of the interface methods that can be called
+*        by an SCI user on an Serialized General Purpose IO (SGPIO) object.
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_types.h>
+
+//Programmable Blink Pattern Durations
+#define SGPIO_BLINK_DURATION_125    0x0
+#define SGPIO_BLINK_DURATION_250    0x1
+#define SGPIO_BLINK_DURATION_375    0x2
+#define SGPIO_BLINK_DURATION_500    0x3
+#define SGPIO_BLINK_DURATION_625    0x4
+#define SGPIO_BLINK_DURATION_750    0x5
+#define SGPIO_BLINK_DURATION_875    0x6
+#define SGPIO_BLINK_DURATION_1000   0x7
+#define SGPIO_BLINK_DURATION_1250   0x8
+#define SGPIO_BLINK_DURATION_1375   0x9
+#define SGPIO_BLINK_DURATION_1500   0xA
+#define SGPIO_BLINK_DURATION_1625   0xB
+#define SGPIO_BLINK_DURATION_1750   0xC
+#define SGPIO_BLINK_DURATION_1875   0xD
+#define SGPIO_BLINK_DURATION_2000   0xF
+
+#define ENABLE_SGPIO_FUNCTIONALITY  1
+#define DISABLE_SGPIO_FUNCTIONALITY 0
+
+#define SGPIO_HARDWARE_CONTROL      0x00000443
+#define SGPIO_SOFTWARE_CONTROL      0x00000444
+
+#define PHY_0_MASK                  0x01
+#define PHY_1_MASK                  0x02
+#define PHY_2_MASK                  0x04
+#define PHY_3_MASK                  0x08
+
+#define SGODSR_INVERT_BIT 0x4
+
+#define SGODSR_ERROR_LED_SHIFT 8
+#define SGODSR_LOCATE_LED_SHIFT 4
+#define SGODSR_ACTIVITY_LED_SHIFT 0
+
+#define SGPIO_BLINK_PATTERN_A 0x1
+#define SGPIO_BLINK_PATTERN_B 0x2
+
+/**
+* @brief This will set the vendor specific code in the SGPIO Vendor Specific Code
+*        register that is sent on the sLoad wire at the start of each
+*        bit stream.
+*
+* @param[in] SCI_CONTROLLER_HANDLE_T controller
+* @param]in] vendor_specific_sequence - Vendor specific sequence set in the
+*         SGVSCR register.
+*
+*/
+void scic_sgpio_set_vendor_code(
+   SCI_CONTROLLER_HANDLE_T controller,
+   U8 vendor_specific_sequence
+);
+
+/**
+* @brief Use this to set both programmable blink patterns A & B in the
+*        SGPBR(Programmable Blink Register). Will set identical patterns
+*        on both SGPIO units.
+*
+* @param[in] SCI_CONTROLLER_HANDLE_T controller
+* @param[in] pattern_a_high - High(LED on) duration time for pattern A
+* @param[in] pattern_a_low - Low(LED off) duration time for pattern A
+* @param[in] pattern_b_high - High(LED on) duration time for pattern B
+* @param[in] pattern_b_low - Low(LED off) duration time for pattern B
+*
+*/
+void scic_sgpio_set_blink_patterns(
+   SCI_CONTROLLER_HANDLE_T controller,
+   U8 pattern_a_low,
+   U8 pattern_a_high,
+   U8 pattern_b_low,
+   U8 pattern_b_high
+);
+
+
+/**
+* @brief This will set the functionality enable bit in the SGPIO interface
+*        control register, when set the bus pins will be used for SGPIO
+*        signaling, if not the bus pins are used for direct led control.
+*
+* @param[in] SCI_CONTROLLER_HANDLE_T controller
+* @param[in] BOOL sgpio_mode - indication for SGPIO signaling.
+*
+*/
+void scic_sgpio_set_functionality(
+   SCI_CONTROLLER_HANDLE_T controller,
+   BOOL sgpio_mode
+);
+
+/**
+ * @brief Communicates with hardware to set the blink pattern
+ *        of the error, locate, and activity LED's for phys
+ *        specified by the phy_mask parameter.
+ *        Function intend to be used to LEDs management
+ *        in non-inteligent backplanes.
+ *
+ * @param[in] SCI_CONTROLLER_HANDLE_T controller
+ * @param[in] phy_mask - This field is a bit mask that specifies the phys
+ *                       to be updated.
+ * @param[in] error - If TRUE, apply pattern for the error LED
+ * @param[in] locate - If TRUE, apply pattern for the locate LED
+ * @param[in] activity - If TRUE, apply pattern for the activity LED
+ * @param[in] pattern_selection - One of two patterns (A or B).
+ *            "A" and "B" patterns should be previously defined
+ *            by scic_sgpio_set_blink_patterns()
+ *
+ * @return none
+ */
+void scic_sgpio_apply_led_blink_pattern(
+   SCI_CONTROLLER_HANDLE_T controller,
+   U32 phy_mask,
+   BOOL error,
+   BOOL locate,
+   BOOL activity,
+   U8 pattern_selection
+);
+
+/**
+ * @brief Communicates with hardware to set the blink pattern
+ *        of the error, locate, and activity LED's for all
+ *        phys in the port. Function intend to be used to LEDs
+ *        management in non-inteligent backplanes.
+ *
+ * @param[in] SCI_CONTROLLER_HANDLE_T controller
+ * @param[in] port_handle - port handle is used to identify SGPIO bay
+ * @param[in] error - If TRUE, apply pattern for the error LED
+ * @param[in] locate - If TRUE, apply pattern for the locate LED
+ * @param[in] activity - If TRUE, apply pattern for the activity LED
+ * @param[in] pattern_selection - One of two patterns (A or B).
+ *            "A" and "B" patterns should be previously defined
+ *            by scic_sgpio_set_blink_patterns()
+ *
+ * @return none
+ */
+void scic_sgpio_set_led_blink_pattern(
+   SCI_CONTROLLER_HANDLE_T controller,
+   SCI_PORT_HANDLE_T port_handle,
+   BOOL error,
+   BOOL locate,
+   BOOL activity,
+   U8 pattern_selection
+);
+
+/**
+ * @brief Communicates with hardware to set the state of the error, locate,
+ *        and activity LED's.
+ *
+ * @param[in] SCI_CONTROLLER_HANDLE_T controller
+ * @param[in] phy_mask - This field is a bit mask that specifies the phys
+ *                       to be updated.
+ * @param[in] error - State to be set for the error LED
+ * @param[in] locate - State to be set for the locate LED
+ * @param[in] activity - State to be set for the activity LED
+ *
+ * @return none
+ */
+void scic_sgpio_update_led_state(
+   SCI_CONTROLLER_HANDLE_T controller,
+   U32 phy_mask,
+   BOOL error,
+   BOOL locate,
+   BOOL activity
+);
+
+/**
+ * @brief Communicates with hardware to set the state of the error, locate,
+ *        and activity LED's for all phys in the port.
+ *
+ * @param[in] SCI_CONTROLLER_HANDLE_T controller
+ * @param[in] port_handle - port handle is used to identify SGPIO bay
+ * @param[in] error - State to be set for the error LED
+ * @param[in] locate - State to be set for the locate LED
+ * @param[in] activity - State to be set for the activity LED
+ *
+ * @return none
+ */
+void scic_sgpio_set_led_state(
+   SCI_CONTROLLER_HANDLE_T controller,
+   SCI_PORT_HANDLE_T port_handle,
+   BOOL error,
+   BOOL locate,
+   BOOL activity
+);
+
+/**
+ * @brief This will set all Activity LED's to hardware controlled
+ *
+ * @param[in] BOOL is_hardware_controlled - indication for the Activity LED's
+ *         to be hardware controlled or driver controlled.
+ * @return none
+ */
+void scic_sgpio_set_to_hardware_control(
+   SCI_CONTROLLER_HANDLE_T controller,
+   BOOL is_hardware_controlled
+);
+
+/**
+ * @brief Reads and returns the data-in from the SGPIO port for the specified controller.
+ *        Bits 00:02 - Drive 0 input data
+ *        Bits 04:06 - Drive 1 input data
+ *        Bits 08:10 - Drive 2 input data
+ *        Bits 12:14 - Drive 3 input data
+ *
+ * @param[in] SCI_CONTROLLER_HANDLE_T controller
+ * @return U32 - Value read from SGPIO, 0xffffffff indicates hardware not readable
+ */
+U32 scic_sgpio_read(
+   SCI_CONTROLLER_HANDLE_T controller
+);
+
+/**
+ * @brief Initializes the SCU for Hardware SGPIO LED control.
+ *
+ * @param[in] SCI_CONTROLLER_HANDLE_T controller
+ */
+void scic_sgpio_hardware_initialize(
+   SCI_CONTROLLER_HANDLE_T controller
+);
+/**
+* @brief Initializes the SCU for Software SGPIO signaling of LED control.
+*
+* @param[in] SCI_CONTROLLER_HANDLE_T controller
+*/
+void scic_sgpio_initialize(
+   SCI_CONTROLLER_HANDLE_T controller
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIC_SGPIO_H_
diff --git a/sys/dev/disk/isci/scil/scic_task_request.h b/sys/dev/disk/isci/scil/scic_task_request.h
new file mode 100644
index 0000000..0233343
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_task_request.h
@@ -0,0 +1,180 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_task_request.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIC_TASK_REQUEST_H_
+#define _SCIC_TASK_REQUEST_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains the structures and interface methods that
+ *        can be referenced and used by the SCI user for to utilize
+ *        task management requests.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/sci_status.h>
+
+#if !defined(DISABLE_TASK_MANAGEMENT)
+
+/**
+ * @brief This method simply returns the size required to build an SCI
+ *        based task managment request object.
+ *
+ * @return Return the size of the SCIC task request object.
+ */
+U32 scic_task_request_get_object_size(
+   void
+);
+
+/**
+ * @brief This method is called by the SCI user to construct all SCI Core
+ *        task management requests, regardless of protocol.  Memory
+ *        initialization and functionality common to all task request types
+ *        is performed in this method.
+ *
+ * @note  The SCI core implementation will create an association between
+ *        the user task request object and the core task request object.
+ *
+ * @param[in]  scic_controller the handle to the core controller object
+ *             for which to build the task managmement request.
+ * @param[in]  scic_remote_device the handle to the core remote device
+ *             object for which to build the task management request.
+ *             passed, then a copy of the request is built internally.  The
+ *             request will be copied into the actual controller request
+ *             memory when the task is allocated internally during the
+ *             scic_controller_start_task() method.
+ * @param[in]  io_tag This parameter specifies the IO tag to be associated
+ *             with this request.  If SCI_CONTROLLER_INVALID_IO_TAG is
+ *             passed, then a copy of the request is built internally.  The
+ *             request will be copied into the actual controller request
+ *             memory when the IO tag is allocated internally during the
+ *             scic_controller_start_io() method.
+ * @param[in]  user_task_request_object This parameter specifies the user
+ *             task request to be utilized during construction.  This task
+ *             pointer will become the associated object for the core
+ *             task request object.
+ * @param[in]  scic_task_request_memory This parameter specifies the memory
+ *             location to be utilized when building the core request.
+ * @param[out] new_scic_task_request_handle This parameter specifies a
+ *             pointer to the handle the core will expect in further
+ *             interactions with the core task request object.
+ *
+ * @return Indicate if the controller successfully built the task request.
+ * @retval SCI_SUCCESS This value is returned if the task request was
+ *         successfully built.
+ */
+SCI_STATUS scic_task_request_construct(
+   SCI_CONTROLLER_HANDLE_T      scic_controller,
+   SCI_REMOTE_DEVICE_HANDLE_T   scic_remote_device,
+   U16                          io_tag,
+   void                       * user_task_request_object,
+   void                       * scic_task_request_memory,
+   SCI_TASK_REQUEST_HANDLE_T  * new_scic_task_request_handle
+);
+
+/**
+ * @brief This method is called by the SCI user to construct all SCI Core
+ *        SSP task management requests.  Memory initialization and
+ *        functionality common to all task request types is performed in
+ *        this method.
+ *
+ * @param[out] scic_task_request This parameter specifies the handle
+ *             to the core task request object for which to construct
+ *             a SATA specific task management request.
+ *
+ * @return Indicate if the controller successfully built the task request.
+ * @retval SCI_SUCCESS This value is returned if the task request was
+ *         successfully built.
+ */
+SCI_STATUS scic_task_request_construct_ssp(
+   SCI_TASK_REQUEST_HANDLE_T  scic_task_request
+);
+
+/**
+ * @brief This method is called by the SCI user to construct all SCI Core
+ *        SATA task management requests.  Memory initialization and
+ *        functionality common to all task request types is performed in
+ *        this method.
+ *
+ * @param[out] scic_task_request_handle This parameter specifies the
+ *             handle to the core task request object for which to construct
+ *             a SATA specific task management request.
+ *
+ * @return Indicate if the controller successfully built the task request.
+ * @retval SCI_SUCCESS This value is returned if the task request was
+ *         successfully built.
+ */
+SCI_STATUS scic_task_request_construct_sata(
+   SCI_TASK_REQUEST_HANDLE_T  scic_task_request_handle
+);
+
+#else // !defined(DISABLE_TASK_MANAGEMENT)
+
+#define scic_task_request_get_object_size() 0
+#define scic_task_request_construct(controller, dev, tag, task, mem, handle) \
+        SCI_FAILURE
+#define scic_task_request_construct_ssp(task) SCI_FAILURE
+#define scic_task_request_construct_sata(task) SCI_FAILURE
+
+#endif // !defined(DISABLE_TASK_MANAGEMENT)
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIC_TASK_REQUEST_H_
diff --git a/sys/dev/disk/isci/scil/scic_user_callback.h b/sys/dev/disk/isci/scil/scic_user_callback.h
new file mode 100644
index 0000000..a782c43
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scic_user_callback.h
@@ -0,0 +1,1145 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scic_user_callback.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIC_USER_CALLBACK_H_
+#define _SCIC_USER_CALLBACK_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the interface methods/macros that must
+ *        be implemented by an SCI Core user.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/sci_status.h>
+#include <dev/disk/isci/scil/sci_controller.h>
+
+/**
+ * @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]  controller This parameter specifies the controller with
+ *             which this timer is to be associated.
+ * @param[in]  timer_callback This parameter specifies the callback method
+ *             to be invoked whenever the timer expires.
+ * @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 * scic_cb_timer_create(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   SCI_TIMER_CALLBACK_T      timer_callback,
+   void                    * cookie
+);
+
+/**
+ * @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 scic_cb_timer_destroy(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   void                    * timer
+);
+
+/**
+ * @brief This callback method asks the user to start the supplied timer.
+ *
+ * @warning All timers in the system started by the SCI Core 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 Core user's should be able to handle
+ *          calls from the SCI Core 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 scic_cb_timer_start(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   void                    * timer,
+   U32                       milliseconds
+);
+
+/**
+ * @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 scic_cb_timer_stop(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   void                    * timer
+);
+
+/**
+ * @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(
+   U32  microseconds
+);
+
+/**
+ * @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 scic_cb_controller_start_complete(
+   SCI_CONTROLLER_HANDLE_T  controller,
+   SCI_STATUS               completion_status
+);
+
+/**
+ * @brief This user callback will inform the user that the controller has
+ *        finished the stop process.
+ *
+ * @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 scic_cb_controller_stop_complete(
+   SCI_CONTROLLER_HANDLE_T  controller,
+   SCI_STATUS               completion_status
+);
+
+/**
+ * @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 is completing.
+ * @param[in]  remote_device This parameter specifies the remote device on
+ *             which this IO 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_SUCCESS indicates successful
+ *             completion.
+ *
+ * @return none
+ */
+void scic_cb_io_request_complete(
+   SCI_CONTROLLER_HANDLE_T     controller,
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
+   SCI_IO_REQUEST_HANDLE_T     io_request,
+   SCI_IO_STATUS               completion_status
+);
+
+/**
+ * @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] scic_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.
+ */
+U8 *scic_cb_io_request_get_virtual_address_from_sgl(
+   void * scic_user_io_request,
+   U32    byte_offset
+);
+
+/**
+ * @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_SUCCESS indicates successful
+ *             completion.
+ *
+ * @return none
+ */
+void scic_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
+);
+
+#ifndef SCI_GET_PHYSICAL_ADDRESS_OPTIMIZATION_ENABLED
+/**
+ * @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
+);
+#endif // SCI_GET_PHYSICAL_ADDRESS_OPTIMIZATION_ENABLED
+
+/**
+ * @brief This callback method asks the user to provide the number of
+ *        bytes to be transfered as part of this request.
+ *
+ * @param[in] scic_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.
+ */
+U32 scic_cb_io_request_get_transfer_length(
+   void * scic_user_io_request
+);
+
+/**
+ * @brief This callback method asks the user to provide the data direction
+ *        for this request.
+ *
+ * @param[in] scic_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 or
+ *         SCI_IO_REQUEST_DATA_IN, or SCI_IO_REQUEST_NO_DATA.
+ */
+SCI_IO_REQUEST_DATA_DIRECTION scic_cb_io_request_get_data_direction(
+   void * scic_user_io_request
+);
+
+#ifdef ENABLE_OSSL_COPY_BUFFER
+/**
+ * @brief This method is presently utilized in the PIO path,
+ *        copies from UF buffer to the SGL buffer. This method
+ *        can be served for other OS related copies.
+ *
+ * @param[in] scic_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] source addr. Address of UF buffer.
+ * @param[in] 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.
+ * @param[in] length. data length
+ *
+ * @return    None
+ */
+void scic_cb_io_request_copy_buffer(
+   void * scic_user_io_request,
+   U8   *source_addr,
+   U32   offset,
+   U32   length
+);
+#endif
+
+#ifndef SCI_SGL_OPTIMIZATION_ENABLED
+/**
+ * @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] scic_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 scic_cb_io_request_get_next_sge(
+   void * scic_user_io_request,
+   void * current_sge_address,
+   void ** next_sge
+);
+#endif // SCI_SGL_OPTIMIZATION_ENABLED
+
+/**
+ * @brief This callback method asks the user to provide the contents of the
+ *        "address" field in the Scatter-Gather Element.
+ *
+ * @param[in] scic_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 scic_cb_sge_get_address_field(
+   void * scic_user_io_request,
+   void * sge_address
+);
+
+/**
+ * @brief This callback method asks the user to provide the contents of the
+ *        "length" field in the Scatter-Gather Element.
+ *
+ * @param[in] scic_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.
+ */
+U32 scic_cb_sge_get_length_field(
+   void * scic_user_io_request,
+   void * sge_address
+);
+
+/**
+ * @brief This callback method asks the user to provide the address for
+ *        the command descriptor block (CDB) associated with this IO request.
+ *
+ * @param[in] scic_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 * scic_cb_ssp_io_request_get_cdb_address(
+   void * scic_user_io_request
+);
+
+/**
+ * @brief This callback method asks the user to provide the length of
+ *        the command descriptor block (CDB) associated with this IO request.
+ *
+ * @param[in] scic_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.
+ */
+U32 scic_cb_ssp_io_request_get_cdb_length(
+   void * scic_user_io_request
+);
+
+/**
+ * @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] scic_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.
+ * @todo This should be U64?
+ */
+U32 scic_cb_ssp_io_request_get_lun(
+   void * scic_user_io_request
+);
+
+/**
+ * @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] scic_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.
+ */
+U32 scic_cb_ssp_io_request_get_task_attribute(
+   void * scic_user_io_request
+);
+
+/**
+ * @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] scic_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.
+ */
+U32 scic_cb_ssp_io_request_get_command_priority(
+   void * scic_user_io_request
+);
+
+/**
+ * @brief This callback method asks the user if the received RX frame data is
+ *        to be copied to the SGL or should be stored by the SCI core to be
+ *        retrieved later with the scic_io_request_get_rx_frame().
+ *
+ * @param[in] scic_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 TRUE if the SCI core should copy the received
+ *         frame data to the SGL location or FALSE if the SCI user wants to
+ *         retrieve the frame data at a later time.
+ */
+BOOL scic_cb_io_request_do_copy_rx_frames(
+   void * scic_user_io_request
+);
+
+/**
+ * @brief This callback method asks the user to return the SAT protocol
+ *        definition for this IO request.  This method is only called by the
+ *        SCI core if the request type constructed is SATA.
+ *
+ * @param[in] scic_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 one of the sat.h defined protocols for the
+ *         given io request.
+ */
+U8 scic_cb_request_get_sat_protocol(
+   void * scic_user_io_request
+);
+
+/**
+ * @brief This callback method asks the user to indicate if the IO is initially
+ *           constructed or is reconstructed using the recycled memory.
+ *
+ * @param[in] scic_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 TRUE if the request is initial constructed.
+ *         This method returns FALSE if the request is constructed using recycled
+ *         memory. For many scic user, this method mostly always returns TRUE.
+ */
+BOOL scic_cb_request_is_initial_construction(
+   void * scic_user_io_request
+);
+
+/**
+ * @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] scic_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?
+ */
+U32 scic_cb_ssp_task_request_get_lun(
+   void * scic_user_task_request
+);
+
+/**
+ * @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] scic_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.
+ */
+U8 scic_cb_ssp_task_request_get_function(
+   void * scic_user_task_request
+);
+
+/**
+ * @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] scic_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.
+ */
+U16 scic_cb_ssp_task_request_get_io_tag_to_manage(
+   void * scic_user_task_request
+);
+
+/**
+ * @brief This callback method asks the user to provide the virtual
+ *        address of the response data buffer for the supplied IO request.
+ *
+ * @param[in] scic_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 * scic_cb_ssp_task_request_get_response_data_address(
+   void * scic_user_task_request
+);
+
+/**
+ * @brief This callback method asks the user to provide the length of the
+ *        response data buffer for the supplied IO request.
+ *
+ * @param[in] scic_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.
+ */
+U32 scic_cb_ssp_task_request_get_response_data_length(
+   void * scic_user_task_request
+);
+
+/**
+ * @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,
+   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 scic_cb_logger_log_warning(
+   SCI_LOGGER_HANDLE_T   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 scic_cb_logger_log_info(
+   SCI_LOGGER_HANDLE_T   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 scic_cb_logger_log_trace(
+   SCI_LOGGER_HANDLE_T   logger_object,
+   U32                   log_object_mask,
+   char                * log_message,
+   ...
+);
+
+
+/**
+ * @brief In this method the user is expected to log the supplied state
+ *        transition 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_states(
+   SCI_LOGGER_HANDLE_T   logger_object,
+   U32                   log_object_mask,
+   char                * log_message,
+   ...
+);
+
+
+/**
+ * @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,
+   U16                      bar_number
+);
+
+/**
+ * @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?
+ */
+U32 scic_cb_pci_read_dword(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   void                    * address
+);
+
+/**
+ * @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 This PCI memory access calls likely need to be optimized into macro?
+ */
+void scic_cb_pci_write_dword(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   void                    * address,
+   U32                       write_value
+);
+
+/**
+ * @brief This method informs the user when a stop operation on the port
+ *        has completed.
+ *
+ * @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] completion_status This parameter specifies the status for
+ *            the operation being completed.
+ *
+ * @return none
+ */
+void scic_cb_port_stop_complete(
+   SCI_CONTROLLER_HANDLE_T  controller,
+   SCI_PORT_HANDLE_T        port,
+   SCI_STATUS               completion_status
+);
+
+/**
+ * @brief This method informs the user when a hard reset on the port
+ *        has completed.  This hard reset could have been initiated by the
+ *        user or by the remote port.
+ *
+ * @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] completion_status This parameter specifies the status for
+ *            the operation being completed.
+ *
+ * @return none
+ */
+void scic_cb_port_hard_reset_complete(
+   SCI_CONTROLLER_HANDLE_T  controller,
+   SCI_PORT_HANDLE_T        port,
+   SCI_STATUS               completion_status
+);
+
+/**
+ * @brief This method informs the user that the port is now in a ready
+ *        state and can be utilized to issue IOs.
+ *
+ * @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.
+ *
+ * @return none
+ */
+void scic_cb_port_ready(
+   SCI_CONTROLLER_HANDLE_T  controller,
+   SCI_PORT_HANDLE_T        port
+);
+
+/**
+ * @brief This method informs the user that the port is now not in a ready
+ *        (i.e. busy) state and can't be utilized to issue IOs.
+ *
+ * @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] reason_code This parameter specifies the reason for the port
+ *            not ready callback.
+ *
+ * @return none
+ */
+void scic_cb_port_not_ready(
+   SCI_CONTROLLER_HANDLE_T  controller,
+   SCI_PORT_HANDLE_T        port,
+   U32                      reason_code
+);
+
+/**
+ * @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
+);
+
+/**
+ * @brief This callback method informs the user that a broadcast change
+ *        primitive was received.
+ *
+ * @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.  For instances where the phy
+ *            on which the primitive was received is not part of a port, this
+ *            parameter will be SCI_INVALID_HANDLE_T.
+ * @param[in] phy This parameter specifies the phy on which the primitive
+ *            was received.
+ *
+ * @return none
+ */
+void scic_cb_port_bc_change_primitive_recieved(
+   SCI_CONTROLLER_HANDLE_T  controller,
+   SCI_PORT_HANDLE_T        port,
+   SCI_PHY_HANDLE_T         phy
+);
+
+/**
+ * @brief This callback method informs the user that a broadcast SES
+ *        primitive was received.
+ *
+ * @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.  For instances where the phy
+ *            on which the primitive was received is not part of a port, this
+ *            parameter will be SCI_INVALID_HANDLE_T.
+ * @param[in] phy This parameter specifies the phy on which the primitive
+ *            was received.
+ *
+ * @return none
+ */
+void scic_cb_port_bc_ses_primitive_recieved(
+   SCI_CONTROLLER_HANDLE_T  controller,
+   SCI_PORT_HANDLE_T        port,
+   SCI_PHY_HANDLE_T         phy
+);
+
+/**
+ * @brief This callback method informs the user that a broadcast EXPANDER
+ *        primitive was received.
+ *
+ * @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.  For instances where the phy
+ *            on which the primitive was received is not part of a port, this
+ *            parameter will be SCI_INVALID_HANDLE_T.
+ * @param[in] phy This parameter specifies the phy on which the primitive
+ *            was received.
+ *
+ * @return none
+ */
+void scic_cb_port_bc_expander_primitive_recieved(
+   SCI_CONTROLLER_HANDLE_T  controller,
+   SCI_PORT_HANDLE_T        port,
+   SCI_PHY_HANDLE_T         phy
+);
+
+/**
+ * @brief This callback method informs the user that a broadcast ASYNCHRONOUS
+ *        EVENT (AEN) primitive was received.
+ *
+ * @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.  For instances where the phy
+ *            on which the primitive was received is not part of a port, this
+ *            parameter will be SCI_INVALID_HANDLE_T.
+ * @param[in] phy This parameter specifies the phy on which the primitive
+ *            was received.
+ *
+ * @return none
+ */
+void scic_cb_port_bc_aen_primitive_recieved(
+   SCI_CONTROLLER_HANDLE_T  controller,
+   SCI_PORT_HANDLE_T        port,
+   SCI_PHY_HANDLE_T         phy
+);
+
+/**
+ * @brief This callback method informs the user that a phy has become
+ *        operational and is capable of communicating with the remote end
+ *        point.
+ *
+ * @param[in] controller This parameter represents the controller
+ *            associated with the phy.
+ * @param[in] port This parameter specifies the port object for which the
+ *            user callback is being invoked.  There may be conditions where
+ *            this parameter can be SCI_INVALID_HANDLE
+ * @param[in] phy This parameter specifies the phy object for which the
+ *            user callback is being invoked.
+ *
+ * @return none
+ */
+void scic_cb_port_link_up(
+   SCI_CONTROLLER_HANDLE_T  controller,
+   SCI_PORT_HANDLE_T        port,
+   SCI_PHY_HANDLE_T         phy
+);
+
+/**
+ * @brief This callback method informs the user that a phy is no longer
+ *        operational and is not capable of communicating with the remote end
+ *        point.
+ *
+ * @param[in] controller This parameter represents the controller
+ *            associated with the phy.
+ * @param[in] port This parameter specifies the port object for which the
+ *            user callback is being invoked.  There may be conditions where
+ *            this parameter can be SCI_INVALID_HANDLE
+ * @param[in] phy This parameter specifies the phy object for which the
+ *            user callback is being invoked.
+ *
+ * @return none
+ */
+void scic_cb_port_link_down(
+   SCI_CONTROLLER_HANDLE_T  controller,
+   SCI_PORT_HANDLE_T        port,
+   SCI_PHY_HANDLE_T         phy
+);
+
+/**
+ * @brief This user callback method will inform the user that a start
+ *        operation has completed.
+ *
+ * @param[in] controller This parameter specifies the core controller
+ *            associated with the completion callback.
+ * @param[in] remote_device This parameter specifies the remote device
+ *            associated with the completion callback.
+ * @param[in] completion_status This parameter specifies the completion
+ *            status for the operation.
+ *
+ * @return none
+ */
+void scic_cb_remote_device_start_complete(
+   SCI_CONTROLLER_HANDLE_T    controller,
+   SCI_REMOTE_DEVICE_HANDLE_T remote_device,
+   SCI_STATUS                 completion_status
+);
+
+/**
+ * @brief This user callback method will inform the user that a stop
+ *        operation has completed.
+ *
+ * @param[in] controller This parameter specifies the core controller
+ *            associated with the completion callback.
+ * @param[in] remote_device This parameter specifies the remote device
+ *            associated with the completion callback.
+ * @param[in] completion_status This parameter specifies the completion
+ *            status for the operation.
+ *
+ * @return none
+ */
+void scic_cb_remote_device_stop_complete(
+   SCI_CONTROLLER_HANDLE_T    controller,
+   SCI_REMOTE_DEVICE_HANDLE_T remote_device,
+   SCI_STATUS                 completion_status
+);
+
+/**
+ * @brief This user callback method will inform the user that a remote
+ *        device is now capable of handling IO requests.
+ *
+ * @param[in] controller This parameter specifies the core controller
+ *            associated with the completion callback.
+ * @param[in] remote_device This parameter specifies the remote device
+ *            associated with the callback.
+ *
+ * @return none
+ */
+void scic_cb_remote_device_ready(
+   SCI_CONTROLLER_HANDLE_T     controller,
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device
+);
+
+/**
+ * @brief This user callback method will inform the user that a remote
+ *        device is no longer capable of handling IO requests (until a
+ *        ready callback is invoked).
+ *
+ * @param[in] controller This parameter specifies the core controller
+ *            associated with the completion callback.
+ * @param[in] remote_device This parameter specifies the remote device
+ *            associated with the callback.
+ * @param[in] reason_code This paramete specifies the reason the remote
+ *            device is not ready.
+ *
+ * @return none
+ */
+void scic_cb_remote_device_not_ready(
+   SCI_CONTROLLER_HANDLE_T     controller,
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
+   U32                         reason_code
+);
+
+
+/**
+ * @brief This user callback method will inform the user that this controller
+ *        is having unexpected error. The user can choose to reset the controller.
+ * @param[in] controller The controller that is failed at the moment.
+ *
+ * @return none
+ */
+void scic_cb_controller_error(
+   SCI_CONTROLLER_HANDLE_T     controller,
+   SCI_CONTROLLER_ERROR        error
+);
+
+
+#if !defined(DISABLE_ATAPI)
+/**
+ * @brief This user callback gets from stp packet io's user request
+ *           the CDB address.
+ * @param[in] scic_user_io_request
+ *
+ * @return The cdb adress.
+ */
+void * scic_cb_stp_packet_io_request_get_cdb_address(
+   void * scic_user_io_request
+);
+
+/**
+ * @brief This user callback gets from stp packet io's user request
+ *           the CDB length.
+ * @param[in] scic_user_io_request
+ *
+ * @return The cdb length.
+ */
+U32 scic_cb_stp_packet_io_request_get_cdb_length(
+   void * scic_user_io_request
+);
+#else //!defined(DISABLE_ATAPI)
+#define scic_cb_stp_packet_io_request_get_cdb_address(scic_user_io_request) NULL
+#define scic_cb_stp_packet_io_request_get_cdb_length(scic_user_io_request) 0
+#endif //!defined(DISABLE_ATAPI)
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIC_USER_CALLBACK_H_
diff --git a/sys/dev/disk/isci/scil/scif_config_parameters.h b/sys/dev/disk/isci/scil/scif_config_parameters.h
new file mode 100644
index 0000000..a591f6d
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_config_parameters.h
@@ -0,0 +1,180 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_config_parameters.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIF_SAS_USER_PARAMETERS_H_
+#define _SCIF_SAS_USER_PARAMETERS_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the interface methods that can be called
+ *        by an SCIF user on a SCIF_SAS_USER_PARAMETERS object.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/sci_status.h>
+#include <dev/disk/isci/scil/intel_sas.h>
+
+
+/**
+ * @struct SCIF_SAS_USER_PARAMETERS
+ *
+ * @brief This structure delineates the various user parameters that can be
+ *        changed by the framework user.
+ */
+typedef struct SCIF_SAS_USER_PARAMETERS
+{
+   /**
+    * This field indicates if the user would like to have the SATA NCQ
+    * feature enabled for all remote devices.
+    */
+   BOOL  is_sata_ncq_enabled;
+
+   /**
+    * This field indicates if the user would like to have the SATA Automatic
+    * Standby Timer feature enabled for all remote devices.
+    */
+   BOOL  is_sata_standby_timer_enabled;
+
+   /**
+    * This field indicates if the user would like to have the SATA Non-zero
+    * Buffer Offset feature enabled for all remote devices.
+    */
+   BOOL  is_non_zero_buffer_offsets_enabled;
+
+   /**
+    * This field indicates if the user would like to clear affiliation for EA
+    * SATA devices during the controller stop process.
+    */
+   BOOL  clear_affiliation_during_controller_stop;
+
+   /**
+    * This field indicates the user's desired NCQ depth for all remote
+    * devices.  The maximum legal value for this field is 32.
+    */
+   U16  max_ncq_depth;
+
+   /**
+    * This field indicates the type of reset to be applied to all remote
+    * devices the first time they are discovered.
+    */
+   SCI_SAS_TASK_MGMT_FUNCTION_T  reset_type;
+
+   /**
+    * This field indicates the os/user recommends ignoring fua in translation
+    * for perfromance reasons.
+    */
+   BOOL  ignore_fua;
+
+} SCIF_SAS_USER_PARAMETERS_T;
+
+/**
+ * @union SCIF_USER_PARAMETERS
+ * @brief This structure/union specifies the various different user
+ *        parameter sets available.  Each type is specific to a
+ *        Serial Attached SCSI implementation of the framework.
+ *
+ */
+typedef union SCIF_USER_PARAMETERS
+{
+   SCIF_SAS_USER_PARAMETERS_T sas;
+
+} SCIF_USER_PARAMETERS_T;
+
+/**
+ * @brief This method allows the user to attempt to change the user
+ *        parameters utilized by the controller.
+ *
+ * @param[in] controller This parameter specifies the controller on which
+ *            to set the user parameters.
+ * @param[in] user_parameters This parameter specifies the USER_PARAMETERS
+ *            object containing the potential new values.
+ *
+ * @return Indicate if the update of the user parameters was successful.
+ * @retval SCI_SUCCESS This value is returned if the operation succeeded.
+ * @retval SCI_FAILURE_INVALID_STATE This value is returned if the attempt
+ *         to change the user parameter failed, because changing one of
+ *         the parameters is not currently allowed.
+ * @retval SCI_FAILURE_INVALID_PARAMETER_VALUE This value is returned if the
+ *         user supplied an invalid reset_type, ncq depth, etc.
+ */
+SCI_STATUS scif_user_parameters_set(
+   SCI_CONTROLLER_HANDLE_T  controller,
+   SCIF_USER_PARAMETERS_T * user_parameters
+);
+
+/**
+ * @brief This method allows the user to retrieve the user parameters
+ *        utilized by the controller.
+ *
+ * @param[in] controller This parameter specifies the controller on which
+ *            to set the user parameters.
+ * @param[in] user_parameters This parameter specifies the USER_PARAMETERS
+ *            object into which the framework shall save it's parameters.
+ *
+ * @return none
+ */
+void scif_user_parameters_get(
+   SCI_CONTROLLER_HANDLE_T  controller,
+   SCIF_USER_PARAMETERS_T * user_parameters
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIF_SAS_USER_PARAMETERS_H_
diff --git a/sys/dev/disk/isci/scil/scif_controller.h b/sys/dev/disk/isci/scil/scif_controller.h
new file mode 100644
index 0000000..b2680dd
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_controller.h
@@ -0,0 +1,453 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_controller.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIF_CONTROLLER_H_
+#define _SCIF_CONTROLLER_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the interface methods that can be called
+ *        by an SCIF user on a SCIF controller object.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/sci_status.h>
+
+
+/**
+ * @brief This method will attempt to construct a framework controller object
+ *        utilizing the supplied parameter information.
+ *
+ * @param[in]  library This parameter specifies the handle to the framework
+ *             library object associated with the controller being constructed.
+ * @param[in]  controller This parameter specifies the framework controller to
+ *             be constructed.
+ * @param[in]  user_object This parameter is a reference to the SCIL users
+ *             controller object and will be used to associate with the
+ *             framework controller.
+ *
+ * @return Indicate if the controller was successfully constructed or if
+ *         it failed in some way.
+ * @retval SCI_SUCCESS This value is returned if the controller was
+ *         successfully constructed.
+ * @retval SCI_FAILURE_UNSUPPORTED_INIT_DATA_VERSION This value is returned
+ *         if the controller does not support the supplied oem parameter
+ *         data version.
+ * @retval SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION This value is returned
+ *         if the controller doesn't support the port configuration scheme
+ *         (APC or MPC).
+ */
+SCI_STATUS scif_controller_construct(
+   SCI_LIBRARY_HANDLE_T      library,
+   SCI_CONTROLLER_HANDLE_T   controller,
+   void *                    user_object
+);
+
+/**
+ * @brief This method will initialize the SCI Framework controller object.
+ *        This includes initialization of the associated core controller.
+ *
+ * @param[in]  controller This parameter specifies the controller to be
+ *             initialized.
+ *
+ * @return Indicate if the controller was successfully initialized or if
+ *         it failed in some way.
+ * @retval SCI_SUCCESS This value is returned if the controller hardware
+ *         was successfully initialized.
+ */
+SCI_STATUS scif_controller_initialize(
+   SCI_CONTROLLER_HANDLE_T  controller
+);
+
+/**
+ * @brief This method returns the suggested scif_controller_start()
+ *        timeout amount.  The user is free to use any timeout value,
+ *        but this method provides the suggested minimum start timeout
+ *        value.  The returned value is based upon empirical information
+ *        determined as a result of interoperability testing.
+ *
+ * @param[in]  controller the handle to the controller object for which
+ *             to return the suggested start timeout.
+ *
+ * @return  This method returns the number of milliseconds for the
+ *          suggested start operation timeout.
+ */
+U32 scif_controller_get_suggested_start_timeout(
+   SCI_CONTROLLER_HANDLE_T  controller
+);
+
+/**
+ * @brief This method will start the SCIF controller.  The SCI User completion
+ *        callback is called when the following conditions are met:
+ *        -# the return status of this method is SCI_SUCCESS.
+ *        -# after all of the phys have successfully started or been given
+ *           the opportunity to start.
+ *
+ * @pre   The controller must be in the INITIALIZED or STARTED state.
+ *
+ * @param[in]  controller the handle to the controller object to start.
+ * @param[in]  timeout This parameter specifies the number of milliseconds
+ *             in which the start operation should complete.
+ *
+ * @return Indicate if the controller start method succeeded or failed in
+ *         some way.
+ * @retval SCI_SUCCESS if the start operation succeeded.
+ * @retval SCI_WARNING_ALREADY_IN_STATE if the controller is already in
+ *         the STARTED state.
+ * @retval SCI_FAILURE_INVALID_STATE if the controller is not either in
+ *         the INITIALIZED or STARTED states.
+ * @retval SCI_FAILURE_INVALID_MEMORY_DESCRIPTOR if there are
+ *         inconsistent or invalid values in the supplied
+ *         SCI_PHYSICAL_MEMORY_DESCRIPTOR array.
+ * @retval SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION This value is
+ *         returned if the phy to port allocation cannot be supported.
+ *
+ * @see For additional information please refer to: scic_controller_start()
+ */
+SCI_STATUS scif_controller_start(
+   SCI_CONTROLLER_HANDLE_T  controller,
+   U32                      timeout
+);
+
+/**
+ * @brief This method will stop an individual framework controller object. This
+ *        includes quiescing IOs, releasing affiliations, and other shutdown
+ *        related operations. This method will invoke the associated user
+ *        callback upon completion.  The completion callback is called when
+ *        the following conditions are met:
+ *           -# the method return status is SCI_SUCCESS.
+ *           -# the controller has been quiesced.
+ *        This method will ensure that all framework IO requests are quiesced
+ *        and any additional framework operations are halted.
+ *
+ * @pre   The controller must be in the STARTED or STOPPED state.
+ *
+ * @param[in]  controller the handle to the controller object to stop.
+ * @param[in]  timeout This parameter specifies the number of milliseconds
+ *             in which the stop operation should complete.
+ *
+ * @return Indicate if the controller stop method succeeded or failed in
+ *         some way.
+ * @retval SCI_SUCCESS if the stop operation successfully began.
+ * @retval SCI_WARNING_ALREADY_IN_STATE if the controller is already in
+ *         the STOPPED state.
+ * @retval SCI_FAILURE_INVALID_STATE if the controller is not either in
+ *         the STARTED or STOPPED states.
+ *
+ * @see For additional information please refer to: scic_controller_stop()
+ */
+SCI_STATUS scif_controller_stop(
+   SCI_CONTROLLER_HANDLE_T  controller,
+   U32                      timeout
+);
+
+/**
+ * @brief This method will reset the supplied framework controller regardless
+ *        of the state of said controller.  This operation is considered
+ *        destructive.  Outstanding IO requests are not aborted or completed
+ *        at the actual remote device.  However, the framework will
+ *        manufacture completion callbacks to the OS driver for the IO
+ *        requests.
+ *
+ * @param[in]  controller the handle to the controller object to reset.
+ *
+ * @return Indicate if the controller reset method succeeded or failed in
+ *         some way.
+ * @retval SCI_SUCCESS if the reset operation successfully started.
+ * @retval SCI_FATAL_ERROR if the controller reset operation is unable to
+ *         complete.
+ *
+ * @see For additional information please refer to: scic_controller_reset()
+ */
+SCI_STATUS scif_controller_reset(
+   SCI_CONTROLLER_HANDLE_T  controller
+);
+
+/**
+ * @brief This method returns the SCI Core controller handle associated
+ *        with this controller.
+ *
+ * @param[in]  scif_controller the handle to the controller object for which
+ *             to retrieve the core specific controller handle
+ *
+ * @return Return the SCI core controller handle associated with the supplied
+ *         framework controller.
+ */
+SCI_CONTROLLER_HANDLE_T scif_controller_get_scic_handle(
+   SCI_CONTROLLER_HANDLE_T   scif_controller
+);
+
+/**
+ * @brief This method is called by the SCIF user to send/start a framework
+ *        IO request.
+ *
+ * @param[in]  controller the handle to the controller object for which
+ *             to start an IO request.
+ * @param[in]  remote_device the handle to the remote device object for which
+ *             to start an IO request.
+ * @param[in]  io_request the handle to the io request object to start.
+ * @param[in]  io_tag This parameter specifies a previously allocated IO tag
+ *             that the user desires to be utilized for this request.
+ *             This parameter is optional.  The user is allowed to supply
+ *             SCI_CONTROLLER_INVALID_IO_TAG as the value for this parameter.
+ *             @see scic_controller_allocate_tag() for more information
+ *             on allocating a tag.
+ *
+ * @return Indicate if the controller successfully started the IO request.
+ * @retval SCI_IO_SUCCESS if the IO request was successfully started.
+ *
+ * @see For additional information please refer to: scic_controller_start_io()
+ *
+ * @todo Determine the failure situations and return values.
+ */
+SCI_IO_STATUS scif_controller_start_io(
+   SCI_CONTROLLER_HANDLE_T     controller,
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
+   SCI_IO_REQUEST_HANDLE_T     io_request,
+   U16                         io_tag
+);
+
+/**
+ * @brief This method is called by the SCIF user to send/start a framework
+ *        task management request.
+ *
+ * @param[in]  controller the handle to the controller object for which
+ *             to start the task management request.
+ * @param[in]  remote_device the handle to the remote device object for which
+ *             to start the task management request.
+ * @param[in]  task_request the handle to the task request object to start.
+ * @param[in]  io_tag This parameter specifies a previously allocated IO tag
+ *             that the user desires to be utilized for this request.  Note
+ *             this not the io_tag of the request being managed.  It is to
+ *             be utilized for the task request itself.
+ *             This parameter is optional.  The user is allowed to supply
+ *             SCI_CONTROLLER_INVALID_IO_TAG as the value for this parameter.
+ *             @see scic_controller_allocate_tag() for more information
+ *             on allocating a tag.
+ *
+ * @return Indicate if the controller successfully started the IO request.
+ * @retval SCI_TASK_SUCCESS if the task request was successfully started.
+ *
+ * @see For additional information please refer to: scic_controller_start_task()
+ *
+ * @todo Determine the failure situations and return values.
+ */
+SCI_TASK_STATUS scif_controller_start_task(
+   SCI_CONTROLLER_HANDLE_T     controller,
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
+   SCI_TASK_REQUEST_HANDLE_T   task_request,
+   U16                         io_tag
+);
+
+/**
+ * @brief This method is called by the SCI user to complete a previously
+ *        started IO request.  After this method is invoked, the user should
+ *        consider the IO request as invalid until it is properly reused
+ *        (i.e. re-constructed).
+ *
+ * @param[in]  controller The handle to the controller object for which
+ *             to complete the IO request.
+ * @param[in]  remote_device The handle to the remote device object for which
+ *             to complete the IO request.
+ * @param[in]  io_request the handle to the io request object to complete.
+ *
+ * @return Indicate if the controller successfully completed the IO request.
+ * @retval SCI_SUCCESS if the completion process was successful.
+ *
+ * @see For additional information please refer to:
+ *      scic_controller_complete_io()
+ */
+SCI_STATUS scif_controller_complete_io(
+   SCI_CONTROLLER_HANDLE_T     controller,
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
+   SCI_IO_REQUEST_HANDLE_T     io_request
+);
+
+/**
+ * @brief This method will perform framework specific completion operations for
+ *        a task management request. After this method is invoked, the user
+ *        should consider the task request as invalid until it is properly
+ *        reused (i.e. re-constructed).
+ *
+ * @param[in]  controller The handle to the controller object for which
+ *             to complete the task management request.
+ * @param[in]  remote_device The handle to the remote device object for which
+ *             to complete the task management request.
+ * @param[in]  task_request the handle to the task management request object
+ *             to complete.
+ *
+ * @return Indicate if the controller successfully completed the task
+ *         management request.
+ * @retval SCI_SUCCESS if the completion process was successful.
+ */
+SCI_STATUS scif_controller_complete_task(
+   SCI_CONTROLLER_HANDLE_T     controller,
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
+   SCI_TASK_REQUEST_HANDLE_T   task_request
+);
+
+/**
+ * @brief This method simply provides the user with a unique handle for a
+ *        given SAS/SATA domain index.
+ *
+ * @param[in]  controller This parameter represents the handle to the
+ *             controller object from which to retrieve a domain (SAS or
+ *             SATA) handle.
+ * @param[in]  port_index This parameter specifies the domain index in
+ *             the controller for which to retrieve the domain handle.
+ *             @note 0 <= port_index < maximum number of phys.
+ * @param[out] domain_handle This parameter specifies the retrieved domain
+ *             handle to be provided to the caller.
+ *
+ * @return Indicate if the retrieval of the domain handle was successful.
+ * @retval SCI_SUCCESS This value is returned if the retrieval was successful.
+ * @retval SCI_FAILURE_INVALID_PORT This value is returned if the supplied
+ *         port index is not invalid.
+ */
+SCI_STATUS scif_controller_get_domain_handle(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   U8                        port_index,
+   SCI_DOMAIN_HANDLE_T     * domain_handle
+);
+
+/**
+ * @brief This method allows the user to configure the SCI Framework
+ *        into either a performance mode or a memory savings mode.
+ *
+ * @param[in]  controller This parameter represents the handle to the
+ *             controller object for which to update the operating
+ *             mode.
+ * @param[in]  mode This parameter specifies the new mode for the
+ *             controller.
+ *
+ * @return Indicate if the user successfully change the operating mode
+ *         of the controller.
+ * @retval SCI_SUCCESS The user successfully updated the mode.
+ */
+SCI_STATUS scif_controller_set_mode(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   SCI_CONTROLLER_MODE       mode
+);
+
+/**
+ * @brief This method simply returns the T10 SCSI to ATA Translation (SAT)
+ *        specification version to which this translator is compliant for
+ *        supported commands.
+ *
+ * @return An integer value indicating the SAT version to which this
+ *         translator complies.
+ */
+U32 scif_controller_get_sat_compliance_version(
+   void
+);
+
+/**
+ * @brief This method simply returns the revision of the T10 SCSI to ATA
+ *        Translation (SAT) specification version to which this translator
+ *        is compliant for supported commands.
+ *
+ * @return An integer value indicating the revision of the SAT version
+ *         to which this translator complies.
+ */
+U32 scif_controller_get_sat_compliance_version_revision(
+   void
+);
+
+/**
+ * @brief This method is called by the SCI user to start internal io.
+ */
+typedef void (*SCI_START_INTERNAL_IO_ROUTINE)(
+   SCI_CONTROLLER_HANDLE_T controller
+);
+
+#if !defined(DISABLE_INTERRUPTS)
+/**
+ * @brief This method allows the user to configure the interrupt coalescence.
+ *           Please refer to the comment header for
+ *           scic_controller_set_interrupt_coalescence() to find details.
+ */
+SCI_STATUS scif_controller_set_interrupt_coalescence(
+   SCI_CONTROLLER_HANDLE_T controller,
+   U32                     coalesce_number,
+   U32                     coalesce_timeout
+);
+
+/**
+ * @brief This method retrieves the interrupt coalescence information.
+ *           Please refer to the comment header for
+ *           scic_controller_get_interrupt_coalescence() to find details.
+ */
+void scif_controller_get_interrupt_coalescence(
+   SCI_CONTROLLER_HANDLE_T controller,
+   U32                   * coalesce_number,
+   U32                   * coalesce_timeout
+);
+
+#else // !defined(DISABLE_INTERRUPTS)
+
+#define scif_controller_set_interrupt_coalescence(controller, num, timeout) \
+        SCI_FAILURE
+#define scif_controller_get_interrupt_coalescence(controller, num, timeout)
+
+#endif // !defined(DISABLE_INTERRUPTS)
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIF_CONTROLLER_H_
diff --git a/sys/dev/disk/isci/scil/scif_domain.h b/sys/dev/disk/isci/scil/scif_domain.h
new file mode 100644
index 0000000..b58a1b6
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_domain.h
@@ -0,0 +1,184 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_domain.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIF_DOMAIN_H_
+#define _SCIF_DOMAIN_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the interface methods that can be called
+ *        by an SCI Framework user on the SAS/SATA domain object.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/sci_status.h>
+#include <dev/disk/isci/scil/intel_sas.h>
+
+
+/**
+ * @brief This method enables the framework user to find the SCI Core Port
+ *        object through which the supplied domain is accessed.
+ *
+ * @param[in]  domain This parameter specifies the framework domain object
+ *             for which to return the corresponding SCI Core port object.
+ *
+ * @return Return a handle to the SCI Core port through which the supplied
+ *         domain is accessed.
+ * @retval SCI_INVALID_HANDLE This value is returned if the core port
+ *         object can not be retrieved.
+ */
+SCI_PORT_HANDLE_T scif_domain_get_scic_port_handle(
+   SCI_DOMAIN_HANDLE_T  domain
+);
+
+/**
+ * @brief This method will find and retreive the device associated with the
+ *        supplied SAS address if such a device exists.
+ *
+ * @param[in]  domain This parameter specifies the framework domain object
+ *             on which to discover devices.
+ * @param[in]  sas_address This parameter specifies the SAS address of the
+ *             object to locate in this domain.
+ *
+ * @return Indicate if the device was successfully found in the domain.
+ * @retval SCI_INVALID_HANDLE This value is returned if the device is not
+ *         found in the domain.
+ * @retval All other values indicate a valid remote device being found.
+ */
+SCI_REMOTE_DEVICE_HANDLE_T scif_domain_get_device_by_sas_address(
+   SCI_DOMAIN_HANDLE_T   domain,
+   SCI_SAS_ADDRESS_T   * sas_address
+);
+
+/**
+ * @brief This method will attempt to discover the supplied domain.
+ *
+ * @warning This method must be synchronized with the controller completion
+ *          handler (see scic_controller_get_handler_methods()).  The user
+ *          may call this method from within the completion handler in which
+ *          case, no synchronization is necessary.
+ *
+ * @note
+ *        - IO requests from the OS driver are held off until discovery
+ *          of the domain is complete.
+ *        - Discovery may perform SSP or STP IO requests to configure
+ *          remote devices prior to informing the SCIF User of their
+ *          existence via the remote_device_ready user callback.
+ *
+ * @param[in]  domain This parameter specifies the framework domain object
+ *             on which to discover devices.
+ * @param[in]  discover_timeout This parameter specifies the number of
+ *             milliseconds in which the domain discovery operation should
+ *             complete.
+ * @param[in]  device_timeout This parameter specifies the number of
+ *             milliseconds in which the device configuration and/or reset
+ *             operations should complete.  Logically, the device_timeout
+ *             parameter should be shorter then the domain_timeout value.
+ *             Especially considering the domain could be made up of "n"
+ *             different devices.
+ *
+ * @return Indicate if the discover operation started successfully.
+ * @retval SCI_SUCCESS This value is returned if the discover operation
+ *         started successfully.
+ * @retval SCI_WARNING_TIMER_CONFLICT This value is returned if the SCI
+ *         implementation doesn't support the desired timeout amounts or if
+ *         the desired timeout amounts conflict in some manner.
+ */
+SCI_STATUS scif_domain_discover(
+   SCI_DOMAIN_HANDLE_T   domain,
+   U32                   discover_timeout,
+   U32                   device_timeout
+);
+
+#if !defined(DISABLE_SCI_ITERATORS)
+/**
+ * @brief This method gets an iterator for the list of remote devices in the
+ *        specified domain.
+ *
+ * @param[in] domain: This parameter specifies the framework domain handle
+ * @param[in] iterator_buffer: This parameters specifies the memory buffer that
+ *            will be used to construct the iterator.
+ *
+ * @retval Handle to the remote device list iterator.
+ */
+SCI_ITERATOR_HANDLE_T scif_domain_get_remote_device_iterator(
+   SCI_DOMAIN_HANDLE_T   domain,
+   void                * iterator_buffer
+);
+#else // !defined(DISABLE_SCI_ITERATORS)
+#define scif_domain_get_remote_device_iterator(the_domain, the_buffer) \
+        SCI_INVALID_HANDLE
+#endif // !defined(DISABLE_SCI_ITERATORS)
+
+/**
+ * @brief This method simply returns a suggest timeout value for discovery.
+ *
+ * @param[in] domain The handle to the domain whose discover activity is to
+ *     be started.
+ *
+ * @return The suggested timeout value for domain discover in milli-seconds.
+ */
+U32 scif_domain_get_suggested_discover_timeout(
+   SCI_DOMAIN_HANDLE_T   domain
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIF_DOMAIN_H_
diff --git a/sys/dev/disk/isci/scil/scif_io_request.h b/sys/dev/disk/isci/scil/scif_io_request.h
new file mode 100644
index 0000000..97837ff
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_io_request.h
@@ -0,0 +1,242 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_io_request.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIF_IO_REQUEST_H_
+#define _SCIF_IO_REQUEST_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains the structures and interface methods that
+ *        can be referenced and used by the SCI user for the SCI IO request
+ *        object.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/sci_status.h>
+
+
+/**
+ * @brief This method simply returns the size required to construct an SCI
+ *        based IO request object (includes core & framework object size).
+ *
+ * @return Return the size of the SCI IO request object.
+ */
+U32 scif_io_request_get_object_size(
+   void
+);
+
+/**
+* @brief This method simply the number of data bytes transfered for a
+*        STP or SSP io request.
+*
+* @param[in] scif_io_request This parameter specifies the framework IO
+*            handle to retrieve the number of data bytes transferred.
+*
+* @return Return the number of data bytes transfered by the io request
+*/
+U32 scif_io_request_get_number_of_bytes_transferred(
+   void * scif_io_request
+);
+
+/**
+ * @brief This method is called by the SCIF user to construct an IO request.
+ *        This method will construct a SCIC IO request internally.  The memory
+ *        for the core IO request is passed as a parameter to this method.
+ *
+ * @note  The SCI framework implementation will create an association between
+ *        the user IO request object and the framework IO request object.
+ *
+ * @param[in]  scif_controller the handle to the framework controller object
+ *             for which to build an IO request.
+ * @param[in]  scif_remote_device This parameter specifies the framework
+ *             remote device with which this IO request is to be associated.
+ * @param[in]  io_tag This parameter specifies the IO tag to be associated
+ *             with this request.  If SCI_CONTROLLER_INVALID_IO_TAG is
+ *             passed, then a copy of the request is built internally.  The
+ *             request will be copied into the actual controller request
+ *             memory when the IO tag is allocated internally during the
+ *             scif_controller_start_io() method.
+ * @param[in]  user_io_request_object This parameter specifies the user
+ *             IO request to be utilized during IO construction.  This IO
+ *             pointer will become the associated object for the framework
+ *             IO request object.
+ * @param[in]  io_request_memory This parameter specifies the memory
+ *             to be utilized in the construction of the framework IO request.
+ * @param[in]  scif_io_request This parameter specifies the handle to be
+ *             utilized for all further interactions with this IO request
+ *             object.
+ *
+ * @return Indicate if the controller successfully built the IO request.
+ * @retval SCI_SUCCESS This value is returned if the IO request was
+ *         successfully built.
+ */
+SCI_STATUS scif_io_request_construct(
+   SCI_CONTROLLER_HANDLE_T      scif_controller,
+   SCI_REMOTE_DEVICE_HANDLE_T   scif_remote_device,
+   U16                          io_tag,
+   void                       * user_io_request_object,
+   void                       * io_request_memory,
+   SCI_IO_REQUEST_HANDLE_T    * scif_io_request
+);
+
+/**
+ * @brief This method simply returns the SCI Core object handle that is
+ *        associated with the supplied SCI Framework object.
+ *
+ * @param[in]  scif_io_request This parameter specifies the framework IO
+ *             for which to return the associated core IO request object.
+ *
+ * @return This method returns a handle to the core IO request object
+ *         associated with the framework IO request object.
+ * @retval SCI_INVALID_HANDLE This return value indicates that the SCI Core
+ *         IO request handle for the supplied framework IO is invalid.
+ */
+SCI_IO_REQUEST_HANDLE_T scif_io_request_get_scic_handle(
+   SCI_IO_REQUEST_HANDLE_T scif_io_request
+);
+
+/**
+ * @brief This method returns the address of the response information unit.
+ *        This call is only valid if the completion status for the io request
+ *        is SCI_FAILURE_IO_RESPONSE_VALID.
+ *
+ * @param[in]  scif_io_request This parameter specifies the framework IO
+ *             for which to return the associated core IO request object.
+ *
+ * @return The address for the response information unit.
+ */
+void * scif_io_request_get_response_iu_address(
+   SCI_IO_REQUEST_HANDLE_T scif_io_request
+);
+
+/**
+ * @brief This method will build an Framework SSP Passthrough IO request based
+ *        on the user information supplied in the pass-through IO request object.
+ *        In case of pass through request construction, the driver creates the
+ *        sci core request object and pass that to the framework
+ *
+ * @pre
+ *
+ * @param[in]  scif_controller. Not used in the function but kept to maintain uniformity
+ *             with other io construct functions
+ * @param[in]  scif_remote_device. This parameter is the device.
+ * @param[in]  scic_io_request. This parameter is the scic request already constructed
+ * @param[in]  user_io_request_object, the user io request
+ * @param[in]  io_request_memory, the scif offset in the user_io_request_object.
+ *
+ * @param[out]  the contructed scif request. This points to the same location as io_request_memory
+ *
+ * @return Indicate if framework IO request is successfully built.
+ * @retval SCI_SUCCESS This value is returned if the IO request was
+ *         successfully built.
+ */
+SCI_STATUS scif_io_request_construct_with_core (
+   SCI_CONTROLLER_HANDLE_T      scif_controller,
+   SCI_REMOTE_DEVICE_HANDLE_T   scif_remote_device,
+   void                       * scic_io_request,
+   void                       * user_io_request_object,
+   void                       * io_request_memory,
+   SCI_IO_REQUEST_HANDLE_T    * scif_io_request
+);
+
+/**
+ * @brief This method will build the basic scif and scic io request object based
+ *        on the user information supplied in the pass-through IO request object.
+ *        This function will not build the protocol specific part of the request
+ *        but set up the memory areas of scif and scic set the association.
+ *
+ * @pre
+ *
+ * @param[in]  scif_controller the handle to the framework controller object
+ *             for which to build an IO request.
+ * @param[in]  scif_remote_device This parameter specifies the framework
+ *             remote device with which this IO request is to be associated.
+ * @param[in]  io_tag This parameter specifies the IO tag to be associated
+ *             with this request.  If SCI_CONTROLLER_INVALID_IO_TAG is
+ *             passed, then a copy of the request is built internally.  The
+ *             request will be copied into the actual controller request
+ *             memory when the IO tag is allocated internally during the
+ *             scif_controller_start_io() method.
+ * @param[in]  user_io_request_object This parameter specifies the user
+ *             IO request to be utilized during IO construction.  This IO
+ *             pointer will become the associated object for the framework
+ *             IO request object.
+ * @param[in]  io_request_memory This parameter specifies the memory
+ *             to be utilized in the construction of the framework IO request.
+ * @param[in]  scif_io_request This parameter specifies the handle to be
+ *             utilized for all further interactions with this IO request
+ *             object.
+ *
+ * @return Indicate if the controller successfully built the IO request.
+ * @retval SCI_SUCCESS This value is returned if the IO request was
+ *         successfully built.
+ */
+SCI_STATUS scif_request_construct(
+   SCI_CONTROLLER_HANDLE_T      scif_controller,
+   SCI_REMOTE_DEVICE_HANDLE_T   scif_remote_device,
+   U16                          io_tag,
+   void                       * user_io_request_object,
+   void                       * io_request_memory,
+   SCI_IO_REQUEST_HANDLE_T    * scif_io_request
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIF_IO_REQUEST_H_
diff --git a/sys/dev/disk/isci/scil/scif_library.h b/sys/dev/disk/isci/scil/scif_library.h
new file mode 100644
index 0000000..d291243
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_library.h
@@ -0,0 +1,195 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_library.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIF_LIBRARY_H_
+#define _SCIF_LIBRARY_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the interface methods that can be called
+ *        by an SCI Framework user on the library object.  The library is
+ *        the container of all other objects being managed (i.e. controllers,
+ *        target devices, sas ports, etc.) by SCIF.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/sci_status.h>
+
+
+/**
+ * @brief This method will contsruct the SCI framework library based on the
+ *        supplied parameter information.  By default, libraries are
+ *        considered "ready" as soon as they are constructed.
+ *
+ * @param[in]  library_memory_p a pointer to the memory at which the
+ *             library object is located.
+ * @param[in]  max_controller_count the maximum number of controllers that
+ *             this library can manage.
+ *
+ * @return An opaque library handle to be used by the SCI user for all
+ *         subsequent library operations.
+ */
+SCI_LIBRARY_HANDLE_T scif_library_construct(
+   void * library_memory_p,
+   U8     max_controller_count
+);
+
+/**
+ * @brief This method returns the size of the framework library object.  The
+ *        size of the framework library object includes the associated core
+ *        object.
+ *
+ * @param[in]  max_controller_count the maximum number of controllers that
+ *             this library can manage.
+ *
+ * @return a positive integer value indicating the size (in bytes) of the
+ *         library object.
+ */
+U32 scif_library_get_object_size(
+   U8  max_controller_count
+);
+
+/**
+ * @brief This method will allocate the next available framework controller
+ *        object that can be managed by this framework library.
+ *
+ * @see For additional information please refer to:
+ *      scic_library_allocate_controller()
+ *
+ * @param[in]  library the handle to the library object for which to allocate
+ *             a controller.
+ * @param[out] new_controller_p This parameter specifies a pointer to the
+ *             controller handle that was added to the library.
+ *
+ * @return Indicate if the controller was successfully allocated or if iti
+ *         failed in some way.
+ * @retval SCI_SUCCESS if the controller was successfully allocated.
+ * @retval SCI_FAILURE_INSUFFICIENT_RESOURCES if the library has no more
+ *         available controller objects to allocate.
+ */
+SCI_STATUS scif_library_allocate_controller(
+   SCI_LIBRARY_HANDLE_T      library,
+   SCI_CONTROLLER_HANDLE_T * new_controller_p
+);
+
+/**
+ * @brief This method will attempt to free the supplied controller to the
+ *        library.
+ *
+ * @param[in]  library the handle to the library object for which to free
+ *             a controller.
+ * @param[in]  controller the handle to the controller object to be freed
+ *             from the library.
+ *
+ * @return Indicate if the controller was successfully freed or if it failed
+ *         in some way.
+ * @retval SCI_SUCCESS if the controller was successfully freed.
+ * @retval SCI_FAILURE_CONTROLLER_NOT_FOUND if the supplied controller is
+ *         not managed by the supplied library.
+ */
+SCI_STATUS scif_library_free_controller(
+   SCI_LIBRARY_HANDLE_T     library,
+   SCI_CONTROLLER_HANDLE_T  controller
+);
+
+
+/**
+ * @brief This method returns the SCI Core library handle
+ *        associated with this library.
+ *
+ * @param[in]  scif_library the handle to the library
+ *             object for which to retrieve the core specific
+ *             library handle
+ *
+ * @return Return the SCI core library handle associated with
+ *         the supplied framework library.
+ */
+SCI_LIBRARY_HANDLE_T scif_library_get_scic_handle(
+   SCI_LIBRARY_HANDLE_T   scif_library
+);
+
+
+/**
+ * @brief This method returns the minimum number of timers needed.  If the
+ *        user supplies timers less then the number specified via this
+ *        call, then the user runs the risk of improper operation.  This
+ *        call includes the minimum number of timers needed by the core.
+ *
+ * @return This method returns a value representing the minimum number of
+ *         timers required by this framework implementation
+ */
+U16 scif_library_get_min_timer_count(
+   void
+);
+
+/**
+ * @brief This method returns the maximum number of timers that could
+ *        be ever be in use by this component at a given time.
+ *
+ * @return This method returns a value representing the minimum number of
+ *         timers required by this framework implementation
+ */
+U16 scif_library_get_max_timer_count(
+   void
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIF_LIBRARY_H_
diff --git a/sys/dev/disk/isci/scil/scif_logger.h b/sys/dev/disk/isci/scil/scif_logger.h
new file mode 100644
index 0000000..3f6184e
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_logger.h
@@ -0,0 +1,117 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_logger.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIF_LOGGER_H_
+#define _SCIF_LOGGER_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the SCI Framework specific logger object
+ *        constant definitions.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_logger.h>
+
+
+/* The following is a list of log objects for which log information can */
+/* be enabled or disabled.                                              */
+
+/** Enables/disables logging specific to the library. */
+#define SCIF_LOG_OBJECT_LIBRARY                 0x00000001
+
+/** Enables/disables logging specific to the controller. */
+#define SCIF_LOG_OBJECT_CONTROLLER              0x00000002
+
+/** Enables/disables logging specific to the sas port. */
+#define SCIF_LOG_OBJECT_DOMAIN                  0x00000004
+
+/** Enables/disables logging specific to the domain discovery process. */
+#define SCIF_LOG_OBJECT_DOMAIN_DISCOVERY        0x00000008
+
+/** Enables/disables logging specific to the remote devices. */
+#define SCIF_LOG_OBJECT_REMOTE_DEVICE           0x00000010
+
+/** Enables/disables logging specific to remote device configuration. */
+#define SCIF_LOG_OBJECT_REMOTE_DEVICE_CONFIG    0x00000020
+
+/** Enables/disables logging specific to performing task management. */
+#define SCIF_LOG_OBJECT_TASK_MANAGEMENT         0x00000040
+
+/** Enables/disables logging specific to SCSI to SATA command translation. */
+#define SCIF_LOG_OBJECT_COMMAND_TRANSLATION     0x00000080
+
+/** Enables/disables logging specific to SCSI to SATA response translation. */
+#define SCIF_LOG_OBJECT_RESPONSE_TRANSLATION    0x00000100
+
+/** Enables/disables logging specific to framework initialization. */
+#define SCIF_LOG_OBJECT_INITIALIZATION          0x00000200
+
+/** Enables/disables logging specific to framework shutdown. */
+#define SCIF_LOG_OBJECT_SHUTDOWN                0x00000400
+
+/** Enables/disables logging specific to all IO requests. */
+#define SCIF_LOG_OBJECT_IO_REQUEST              0x00000800
+
+/** Enables/disables logging specific to all IO requests. */
+#define SCIF_LOG_OBJECT_CONTROLLER_RESET        0x00001000
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIF_LOGGER_H_
diff --git a/sys/dev/disk/isci/scil/scif_overview.h b/sys/dev/disk/isci/scil/scif_overview.h
new file mode 100644
index 0000000..2c23f47
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_overview.h
@@ -0,0 +1,115 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_overview.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIF_OVERVIEW_H_
+#define _SCIF_OVERVIEW_H_
+
+/**
+@page framework_page SCI Framework
+
+@section scif_introduction_section Introduction
+
+The SCI Framework component provides SAS and SATA storage specific abstraction
+to any OS driver devoid of this type of functionality. The functionality
+provided by this component is of a higher nature and considered unnecessary
+for some driver environments.  Basically, a user should be able to utilize
+the same SCI Framework with different SCI Core implementations, with the
+little to no changes necessary.
+
+@warning In situations where the SCI framework is utilized, users should NOT
+         invoke core methods on core objects for which there are associated
+         framework objects and framework methods. Therefore, if a method is
+         common to both the core and the framework object, do not invoke the
+         core method if utilizing the framework.  Some exceptions to this
+         exist and are called out.  It is important to mention that methods
+         found only in the core are safe to invoke at times specified per
+         that methods definition.
+
+The following is a list of features found in an SCI Framework implementation:
+
+-# SCI Core management
+-# Port configuration scheme enforcement.  There are 2 port configuration
+schemes:
+  -# Automatic Port Configuration (APC).  In APC mode the framework will
+     allow for any port configuration based on what is physically connected,
+     assuming the underlying SCI Core also supports the configuration.
+  -# Manual Port Configuration (MPC).  In MPC mode the framework expects the
+     user to supply exactly which phys are to be allocated to each specific
+     port.  If the discovered direct attached physical connections do not match
+     the user supplied map, then an error is raised and the initialization
+     process is halted.
+-# Domain Discovery
+-# Domain level resets (i.e. bus reset)
+-# Task management processing
+-# Controller Shutdown management (e.g. release STP affiliations, quiesce IOs)
+-# Remote Device Configuration. Potential features:
+  -# SSP: maybe mode selects to set timers or modify DIF settings.
+  -# STP: IDENTIFY_DEVICE, SET FEATURES, etc.
+  -# SMP: CONTROL type requests to set timers.
+-# SAT Translation (Actually contained in SATI component)
+-# SMP Zoning management
+
+@image latex sci_framework.eps "SCI Framework Class Diagram" width=10cm
+
+@note
+For the SCU Driver Standard implementation of the SCI Framework interface the
+following definitions should be used to augment the cardinalities described
+in the previous diagram:
+-# There are exactly 4 scif_domain objects in the scif_controller.  This
+   number directly correlates to the number of scic_port objects in the core.
+-# The maximum number of supported controllers in a library is a truly flexible
+   value, but the likely maximum number is 4.
+
+ */
+
+#endif // _SCIF_OVERVIEW_H_
diff --git a/sys/dev/disk/isci/scil/scif_remote_device.h b/sys/dev/disk/isci/scil/scif_remote_device.h
new file mode 100644
index 0000000..326aef3
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_remote_device.h
@@ -0,0 +1,294 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_remote_device.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIF_REMOTE_DEVICE_H_
+#define _SCIF_REMOTE_DEVICE_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the interface methods that can be called
+ *        by an SCI Framework user on a remote device object.  The
+ *        framework remote device object provides management of resets for
+ *        the remote device, IO thresholds, potentially NCQ tag management,
+ *        etc.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/sci_status.h>
+#include <dev/disk/isci/scil/intel_sas.h>
+
+
+/**
+ * This constant is utilized to inform the user that there is no defined
+ * maximum request queue depth associated with a remote device.
+ */
+#define SCIF_REMOTE_DEVICE_NO_MAX_QUEUE_DEPTH  0xFFFF
+
+/**
+ * @brief This method simply returns the maximum memory space needed to
+ *        store a remote device object.  The value returned includes enough
+ *        space for the framework and core device objects.
+ *
+ * @return a positive integer value indicating the size (in bytes) of the
+ *         remote device object.
+ */
+U32 scif_remote_device_get_object_size(
+   void
+);
+
+/**
+ * @brief This method performs the construction common to all device object
+ *        types in the framework.
+ *
+ * @note
+ *      - Remote device objects in the core are a limited resource.  Since
+ *        the framework construction/destruction methods wrap the core, the
+ *        user must ensure that a construct or destruct method is never
+ *        invoked when an existing construct or destruct method is ongoing.
+ *        This method shall be utilized for discovered direct attached
+ *        devices.
+ *      - It isn't necessary to call scif_remote_device_destruct() for
+ *        device objects that have only called this method for construction.
+ *        Once subsequent construction methods have been invoked (e.g.
+ *        scif_remote_device_da_construct()), then destruction should occur.
+ *
+ * @param[in]  domain This parameter specifies the domain in which this
+ *             remote device is contained.
+ * @param[in]  remote_device_memory This parameter specifies the memory
+ *             location into which this method shall construct the new
+ *             framework device object.
+ * @param[out] new_scif_remote_device_handle This parameter specifies the
+ *             handle to be used to communicate with the newly constructed
+ *             framework remote device.
+ *
+ * @return none
+ */
+void scif_remote_device_construct(
+   SCI_DOMAIN_HANDLE_T          domain,
+   void                       * remote_device_memory,
+   SCI_REMOTE_DEVICE_HANDLE_T * new_scif_remote_device_handle
+);
+
+/**
+ * @brief This method constructs a new framework remote device object.  The
+ *        remote device object shall remember it's counterpart core device
+ *        object as well as the domain in which it is contained.
+ *
+ * @note  Remote device objects in the core are a limited resource.  Since
+ *        the framework construction/destruction methods wrap the core, the
+ *        user must ensure that a construct or destruct method is never
+ *        invoked when an existing construct or destruct method is ongoing.
+ *        This method shall be utilized for discovered direct attached
+ *        devices.
+ *
+ * @pre The user must have previously called scif_remote_device_construct()
+ *
+ * @param[in]  remote_device This parameter specifies the framework device
+ *             for which to perform direct attached specific construction.
+ * @param[in]  sas_address  This parameter specifies the SAS address of the
+ *             remote device object being constructed.
+ * @param[in]  protocols This parameter specifies the protocols supported
+ *             by the remote device to be constructed.
+ *
+ * @return Indicate if the remote device was successfully constructed.
+ * @retval SCI_SUCCESS This value is returned if the remote device was
+ *         successfully constructed.
+ * @retval SCI_FAILURE_DEVICE_EXISTS Returned if the device has already
+ *         been constructed.
+ * @retval SCI_FAILURE_INSUFFICIENT_RESOURCES This value is returned if
+ *         the core controller associated with the supplied parameters
+ *         is unable to support additional remote devices.
+ */
+SCI_STATUS scif_remote_device_da_construct(
+   SCI_REMOTE_DEVICE_HANDLE_T                   remote_device,
+   SCI_SAS_ADDRESS_T                          * sas_address,
+   SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T * protocols
+);
+
+/**
+ * @brief This method constructs a new framework remote device object.  The
+ *        remote device object shall remember it's counterpart core device
+ *        object as well as the domain in which it is contained.
+ *
+ * @pre The user must have previously called scif_remote_device_construct()
+ *
+ * @note  Remote device objects in the core are a limited resource.  Since
+ *        the framework construction/destruction methods wrap the core, the
+ *        user must ensure that a construct or destruct method is never
+ *        invoked when an existing construct or destruct method is ongoing.
+ *        This method shall be utilized for discovered expander attached
+ *        devices.
+ *
+ * @param[in]  remote_device This parameter specifies the framework device
+ *             for which to perform expander specific construction.
+ * @param[in]  containing_device This parameter specifies the remote
+ *             device (i.e. an expander) that contains the device being
+ *             constructed.
+ * @param[in]  smp_response This parameter specifies the SMP_RESPONSE_DISCOVER
+ *             associated with the remote device being constructed.
+ *
+ * @return Indicate if the remote device was successfully constructed.
+ * @retval SCI_SUCCESS This value is returned if the remote device was
+ *         successfully constructed.
+ * @retval SCI_FAILURE_DEVICE_EXISTS Returned if the device has already
+ *         been constructed.
+ * @retval SCI_FAILURE_INSUFFICIENT_RESOURCES This value is returned if
+ *         the core controller associated with the supplied parameters
+ *         is unable to support additional remote devices.
+ */
+SCI_STATUS scif_remote_device_ea_construct(
+   SCI_REMOTE_DEVICE_HANDLE_T   remote_device,
+   SCI_REMOTE_DEVICE_HANDLE_T   containing_device,
+   SMP_RESPONSE_DISCOVER_T    * smp_response
+);
+
+
+/**
+ * @brief This method is utilized to free up a framework's remote
+ *        device object.
+ *
+ * @note  Remote device objects in the core are a limited resource.  Since
+ *        the framework construction/destruction methods wrap the core, the
+ *        user must ensure that a construct or destruct method is never
+ *        invoked when an existing construct or destruct method is ongoing.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device to be
+ *             destructed.
+ *
+ * @return The return value shall indicate if the device was successfully
+ *         destructed or if some failure occurred.
+ * @retval SCI_STATUS This value is returned if the device is successfully
+ *         destructed.
+ * @retval SCI_FAILURE_INVALID_REMOTE_DEVICE This value is returned if the
+ *         supplied device isn't valid (e.g. it's already been destructed,
+ *         the handle isn't valid, etc.).
+ */
+SCI_STATUS scif_remote_device_destruct(
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device
+);
+
+/**
+ * @brief This method simply returns the SCI Core object handle that is
+ *        associated with the supplied SCI Framework object.
+ *
+ * @param[in]  remote_device This parameter specifies the framework device
+ *             for which to return the associated core remote device.
+ *
+ * @return This method returns a handle to the core remote device object
+ *         associated with the framework remote device object.
+ * @retval SCI_INVALID_HANDLE This return value indicates that the SCI Core
+ *         remote device handle for the supplied framework device is invalid.
+ */
+SCI_REMOTE_DEVICE_HANDLE_T scif_remote_device_get_scic_handle(
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device
+);
+
+/**
+ * @brief This method returns the maximum queue depth supported for the
+ *        supplied target by this SCI Framework impementation.
+ *
+ * @param[in]  remote_device This parameter specifies the framework
+ *             device for which to return the maximum queue depth.
+ *
+ * @return This method returns a value indicating the maximum number of
+ *         IO requests that can be outstanding for the target at any
+ *         point in time.
+ * @retval SCIF_REMOTE_DEVICE_NO_MAX_QUEUE_DEPTH This value is returned
+ *         when there is no defined maximum queue depth for the target.
+ */
+U16 scif_remote_device_get_max_queue_depth(
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device
+);
+
+/**
+ * @brief This method will return the handle to the parent device of the
+ *        remote device.
+ *
+ * @param[in]  remote_device This parameter specifies the device for which
+ *             to return the parent device.
+ * @param[out] containing_device This parameter specifies the device
+ *             handle, from the remote device object, which indicate
+ *             the parent device of the supplied remote_device.
+ *
+ * @return none
+ */
+SCI_STATUS scif_remote_device_get_containing_device(
+   SCI_REMOTE_DEVICE_HANDLE_T          remote_device,
+   SCI_REMOTE_DEVICE_HANDLE_T        * containing_device
+);
+
+/**
+ * @brief This method returns the number of IO currently started
+ *        to the supplied target.  It does not include task
+ *        management requests.
+ *
+ * @param[in]  remote_device This parameter specifies the framework
+ *             device for which to return the number of started IO.
+ *
+ * @return This method returns a value indicating the number of started
+ *         IO requests.
+ */
+U32 scif_remote_device_get_started_io_count(
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIF_REMOTE_DEVICE_H_
diff --git a/sys/dev/disk/isci/scil/scif_sas_constants.h b/sys/dev/disk/isci/scil/scif_sas_constants.h
new file mode 100644
index 0000000..098ed73
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_constants.h
@@ -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: src/sys/dev/isci/scil/scif_sas_constants.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIF_SAS_CONSTANTS_H_
+#define _SCIF_SAS_CONSTANTS_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains the SCU hardware constants.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_controller_constants.h>
+
+#if !defined(ENABLE_MINIMUM_MEMORY_MODE)
+#define SCIF_SAS_SMP_PHY_COUNT        SCI_MAX_SMP_PHYS
+#else
+#define SCIF_SAS_SMP_PHY_COUNT        SCI_MIN_SMP_PHYS
+#endif // !defined(ENABLE_MINIMUM_MEMORY_OPERATION)
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIF_SAS_CONSTANTS_H_
diff --git a/sys/dev/disk/isci/scil/scif_sas_controller.c b/sys/dev/disk/isci/scil/scif_sas_controller.c
new file mode 100644
index 0000000..c954dcf
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_controller.c
@@ -0,0 +1,1254 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_controller.c,v 1.3 2012/02/09 17:50:24 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains the implementation of the SCIF_SAS_CONTROLLER
+ *        object.
+ */
+
+
+#include <dev/disk/isci/scil/sci_status.h>
+#include <dev/disk/isci/scil/sci_util.h>
+#include <dev/disk/isci/scil/sci_controller.h>
+#include <dev/disk/isci/scil/scic_controller.h>
+#include <dev/disk/isci/scil/scic_user_callback.h>
+#include <dev/disk/isci/scil/scif_user_callback.h>
+
+#include <dev/disk/isci/scil/scif_sas_controller.h>
+#include <dev/disk/isci/scil/scif_sas_library.h>
+#include <dev/disk/isci/scil/scif_sas_logger.h>
+
+
+//******************************************************************************
+//* P U B L I C   M E T H O D S
+//******************************************************************************
+
+SCI_STATUS scif_controller_construct(
+   SCI_LIBRARY_HANDLE_T      library,
+   SCI_CONTROLLER_HANDLE_T   controller,
+   void *                    user_object
+)
+{
+   SCI_STATUS              status        = SCI_SUCCESS;
+   SCIF_SAS_LIBRARY_T    * fw_library    = (SCIF_SAS_LIBRARY_T*) library;
+   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
+
+   // Validate the user supplied parameters.
+   if ((library == SCI_INVALID_HANDLE) || (controller == SCI_INVALID_HANDLE))
+      return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(library),
+      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION,
+      "scif_controller_construct(0x%x, 0x%x) enter\n",
+      library, controller
+   ));
+
+   // Construct the base controller.  As part of constructing the base
+   // controller we ask it to also manage the MDL iteration for the Core.
+   sci_base_controller_construct(
+      &fw_controller->parent,
+      sci_base_object_get_logger(fw_library),
+      scif_sas_controller_state_table,
+      fw_controller->mdes,
+      SCIF_SAS_MAX_MEMORY_DESCRIPTORS,
+      sci_controller_get_memory_descriptor_list_handle(fw_controller->core_object)
+   );
+
+   scif_sas_controller_initialize_state_logging(fw_controller);
+
+   sci_object_set_association(fw_controller, user_object);
+
+   status = scic_controller_construct(
+               fw_library->core_object, fw_controller->core_object, fw_controller
+            );
+
+   // If the core controller was successfully constructed, then
+   // finish construction of the framework controller.
+   if (status == SCI_SUCCESS)
+   {
+      // Set the association in the core controller to this framework
+      // controller.
+      sci_object_set_association(
+         (SCI_OBJECT_HANDLE_T) fw_controller->core_object, fw_controller
+      );
+
+      sci_base_state_machine_change_state(
+        &fw_controller->parent.state_machine,
+         SCI_BASE_CONTROLLER_STATE_RESET
+      );
+   }
+
+   return status;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scif_controller_initialize(
+   SCI_CONTROLLER_HANDLE_T   controller
+)
+{
+   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
+
+   // Validate the user supplied parameters.
+   if (controller == SCI_INVALID_HANDLE)
+      return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION,
+      "scif_controller_initialize(0x%x) enter\n",
+      controller
+   ));
+
+   return fw_controller->state_handlers->initialize_handler(
+             &fw_controller->parent
+          );
+}
+
+// ---------------------------------------------------------------------------
+
+U32 scif_controller_get_suggested_start_timeout(
+   SCI_CONTROLLER_HANDLE_T  controller
+)
+{
+   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
+
+   // Validate the user supplied parameters.
+   if (controller == SCI_INVALID_HANDLE)
+      return 0;
+
+   // Currently we aren't adding any additional time into the suggested
+   // timeout value for the start operation.  Simply utilize the core
+   // value.
+   return scic_controller_get_suggested_start_timeout(fw_controller->core_object);
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scif_controller_start(
+   SCI_CONTROLLER_HANDLE_T  controller,
+   U32                      timeout
+)
+{
+   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
+
+   // Validate the user supplied parameters.
+   if (controller == SCI_INVALID_HANDLE)
+      return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION,
+      "scif_controller_start(0x%x, 0x%x) enter\n",
+      controller, timeout
+   ));
+
+   return fw_controller->state_handlers->
+          start_handler(&fw_controller->parent, timeout);
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scif_controller_stop(
+   SCI_CONTROLLER_HANDLE_T  controller,
+   U32                      timeout
+)
+{
+   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
+
+   // Validate the user supplied parameters.
+   if (controller == SCI_INVALID_HANDLE)
+      return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_SHUTDOWN,
+      "scif_controller_stop(0x%x, 0x%x) enter\n",
+      controller, timeout
+   ));
+
+   return fw_controller->state_handlers->
+          stop_handler(&fw_controller->parent, timeout);
+
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scif_controller_reset(
+   SCI_CONTROLLER_HANDLE_T  controller
+)
+{
+   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
+
+   // Validate the user supplied parameters.
+   if (controller == SCI_INVALID_HANDLE)
+      return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_CONTROLLER_RESET,
+      "scif_controller_reset(0x%x) enter\n",
+      controller
+   ));
+
+   return fw_controller->state_handlers->
+          reset_handler(&fw_controller->parent);
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_CONTROLLER_HANDLE_T scif_controller_get_scic_handle(
+   SCI_CONTROLLER_HANDLE_T   controller
+)
+{
+   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
+
+   return fw_controller->core_object;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_IO_STATUS scif_controller_start_io(
+   SCI_CONTROLLER_HANDLE_T     controller,
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
+   SCI_IO_REQUEST_HANDLE_T     io_request,
+   U16                         io_tag
+)
+{
+   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
+   SCI_STATUS              status;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
+      "scif_controller_start_io(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
+      controller, remote_device, io_request, io_tag
+   ));
+
+   if (
+         sci_pool_empty(fw_controller->hprq.pool)
+      || scif_sas_controller_sufficient_resource(controller)
+      )
+   {
+      status = fw_controller->state_handlers->start_io_handler(
+                (SCI_BASE_CONTROLLER_T*) controller,
+                (SCI_BASE_REMOTE_DEVICE_T*) remote_device,
+                (SCI_BASE_REQUEST_T*) io_request,
+                io_tag
+             );
+   }
+   else
+      status = SCI_FAILURE_INSUFFICIENT_RESOURCES;
+
+   return (SCI_IO_STATUS)status;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_TASK_STATUS scif_controller_start_task(
+   SCI_CONTROLLER_HANDLE_T     controller,
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
+   SCI_TASK_REQUEST_HANDLE_T   task_request,
+   U16                         io_tag
+)
+{
+   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
+   SCI_STATUS              status;
+
+   // Validate the user supplied parameters.
+   if (  (controller == SCI_INVALID_HANDLE)
+      || (remote_device == SCI_INVALID_HANDLE)
+      || (task_request == SCI_INVALID_HANDLE) )
+   {
+      return SCI_TASK_FAILURE_INVALID_PARAMETER_VALUE;
+   }
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_TASK_MANAGEMENT,
+      "scif_controller_start_task(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
+      controller, remote_device, task_request, io_tag
+   ));
+
+   if (scif_sas_controller_sufficient_resource(controller))
+   {
+      status = fw_controller->state_handlers->start_task_handler(
+             (SCI_BASE_CONTROLLER_T*) controller,
+             (SCI_BASE_REMOTE_DEVICE_T*) remote_device,
+             (SCI_BASE_REQUEST_T*) task_request,
+             io_tag
+          );
+   }
+   else
+      status = SCI_FAILURE_INSUFFICIENT_RESOURCES;
+
+   return (SCI_TASK_STATUS)status;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scif_controller_complete_io(
+   SCI_CONTROLLER_HANDLE_T     controller,
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
+   SCI_IO_REQUEST_HANDLE_T     io_request
+)
+{
+   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
+      "scif_controller_complete_io(0x%x, 0x%x, 0x%x) enter\n",
+      controller, remote_device, io_request
+   ));
+
+   return fw_controller->state_handlers->complete_io_handler(
+             (SCI_BASE_CONTROLLER_T*) controller,
+             (SCI_BASE_REMOTE_DEVICE_T*) remote_device,
+             (SCI_BASE_REQUEST_T*) io_request
+          );
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scif_controller_complete_task(
+   SCI_CONTROLLER_HANDLE_T     controller,
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
+   SCI_TASK_REQUEST_HANDLE_T   task_request
+)
+{
+   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
+
+   // Validate the user supplied parameters.
+   if (  (controller == SCI_INVALID_HANDLE)
+      || (remote_device == SCI_INVALID_HANDLE)
+      || (task_request == SCI_INVALID_HANDLE) )
+   {
+      return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+   }
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_TASK_MANAGEMENT,
+      "scif_controller_complete_task(0x%x, 0x%x, 0x%x) enter\n",
+      controller, remote_device, task_request
+   ));
+
+   return fw_controller->state_handlers->complete_task_handler(
+             (SCI_BASE_CONTROLLER_T*) controller,
+             (SCI_BASE_REMOTE_DEVICE_T*) remote_device,
+             (SCI_BASE_REQUEST_T*) task_request
+          );
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scif_controller_get_domain_handle(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   U8                        port_index,
+   SCI_DOMAIN_HANDLE_T     * domain_handle
+)
+{
+   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
+
+   // Validate the user supplied parameters.
+   if (controller == SCI_INVALID_HANDLE)
+      return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+
+   // Retrieve the domain handle if the supplied index is legitimate.
+   if (port_index < SCI_MAX_PORTS)
+   {
+      *domain_handle = &fw_controller->domains[port_index];
+      return SCI_SUCCESS;
+   }
+
+   return SCI_FAILURE_INVALID_PORT;
+}
+
+/**
+ * @brief This method builds the memory descriptor list for this
+ *        controller.
+ *
+ * @param[in] fw_controller This parameter specifies the framework
+ *            controller object for which to build the MDL.
+ *
+ * @return none
+ */
+void scif_sas_controller_build_mdl(
+   SCIF_SAS_CONTROLLER_T * fw_controller
+)
+{
+   // one internal request for each domain.
+   sci_base_mde_construct(
+      &fw_controller->mdes[SCIF_SAS_MDE_INTERNAL_IO],
+      4,
+      fw_controller->internal_request_entries *
+         scif_sas_internal_request_get_object_size(),
+      SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
+   );
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scif_controller_set_mode(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   SCI_CONTROLLER_MODE       mode
+)
+{
+   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
+   SCI_STATUS              status          = SCI_SUCCESS;
+
+   if (
+         (fw_controller->parent.state_machine.current_state_id
+          == SCI_BASE_CONTROLLER_STATE_INITIALIZING)
+      || (fw_controller->parent.state_machine.current_state_id
+          == SCI_BASE_CONTROLLER_STATE_INITIALIZED)
+      )
+   {
+      switch (mode)
+      {
+      case SCI_MODE_SPEED:
+         fw_controller->internal_request_entries =
+            MIN(fw_controller->internal_request_entries, SCIF_SAS_MAX_INTERNAL_REQUEST_COUNT);
+         scif_sas_controller_build_mdl(fw_controller);
+      break;
+
+      case SCI_MODE_SIZE:
+         fw_controller->internal_request_entries =
+            MIN(fw_controller->internal_request_entries, SCIF_SAS_MIN_INTERNAL_REQUEST_COUNT);
+         scif_sas_controller_build_mdl(fw_controller);
+      break;
+
+      default:
+         status = SCI_FAILURE_INVALID_PARAMETER_VALUE;
+      break;
+      }
+   }
+   else
+      status = SCI_FAILURE_INVALID_STATE;
+
+   if (status != SCI_SUCCESS)
+   {
+      return status;
+   }
+   else
+   {
+      // Currently, the framework doesn't change any configurations for
+      // speed or size modes.  Default to speed mode basically.
+      return scic_controller_set_mode(fw_controller->core_object, mode);
+   }
+}
+
+// ---------------------------------------------------------------------------
+
+U32 scif_controller_get_sat_compliance_version(
+   void
+)
+{
+   /// @todo Fix return of SAT compliance version.
+   return 0;
+}
+
+// ---------------------------------------------------------------------------
+
+U32 scif_controller_get_sat_compliance_version_revision(
+   void
+)
+{
+   /// @todo Fix return of SAT compliance revision.
+   return 0;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scif_user_parameters_set(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   SCIF_USER_PARAMETERS_T  * scif_parms
+)
+{
+   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
+
+   //validate all the registry entries before overwriting the default parameter
+   //values.
+   if (scif_parms->sas.is_sata_ncq_enabled != 1 && scif_parms->sas.is_sata_ncq_enabled != 0)
+      return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+
+   if (scif_parms->sas.max_ncq_depth < 1 && scif_parms->sas.max_ncq_depth > 32)
+      return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+
+   if (scif_parms->sas.is_sata_standby_timer_enabled != 1
+       && scif_parms->sas.is_sata_standby_timer_enabled != 0)
+      return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+
+   if (scif_parms->sas.is_non_zero_buffer_offsets_enabled != 1
+       && scif_parms->sas.is_non_zero_buffer_offsets_enabled != 0)
+      return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+
+   if (scif_parms->sas.reset_type != SCI_SAS_ABORT_TASK
+       && scif_parms->sas.reset_type != SCI_SAS_ABORT_TASK_SET
+       && scif_parms->sas.reset_type != SCI_SAS_CLEAR_TASK_SET
+       && scif_parms->sas.reset_type != SCI_SAS_LOGICAL_UNIT_RESET
+       && scif_parms->sas.reset_type != SCI_SAS_I_T_NEXUS_RESET
+       && scif_parms->sas.reset_type != SCI_SAS_CLEAR_ACA
+       && scif_parms->sas.reset_type != SCI_SAS_QUERY_TASK
+       && scif_parms->sas.reset_type != SCI_SAS_QUERY_TASK_SET
+       && scif_parms->sas.reset_type != SCI_SAS_QUERY_ASYNCHRONOUS_EVENT
+       && scif_parms->sas.reset_type != SCI_SAS_HARD_RESET)
+      return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+
+   if (scif_parms->sas.clear_affiliation_during_controller_stop != 1
+       && scif_parms->sas.clear_affiliation_during_controller_stop !=0)
+       return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+
+   memcpy((&fw_controller->user_parameters), scif_parms, sizeof(*scif_parms));
+
+   // In the future more could be done to prevent setting parameters at the
+   // wrong time, but for now we'll simply set the values even if it is too
+   // late for them to take affect.
+   return SCI_SUCCESS;
+}
+
+// ---------------------------------------------------------------------------
+
+#if !defined(DISABLE_INTERRUPTS)
+
+/**
+ * @brief This routine check each domain of the controller to see if
+ *           any domain is overriding interrupt coalescence.
+ *
+ * @param[in] fw_controller frame controller
+ * @param[in] fw_smp_phy The smp phy to be freed.
+ *
+ * @return none
+ */
+static
+BOOL scif_sas_controller_is_overriding_interrupt_coalescence(
+   SCIF_SAS_CONTROLLER_T * fw_controller
+)
+{
+   U8 index;
+
+   for(index = 0; index < SCI_MAX_DOMAINS; index++)
+   {
+      if(fw_controller->domains[index].parent.state_machine.current_state_id ==
+            SCI_BASE_DOMAIN_STATE_DISCOVERING)
+         return TRUE;
+   }
+
+   return FALSE;
+}
+
+SCI_STATUS scif_controller_set_interrupt_coalescence(
+   SCI_CONTROLLER_HANDLE_T controller,
+   U32                     coalesce_number,
+   U32                     coalesce_timeout
+)
+{
+   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T * )controller;
+
+   ///when framework is in the middle of temporarily overriding the interrupt
+   ///coalescence values, user's request of setting interrupt coalescence
+   ///will be saved. As soon as the framework done the temporary overriding,
+   ///it will serve user's request to set new interrupt coalescence.
+   if (scif_sas_controller_is_overriding_interrupt_coalescence(fw_controller))
+   {
+      U32 curr_coalesce_number;
+      U32 curr_coalesce_timeout;
+      SCI_STATUS core_status;
+
+      // save current interrupt coalescence info.
+      scic_controller_get_interrupt_coalescence (
+         fw_controller->core_object, &curr_coalesce_number, &curr_coalesce_timeout);
+
+      //try user's request out in the core, but immediately restore core's
+      //current setting.
+      core_status = scic_controller_set_interrupt_coalescence(
+                       fw_controller->core_object, coalesce_number, coalesce_timeout);
+
+      if ( core_status == SCI_SUCCESS )
+      {
+         fw_controller->saved_interrupt_coalesce_number = (U16)coalesce_number;
+         fw_controller->saved_interrupt_coalesce_timeout = coalesce_timeout;
+      }
+
+       //restore current interrupt coalescence.
+      scic_controller_set_interrupt_coalescence(
+         fw_controller->core_object, curr_coalesce_number, curr_coalesce_timeout);
+
+      return core_status;
+   }
+   else
+   {
+      ///If framework is not internally overriding the interrupt coalescence,
+      ///serve user's request immediately by passing the reqeust to core.
+      return scic_controller_set_interrupt_coalescence(
+                fw_controller->core_object, coalesce_number, coalesce_timeout);
+   }
+}
+
+// ---------------------------------------------------------------------------
+
+void scif_controller_get_interrupt_coalescence(
+   SCI_CONTROLLER_HANDLE_T controller,
+   U32                   * coalesce_number,
+   U32                   * coalesce_timeout
+)
+{
+   SCIF_SAS_CONTROLLER_T * scif_controller = (SCIF_SAS_CONTROLLER_T * )controller;
+
+   scic_controller_get_interrupt_coalescence(
+      scif_controller->core_object, coalesce_number, coalesce_timeout);
+}
+
+/**
+ * @brief This method will save the interrupt coalescence values.  If
+ *        the interrupt coalescence values have already been saved,
+ *        then this method performs no operations.
+ *
+ * @param[in,out] fw_controller This parameter specifies the controller
+ *                for which to save the interrupt coalescence values.
+ *
+ * @return none
+ */
+void scif_sas_controller_save_interrupt_coalescence(
+   SCIF_SAS_CONTROLLER_T * fw_controller
+)
+{
+   if ( !scif_sas_controller_is_overriding_interrupt_coalescence(fw_controller))
+   {
+      // Override core's interrupt coalescing settings during SMP
+      // DISCOVER process cause' there is only 1 outstanding SMP
+      // request per domain is allowed.
+      scic_controller_get_interrupt_coalescence(
+         fw_controller->core_object,
+         (U32*)&(fw_controller->saved_interrupt_coalesce_number),
+         &(fw_controller->saved_interrupt_coalesce_timeout)
+      );
+
+      // Temporarily disable the interrupt coalescing.
+      scic_controller_set_interrupt_coalescence(fw_controller->core_object,0,0);
+   }
+}
+
+/**
+ * @brief This method will restore the interrupt coalescence values.  If
+ *        the interrupt coalescence values have not already been saved,
+ *        then this method performs no operations.
+ *
+ * @param[in,out] fw_controller This parameter specifies the controller
+ *                for which to restore the interrupt coalescence values.
+ *
+ * @return none
+ */
+void scif_sas_controller_restore_interrupt_coalescence(
+   SCIF_SAS_CONTROLLER_T * fw_controller
+)
+{
+   if ( !scif_sas_controller_is_overriding_interrupt_coalescence(fw_controller))
+      scic_controller_set_interrupt_coalescence(
+         fw_controller->core_object,
+         fw_controller->saved_interrupt_coalesce_number,
+         fw_controller->saved_interrupt_coalesce_timeout
+      );
+}
+
+#endif // !defined(DISABLE_INTERRUPTS)
+
+// ---------------------------------------------------------------------------
+
+void scic_cb_controller_start_complete(
+   SCI_CONTROLLER_HANDLE_T  controller,
+   SCI_STATUS               completion_status
+)
+{
+   SCIF_SAS_CONTROLLER_T *fw_controller = (SCIF_SAS_CONTROLLER_T*)
+                                         sci_object_get_association(controller);
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION,
+      "scic_cb_controller_start_complete(0x%x, 0x%x) enter\n",
+      controller, completion_status
+   ));
+
+   if (completion_status == SCI_SUCCESS
+       || completion_status == SCI_FAILURE_TIMEOUT)
+   {
+      // Even the initialization of the core controller timed out, framework
+      // controller should still transit to READY state.
+      sci_base_state_machine_change_state(
+         &fw_controller->parent.state_machine,
+         SCI_BASE_CONTROLLER_STATE_READY
+      );
+   }
+
+   scif_cb_controller_start_complete(fw_controller, completion_status);
+}
+
+// ---------------------------------------------------------------------------
+
+void scic_cb_controller_stop_complete(
+   SCI_CONTROLLER_HANDLE_T  controller,
+   SCI_STATUS               completion_status
+)
+{
+   SCIF_SAS_CONTROLLER_T *fw_controller = (SCIF_SAS_CONTROLLER_T*)
+                                         sci_object_get_association(controller);
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_SHUTDOWN,
+      "scic_cb_controller_stop_complete(0x%x, 0x%x) enter\n",
+      controller, completion_status
+   ));
+
+   if (completion_status == SCI_SUCCESS)
+   {
+      sci_base_state_machine_change_state(
+         &fw_controller->parent.state_machine,
+         SCI_BASE_CONTROLLER_STATE_STOPPED
+      );
+   }
+   else
+   {
+      sci_base_state_machine_change_state(
+         &fw_controller->parent.state_machine,
+         SCI_BASE_CONTROLLER_STATE_FAILED
+      );
+   }
+
+   scif_cb_controller_stop_complete(fw_controller, completion_status);
+}
+
+
+// ---------------------------------------------------------------------------
+
+void scic_cb_controller_error(
+   SCI_CONTROLLER_HANDLE_T  controller,
+   SCI_CONTROLLER_ERROR error
+)
+{
+   SCIF_SAS_CONTROLLER_T *fw_controller = (SCIF_SAS_CONTROLLER_T*)
+                                         sci_object_get_association(controller);
+
+   fw_controller->parent.error = error;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_SHUTDOWN,
+      "scic_cb_controller_not_ready(0x%x) enter\n",
+      controller
+   ));
+
+   sci_base_state_machine_change_state(
+      &fw_controller->parent.state_machine,
+      SCI_BASE_CONTROLLER_STATE_FAILED
+   );
+}
+
+//******************************************************************************
+//* P R O T E C T E D    M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method is utilized to continue an internal IO operation
+ *        on the controller.  This method is utilized for SAT translated
+ *        requests that generate multiple ATA commands in order to fulfill
+ *        the original SCSI request.
+ *
+ * @param[in]  controller This parameter specifies the controller on which
+ *             to continue an internal IO request.
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             on which to continue an internal IO request.
+ * @param[in]  io_request This parameter specifies the IO request to be
+ *             continue.
+ *
+ * @return Indicate if the continue operation was successful.
+ * @retval SCI_SUCCESS This value is returned if the operation succeeded.
+ */
+SCI_STATUS scif_sas_controller_continue_io(
+   SCI_CONTROLLER_HANDLE_T     controller,
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
+   SCI_IO_REQUEST_HANDLE_T     io_request
+)
+{
+   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
+
+   return fw_controller->state_handlers->continue_io_handler(
+             (SCI_BASE_CONTROLLER_T*) controller,
+             (SCI_BASE_REMOTE_DEVICE_T*) remote_device,
+             (SCI_BASE_REQUEST_T*) io_request
+          );
+}
+
+/**
+ * @brief This method will attempt to destruct a framework controller.
+ *        This includes free any resources retreived from the user (e.g.
+ *        timers).
+ *
+ * @param[in]  fw_controller This parameter specifies the framework
+ *             controller to destructed.
+ *
+ * @return none
+ */
+void scif_sas_controller_destruct(
+   SCIF_SAS_CONTROLLER_T * fw_controller
+)
+{
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_controller),
+      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_SHUTDOWN,
+      "scif_sas_controller_destruct(0x%x) enter\n",
+      fw_controller
+   ));
+}
+
+//-----------------------------------------------------------------------------
+// INTERNAL REQUEST RELATED METHODS
+//-----------------------------------------------------------------------------
+
+/**
+ * @brief This routine is to allocate the memory for creating a new internal
+ *        request.
+ *
+ * @param[in] scif_controller handle to frame controller
+ *
+ * @return void* address to internal request memory
+ */
+void * scif_sas_controller_allocate_internal_request(
+   SCIF_SAS_CONTROLLER_T * fw_controller
+)
+{
+   POINTER_UINT internal_io_address;
+
+   if( !sci_pool_empty(fw_controller->internal_request_memory_pool) )
+   {
+      sci_pool_get(
+         fw_controller->internal_request_memory_pool, internal_io_address
+      );
+
+      //clean the memory.
+      memset((char*)internal_io_address, 0, scif_sas_internal_request_get_object_size());
+
+      return (void *) internal_io_address;
+   }
+   else
+      return NULL;
+}
+
+/**
+ * @brief This routine is to free the memory for a completed internal request.
+ *
+ * @param[in] scif_controller handle to frame controller
+ * @param[in] fw_internal_io The internal IO to be freed.
+ *
+ * @return none
+ */
+void scif_sas_controller_free_internal_request(
+   SCIF_SAS_CONTROLLER_T * fw_controller,
+   void                  * fw_internal_request_buffer
+)
+{
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_controller),
+      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
+      "scif_controller_free_internal_request(0x%x, 0x%x) enter\n",
+      fw_controller, fw_internal_request_buffer
+   ));
+
+   //return the memory to to pool.
+   if( !sci_pool_full(fw_controller->internal_request_memory_pool) )
+   {
+      sci_pool_put(
+         fw_controller->internal_request_memory_pool,
+         (POINTER_UINT) fw_internal_request_buffer
+      );
+   }
+}
+
+
+/**
+ * @brief this routine is called by OS' DPC to start io requests from internal
+ *        high priority request queue
+ * @param[in] fw_controller The framework controller.
+ *
+ * @return none
+ */
+void scif_sas_controller_start_high_priority_io(
+   SCIF_SAS_CONTROLLER_T * fw_controller
+)
+{
+   POINTER_UINT            io_address;
+   SCIF_SAS_IO_REQUEST_T * fw_io;
+   SCI_STATUS              status;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_controller),
+      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
+      "scif_controller_start_high_priority_io(0x%x) enter\n",
+      fw_controller
+   ));
+
+   while ( !sci_pool_empty(fw_controller->hprq.pool) )
+   {
+      sci_pool_get(fw_controller->hprq.pool, io_address);
+
+      fw_io = (SCIF_SAS_IO_REQUEST_T *)io_address;
+
+      status = fw_controller->state_handlers->start_high_priority_io_handler(
+         (SCI_BASE_CONTROLLER_T*) fw_controller,
+         (SCI_BASE_REMOTE_DEVICE_T*) fw_io->parent.device,
+         (SCI_BASE_REQUEST_T*) fw_io,
+         SCI_CONTROLLER_INVALID_IO_TAG
+      );
+   }
+}
+
+/**
+ * @brief This method will check how many outstanding IOs currently and number
+ * of IOs in high priority queue, if the overall number exceeds the max_tc,
+ * return FALSE.
+ *
+ * @param[in] fw_controller The framework controller.
+ *
+ * @return BOOL Indicate whether there is sufficient resource to start an IO.
+ * @retvalue TRUE The controller has sufficient resource.
+ * @retvalue FALSE There is not sufficient resource available.
+ */
+BOOL scif_sas_controller_sufficient_resource(
+   SCIF_SAS_CONTROLLER_T *fw_controller
+)
+{
+   SCIF_SAS_DOMAIN_T * fw_domain;
+   U32 domain_index;
+   U32 outstanding_io_count = 0;
+   U32 high_priority_io_count = 0;
+
+   for(domain_index = 0; domain_index < SCI_MAX_DOMAINS; domain_index++)
+   {
+      fw_domain = &fw_controller->domains[domain_index];
+      outstanding_io_count += fw_domain->request_list.element_count;
+   }
+
+   high_priority_io_count = sci_pool_count(fw_controller->hprq.pool);
+
+   if ( (outstanding_io_count + high_priority_io_count) > SCI_MAX_IO_REQUESTS )
+      return FALSE;
+
+   return TRUE;
+}
+
+
+/**
+ * @brief This method is the starting point to complete high prority io for a
+ *        controller then down to domain, device.
+ *
+ * @param[in] fw_controller The framework controller
+ * @param[in] remote_device  The framework remote device.
+ * @param[in] io_request The high priority io request to be completed.
+ *
+ * @return SCI_STATUS indicate the completion status from framework down to the
+ *         core.
+ */
+SCI_STATUS scif_sas_controller_complete_high_priority_io(
+   SCIF_SAS_CONTROLLER_T    *fw_controller,
+   SCIF_SAS_REMOTE_DEVICE_T *remote_device,
+   SCIF_SAS_REQUEST_T       *io_request
+)
+{
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_controller),
+      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
+      "scif_sas_controller_complete_high_priority_io(0x%x, 0x%x, 0x%x) enter\n",
+      fw_controller, remote_device, io_request
+   ));
+
+   //call controller's new added complete_high_priority_io_handler
+   return fw_controller->state_handlers->complete_high_priority_io_handler(
+             (SCI_BASE_CONTROLLER_T*) fw_controller,
+             (SCI_BASE_REMOTE_DEVICE_T*) remote_device,
+             (SCI_BASE_REQUEST_T*) io_request
+          );
+}
+
+/**
+
+ * @brief This routine is to allocate the memory for creating a smp phy object.
+ *
+ * @param[in] scif_controller handle to frame controller
+ *
+ * @return SCIF_SAS_SMP_PHY_T * An allocated space for smp phy. If failed to allocate,
+ *            return NULL.
+ */
+SCIF_SAS_SMP_PHY_T * scif_sas_controller_allocate_smp_phy(
+   SCIF_SAS_CONTROLLER_T * fw_controller
+)
+{
+   SCIF_SAS_SMP_PHY_T * smp_phy;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_controller),
+      SCIF_LOG_OBJECT_CONTROLLER,
+      "scif_controller_allocate_smp_phy(0x%x) enter\n",
+      fw_controller
+   ));
+
+   if( !sci_fast_list_is_empty(&fw_controller->smp_phy_memory_list) )
+   {
+      smp_phy = (SCIF_SAS_SMP_PHY_T *)
+         sci_fast_list_remove_head(&fw_controller->smp_phy_memory_list);
+
+      //clean the memory.
+      memset((char*)smp_phy,
+             0,
+             sizeof(SCIF_SAS_SMP_PHY_T)
+            );
+
+      return smp_phy;
+   }
+   else
+      return NULL;
+}
+
+/**
+ * @brief This routine is to free the memory for a released smp phy.
+ *
+ * @param[in] fw_controller The framework controller, a smp phy is released
+ *                to its memory.
+ * @param[in] fw_smp_phy The smp phy to be freed.
+ *
+ * @return none
+ */
+void scif_sas_controller_free_smp_phy(
+   SCIF_SAS_CONTROLLER_T * fw_controller,
+   SCIF_SAS_SMP_PHY_T    * smp_phy
+)
+{
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_controller),
+      SCIF_LOG_OBJECT_CONTROLLER,
+      "scif_controller_free_smp_phy(0x%x, 0x%x) enter\n",
+      fw_controller, smp_phy
+   ));
+
+   //return the memory to the list.
+   sci_fast_list_insert_tail(
+      &fw_controller->smp_phy_memory_list,
+      &smp_phy->list_element
+   );
+}
+
+
+/**
+ * @brief This method clear affiliation for all the EA SATA devices associated
+ *        to this controller.
+ *
+ * @param[in] fw_controller This parameter specifies the framework
+ *            controller object for whose remote devices are to be stopped.
+ *
+ * @return This method returns a value indicating if the operation completed.
+ * @retval SCI_COMPLETE This value indicates that all the EA SATA devices'
+ *         affiliation was cleared.
+ * @retval SCI_INCOMPLETE This value indicates clear affiliation activity is
+ *         yet to be completed.
+ */
+SCI_STATUS scif_sas_controller_clear_affiliation(
+   SCIF_SAS_CONTROLLER_T * fw_controller
+)
+{
+   U8 index;
+   SCI_STATUS status;
+   SCIF_SAS_DOMAIN_T * fw_domain;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_controller),
+      SCIF_LOG_OBJECT_CONTROLLER,
+      "scif_sas_controller_clear_affiliation(0x%x) enter\n",
+      fw_controller
+   ));
+
+   index = fw_controller->current_domain_to_clear_affiliation;
+
+   if (index < SCI_MAX_DOMAINS)
+   {
+      fw_domain = &fw_controller->domains[index];
+
+      //Need to stop all the on-going smp activities before clearing affiliation.
+      scif_sas_domain_cancel_smp_activities(fw_domain);
+
+      scif_sas_domain_start_clear_affiliation(fw_domain);
+
+      status = SCI_WARNING_SEQUENCE_INCOMPLETE;
+   }
+   else
+   {  //the controller has done clear affiliation work to all its domains.
+      scif_sas_controller_continue_to_stop(fw_controller);
+      status = SCI_SUCCESS;
+   }
+
+   return status;
+}
+
+
+/**
+ * @brief This method sets SCIF user parameters to
+ *        default values.  Users can override these values utilizing
+ *        the sciF_user_parameters_set() methods.
+ *
+ * @param[in] controller This parameter specifies the controller for
+ *            which to set the configuration parameters to their
+ *            default values.
+ *
+ * @return none
+ */
+void scif_sas_controller_set_default_config_parameters(
+   SCIF_SAS_CONTROLLER_T * this_controller
+)
+{
+   SCIF_USER_PARAMETERS_T * scif_parms = &(this_controller->user_parameters);
+
+   scif_parms->sas.is_sata_ncq_enabled = TRUE;
+   scif_parms->sas.max_ncq_depth = 32;
+   scif_parms->sas.is_sata_standby_timer_enabled = FALSE;
+   scif_parms->sas.is_non_zero_buffer_offsets_enabled = FALSE;
+   scif_parms->sas.reset_type = SCI_SAS_LOGICAL_UNIT_RESET;
+   scif_parms->sas.clear_affiliation_during_controller_stop = TRUE;
+   scif_parms->sas.ignore_fua = FALSE;
+
+}
+
+
+/**
+ * @brief This method releases resource for framework controller and associated
+ *        objects.
+ *
+ * @param[in] fw_controller This parameter specifies the framework
+ *            controller and associated objects whose resources are to be released.
+ *
+ * @return This method returns a value indicating if the operation succeeded.
+ * @retval SCI_SUCCESS This value indicates that resource release succeeded.
+ * @retval SCI_FAILURE This value indicates certain failure during the process
+ *            of resource release.
+ */
+SCI_STATUS scif_sas_controller_release_resource(
+   SCIF_SAS_CONTROLLER_T * fw_controller
+)
+{
+   U8 index;
+   SCIF_SAS_DOMAIN_T * fw_domain;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_controller),
+      SCIF_LOG_OBJECT_CONTROLLER,
+      "scif_sas_controller_release_resource(0x%x) enter\n",
+      fw_controller
+   ));
+
+   //currently the only resource to be released is domain's timer.
+   for (index = 0; index < SCI_MAX_DOMAINS; index++)
+   {
+      fw_domain = &fw_controller->domains[index];
+
+      scif_sas_domain_release_resource(fw_controller, fw_domain);
+   }
+
+   return SCI_SUCCESS;
+}
+
+
+#ifdef SCI_LOGGING
+/**
+ * This method will start state transition logging for the framework
+ * controller object.
+ *
+ * @param[in] fw_controller The framework controller object on which to
+ *       observe state changes.
+ *
+ * @return none
+ */
+void scif_sas_controller_initialize_state_logging(
+   SCIF_SAS_CONTROLLER_T * fw_controller
+)
+{
+   sci_base_state_machine_logger_initialize(
+      &fw_controller->parent.state_machine_logger,
+      &fw_controller->parent.state_machine,
+      &fw_controller->parent.parent,
+      scif_cb_logger_log_states,
+      "SCIF_SAS_CONTROLLER_T", "base state machine",
+      SCIF_LOG_OBJECT_CONTROLLER
+   );
+}
+
+/**
+ * This method will remove the logging of state transitions from the framework
+ * controller object.
+ *
+ * @param[in] fw_controller The framework controller to change.
+ *
+ * @return none
+ */
+void scif_sas_controller_deinitialize_state_logging(
+   SCIF_SAS_CONTROLLER_T * fw_controller
+)
+{
+   sci_base_state_machine_logger_deinitialize(
+      &fw_controller->parent.state_machine_logger,
+      &fw_controller->parent.state_machine
+   );
+}
+#endif // SCI_LOGGING
diff --git a/sys/dev/disk/isci/scil/scif_sas_controller.h b/sys/dev/disk/isci/scil/scif_sas_controller.h
new file mode 100644
index 0000000..04b4bc6
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_controller.h
@@ -0,0 +1,307 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_controller.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIF_SAS_CONTROLLER_H_
+#define _SCIF_SAS_CONTROLLER_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains the protected interface structures, constants,
+ *        and methods for the SCIF_SAS_CONTROLLER object.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/sci_abstract_list.h>
+#include <dev/disk/isci/scil/sci_controller_constants.h>
+#include <dev/disk/isci/scil/sci_memory_descriptor_list.h>
+#include <dev/disk/isci/scil/sci_base_controller.h>
+#include <dev/disk/isci/scil/scif_controller.h>
+#include <dev/disk/isci/scil/scif_config_parameters.h>
+#include <dev/disk/isci/scil/scif_sas_domain.h>
+#include <dev/disk/isci/scil/scif_sas_io_request.h>
+#include <dev/disk/isci/scil/scif_sas_task_request.h>
+#include <dev/disk/isci/scil/scif_sas_constants.h>
+#include <dev/disk/isci/scil/sci_pool.h>
+#include <dev/disk/isci/scil/scif_sas_internal_io_request.h>
+#include <dev/disk/isci/scil/scif_sas_high_priority_request_queue.h>
+#include <dev/disk/isci/scil/scif_sas_smp_phy.h>
+
+
+// Currently there is only a need for 1 memory descriptor.  This descriptor
+// describes the internal IO request memory.
+#define SCIF_SAS_MAX_MEMORY_DESCRIPTORS 1
+
+enum _SCIF_SAS_MAX_MEMORY_DESCRIPTORS
+{
+   SCIF_SAS_MDE_INTERNAL_IO = 0
+
+};
+
+/**
+ * @struct SCIF_SAS_CONTROLLER
+ *
+ * @brief The SCI SAS Framework controller object abstracts storage controller
+ *        level behavior for the framework component.
+ */
+typedef struct SCIF_SAS_CONTROLLER
+{
+   /**
+    * The SCI_BASE_CONTROLLER is the parent object for the SCIF_SAS_CONTROLLER
+    * object.
+    */
+   SCI_BASE_CONTROLLER_T  parent;
+
+   /**
+    * This field contains the handle for the SCI Core controller object that
+    * is managed by this framework controller.
+    */
+   SCI_CONTROLLER_HANDLE_T  core_object;
+
+   /**
+    * This field references the list of state specific handler methods to
+    * be utilized for this controller instance.
+    */
+   SCI_BASE_CONTROLLER_STATE_HANDLER_T * state_handlers;
+
+   /**
+    * This field contains the memory desciptors defining the physical
+    * memory requirements for this controller.
+    */
+   SCI_PHYSICAL_MEMORY_DESCRIPTOR_T mdes[SCIF_SAS_MAX_MEMORY_DESCRIPTORS];
+
+   /**
+    * This field contains the SAS domain objects managed by this controller.
+    */
+   SCIF_SAS_DOMAIN_T  domains[SCI_MAX_DOMAINS];
+
+   /**
+    * This field represents the pool of available remote device objects
+    * supported by the controller.
+    */
+   SCI_ABSTRACT_ELEMENT_POOL_T  free_remote_device_pool;
+
+   /**
+    * This field contains the maximum number of abstract elements that
+    * can be placed in the pool.
+    */
+   SCI_ABSTRACT_ELEMENT_T  remote_device_pool_elements[SCI_MAX_REMOTE_DEVICES];
+
+   /**
+    * This field provides the controller object a scratch area to indicate
+    * status of an ongoing operation.
+    */
+   SCI_STATUS  operation_status;
+
+   /**
+    * This field will contain an user specified parameter information
+    * to be utilized by the framework.
+    */
+   SCIF_USER_PARAMETERS_T user_parameters;
+
+   /**
+    * This field records the index for the current domain to clear affiliation
+    * EA SATA remote devices, during the controller stop process.
+    */
+   U8 current_domain_to_clear_affiliation;
+
+   U32 internal_request_entries;
+
+   /**
+    * This field provides a pool to manage the memory resource for all internal
+    * requests.
+    * requests.
+    */
+   SCI_POOL_CREATE(
+      internal_request_memory_pool,
+      POINTER_UINT,
+      SCIF_SAS_MAX_INTERNAL_REQUEST_COUNT
+   );
+
+   /**
+    * This field provides a queue for built internal requests waiting to be
+    * started.
+    */
+   SCIF_SAS_HIGH_PRIORITY_REQUEST_QUEUE_T  hprq;
+
+   /**
+    * This represents the number of available SMP phy objects that can
+    * be managed by the framework.
+    */
+   SCIF_SAS_SMP_PHY_T smp_phy_array[SCIF_SAS_SMP_PHY_COUNT];
+
+   /**
+    * This field provides a list to manage the memory resource for all
+    * smp_phy objects.
+    */
+   SCI_FAST_LIST_T smp_phy_memory_list;
+
+#if !defined(DISABLE_INTERRUPTS)
+   /**
+    * This field saves the interrupt coalescing count before changing interrupt
+    * coalescence.
+    */
+   U16 saved_interrupt_coalesce_number;
+
+   /**
+    * This field saves the interrupt coalescing timeout values in micorseconds
+    * before changing interrupt coalescence.
+    */
+   U32 saved_interrupt_coalesce_timeout;
+#endif // !defined(DISABLE_INTERRUPTS)
+
+} SCIF_SAS_CONTROLLER_T;
+
+extern SCI_BASE_STATE_T scif_sas_controller_state_table[];
+extern SCI_BASE_CONTROLLER_STATE_HANDLER_T
+   scif_sas_controller_state_handler_table[];
+
+SCI_STATUS scif_sas_controller_continue_io(
+   SCI_CONTROLLER_HANDLE_T     controller,
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
+   SCI_IO_REQUEST_HANDLE_T     io_request
+);
+
+void scif_sas_controller_destruct(
+   SCIF_SAS_CONTROLLER_T * fw_controller
+);
+
+void * scif_sas_controller_allocate_internal_request(
+   SCIF_SAS_CONTROLLER_T * fw_controller
+);
+
+void scif_sas_controller_free_internal_request(
+   SCIF_SAS_CONTROLLER_T * fw_controller,
+   void                  * fw_internal_request_buffer
+);
+
+void scif_sas_controller_start_high_priority_io(
+   SCIF_SAS_CONTROLLER_T * fw_controller
+);
+
+BOOL scif_sas_controller_sufficient_resource(
+   SCIF_SAS_CONTROLLER_T *fw_controller
+);
+
+SCI_STATUS scif_sas_controller_complete_high_priority_io(
+   SCIF_SAS_CONTROLLER_T    * fw_controller,
+   SCIF_SAS_REMOTE_DEVICE_T * remote_device,
+   SCIF_SAS_REQUEST_T       * io_request
+);
+
+SCIF_SAS_SMP_PHY_T * scif_sas_controller_allocate_smp_phy(
+   SCIF_SAS_CONTROLLER_T * fw_controller
+);
+
+void scif_sas_controller_free_smp_phy(
+   SCIF_SAS_CONTROLLER_T * fw_controller,
+   SCIF_SAS_SMP_PHY_T    * smp_phy
+);
+
+SCI_STATUS scif_sas_controller_clear_affiliation(
+   SCIF_SAS_CONTROLLER_T * fw_controller
+);
+
+SCI_STATUS scif_sas_controller_continue_to_stop(
+   SCIF_SAS_CONTROLLER_T * fw_controller
+);
+
+void scif_sas_controller_set_default_config_parameters(
+   SCIF_SAS_CONTROLLER_T * this_controller
+);
+
+SCI_STATUS scif_sas_controller_release_resource(
+   SCIF_SAS_CONTROLLER_T * fw_controller
+);
+
+void scif_sas_controller_build_mdl(
+   SCIF_SAS_CONTROLLER_T * fw_controller
+);
+
+#if !defined(DISABLE_INTERRUPTS)
+
+void scif_sas_controller_save_interrupt_coalescence(
+   SCIF_SAS_CONTROLLER_T * fw_controller
+);
+
+void scif_sas_controller_restore_interrupt_coalescence(
+   SCIF_SAS_CONTROLLER_T * fw_controller
+);
+
+#else // !defined(DISABLE_INTERRUPTS)
+#define scif_sas_controller_save_interrupt_coalescence(controller)
+#define scif_sas_controller_restore_interrupt_coalescence(controller)
+#endif // !defined(DISABLE_INTERRUPTS)
+
+#ifdef SCI_LOGGING
+void scif_sas_controller_initialize_state_logging(
+   SCIF_SAS_CONTROLLER_T *this_controller
+);
+
+void scif_sas_controller_deinitialize_state_logging(
+   SCIF_SAS_CONTROLLER_T *this_controller
+);
+#else // SCI_LOGGING
+#define scif_sas_controller_initialize_state_logging(x)
+#define scif_sas_controller_deinitialize_state_logging(x)
+#endif // SCI_LOGGING
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIF_SAS_CONTROLLER_H_
diff --git a/sys/dev/disk/isci/scil/scif_sas_controller_state_handlers.c b/sys/dev/disk/isci/scil/scif_sas_controller_state_handlers.c
new file mode 100644
index 0000000..ae5564c
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_controller_state_handlers.c
@@ -0,0 +1,1843 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_controller_state_handlers.c,v 1.2 2012/02/09 17:50:24 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the state handler routines for each
+ *        of the controller states defined by the SCI_BASE_CONTROLLER state
+ *        machine.
+ */
+
+#include <dev/disk/isci/scil/sci_util.h>
+#include <dev/disk/isci/scil/scic_controller.h>
+#include <dev/disk/isci/scil/scic_port.h>
+#include <dev/disk/isci/scil/scic_remote_device.h>
+#include <dev/disk/isci/scil/scic_io_request.h>
+
+#include <dev/disk/isci/scil/scif_sas_controller.h>
+#include <dev/disk/isci/scil/scif_sas_remote_device.h>
+#include <dev/disk/isci/scil/scif_sas_logger.h>
+#include <dev/disk/isci/scil/scif_sas_smp_remote_device.h>
+
+//******************************************************************************
+//* P R I V A T E   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method simply executes the reset operation by entering
+ *        the reset state and allowing the state to perform it's work.
+ *
+ * @param[in]  fw_controller This parameter specifies the SAS framework
+ *             controller for execute the reset.
+ *
+ * @return Indicate the status of the reset operation.  Was it successful?
+ * @retval SCI_SUCCESS This value is returned if it was successfully reset.
+ */
+static
+SCI_STATUS scif_sas_controller_execute_reset(
+   SCIF_SAS_CONTROLLER_T * fw_controller
+)
+{
+   SCI_STATUS  status;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_controller),
+      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_CONTROLLER_RESET,
+      "scif_sas_controller_execute_reset(0x%x) enter\n",
+      fw_controller
+   ));
+
+   //clean the timer to avoid timer leak.
+   scif_sas_controller_release_resource(fw_controller);
+
+   sci_base_state_machine_change_state(
+      &fw_controller->parent.state_machine,
+      SCI_BASE_CONTROLLER_STATE_RESETTING
+   );
+
+   // Retrieve the status for the operations performed during the entrance
+   // to the resetting state were executing successfully.
+   status = fw_controller->operation_status;
+   fw_controller->operation_status = SCI_SUCCESS;
+
+   return status;
+}
+
+/**
+ * @brief This method checks that the memory descriptor list is valid
+ *        and hasn't been corrupted in some way by the user.
+ *
+ * @param[in] fw_controller This parameter specifies the framework
+ *            controller object for which to validation the MDL.
+ *
+ * @return This method returns a value indicating if the operation succeeded.
+ * @retval SCI_SUCCESS This value indicates that MDL is valid.
+ * @retval SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD This value indicates
+ *         that some portion of the memory descriptor list is invalid.
+ */
+static
+SCI_STATUS scif_sas_controller_validate_mdl(
+   SCIF_SAS_CONTROLLER_T * fw_controller
+)
+{
+   BOOL is_mde_list_valid;
+
+   // Currently there is only a single MDE in the list.
+   is_mde_list_valid = sci_base_mde_is_valid(
+                          &fw_controller->mdes[SCIF_SAS_MDE_INTERNAL_IO],
+                          4,
+                          fw_controller->internal_request_entries *
+                             scif_sas_internal_request_get_object_size(),
+                          SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
+                       );
+
+   if (is_mde_list_valid == FALSE)
+      return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD;
+
+   return SCI_SUCCESS;
+}
+
+
+/**
+ * @brief This method stops all the domains associated to this
+ *           controller.
+ *
+ * @param[in] fw_controller This parameter specifies the framework
+ *            controller object for whose remote devices are to be stopped.
+ *
+ * @return This method returns a value indicating if the operation succeeded.
+ * @retval SCI_SUCCESS This value indicates that all the devices are stopped.
+ * @retval SCI_FAILURE This value indicates certain failure during the process
+ *            of stopping remote devices.
+ */
+static
+SCI_STATUS scif_sas_controller_stop_domains(
+   SCIF_SAS_CONTROLLER_T * fw_controller
+)
+{
+   U8 index;
+   SCI_STATUS status = SCI_SUCCESS;
+   SCIF_SAS_DOMAIN_T * fw_domain;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_controller),
+      SCIF_LOG_OBJECT_CONTROLLER,
+      "scif_sas_controller_stop_domains(0x%x) enter\n",
+      fw_controller
+   ));
+
+   for (index = 0; index < SCI_MAX_DOMAINS && status == SCI_SUCCESS; index++)
+   {
+      fw_domain = &fw_controller->domains[index];
+
+      //Change this domain to STOPPING state. All the remote devices will be
+      //stopped subsquentially.
+      if (fw_domain->parent.state_machine.current_state_id ==
+             SCI_BASE_DOMAIN_STATE_READY
+          || fw_domain->parent.state_machine.current_state_id ==
+             SCI_BASE_DOMAIN_STATE_DISCOVERING)
+      {
+         sci_base_state_machine_change_state(
+            &fw_domain->parent.state_machine, SCI_BASE_DOMAIN_STATE_STOPPING
+         );
+      }
+   }
+
+   return status;
+}
+
+
+/**
+ * @brief This method continue to stop the controller after clear affiliation
+ *        is done.
+ *
+ * @param[in] fw_controller This parameter specifies the framework
+ *            controller object to be stopped.
+ *
+ * @return This method returns a value indicating if the operation succeeded.
+ * @retval SCI_SUCCESS This value indicates the controller_stop succeeds.
+ * @retval SCI_FAILURE This value indicates certain failure during the process
+ *            of stopping controller.
+ */
+SCI_STATUS scif_sas_controller_continue_to_stop(
+   SCIF_SAS_CONTROLLER_T * fw_controller
+)
+{
+   SCI_STATUS status;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_controller),
+      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_SHUTDOWN,
+      "scif_sas_controller_continue_to_stop (0x%x).\n",
+      fw_controller
+   ));
+
+   //stop all the domains and their remote devices.
+   status = scif_sas_controller_stop_domains(fw_controller);
+
+   if (status == SCI_SUCCESS)
+   {
+      // Attempt to stop the core controller.
+      status = scic_controller_stop(fw_controller->core_object, 0);
+
+      if (status != SCI_SUCCESS)
+      {
+         SCIF_LOG_ERROR((
+            sci_base_object_get_logger(fw_controller),
+            SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_SHUTDOWN,
+            "Controller:0x%x Status:0x%x unable to stop controller.\n",
+            fw_controller, status
+         ));
+
+         sci_base_state_machine_change_state(
+            &fw_controller->parent.state_machine,
+            SCI_BASE_CONTROLLER_STATE_FAILED
+         );
+      }
+   }
+   else
+   {
+      SCIF_LOG_ERROR((
+         sci_base_object_get_logger(fw_controller),
+         SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_SHUTDOWN,
+         "Controller:0x%x Status:0x%x unable to stop domains.\n",
+         fw_controller, status
+      ));
+
+      sci_base_state_machine_change_state(
+         &fw_controller->parent.state_machine,
+         SCI_BASE_CONTROLLER_STATE_FAILED
+      );
+   }
+
+   return status;
+}
+
+
+//******************************************************************************
+//* R E S E T   H A N D L E R S
+//******************************************************************************
+
+/**
+ * @brief This method provides RESET state specific handling for
+ *        when a user attempts to initialize a controller.  This is a legal
+ *        state in which to attempt an initialize call.
+ *
+ * @param[in]  controller This parameter specifies the controller object
+ *             on which the user is attempting to perform an initialize
+ *             operation.
+ *
+ * @return This method returns an indication of whether the initialize
+ *         operation succeeded.
+ * @retval SCI_SUCCESS This value when the initialization completes
+ *         successfully.
+ */
+static
+SCI_STATUS scif_sas_controller_reset_initialize_handler(
+   SCI_BASE_CONTROLLER_T    * controller
+)
+{
+   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)controller;
+   SCI_STATUS              status;
+   U32                     index;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_controller),
+      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION,
+      "scif_sas_controller_reset_initialize_handler(0x%x) enter\n",
+      controller
+   ));
+
+   sci_base_state_machine_change_state(
+      &fw_controller->parent.state_machine,
+      SCI_BASE_CONTROLLER_STATE_INITIALIZING
+   );
+
+   scif_sas_controller_build_mdl(fw_controller);
+
+   // Perform any domain object initialization that is necessary.
+   for (index = 0; index < SCI_MAX_DOMAINS; index++)
+      scif_sas_domain_initialize(&fw_controller->domains[index]);
+
+   scif_cb_lock_associate(fw_controller, &fw_controller->hprq.lock);
+
+   // Attempt to initialize the core controller.
+   status = scic_controller_initialize(fw_controller->core_object);
+   if (status == SCI_SUCCESS)
+   {
+      sci_base_state_machine_change_state(
+         &fw_controller->parent.state_machine,
+         SCI_BASE_CONTROLLER_STATE_INITIALIZED
+      );
+   }
+
+   if (status != SCI_SUCCESS)
+   {
+      // Initialization failed, Release resources and do not change state
+      scif_sas_controller_release_resource(fw_controller);
+
+      SCIF_LOG_ERROR((
+         sci_base_object_get_logger(fw_controller),
+         SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION,
+         "Controller:0x%x Status:0x%x unable to successfully initialize.\n",
+         fw_controller, status
+      ));
+   }
+
+   return status;
+}
+
+//******************************************************************************
+//* I N I T I A L I Z E D   H A N D L E R S
+//******************************************************************************
+
+/**
+ * @brief This method provides INITIALIZED state specific handling for
+ *        when a user attempts to start a controller.
+ *
+ * @param[in]  controller This parameter specifies the controller object
+ *             on which the user is attempting to perform a start
+ *             operation.
+ * @param[in]  timeout This parameter specifies the timeout value (in
+ *             milliseconds) to be utilized for this operation.
+ *
+ * @return This method returns an indication of whether the start operation
+ *         succeeded.
+ * @retval SCI_SUCCESS This value is returned when the start operation
+ *         begins successfully.
+ */
+static
+SCI_STATUS scif_sas_controller_initialized_start_handler(
+   SCI_BASE_CONTROLLER_T * controller,
+   U32                     timeout
+)
+{
+   SCI_STATUS              status        = SCI_SUCCESS;
+   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)controller;
+   U16                     index         = 0;
+
+   SCI_PHYSICAL_MEMORY_DESCRIPTOR_T internal_reqeust_mde =
+      fw_controller->mdes[SCIF_SAS_MDE_INTERNAL_IO];
+
+   void * internal_request_virtual_address =  internal_reqeust_mde.virtual_address;
+   POINTER_UINT address = (POINTER_UINT)internal_request_virtual_address;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_controller),
+      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION,
+      "scif_sas_controller_initialized_start_handler(0x%x, 0x%x) enter\n",
+      controller, timeout
+   ));
+
+   sci_base_state_machine_change_state(
+      &fw_controller->parent.state_machine,
+      SCI_BASE_CONTROLLER_STATE_STARTING
+   );
+
+   status = scif_sas_controller_validate_mdl(fw_controller);
+
+   // initialization work for internal request path. It must be done before
+   // starting domain.
+   if (status == SCI_SUCCESS)
+   {
+      // fill in the sci_pool for internal requests.
+      sci_pool_initialize(fw_controller->internal_request_memory_pool);
+
+      for (index = 0; index < fw_controller->internal_request_entries; index++)
+      {
+         sci_pool_put(fw_controller->internal_request_memory_pool, address);
+
+         address += scif_sas_internal_request_get_object_size();
+      }
+
+      // Using DPC for starting internal IOs, if yes, we need to intialize
+      // DPC here.
+      scif_cb_start_internal_io_task_create(fw_controller);
+   }
+
+   if (status == SCI_SUCCESS)
+   {
+      // Kick-start the domain state machines and, by association, the
+      // core port's.
+
+      // This will ensure we get valid port objects supplied with link up
+      // messages.
+      for (index = 0;
+           (index < SCI_MAX_DOMAINS) && (status == SCI_SUCCESS);
+           index++)
+      {
+         sci_base_state_machine_change_state(
+            &fw_controller->domains[index].parent.state_machine,
+            SCI_BASE_DOMAIN_STATE_STARTING
+         );
+         status = fw_controller->domains[index].operation.status;
+      }
+   }
+
+   // Validate that all the domain state machines began successfully.
+   if (status != SCI_SUCCESS)
+   {
+      SCIF_LOG_ERROR((
+         sci_base_object_get_logger(fw_controller),
+         SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION,
+         "Controller:0x%x Domain:0x%x Status:0x%x unable to start\n",
+         fw_controller, index, status
+      ));
+
+      return status;
+   }
+
+   // Attempt to start the core controller.
+   status = scic_controller_start(fw_controller->core_object, timeout);
+   if (status != SCI_SUCCESS)
+   {
+      SCIF_LOG_ERROR((
+         sci_base_object_get_logger(fw_controller),
+         SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION,
+         "Controller:0x%x Status:0x%x unable to start controller.\n",
+         fw_controller, status
+      ));
+
+      sci_base_state_machine_change_state(
+         &fw_controller->parent.state_machine,
+         SCI_BASE_CONTROLLER_STATE_FAILED
+      );
+   }
+
+   return status;
+}
+
+//******************************************************************************
+//* R E A D Y   H A N D L E R S
+//******************************************************************************
+
+/**
+ * @brief This method provides READY state specific handling for
+ *        when a user attempts to stop a controller.
+ *
+ * @param[in]  controller This parameter specifies the controller object
+ *             on which the user is attempting to perform a stop
+ *             operation.
+ * @param[in]  timeout This parameter specifies the timeout value (in
+ *             milliseconds) to be utilized for this operation.
+ *
+ * @return This method returns an indication of whether the stop operation
+ *         succeeded.
+ * @retval SCI_SUCCESS This value is returned when the stop operation
+ *         begins successfully.
+ */
+static
+SCI_STATUS scif_sas_controller_ready_stop_handler(
+   SCI_BASE_CONTROLLER_T * controller,
+   U32                     timeout
+)
+{
+   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)controller;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_controller),
+      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION,
+      "scif_sas_controller_ready_stop_handler(0x%x, 0x%x) enter\n",
+      controller, timeout
+   ));
+
+   sci_base_state_machine_change_state(
+      &fw_controller->parent.state_machine,
+      SCI_BASE_CONTROLLER_STATE_STOPPING
+   );
+
+   if (fw_controller->user_parameters.sas.clear_affiliation_during_controller_stop)
+   {
+      fw_controller->current_domain_to_clear_affiliation = 0;
+
+      //clear affiliation first. After the last domain finishes clearing
+      //affiliation, it will call back to controller to continue to stop.
+      scif_sas_controller_clear_affiliation(fw_controller);
+   }
+   else
+      scif_sas_controller_continue_to_stop(fw_controller);
+
+   //Must return SUCCESS at this point.
+   return SCI_SUCCESS;
+}
+
+/**
+ * @brief This method provides READY state specific handling for
+ *        when a user attempts to reset a controller.
+ *
+ * @param[in]  controller This parameter specifies the controller object
+ *             on which the user is attempting to perform a reset
+ *             operation.
+ *
+ * @return This method returns an indication of whether the reset operation
+ *         succeeded.
+ * @retval SCI_SUCCESS This value is returned when the reset operation
+ *         completes successfully.
+ */
+static
+SCI_STATUS scif_sas_controller_ready_reset_handler(
+   SCI_BASE_CONTROLLER_T    * controller
+)
+{
+   return scif_sas_controller_execute_reset((SCIF_SAS_CONTROLLER_T*)controller);
+}
+
+/**
+ * @brief This method provides READY state specific handling for
+ *        when a user attempts to start an IO request.
+ *
+ * @param[in]  controller This parameter specifies the controller object
+ *             on which the user is attempting to perform a start IO
+ *             operation.
+ * @param[in]  remote_device This parameter specifies the remote deivce
+ *             object on which the user is attempting to perform a start IO
+ *             operation.
+ * @param[in]  io_request This parameter specifies the IO request to be
+ *             started.
+ * @param[in]  io_tag This parameter specifies the optional allocated
+ *             IO tag.  Please reference scif_controller_start_io() for
+ *             more information.
+ *
+ * @return This method returns an indication of whether the start IO
+ *         operation succeeded.
+ * @retval SCI_SUCCESS This value is returned when the start IO operation
+ *         begins successfully.
+ */
+static
+SCI_STATUS scif_sas_controller_ready_start_io_handler(
+   SCI_BASE_CONTROLLER_T    * controller,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request,
+   U16                        io_tag
+)
+{
+   SCI_STATUS                status;
+   SCIF_SAS_IO_REQUEST_T    *fw_io         = (SCIF_SAS_IO_REQUEST_T*)io_request;
+   SCIF_SAS_CONTROLLER_T    *fw_controller = (SCIF_SAS_CONTROLLER_T*)controller;
+   SCIF_SAS_REMOTE_DEVICE_T *fw_device     = (SCIF_SAS_REMOTE_DEVICE_T*)
+                                             remote_device;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_controller),
+      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
+      "scif_sas_controller_ready_start_io_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
+      controller, remote_device, io_request, io_tag
+   ));
+
+   status = fw_device->domain->state_handlers->start_io_handler(
+               &fw_device->domain->parent, remote_device, io_request
+            );
+
+   // Check to see that the other objects in the framework allowed
+   // this IO to be started.
+   if (status == SCI_SUCCESS)
+   {
+      // Ask the core to start processing for this IO request.
+      status = (SCI_STATUS)scic_controller_start_io(
+                  fw_controller->core_object,
+                  fw_device->core_object,
+                  fw_io->parent.core_object,
+                  io_tag
+               );
+
+      if (status == SCI_SUCCESS)
+      {
+         // We were able to start the core request. As a result,
+         // commit to starting the request for the framework by changing
+         // the state of the IO request.
+         sci_base_state_machine_change_state(
+            &io_request->state_machine, SCI_BASE_REQUEST_STATE_STARTED
+         );
+      }
+      else
+      {
+         // We were unable to start the core IO request. As a result,
+         // back out the start operation for the framework.  It's easier to
+         // back out the framework start operation then to backout the core
+         // start IO operation.
+         fw_device->domain->state_handlers->complete_io_handler(
+            &fw_device->domain->parent, remote_device, io_request
+         );
+
+         // Invoke the IO completion handler.  For most IOs, this does nothing
+         // since we are still in the constructed state.  For NCQ, this will
+         // the return of the NCQ tag back to the remote device free pool.
+         fw_io->parent.state_handlers->complete_handler(io_request);
+
+         SCIF_LOG_WARNING((
+            sci_base_object_get_logger(fw_controller),
+            SCIF_LOG_OBJECT_CONTROLLER,
+            "Controller:0x%x IORequest:0x%x Status:0x%x core IO start failed\n",
+            fw_controller, fw_io, status
+         ));
+      }
+   }
+   else
+   {
+      SCIF_LOG_WARNING((
+         sci_base_object_get_logger(fw_controller),
+         SCIF_LOG_OBJECT_CONTROLLER,
+         "Controller:0x%x IORequest:0x%x Status:0x%x IO start failed\n",
+         fw_controller, fw_io, status
+      ));
+   }
+
+   return status;
+}
+
+/**
+ * @brief This method provides READY state specific handling for
+ *        when a user attempts to complete an IO request.
+ *
+ * @param[in]  controller This parameter specifies the controller object
+ *             on which the user is attempting to perform a complete IO
+ *             operation.
+ * @param[in]  remote_device This parameter specifies the remote deivce
+ *             object on which the user is attempting to perform a start IO
+ *             operation.
+ * @param[in]  io_request This parameter specifies the IO request to be
+ *             started.
+ *
+ * @return This method returns an indication of whether the complete IO
+ *         operation succeeded.
+ * @retval SCI_SUCCESS This value is returned when the complete IO operation
+ *         begins successfully.
+ */
+static
+SCI_STATUS scif_sas_controller_ready_complete_io_handler(
+   SCI_BASE_CONTROLLER_T    * controller,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request
+)
+{
+   SCIF_SAS_CONTROLLER_T    * fw_controller = (SCIF_SAS_CONTROLLER_T*)
+                                              controller;
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device     = (SCIF_SAS_REMOTE_DEVICE_T*)
+                                              remote_device;
+   SCIF_SAS_IO_REQUEST_T    * fw_io         = (SCIF_SAS_IO_REQUEST_T*)
+                                              io_request;
+   SCI_STATUS                 status;
+   SCI_STATUS                 core_status;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_controller),
+      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
+      "scif_sas_controller_ready_complete_io_handler(0x%x, 0x%x, 0x%x) enter\n",
+      controller, remote_device, io_request
+   ));
+
+   fw_io->parent.state_handlers->destruct_handler(&fw_io->parent.parent);
+   status = fw_device->domain->state_handlers->complete_io_handler(
+               &fw_device->domain->parent, remote_device, io_request
+            );
+
+   // Ask the core to finish processing for this IO request.
+   core_status = scic_controller_complete_io(
+                    fw_controller->core_object,
+                    fw_device->core_object,
+                    fw_io->parent.core_object
+                 );
+
+   if (status == SCI_SUCCESS)
+      status = core_status;
+
+   if (status != SCI_SUCCESS)
+   {
+      SCIF_LOG_WARNING((
+         sci_base_object_get_logger(fw_controller),
+         SCIF_LOG_OBJECT_CONTROLLER,
+         "Controller:0x%x IORequest:0x%x Status:0x%x CoreStatus:0x%x "
+         "failure to complete IO\n",
+         fw_controller, fw_io, status, core_status
+      ));
+   }
+
+   return status;
+}
+
+
+/**
+ * @brief This method provides READY state specific handling for
+ *        when a user attempts to complete a high priority IO request.
+ *
+ * @param[in]  controller This parameter specifies the controller object
+ *             on which the user is attempting to perform a complete IO
+ *             operation.
+ * @param[in]  remote_device This parameter specifies the remote deivce
+ *             object on which the user is attempting to perform a start IO
+ *             operation.
+ * @param[in]  io_request This parameter specifies the IO request to be
+ *             started.
+ *
+ * @return This method returns an indication of whether the complete IO
+ *         operation succeeded.
+ * @retval SCI_SUCCESS This value is returned when the complete IO operation
+ *         begins successfully.
+ */
+static
+SCI_STATUS scif_sas_controller_ready_complete_high_priority_io_handler(
+   SCI_BASE_CONTROLLER_T    * controller,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request
+)
+{
+   SCIF_SAS_CONTROLLER_T    * fw_controller = (SCIF_SAS_CONTROLLER_T*)
+                                              controller;
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device     = (SCIF_SAS_REMOTE_DEVICE_T*)
+                                              remote_device;
+   SCIF_SAS_IO_REQUEST_T    * fw_io         = (SCIF_SAS_IO_REQUEST_T*)
+                                              io_request;
+   SCI_IO_STATUS core_completion_status =
+                    scic_request_get_sci_status(fw_io->parent.core_object);
+
+   U8 response_data[SCIF_SAS_RESPONSE_DATA_LENGTH];
+
+   SCI_STATUS                 status;
+   SCI_STATUS                 core_status;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_controller),
+      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
+      "scif_sas_controller_ready_complete_high_priority_io_handler(0x%x, 0x%x, 0x%x) enter\n",
+      controller, remote_device, io_request
+   ));
+
+   // In high priority path, we ask the core to finish IO request before framework.
+
+   // retrieve and save io response from core now.
+   memcpy(response_data,
+          scic_io_request_get_response_iu_address(fw_io->parent.core_object),
+          SCIF_SAS_RESPONSE_DATA_LENGTH
+         );
+
+   core_status = scic_controller_complete_io(
+                    fw_controller->core_object,
+                    fw_device->core_object,
+                    fw_io->parent.core_object
+                 );
+
+   fw_io->parent.state_handlers->destruct_handler(&fw_io->parent.parent);
+   status = fw_device->domain->state_handlers->complete_high_priority_io_handler(
+               &fw_device->domain->parent,
+               remote_device,
+               io_request,
+               (void *)response_data,
+               core_completion_status
+            );
+
+   if (status == SCI_SUCCESS)
+      status = core_status;
+
+   if (status == SCI_SUCCESS)
+   {
+       //issue DPC to start next internal io in high prioriy queue.
+      if( !sci_pool_empty(fw_controller->hprq.pool) )
+         scif_cb_start_internal_io_task_schedule(
+            fw_controller,
+            scif_sas_controller_start_high_priority_io,
+            fw_controller
+         );
+   }
+   else
+   {
+      SCIF_LOG_WARNING((
+         sci_base_object_get_logger(fw_controller),
+         SCIF_LOG_OBJECT_CONTROLLER,
+         "Controller:0x%x IORequest:0x%x Status:0x%x CoreStatus:0x%x "
+         "failure to complete IO\n",
+         fw_controller, fw_io, status, core_status
+      ));
+   }
+
+   return status;
+}
+
+/**
+ * @brief This method provides READY state specific handling for
+ *        when a user attempts to continue an IO request.
+ *
+ * @param[in]  controller This parameter specifies the controller object
+ *             on which the user is attempting to perform a continue IO
+ *             operation.
+ * @param[in]  remote_device This parameter specifies the remote deivce
+ *             object on which the user is attempting to perform a start IO
+ *             operation.
+ * @param[in]  io_request This parameter specifies the IO request to be
+ *             started.
+ *
+ * @return This method returns an indication of whether the continue IO
+ *         operation succeeded.
+ * @retval SCI_SUCCESS This value is returned when the continue IO operation
+ *         begins successfully.
+ */
+static
+SCI_STATUS scif_sas_controller_ready_continue_io_handler(
+   SCI_BASE_CONTROLLER_T    * controller,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request
+)
+{
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
+      "scif_sas_controller_ready_continue_io_handler(0x%x, 0x%x, 0x%x) enter\n",
+      controller, remote_device, io_request
+   ));
+
+   /// @todo Function unimplemented.  fix return code handling.
+   return SCI_FAILURE;
+}
+
+/**
+ * @brief This method provides READY state specific handling for
+ *        when a user attempts to start a task request.
+ *
+ * @param[in]  controller This parameter specifies the controller object
+ *             on which the user is attempting to perform a start task
+ *             operation.
+ * @param[in]  remote_device This parameter specifies the remote deivce
+ *             object on which the user is attempting to perform a start
+ *             task operation.
+ * @param[in]  task_request This parameter specifies the task management
+ *             request to be started.
+ * @param[in]  io_tag This parameter specifies the optional allocated
+ *             IO tag.  Please reference scif_controller_start_task() for
+ *             more information.
+ *
+ * @return This method returns an indication of whether the start task
+ *         operation succeeded.
+ * @retval SCI_SUCCESS This value is returned when the start task operation
+ *         begins successfully.
+ */
+static
+SCI_STATUS scif_sas_controller_ready_start_task_handler(
+   SCI_BASE_CONTROLLER_T    * controller,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * task_request,
+   U16                        io_tag
+)
+{
+   SCIF_SAS_CONTROLLER_T    * fw_controller = (SCIF_SAS_CONTROLLER_T*)
+                                              controller;
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
+                                          remote_device;
+   SCIF_SAS_TASK_REQUEST_T  * fw_task = (SCIF_SAS_TASK_REQUEST_T*)task_request;
+   SCI_STATUS                 status;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_controller),
+      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_TASK_MANAGEMENT,
+      "scif_sas_controller_ready_start_task_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
+      controller, remote_device, task_request, io_tag
+   ));
+
+   status = fw_device->domain->state_handlers->start_task_handler(
+               &fw_device->domain->parent, remote_device, task_request
+            );
+
+   if (status == SCI_SUCCESS)
+   {
+      if (scif_sas_task_request_get_function(fw_task)
+             == SCI_SAS_HARD_RESET)
+      {
+         // Go off to special target reset path. Don't start task to core.
+         scif_sas_remote_device_target_reset(
+            fw_device,
+            (SCIF_SAS_REQUEST_T *)fw_task
+         );
+
+         return SCI_SUCCESS;
+      }
+
+      // Ask the core to start processing for this task request.
+      status = (SCI_STATUS)scic_controller_start_task(
+                  fw_controller->core_object,
+                  fw_device->core_object,
+                  fw_task->parent.core_object,
+                  io_tag
+               );
+
+      if (status == SCI_SUCCESS)
+      {
+         // We were able to start the core request. As a result,
+         // commit to starting the request for the framework by changing
+         // the state of the task request.
+         fw_task->parent.state_handlers->start_handler(&fw_task->parent.parent);
+      }
+      else
+      {
+         // We were unable to start the core task request. As a result,
+         // back out the start operation for the framework.  It's easier to
+         // back out the framework start operation then to backout the core
+         // start task operation.
+         fw_device->domain->state_handlers->complete_task_handler(
+            &fw_device->domain->parent, remote_device, task_request
+         );
+
+         if (status == SCI_SUCCESS)
+         {
+            SCIF_LOG_WARNING((
+               sci_base_object_get_logger(fw_controller),
+               SCIF_LOG_OBJECT_CONTROLLER,
+               "Controller:0x%x TaskRequest:0x%x Status:0x%x core start failed\n",
+               fw_controller, fw_task, status
+            ));
+         }
+      }
+   }
+   else
+   {
+      SCIF_LOG_WARNING((
+         sci_base_object_get_logger(fw_controller),
+         SCIF_LOG_OBJECT_CONTROLLER,
+         "Controller:0x%x TaskRequest:0x%x Status:0x%x Task start failed\n",
+         fw_controller, fw_task, status
+      ));
+   }
+
+   return status;
+}
+
+/**
+ * @brief This method provides READY state specific handling for
+ *        when a user attempts to complete a task request.
+ *
+ * @param[in]  controller This parameter specifies the controller object
+ *             on which the user is attempting to perform a complete task
+ *             operation.
+ * @param[in]  remote_device This parameter specifies the remote deivce
+ *             object on which the user is attempting to perform a start
+ *             task operation.
+ * @param[in]  task_request This parameter specifies the task management
+ *             request to be started.
+ *
+ * @return This method returns an indication of whether the complete task
+ *         operation succeeded.
+ * @retval SCI_SUCCESS This value is returned when the complete task operation
+ *         begins successfully.
+ */
+static
+SCI_STATUS scif_sas_controller_ready_complete_task_handler(
+   SCI_BASE_CONTROLLER_T    * controller,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * task_request
+)
+{
+   SCIF_SAS_CONTROLLER_T    *fw_controller = (SCIF_SAS_CONTROLLER_T*)controller;
+   SCIF_SAS_REMOTE_DEVICE_T *fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)remote_device;
+   SCIF_SAS_TASK_REQUEST_T  *fw_task = (SCIF_SAS_TASK_REQUEST_T*)task_request;
+   SCI_STATUS                status;
+   SCI_STATUS                core_status;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_controller),
+      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_TASK_MANAGEMENT,
+      "scif_sas_controller_ready_complete_task_handler(0x%x, 0x%x, 0x%x) enter\n",
+      controller, remote_device, task_request
+   ));
+
+   status = fw_device->domain->state_handlers->complete_task_handler(
+               &fw_device->domain->parent, remote_device, task_request
+            );
+
+   if (scif_sas_task_request_get_function(fw_task)
+          == SCI_SAS_HARD_RESET)
+   {
+      //No more things to do in the core, since this task is for Target Reset.
+      return status;
+   }
+
+   fw_task->parent.state_handlers->destruct_handler(&fw_task->parent.parent);
+
+   // Ask the core to finish processing for this task request.
+   core_status = scic_controller_complete_task(
+                    fw_controller->core_object,
+                    fw_device->core_object,
+                    fw_task->parent.core_object
+                 );
+
+   if (status == SCI_SUCCESS)
+      status = core_status;
+
+   if (status != SCI_SUCCESS)
+   {
+      SCIF_LOG_WARNING((
+         sci_base_object_get_logger(fw_controller),
+         SCIF_LOG_OBJECT_CONTROLLER,
+         "Controller:0x%x TaskRequest:0x%x Status:0x%x CoreStatus:0x%x "
+         "failed to complete\n",
+         fw_controller, fw_task, status, core_status
+      ));
+   }
+
+   return status;
+}
+
+
+
+/**
+ * @brief This method provides common handling for several states
+ *        when a user attempts to start an internal request.
+ *
+ * @param[in]  controller This parameter specifies the controller object
+ *             on which the user is attempting to perform a start IO
+ *             operation.
+ * @param[in]  remote_device This parameter specifies the remote deivce
+ *             object on which the user is attempting to perform a start IO
+ *             operation.
+ * @param[in]  io_request This parameter specifies the IO request to be
+ *             started.
+ * @param[in]  io_tag This parameter specifies the optional allocated
+ *             IO tag.  Please reference scif_controller_start_io() for
+ *             more information.
+ *
+ * @return This method returns an indication of whether the start IO
+ *         operation succeeded.
+ * @retval SCI_SUCCESS This value is returned when the start IO operation
+ *         begins successfully.
+ */
+static
+SCI_STATUS scif_sas_controller_common_start_high_priority_io_handler(
+   SCI_BASE_CONTROLLER_T    * controller,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request,
+   U16                        io_tag
+)
+{
+   SCI_STATUS                status;
+   SCIF_SAS_IO_REQUEST_T    *fw_io         = (SCIF_SAS_IO_REQUEST_T*)io_request;
+   SCIF_SAS_CONTROLLER_T    *fw_controller = (SCIF_SAS_CONTROLLER_T*)controller;
+   SCIF_SAS_REMOTE_DEVICE_T *fw_device     = (SCIF_SAS_REMOTE_DEVICE_T*)
+                                             remote_device;
+
+   status = fw_device->domain->state_handlers->start_high_priority_io_handler(
+               &fw_device->domain->parent, remote_device, io_request
+            );
+
+   // Check to see that the other objects in the framework allowed
+   // this IO to be started.
+   if (status == SCI_SUCCESS)
+   {
+      // Ask the core to start processing for this IO request.
+      status = (SCI_STATUS)scic_controller_start_io(
+                  fw_controller->core_object,
+                  fw_device->core_object,
+                  fw_io->parent.core_object,
+                  io_tag
+               );
+
+      if (status == SCI_SUCCESS)
+      {
+         // We were able to start the core request. As a result,
+         // commit to starting the request for the framework by changing
+         // the state of the IO request.
+         sci_base_state_machine_change_state(
+            &io_request->state_machine, SCI_BASE_REQUEST_STATE_STARTED
+         );
+      }
+      else
+      {
+         // We were unable to start the core IO request. As a result,
+         // back out the start operation for the framework.  It's easier to
+         // back out the framework start operation then to backout the core
+         // start IO operation.
+         fw_device->domain->state_handlers->complete_io_handler(
+            &fw_device->domain->parent, remote_device, io_request
+         );
+
+         // Invoke the IO completion handler.  For most IOs, this does nothing
+         // since we are still in the constructed state.  For NCQ, this will
+         // the return of the NCQ tag back to the remote device free pool.
+         fw_io->parent.state_handlers->complete_handler(io_request);
+
+         SCIF_LOG_WARNING((
+            sci_base_object_get_logger(fw_controller),
+            SCIF_LOG_OBJECT_CONTROLLER,
+            "Controller:0x%x IORequest:0x%x Status:0x%x core IO start failed\n",
+            fw_controller, fw_io, status
+         ));
+      }
+   }
+   else
+   {
+      SCIF_LOG_WARNING((
+         sci_base_object_get_logger(fw_controller),
+         SCIF_LOG_OBJECT_CONTROLLER,
+         "Controller:0x%x IORequest:0x%x Status:0x%x IO start failed\n",
+         fw_controller, fw_io, status
+      ));
+
+      // Invoke the IO completion handler.  For most IOs, this does nothing
+      // since we are still in the constructed state.  For NCQ, this will
+      // the return of the NCQ tag back to the remote device free pool.
+      fw_io->parent.state_handlers->complete_handler(io_request);
+
+   }
+
+   if (fw_io->parent.is_internal && status != SCI_SUCCESS )
+   {
+      SCIC_TRANSPORT_PROTOCOL protocol =
+         scic_io_request_get_protocol(fw_io->parent.core_object);
+
+      U8 retry_count = fw_io->retry_count;
+
+      scif_sas_internal_io_request_destruct(
+         fw_device->domain->controller,
+         (SCIF_SAS_INTERNAL_IO_REQUEST_T *)fw_io
+      );
+
+      if ( protocol == SCIC_SMP_PROTOCOL )
+      {
+         if (fw_device->protocol_device.smp_device.smp_activity_timer != NULL)
+         {
+            //destroy the smp_activity_timer
+            scif_cb_timer_destroy (
+               fw_controller,
+               fw_device->protocol_device.smp_device.smp_activity_timer
+            );
+
+            fw_device->protocol_device.smp_device.smp_activity_timer = NULL;
+         }
+
+         //we should retry for finite times
+         if ( retry_count < SCIF_SAS_IO_RETRY_LIMIT)
+         {
+         //An internal smp request failed being started, most likely due to remote device
+         //is not in ready state, for example, UPDATING_PORT_WIDTH state. In this case,
+         //we should retry the IO.
+         scif_sas_smp_remote_device_retry_internal_io(
+            (SCIF_SAS_REMOTE_DEVICE_T *)remote_device,
+            retry_count,
+            SMP_REQUEST_RETRY_WAIT_DURATION
+         );
+      }
+   }
+   }
+
+   return status;
+}
+
+
+/**
+ * @brief This method provides READY state specific handling for
+ *        when a user attempts to start an internal request. If the high
+ *        priority IO is also internal, this method will schedule its timer.
+ *
+ * @param[in]  controller This parameter specifies the controller object
+ *             on which the user is attempting to perform a start IO
+ *             operation.
+ * @param[in]  remote_device This parameter specifies the remote deivce
+ *             object on which the user is attempting to perform a start IO
+ *             operation.
+ * @param[in]  io_request This parameter specifies the IO request to be
+ *             started.
+ * @param[in]  io_tag This parameter specifies the optional allocated
+ *             IO tag.  Please reference scif_controller_start_io() for
+ *             more information.
+ *
+ * @return This method returns an indication of whether the start IO
+ *         operation succeeded.
+ * @retval SCI_SUCCESS This value is returned when the start IO operation
+ *         begins successfully.
+ */
+static
+SCI_STATUS scif_sas_controller_ready_start_high_priority_io_handler(
+   SCI_BASE_CONTROLLER_T    * controller,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request,
+   U16                        io_tag
+)
+{
+   SCI_STATUS status;
+   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *)io_request;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
+      "scif_sas_controller_ready_start_high_priority_io_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
+      controller, remote_device, io_request, io_tag
+   ));
+
+   status = scif_sas_controller_common_start_high_priority_io_handler(
+               controller, remote_device, io_request, io_tag);
+
+   if (status == SCI_SUCCESS)
+   {
+      //External io could also be put in high priority queue. i.e. the
+      //smp request for EA Target Reset.
+      if (fw_io->parent.is_internal)
+      {
+         SCIF_SAS_INTERNAL_IO_REQUEST_T * fw_internal_io =
+            (SCIF_SAS_INTERNAL_IO_REQUEST_T *)fw_io;
+
+         //start the timer for internal io
+         scif_cb_timer_start(
+            (SCI_CONTROLLER_HANDLE_T)controller,
+             fw_internal_io->internal_io_timer,
+             SCIF_SAS_INTERNAL_REQUEST_TIMEOUT
+         );
+      }
+   }
+   else
+   {
+      //If failed to start, most likely the device or domain is not in
+      //correct state, and the IO has been cleaned up in controller's start
+      //high priority IO handler. We should just continue to start the next
+      //IO in the HP queue.
+
+      SCIF_LOG_TRACE((
+         sci_base_object_get_logger(controller),
+         SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
+         "scif_controller_start_high_priority_io(0x%x, 0x%x), starting io failed\n",
+         controller, fw_io
+      ));
+   }
+
+   return status;
+}
+
+
+//******************************************************************************
+//* S T O P P I N G   H A N D L E R S
+//******************************************************************************
+/**
+ * @brief This method provides STOPPING state specific handling for
+ *        when a user attempts to start an internal request. Note that we don't
+ *        start the timer for internal IO during controller stopping state.
+ *
+ * @param[in]  controller This parameter specifies the controller object
+ *             on which the user is attempting to perform a start IO
+ *             operation.
+ * @param[in]  remote_device This parameter specifies the remote deivce
+ *             object on which the user is attempting to perform a start IO
+ *             operation.
+ * @param[in]  io_request This parameter specifies the IO request to be
+ *             started.
+ * @param[in]  io_tag This parameter specifies the optional allocated
+ *             IO tag.  Please reference scif_controller_start_io() for
+ *             more information.
+ *
+ * @return This method returns an indication of whether the start IO
+ *         operation succeeded.
+ * @retval SCI_SUCCESS This value is returned when the start IO operation
+ *         begins successfully.
+ */
+static
+SCI_STATUS scif_sas_controller_stopping_start_high_priority_io_handler(
+   SCI_BASE_CONTROLLER_T    * controller,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request,
+   U16                        io_tag
+)
+{
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
+      "scif_sas_controller_stopping_start_high_priority_io_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
+      controller, remote_device, io_request, io_tag
+   ));
+
+   return scif_sas_controller_common_start_high_priority_io_handler(
+             controller, remote_device, io_request, io_tag);
+}
+
+
+//******************************************************************************
+//* S T O P P E D   H A N D L E R S
+//******************************************************************************
+
+/**
+ * @brief This method provides STOPPED state specific handling for
+ *        when a user attempts to reset a controller.
+ *
+ * @param[in]  controller This parameter specifies the controller object
+ *             on which the user is attempting to perform a reset
+ *             operation.
+ *
+ * @return This method returns an indication of whether the reset operation
+ *         succeeded.
+ * @retval SCI_SUCCESS This value is returned when the reset operation
+ *         completes successfully.
+ */
+static
+SCI_STATUS scif_sas_controller_stopped_reset_handler(
+   SCI_BASE_CONTROLLER_T    * controller
+)
+{
+   return scif_sas_controller_execute_reset((SCIF_SAS_CONTROLLER_T*)controller);
+}
+
+
+//******************************************************************************
+//* F A I L E D   H A N D L E R S
+//******************************************************************************
+
+/**
+ * @brief This method provides FAILED state specific handling for
+ *        when a user attempts to reset a controller.
+ *
+ * @param[in]  controller This parameter specifies the controller object
+ *             on which the user is attempting to perform a reset
+ *             operation.
+ *
+ * @return This method returns an indication of whether the reset operation
+ *         succeeded.
+ * @retval SCI_SUCCESS This value is returned when the reset operation
+ *         completes successfully.
+ */
+static
+SCI_STATUS scif_sas_controller_failed_reset_handler(
+   SCI_BASE_CONTROLLER_T * controller
+)
+{
+   return scif_sas_controller_execute_reset((SCIF_SAS_CONTROLLER_T*)controller);
+}
+
+//******************************************************************************
+//* D E F A U L T   H A N D L E R S
+//******************************************************************************
+
+/**
+ * @brief This method provides default handling (i.e. returns an error)
+ *        when a user attempts to start a controller and a start operation
+ *        is not allowed.
+ *
+ * @param[in]  controller This parameter specifies the controller object
+ *             on which the user is attempting to perform a start operation.
+ * @param[in]  timeout This parameter specifies the timeout value (in
+ *             milliseconds) to be utilized for this operation.
+ *
+ * @return This method returns an indication that start operations are not
+ *         allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+static
+SCI_STATUS scif_sas_controller_default_start_handler(
+   SCI_BASE_CONTROLLER_T * controller,
+   U32                     timeout
+)
+{
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger((SCIF_SAS_CONTROLLER_T *)controller),
+      SCIF_LOG_OBJECT_CONTROLLER,
+      "Controller:0x%x State:0x%x invalid state to start controller.\n",
+      controller,
+      sci_base_state_machine_get_state(
+         &((SCIF_SAS_CONTROLLER_T *)controller)->parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * @brief This method provides default handling (i.e. returns an error)
+ *        when a user attempts to stop a controller and a stop operation
+ *        is not allowed.
+ *
+ * @param[in]  controller This parameter specifies the controller object
+ *             on which the user is attempting to perform a stop operation.
+ * @param[in]  timeout This parameter specifies the timeout value (in
+ *             milliseconds) to be utilized for this operation.
+ *
+ * @return This method returns an indication that stop operations are not
+ *         allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+static
+SCI_STATUS scif_sas_controller_default_stop_handler(
+   SCI_BASE_CONTROLLER_T * controller,
+   U32                     timeout
+)
+{
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger((SCIF_SAS_CONTROLLER_T *)controller),
+      SCIF_LOG_OBJECT_CONTROLLER,
+      "Controller:0x%x State:0x%x invalid state to stop controller.\n",
+      controller,
+      sci_base_state_machine_get_state(
+         &((SCIF_SAS_CONTROLLER_T *)controller)->parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * @brief This method provides default handling (i.e. returns an error)
+ *        when a user attempts to reset a controller and a reset operation
+ *        is not allowed.
+ *
+ * @param[in]  controller This parameter specifies the controller object
+ *             on which the user is attempting to perform a reset operation.
+ *
+ * @return This method returns an indication that reset operations are not
+ *         allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+static
+SCI_STATUS scif_sas_controller_default_reset_handler(
+   SCI_BASE_CONTROLLER_T * controller
+)
+{
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger((SCIF_SAS_CONTROLLER_T *)controller),
+      SCIF_LOG_OBJECT_CONTROLLER,
+      "Controller:0x%x State:0x%x invalid state to reset controller.\n",
+      controller,
+      sci_base_state_machine_get_state(
+         &((SCIF_SAS_CONTROLLER_T *)controller)->parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * @brief This method provides default handling (i.e. returns an error)
+ *        when a user attempts to initialize a controller and an initialize
+ *        operation is not allowed.
+ *
+ * @param[in]  controller This parameter specifies the controller object
+ *             on which the user is attempting to perform an initialize
+ *             operation.
+ *
+ * @return This method returns an indication that initialize operations
+ *         are not allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+static
+SCI_STATUS scif_sas_controller_default_initialize_handler(
+   SCI_BASE_CONTROLLER_T * controller
+)
+{
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger((SCIF_SAS_CONTROLLER_T *)controller),
+      SCIF_LOG_OBJECT_CONTROLLER,
+      "Controller:0x%x State:0x%x invalid state to initialize controller.\n",
+      controller,
+      sci_base_state_machine_get_state(
+         &((SCIF_SAS_CONTROLLER_T *)controller)->parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * @brief This method provides default handling (i.e. returns an error)
+ *        when a user attempts to start an IO on a controller and a start
+ *        IO operation is not allowed.
+ *
+ * @param[in]  controller This parameter specifies the controller object
+ *             on which the user is attempting to perform a start IO
+ *             operation.
+ * @param[in]  remote_device This parameter specifies the remote deivce
+ *             object on which the user is attempting to perform a start IO
+ *             operation.
+ * @param[in]  io_request This parameter specifies the IO request to be
+ *             started.
+ * @param[in]  io_tag This parameter specifies the optional allocated
+ *             IO tag.  Please reference scif_controller_start_io() for
+ *             more information.
+ *
+ * @return This method returns an indication that start IO operations
+ *         are not allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+static
+SCI_STATUS scif_sas_controller_default_start_io_handler(
+   SCI_BASE_CONTROLLER_T    * controller,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request,
+   U16                        io_tag
+)
+{
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger((SCIF_SAS_CONTROLLER_T *)controller),
+      SCIF_LOG_OBJECT_CONTROLLER,
+      "Controller:0x%x State:0x%x invalid state to start IO.\n",
+      controller,
+      sci_base_state_machine_get_state(
+         &((SCIF_SAS_CONTROLLER_T *)controller)->parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * @brief This method provides default handling (i.e. returns an error)
+ *        when a user attempts to complete an IO on a controller and a
+ *        complete IO operation is not allowed.
+ *
+ * @param[in]  controller This parameter specifies the controller object
+ *             on which the user is attempting to perform a complete IO
+ *             operation.
+ * @param[in]  remote_device This parameter specifies the remote deivce
+ *             object on which the user is attempting to perform a start IO
+ *             operation.
+ * @param[in]  io_request This parameter specifies the IO request to be
+ *             started.
+ *
+ * @return This method returns an indication that complete IO operations
+ *         are not allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+static
+SCI_STATUS scif_sas_controller_default_complete_io_handler(
+   SCI_BASE_CONTROLLER_T    * controller,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request
+)
+{
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger((SCIF_SAS_CONTROLLER_T *)controller),
+      SCIF_LOG_OBJECT_CONTROLLER,
+      "Controller:0x%x State:0x%x invalid state to complete IO.\n",
+      controller,
+      sci_base_state_machine_get_state(
+         &((SCIF_SAS_CONTROLLER_T *)controller)->parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * @brief This method provides default handling (i.e. returns an error)
+ *        when a user attempts to continue an IO on a controller and a
+ *        continue IO operation is not allowed.
+ *
+ * @param[in]  controller This parameter specifies the controller object
+ *             on which the user is attempting to perform a continue IO
+ *             operation.
+ * @param[in]  remote_device This parameter specifies the remote deivce
+ *             object on which the user is attempting to perform a start IO
+ *             operation.
+ * @param[in]  io_request This parameter specifies the IO request to be
+ *             started.
+ *
+ * @return This method returns an indication that continue IO operations
+ *         are not allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+static
+SCI_STATUS scif_sas_controller_default_continue_io_handler(
+   SCI_BASE_CONTROLLER_T    * controller,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request
+)
+{
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger((SCIF_SAS_CONTROLLER_T *)controller),
+      SCIF_LOG_OBJECT_CONTROLLER,
+      "Controller:0x%x State:0x%x invalid state to continue IO.\n",
+      controller,
+      sci_base_state_machine_get_state(
+         &((SCIF_SAS_CONTROLLER_T *)controller)->parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * @brief This method provides default handling (i.e. returns an error)
+ *        when a user attempts to start a task on a controller and a start
+ *        task operation is not allowed.
+ *
+ * @param[in]  controller This parameter specifies the controller object
+ *             on which the user is attempting to perform a start task
+ *             operation.
+ * @param[in]  remote_device This parameter specifies the remote deivce
+ *             object on which the user is attempting to perform a start
+ *             task operation.
+ * @param[in]  task_request This parameter specifies the task management
+ *             request to be started.
+ * @param[in]  io_tag This parameter specifies the optional allocated
+ *             IO tag.  Please reference scif_controller_start_task() for
+ *             more information.
+ *
+ * @return This method returns an indication that start task operations
+ *         are not allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+static
+SCI_STATUS scif_sas_controller_default_start_task_handler(
+   SCI_BASE_CONTROLLER_T    * controller,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * task_request,
+   U16                        io_tag
+)
+{
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger((SCIF_SAS_CONTROLLER_T *)controller),
+      SCIF_LOG_OBJECT_CONTROLLER,
+      "Controller:0x%x State:0x%x invalid state to start task mgmt.\n",
+      controller,
+      sci_base_state_machine_get_state(
+         &((SCIF_SAS_CONTROLLER_T *)controller)->parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * @brief This method provides default handling (i.e. returns an error)
+ *        when a user attempts to complete a task on a controller and a
+ *        complete task operation is not allowed.
+ *
+ * @param[in]  controller This parameter specifies the controller object
+ *             on which the user is attempting to perform a complete task
+ *             operation.
+ * @param[in]  remote_device This parameter specifies the remote deivce
+ *             object on which the user is attempting to perform a start
+ *             task operation.
+ * @param[in]  task_request This parameter specifies the task management
+ *             request to be started.
+ *
+ * @return This method returns an indication that complete task operations
+ *         are not allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+static
+SCI_STATUS scif_sas_controller_default_complete_task_handler(
+   SCI_BASE_CONTROLLER_T    * controller,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * task_request
+)
+{
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger((SCIF_SAS_CONTROLLER_T *)controller),
+      SCIF_LOG_OBJECT_CONTROLLER,
+      "Controller:0x%x State:0x%x invalid state to complete task mgmt.\n",
+      controller,
+      sci_base_state_machine_get_state(
+         &((SCIF_SAS_CONTROLLER_T *)controller)->parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+static
+SCI_STATUS scif_sas_controller_failed_state_start_io_handler(
+   SCI_BASE_CONTROLLER_T    * controller,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request,
+   U16                        io_tag
+)
+{
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger((SCIF_SAS_CONTROLLER_T *)controller),
+      SCIF_LOG_OBJECT_CONTROLLER,
+      "Controller:0x%x State:0x%x invalid state to start IO.\n",
+      controller,
+      sci_base_state_machine_get_state(
+         &((SCIF_SAS_CONTROLLER_T *)controller)->parent.state_machine)
+   ));
+
+   return SCI_FAILURE;
+}
+
+#define scif_sas_controller_stopping_complete_io_handler   \
+        scif_sas_controller_ready_complete_io_handler
+#define scif_sas_controller_stopping_complete_task_handler \
+        scif_sas_controller_ready_complete_task_handler
+#define scif_sas_controller_default_start_high_priority_io_handler \
+        scif_sas_controller_default_start_io_handler
+#define scif_sas_controller_default_complete_high_priority_io_handler \
+        scif_sas_controller_default_complete_io_handler
+#define scif_sas_controller_stopping_complete_high_priority_io_handler \
+        scif_sas_controller_ready_complete_high_priority_io_handler
+
+
+SCI_BASE_CONTROLLER_STATE_HANDLER_T
+   scif_sas_controller_state_handler_table[SCI_BASE_CONTROLLER_MAX_STATES] =
+{
+   // SCI_BASE_CONTROLLER_STATE_INITIAL
+   {
+      scif_sas_controller_default_start_handler,
+      scif_sas_controller_default_stop_handler,
+      scif_sas_controller_default_reset_handler,
+      scif_sas_controller_default_initialize_handler,
+      scif_sas_controller_default_start_io_handler,
+      scif_sas_controller_default_start_high_priority_io_handler,
+      scif_sas_controller_default_complete_io_handler,
+      scif_sas_controller_default_complete_high_priority_io_handler,
+      scif_sas_controller_default_continue_io_handler,
+      scif_sas_controller_default_start_task_handler,
+      scif_sas_controller_default_complete_task_handler
+   },
+   // SCI_BASE_CONTROLLER_STATE_RESET
+   {
+      scif_sas_controller_default_start_handler,
+      scif_sas_controller_default_stop_handler,
+      scif_sas_controller_default_reset_handler,
+      scif_sas_controller_reset_initialize_handler,
+      scif_sas_controller_default_start_io_handler,
+      scif_sas_controller_default_start_high_priority_io_handler,
+      scif_sas_controller_default_complete_io_handler,
+      scif_sas_controller_default_complete_high_priority_io_handler,
+      scif_sas_controller_default_continue_io_handler,
+      scif_sas_controller_default_start_task_handler,
+      scif_sas_controller_default_complete_task_handler
+   },
+   // SCI_BASE_CONTROLLER_STATE_INITIALIZING
+   {
+      scif_sas_controller_default_start_handler,
+      scif_sas_controller_default_stop_handler,
+      scif_sas_controller_default_reset_handler,
+      scif_sas_controller_default_initialize_handler,
+      scif_sas_controller_default_start_io_handler,
+      scif_sas_controller_default_start_high_priority_io_handler,
+      scif_sas_controller_default_complete_io_handler,
+      scif_sas_controller_default_complete_high_priority_io_handler,
+      scif_sas_controller_default_continue_io_handler,
+      scif_sas_controller_default_start_task_handler,
+      scif_sas_controller_default_complete_task_handler
+   },
+   // SCI_BASE_CONTROLLER_STATE_INITIALIZED
+   {
+      scif_sas_controller_initialized_start_handler,
+      scif_sas_controller_default_stop_handler,
+      scif_sas_controller_default_reset_handler,
+      scif_sas_controller_default_initialize_handler,
+      scif_sas_controller_default_start_io_handler,
+      scif_sas_controller_default_start_high_priority_io_handler,
+      scif_sas_controller_default_complete_io_handler,
+      scif_sas_controller_default_complete_high_priority_io_handler,
+      scif_sas_controller_default_continue_io_handler,
+      scif_sas_controller_default_start_task_handler,
+      scif_sas_controller_default_complete_task_handler
+   },
+   // SCI_BASE_CONTROLLER_STATE_STARTING
+   {
+      scif_sas_controller_default_start_handler,
+      scif_sas_controller_default_stop_handler,
+      scif_sas_controller_default_reset_handler,
+      scif_sas_controller_default_initialize_handler,
+      scif_sas_controller_default_start_io_handler,
+      scif_sas_controller_default_start_high_priority_io_handler,
+      scif_sas_controller_default_complete_io_handler,
+      scif_sas_controller_default_complete_high_priority_io_handler,
+      scif_sas_controller_default_continue_io_handler,
+      scif_sas_controller_default_start_task_handler,
+      scif_sas_controller_default_complete_task_handler
+   },
+   // SCI_BASE_CONTROLLER_STATE_READY
+   {
+      scif_sas_controller_default_start_handler,
+      scif_sas_controller_ready_stop_handler,
+      scif_sas_controller_ready_reset_handler,
+      scif_sas_controller_default_initialize_handler,
+      scif_sas_controller_ready_start_io_handler,
+      scif_sas_controller_ready_start_high_priority_io_handler,
+      scif_sas_controller_ready_complete_io_handler,
+      scif_sas_controller_ready_complete_high_priority_io_handler,
+      scif_sas_controller_ready_continue_io_handler,
+      scif_sas_controller_ready_start_task_handler,
+      scif_sas_controller_ready_complete_task_handler
+   },
+   // SCI_BASE_CONTROLLER_STATE_RESETTING
+   {
+      scif_sas_controller_default_start_handler,
+      scif_sas_controller_default_stop_handler,
+      scif_sas_controller_default_reset_handler,
+      scif_sas_controller_default_initialize_handler,
+      scif_sas_controller_default_start_io_handler,
+      scif_sas_controller_default_start_high_priority_io_handler,
+      scif_sas_controller_default_complete_io_handler,
+      scif_sas_controller_default_complete_high_priority_io_handler,
+      scif_sas_controller_default_continue_io_handler,
+      scif_sas_controller_default_start_task_handler,
+      scif_sas_controller_default_complete_task_handler
+   },
+   // SCI_BASE_CONTROLLER_STATE_STOPPING
+   {
+      scif_sas_controller_default_start_handler,
+      scif_sas_controller_default_stop_handler,
+      scif_sas_controller_default_reset_handler,
+      scif_sas_controller_default_initialize_handler,
+      scif_sas_controller_default_start_io_handler,
+      scif_sas_controller_stopping_start_high_priority_io_handler,
+      scif_sas_controller_stopping_complete_io_handler,
+      scif_sas_controller_stopping_complete_high_priority_io_handler,
+      scif_sas_controller_default_continue_io_handler,
+      scif_sas_controller_default_start_task_handler, /**@todo Allow in core?*/
+      scif_sas_controller_stopping_complete_task_handler
+   },
+   // SCI_BASE_CONTROLLER_STATE_STOPPED
+   {
+      scif_sas_controller_default_start_handler,
+      scif_sas_controller_default_stop_handler,
+      scif_sas_controller_stopped_reset_handler,
+      scif_sas_controller_default_initialize_handler,
+      scif_sas_controller_default_start_io_handler,
+      scif_sas_controller_default_start_high_priority_io_handler,
+      scif_sas_controller_default_complete_io_handler,
+      scif_sas_controller_default_complete_high_priority_io_handler,
+      scif_sas_controller_default_continue_io_handler,
+      scif_sas_controller_default_start_task_handler,
+      scif_sas_controller_default_complete_task_handler
+   },
+   // SCI_BASE_CONTROLLER_STATE_FAILED
+   {
+      scif_sas_controller_default_start_handler,
+      scif_sas_controller_default_stop_handler,
+      scif_sas_controller_failed_reset_handler,
+      scif_sas_controller_default_initialize_handler,
+      scif_sas_controller_failed_state_start_io_handler,
+      scif_sas_controller_failed_state_start_io_handler,
+      scif_sas_controller_default_complete_io_handler,
+      scif_sas_controller_default_complete_high_priority_io_handler,
+      scif_sas_controller_default_continue_io_handler,
+      scif_sas_controller_default_start_task_handler,
+      scif_sas_controller_default_complete_task_handler
+   }
+};
diff --git a/sys/dev/disk/isci/scil/scif_sas_controller_states.c b/sys/dev/disk/isci/scil/scif_sas_controller_states.c
new file mode 100644
index 0000000..baf5736
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_controller_states.c
@@ -0,0 +1,458 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_controller_states.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the entrance and exit methods for each
+ *        of the controller states defined by the SCI_BASE_CONTROLLER state
+ *        machine.
+ */
+
+#include <dev/disk/isci/scil/scic_controller.h>
+
+#include <dev/disk/isci/scil/scif_sas_logger.h>
+#include <dev/disk/isci/scil/scif_sas_controller.h>
+
+//******************************************************************************
+//* P R O T E C T E D    M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        INITIAL state.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_CONTROLLER object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_controller_initial_state_enter(
+   SCI_BASE_OBJECT_T * object
+)
+{
+   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
+
+   SET_STATE_HANDLER(
+      fw_controller,
+      scif_sas_controller_state_handler_table,
+      SCI_BASE_CONTROLLER_STATE_INITIAL
+   );
+}
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        RESET state.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_CONTROLLER object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_controller_reset_state_enter(
+   SCI_BASE_OBJECT_T * object
+)
+{
+   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
+   U8 index;
+   U16 smp_phy_index;
+
+   SET_STATE_HANDLER(
+      fw_controller,
+      scif_sas_controller_state_handler_table,
+      SCI_BASE_CONTROLLER_STATE_RESET
+   );
+
+   scif_sas_high_priority_request_queue_construct(
+      &fw_controller->hprq, sci_base_object_get_logger(fw_controller)
+   );
+
+   // Construct the abstract element pool. This pool will store the
+   // references to the framework's remote devices objects.
+   sci_abstract_element_pool_construct(
+      &fw_controller->free_remote_device_pool,
+      fw_controller->remote_device_pool_elements,
+      SCI_MAX_REMOTE_DEVICES
+   );
+
+   // Construct the domain objects.
+   for (index = 0; index < SCI_MAX_DOMAINS; index++)
+   {
+      scif_sas_domain_construct(
+         &fw_controller->domains[index], index, fw_controller
+      );
+   }
+
+   //Initialize SMP PHY MEMORY LIST.
+   sci_fast_list_init(&fw_controller->smp_phy_memory_list);
+
+   for (smp_phy_index = 0;
+        smp_phy_index < SCIF_SAS_SMP_PHY_COUNT;
+        smp_phy_index++)
+   {
+      sci_fast_list_element_init(
+         &fw_controller->smp_phy_array[smp_phy_index],
+         &(fw_controller->smp_phy_array[smp_phy_index].list_element)
+      );
+
+      //insert to owning device's smp phy list.
+      sci_fast_list_insert_tail(
+         (&(fw_controller->smp_phy_memory_list)),
+         (&(fw_controller->smp_phy_array[smp_phy_index].list_element))
+      );
+   }
+
+   scif_sas_controller_set_default_config_parameters(fw_controller);
+
+   fw_controller->internal_request_entries =
+      SCIF_SAS_MAX_INTERNAL_REQUEST_COUNT;
+
+   //@Todo: may need to verify all timers are released. Including domain's
+   //operation timer and all the Internal IO's timer.
+
+   //take care of the lock.
+   scif_cb_lock_disassociate(fw_controller, &fw_controller->hprq.lock);
+}
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        INITIALIZING state.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_CONTROLLER object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_controller_initializing_state_enter(
+   SCI_BASE_OBJECT_T * object
+)
+{
+   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
+
+   SET_STATE_HANDLER(
+      fw_controller,
+      scif_sas_controller_state_handler_table,
+      SCI_BASE_CONTROLLER_STATE_INITIALIZING
+   );
+}
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        INITIALIZED state.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_CONTROLLER object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_controller_initialized_state_enter(
+   SCI_BASE_OBJECT_T * object
+)
+{
+   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
+
+   SET_STATE_HANDLER(
+      fw_controller,
+      scif_sas_controller_state_handler_table,
+      SCI_BASE_CONTROLLER_STATE_INITIALIZED
+   );
+}
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        STARTING state.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_CONTROLLER object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_controller_starting_state_enter(
+   SCI_BASE_OBJECT_T * object
+)
+{
+   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
+
+   SET_STATE_HANDLER(
+      fw_controller,
+      scif_sas_controller_state_handler_table,
+      SCI_BASE_CONTROLLER_STATE_STARTING
+   );
+}
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        READY state.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_CONTROLLER object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_controller_ready_state_enter(
+   SCI_BASE_OBJECT_T * object
+)
+{
+   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
+
+   SET_STATE_HANDLER(
+      fw_controller,
+      scif_sas_controller_state_handler_table,
+      SCI_BASE_CONTROLLER_STATE_READY
+   );
+}
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        STOPPING state.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_CONTROLLER object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_controller_stopping_state_enter(
+   SCI_BASE_OBJECT_T * object
+)
+{
+   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
+
+   SET_STATE_HANDLER(
+      fw_controller,
+      scif_sas_controller_state_handler_table,
+      SCI_BASE_CONTROLLER_STATE_STOPPING
+   );
+}
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        STOPPED state.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_CONTROLLER object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_controller_stopped_state_enter(
+   SCI_BASE_OBJECT_T * object
+)
+{
+   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
+
+   SET_STATE_HANDLER(
+      fw_controller,
+      scif_sas_controller_state_handler_table,
+      SCI_BASE_CONTROLLER_STATE_STOPPED
+   );
+}
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        RESETTING state.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_CONTROLLER object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_controller_resetting_state_enter(
+   SCI_BASE_OBJECT_T * object
+)
+{
+   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
+
+   SET_STATE_HANDLER(
+      fw_controller,
+      scif_sas_controller_state_handler_table,
+      SCI_BASE_CONTROLLER_STATE_RESETTING
+   );
+
+   // Attempt to reset the core controller.
+   fw_controller->operation_status = scic_controller_reset(
+                                        fw_controller->core_object
+                                     );
+   if (fw_controller->operation_status == SCI_SUCCESS)
+   {
+      // Reset the framework controller.
+      sci_base_state_machine_change_state(
+         &fw_controller->parent.state_machine,
+         SCI_BASE_CONTROLLER_STATE_RESET
+      );
+   }
+   else
+   {
+      SCIF_LOG_ERROR((
+         sci_base_object_get_logger(fw_controller),
+         SCIF_LOG_OBJECT_CONTROLLER,
+         "Controller: unable to successfully reset controller.\n"
+      ));
+
+      sci_base_state_machine_change_state(
+         &fw_controller->parent.state_machine,
+         SCI_BASE_CONTROLLER_STATE_FAILED
+      );
+   }
+}
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        FAILED state.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_CONTROLLER object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_controller_failed_state_enter(
+   SCI_BASE_OBJECT_T * object
+)
+{
+   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
+
+   SCIF_LOG_ERROR((
+      sci_base_object_get_logger(fw_controller),
+      SCIF_LOG_OBJECT_CONTROLLER,
+      "Controller: entered FAILED state.\n"
+   ));
+
+   SET_STATE_HANDLER(
+      fw_controller,
+      scif_sas_controller_state_handler_table,
+      SCI_BASE_CONTROLLER_STATE_FAILED
+   );
+
+   if (fw_controller->parent.error != SCI_CONTROLLER_FATAL_MEMORY_ERROR)
+   {
+       //clean timers to avoid timer leak.
+       scif_sas_controller_release_resource(fw_controller);
+
+       //notify user.
+       scif_cb_controller_error(fw_controller, fw_controller->parent.error);
+   }
+}
+
+SCI_BASE_STATE_T
+scif_sas_controller_state_table[SCI_BASE_CONTROLLER_MAX_STATES] =
+{
+   {
+      SCI_BASE_CONTROLLER_STATE_INITIAL,
+      scif_sas_controller_initial_state_enter,
+      NULL,
+   },
+   {
+      SCI_BASE_CONTROLLER_STATE_RESET,
+      scif_sas_controller_reset_state_enter,
+      NULL,
+   },
+   {
+      SCI_BASE_CONTROLLER_STATE_INITIALIZING,
+      scif_sas_controller_initializing_state_enter,
+      NULL,
+   },
+   {
+      SCI_BASE_CONTROLLER_STATE_INITIALIZED,
+      scif_sas_controller_initialized_state_enter,
+      NULL,
+   },
+   {
+      SCI_BASE_CONTROLLER_STATE_STARTING,
+      scif_sas_controller_starting_state_enter,
+      NULL,
+   },
+   {
+      SCI_BASE_CONTROLLER_STATE_READY,
+      scif_sas_controller_ready_state_enter,
+      NULL,
+   },
+   {
+      SCI_BASE_CONTROLLER_STATE_RESETTING,
+      scif_sas_controller_resetting_state_enter,
+      NULL,
+   },
+   {
+      SCI_BASE_CONTROLLER_STATE_STOPPING,
+      scif_sas_controller_stopping_state_enter,
+      NULL,
+   },
+   {
+      SCI_BASE_CONTROLLER_STATE_STOPPED,
+      scif_sas_controller_stopped_state_enter,
+      NULL,
+   },
+   {
+      SCI_BASE_CONTROLLER_STATE_FAILED,
+      scif_sas_controller_failed_state_enter,
+      NULL,
+   }
+};
diff --git a/sys/dev/disk/isci/scil/scif_sas_design.h b/sys/dev/disk/isci/scil/scif_sas_design.h
new file mode 100644
index 0000000..ef6cd40
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_design.h
@@ -0,0 +1,348 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_design.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIF_SAS_DESIGN_H_
+#define _SCIF_SAS_DESIGN_H_
+
+/**
+@page scif_sas_design_page SCIF SAS High Level Design
+
+<b>Authors:</b>
+- Nathan Marushak
+
+<b>Key Contributors:</b>
+- Richard Boyd
+
+@section scif_sas_scope_and_audience Scope and Audience
+
+This document provides design information relating to the SAS specific
+implementation of the SCI Framework.  Driver developers are the primary
+audience for this document.  The reader is expected to have an understanding
+of the SCU Software Architecture Specification, the Storage Controller
+Interface Specification, and the SCI Base Design.
+
+@section scif_sas_overview Overview
+
+To begin, it's important to discuss the utilization of state machines in
+the design.  State machines are pervasive in this design, because of the
+abilities they provide.  A properly implemented state machine allows the
+developer to code for a specific task.  The developer is not encumbered
+with needed to handle other situations all in a single function.  For
+example, if a specific event can only occur when the object is in a specific
+state, then the event handler is added to handle such an event.  Thus, a
+single function is not spliced to handle multiple events under various
+potentially disparate conditions.
+
+Additionally, the SCI Base Design document specifies a number of state
+machines, objects, and methods that are heavily utilized by this design.
+Please refer to Base Design specification for further information.
+
+Many of the framework objects have state machines associated with them.
+As a result, there are a number of state entrance and exit methods as well
+as event handlers for each individual state.  This design places all of
+the state entrance and exit methods for a given state machine into a single
+file (e.g. scif_sas_controller_states.c).  Furthermore, all of the state
+event handler methods are also placed into a single file (e.g.
+scif_sas_controller_state_handlers.c).  This format is reused for each
+object that contains state machine(s).
+
+Some of the SAS framework objects contain sub-state machines.  These
+sub-state machines are started upon entrance to the super-state and stopped
+upon exit of the super-state.
+
+All other method, data, constant description information will be found in
+the remaining source file (e.g. scif_sas_controller.c).  As a result, please
+be sure to follow the link to that specific object/file definition for
+further information.
+
+@note Currently a large number of function pointers are utilized during the
+course of a normal IO request.  Once stability of the driver is achieved,
+performance improvements will be made as needed.  This likely will include
+removal of the function pointers from the IO path.
+
+@section scif_sas_use_cases Use Cases
+
+The following use case diagram depicts the high-level user interactions with
+the SAS framework.  This diagram does not encompass all use cases implemented
+in the system.  The low-level design section will contain detailed use cases
+for each significant object and their associated detailed sequences and/or
+activities.  For the purposes of readability, the use cases are not directly
+connected to the associated actor utilizing the use case.  Instead naming
+is utilized to different which actor is involved with the use case.
+
+Actors:
+- The Framework user also called the OS Specific Driver initiates activities in
+the Framework.
+- The SCI Core calls back into the Framework as a result of an operation either
+started by the OS Specific Driver or by the Framework itself.
+
+@image latex Use_Case_Diagram__SCIF_SAS__Use_Cases.eps "SCIF SAS OS Use Cases" width=11cm
+@image html Use_Case_Diagram__SCIF_SAS__Use_Cases.jpg "SCIF SAS OS Use Cases"
+
+@section scif_sas_class_hierarchy Class Hierarchy
+
+This section delineates the high-level class organization for the SCIF_SAS
+component.  Details concerning each class will be found in the corresponding
+low-level design sections.  Furthermore, additional classes not germane to
+the overall architecture of the component will also be defined in these
+low-level design sections.
+
+@image latex Class_Diagram__scif_sas__Class_Diagram.eps "SCIF SAS Class Diagram" width=16cm
+@image html Class_Diagram__scif_sas__Class_Diagram.jpg "SCIF SAS Class Diagram"
+
+For more information on each object appearing in the diagram, please
+reference the subsequent sections.
+
+@section scif_sas_library SCIF SAS Library
+
+First, the SCIF_SAS_LIBRARY object provides an implementation
+for the roles and responsibilities defined in the Storage Controller
+Interface (SCI) specification.  It is suggested that the user read the
+storage controller interface specification for background information on
+the library object.
+
+The SCIF_SAS_LIBRARY object is broken down into 2 individual source files
+and one direct header file.  These files delineate the methods, members, etc.
+associated with this object.  Please reference these files directly for
+further design information:
+- scif_sas_library.h
+- scif_sas_library.c
+
+@section scif_sas_controller SCIF SAS Controller
+
+First, the SCIF_SAS_CONTROLLER object provides an implementation
+for the roles and responsibilities defined in the Storage Controller
+Interface (SCI) specification.  It is suggested that the user read the
+storage controller interface specification for background information on
+the controller object.
+
+The SCIF_SAS_CONTROLLER object is broken down into 3 individual source files
+and one direct header file.  These files delineate the methods, members, etc.
+associated with this object.  Please reference these files directly for
+further design information:
+- scif_sas_controller.h
+- scif_sas_controller.c
+- scif_sas_controller_state_handlers.c
+- scif_sas_controller_states.c
+
+@section scif_sas_domain SCIF SAS Domain
+
+First, the SCIF_SAS_DOMAIN object provides an implementation
+for the roles and responsibilities defined in the Storage Controller
+Interface (SCI) specification.  It is suggested that the user read the
+storage controller interface specification for background information on
+the SCIF_SAS_DOMAIN object.
+
+The SCIF_SAS_DOMAIN object is broken down into 3 individual
+source files and one direct header file.  These files delineate the
+methods, members, etc. associated with this object.  Please reference
+these files directly for
+further design information:
+- scif_sas_domain.h
+- scif_sas_domain.c
+- scif_sas_domain_state_handlers.c
+- scif_sas_domain_states.c
+
+@section scif_sas_remote_device SCIF SAS Remote Device
+
+First, the SCIF_SAS_REMOTE_DEVICE object provides an implementation
+for the roles and responsibilities defined in the Storage Controller
+Interface (SCI) specification.  It is suggested that the user read the
+storage controller interface specification for background information on
+the SCIF_SAS_REMOTE_DEVICE object.
+
+The SCIF_SAS_REMOTE_DEVICE object is broken down into 7 individual source files
+and one direct header file.  These files delineate the methods, members, etc.
+associated with this object.  Methods, data, and functionality specific to a
+particular protocol type (e.g. SMP, STP, etc.) are broken out into their own
+object/file.  SSP specific remote device functionality is covered by the base
+classes (common files).  Please reference these files directly for further
+design information:
+- scif_sas_remote_device.h
+- scif_sas_smp_remote_device.h
+- scif_sas_stp_remote_device.h
+- scif_sas_remote_device.c
+- scif_sas_remote_device_state_handlers.c
+- scif_sas_remote_device_states.c
+- scif_sas_remote_device_starting_substate_handlers.c
+- scif_sas_remote_device_starting_substates.c
+- scif_sas_remote_device_ready_substate_handlers.c
+- scif_sas_remote_device_ready_substates.c
+- scif_sas_smp_remote_device.c
+- scif_sas_stp_remote_device.c
+
+The SCIF_SAS_REMOTE_DEVICE object has sub-state machines defined for
+the READY and STARTING super-states.  For more information on the
+super-state machine please refer to SCI_BASE_REMOTE_DEVICE_STATES
+in the SCI Base design document.
+
+In the SCIF_SAS_REMOTE_DEVICE_STARTING_SUBSTATES sub-state machine,
+the remote device currently has to wait for the core to
+return an indication that the remote device has successfully started
+and become ready.  If all goes well, then the remote device will
+transition into the READY state.
+
+For more information on the starting sub-state machine states please refer
+to the scif_sas_remote_device.h::_SCIF_SAS_REMOTE_DEVICE_STARTING_SUBSTATES
+enumeration.
+
+@image latex State_Machine_Diagram__STARTING_SUB-STATE__STARTING_SUB-STATE.eps "SCIF SAS Remote Device Starting Sub-state Machine Diagram" width=16cm
+@image html State_Machine_Diagram__STARTING_SUB-STATE__STARTING_SUB-STATE.jpg "SCIF SAS Remote Device Starting Sub-state Machine Diagram"
+
+In the SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATES sub-state machine,
+the remote device currently only allows new host IO requests during the
+OPERATIONAL state.  In the TASK MANAGEMENT state only new task management
+requests are allowed.
+
+For more information on the ready sub-state machine states please refer
+to the scif_sas_remote_device.h::_SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATES
+enumeration.
+
+@image latex State_Machine_Diagram__READY_SUB-STATE__READY_SUB-STATE.eps "SCIF SAS Remote Device Ready Sub-state Machine Diagram" width=16cm
+@image html State_Machine_Diagram__READY_SUB-STATE__READY_SUB-STATE.jpg "SCIF SAS Remote Device Ready Sub-state Machine Diagram"
+
+@section scif_sas_request SCIF SAS Request
+
+The SCIF_SAS_REQUEST object provide common functionality for the
+SCIF_SAS_IO_REQUEST and the SCIF_SAS_TASK_REQUEST objects.  This object
+does not directly map to an SCI defined object, but its children do.  For
+additional information, you may reference the SCIF_SAS_IO_REQUEST or
+SCIF_SAS_TASK_REQUEST objects.
+
+The SCIF_SAS_REQUEST object is broken down into 1 individual source file
+and one direct header file.  These files delineate the methods, members, etc.
+associated with this object.  Please reference these files directly for
+further design information:
+- scif_sas_request.h
+- scif_sas_request.c
+
+@section scif_sas_io_request SCIF SAS IO Request
+
+First, the SCIF_SAS_IO_REQUEST object provides an implementation
+for the roles and responsibilities defined in the Storage Controller
+Interface (SCI) specification.  It is suggested that the user read the
+storage controller interface specification for background information on
+the SCIF_SAS_IO_REQUEST object.
+
+The SCIF_SAS_IO_REQUEST object is broken down into 3 individual
+source files and one direct header file.  These files delineate the
+methods, members, etc. associated with this object.  Please reference
+these files directly for further design information:
+- scif_sas_io_request.h
+- scif_sas_smp_io_request.h
+- scif_sas_stp_io_request.h
+- scif_sas_sati_binding.h
+- scif_sas_io_request.c
+- scif_sas_io_request_state_handlers.c
+- scif_sas_io_request_states.c
+- scif_sas_smp_io_request.c
+- scif_sas_stp_io_request.c
+
+@section scif_sas_task_request SCIF SAS Task Request
+
+First, the SCIF_SAS_TASK_REQUEST object provides an implementation
+for the roles and responsibilities defined in the Storage Controller
+Interface (SCI) specification.  It is suggested that the user read the
+storage controller interface specification for background information on
+the SCIF_SAS_TASK_REQUEST object.
+
+The SCIF_SAS_TASK_REQUEST object is broken down into 3 individual
+source files and one direct header file.  These files delineate the
+methods, members, etc. associated with this object.  Please reference
+these files directly for further design information:
+- scif_sas_task_request.h
+- scif_sas_stp_task_request.h
+- scif_sas_task_request.c
+- scif_sas_task_request_state_handlers.c
+- scif_sas_task_request_states.c
+- scif_sas_stp_task_request.c
+
+@section scif_sas_internal_io_request SCIF SAS INTERNAL IO Request
+
+The SCIF_SAS_INTERNAL_IO_REQUEST object fulfills the SCI's need to create
+and send out the internal io request. These internal io requests could be
+smp request for expander device discover process, or stp request for NCQ
+error handling. Internal IOs consume the reserved internal io space in
+scif_sas_controller. When an internal IO is constructed, it is put into an
+internal high priority queue. A defferred task (start_internal_io_task) will be
+scheduled at the end of every completion process. The task looks up the high
+priority queue and starts each internal io in the queue. There is one exception
+that start_internal_io_task is scheduled immediately when the first internal io
+is constructed. A retry mechanism is also provided for internal io. When an
+internal io response is decoded, if the decoding indicates a retry is needed,
+the internal io will be retried.
+
+Please refer to these files directly for further design information:
+- scif_sas_internal_io_request.h
+- scif_sas_internal_io_request.c
+- scif_sas_controller.h
+
+@section scif_sas_smp_remote_device SCIF SAS SMP REMOTE DEVICE
+
+The SCIF SAS SMP REMOTE DEVICE object represents the expander device and fulfills
+its SMP discover activities. The discover procedure includes a initial discover
+phase and a follwoing SATA spinup_hold release phase, if there are expander attached
+SATA device is discovered and in spinup_hold conditon. The SCIF SAS SMP REMOTE DEVICE
+object also fulfills expander attached device Target Reset (Phy Control) activity.
+
+@image latex Discover Process.eps "SMP Discover Activity Diagram" width=10cm
+@image html Discover Process.jpg "SMP Discover Activity Diagram"
+
+Please refer to these files directly for further design information:
+- scif_sas_smp_remote_device.h
+- scif_sas_smp_remote_device.c
+- scif_sas_smp_request.h
+- scif_sas_smp_request.c
+*/
+
+#endif // _SCIF_SAS_DESIGN_H_
diff --git a/sys/dev/disk/isci/scil/scif_sas_domain.c b/sys/dev/disk/isci/scil/scif_sas_domain.c
new file mode 100644
index 0000000..a9860fc
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_domain.c
@@ -0,0 +1,1535 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_domain.c,v 1.2 2012/02/07 17:45:11 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains the implementation of the SCIF_SAS_DOMAIN
+ *        object.
+ */
+
+#include <dev/disk/isci/scil/intel_sas.h>
+#include <dev/disk/isci/scil/sci_fast_list.h>
+#include <dev/disk/isci/scil/scic_controller.h>
+#include <dev/disk/isci/scil/scic_port.h>
+#include <dev/disk/isci/scil/scic_remote_device.h>
+#include <dev/disk/isci/scil/scic_io_request.h>
+#include <dev/disk/isci/scil/scic_user_callback.h>
+#include <dev/disk/isci/scil/scif_user_callback.h>
+#include <dev/disk/isci/scil/sci_abstract_list.h>
+#include <dev/disk/isci/scil/sci_base_iterator.h>
+
+#include <dev/disk/isci/scil/scif_sas_logger.h>
+#include <dev/disk/isci/scil/scif_sas_domain.h>
+#include <dev/disk/isci/scil/scif_sas_controller.h>
+#include <dev/disk/isci/scil/scif_sas_remote_device.h>
+#include <dev/disk/isci/scil/scif_sas_smp_remote_device.h>
+#include <dev/disk/isci/scil/sci_util.h>
+
+//******************************************************************************
+//* P R I V A T E   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method will attempt to handle an operation timeout (i.e.
+ *        discovery or reset).
+ *
+ * @param[in]  cookie This parameter specifies the domain in which the
+ *             timeout occurred.
+ *
+ * @return none
+ */
+static
+void scif_sas_domain_operation_timeout_handler(
+   void * cookie
+)
+{
+   SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T*) cookie;
+   U32                 state;
+
+   state = sci_base_state_machine_get_state(&fw_domain->parent.state_machine);
+
+   // Based upon the state of the domain, we know whether we were in the
+   // process of performing discovery or a reset.
+   if (state == SCI_BASE_DOMAIN_STATE_DISCOVERING)
+   {
+      SCIF_LOG_WARNING((
+         sci_base_object_get_logger(fw_domain),
+         SCIF_LOG_OBJECT_DOMAIN,
+         "Domain:0x%x State:0x%x DISCOVER timeout!\n",
+         fw_domain, state
+      ));
+
+      fw_domain->operation.status = SCI_FAILURE_TIMEOUT;
+
+      //search all the smp devices in the domain and cancel their activities
+      //if there is any outstanding activity remained. The smp devices will terminate
+      //all the started internal IOs.
+      scif_sas_domain_cancel_smp_activities(fw_domain);
+
+      scif_sas_domain_continue_discover(fw_domain);
+   }
+   else
+   {
+      SCIF_LOG_ERROR((
+         sci_base_object_get_logger(fw_domain),
+         SCIF_LOG_OBJECT_DOMAIN,
+         "Domain:0x%x State:0x%x operation timeout in invalid state\n",
+         fw_domain, state
+      ));
+   }
+}
+
+//******************************************************************************
+//* P U B L I C   M E T H O D S
+//******************************************************************************
+
+SCI_PORT_HANDLE_T scif_domain_get_scic_port_handle(
+   SCI_DOMAIN_HANDLE_T  domain
+)
+{
+   SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T*) domain;
+
+   if ( (fw_domain == NULL) || (fw_domain->core_object == SCI_INVALID_HANDLE) )
+      return SCI_INVALID_HANDLE;
+
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger(fw_domain),
+      SCIF_LOG_OBJECT_DOMAIN,
+      "Domain:0x%x no associated core port found\n",
+      fw_domain
+   ));
+
+   return fw_domain->core_object;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_REMOTE_DEVICE_HANDLE_T scif_domain_get_device_by_sas_address(
+   SCI_DOMAIN_HANDLE_T   domain,
+   SCI_SAS_ADDRESS_T   * sas_address
+)
+{
+   SCIF_SAS_DOMAIN_T        * fw_domain = (SCIF_SAS_DOMAIN_T*) domain;
+   SCI_ABSTRACT_ELEMENT_T   * element   = sci_abstract_list_get_front(
+                                             &fw_domain->remote_device_list
+                                          );
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device;
+   SCI_SAS_ADDRESS_T          fw_device_address;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(domain),
+      SCIF_LOG_OBJECT_DOMAIN,
+      "scif_domain_get_device_by_sas_address(0x%x, 0x%x) enter\n",
+      domain, sas_address
+   ));
+
+   // Search the abstract list to see if there is a remote device with the
+   // same SAS address.
+   while (element != NULL)
+   {
+      fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
+                  sci_abstract_list_get_object(element);
+
+      scic_remote_device_get_sas_address(
+         fw_device->core_object, &fw_device_address
+      );
+
+      // Check to see if this is the device for which we are searching.
+      if (  (fw_device_address.low == sas_address->low)
+         && (fw_device_address.high == sas_address->high) )
+      {
+         return fw_device;
+      }
+
+      element = sci_abstract_list_get_next(element);
+   }
+
+   return SCI_INVALID_HANDLE;
+}
+
+// ---------------------------------------------------------------------------
+
+#if !defined(DISABLE_SCI_ITERATORS)
+
+SCI_ITERATOR_HANDLE_T scif_domain_get_remote_device_iterator(
+   SCI_DOMAIN_HANDLE_T   domain,
+   void                * iterator_buffer
+)
+{
+   SCI_ITERATOR_HANDLE_T iterator = (SCI_ITERATOR_HANDLE_T *)iterator_buffer;
+
+   sci_base_iterator_construct(
+      iterator, &((SCIF_SAS_DOMAIN_T*) domain)->remote_device_list
+   );
+
+
+   return iterator;
+}
+
+#endif // !defined(DISABLE_SCI_ITERATORS)
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scif_domain_discover(
+   SCI_DOMAIN_HANDLE_T   domain,
+   U32                   discover_timeout,
+   U32                   device_timeout
+)
+{
+   SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T*) domain;
+   SCI_STATUS          status    = SCI_SUCCESS;
+   SCI_STATUS          op_status = SCI_SUCCESS;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(domain),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_domain_discover(0x%x, 0x%x, 0x%x) enter\n",
+      domain, discover_timeout, device_timeout
+   ));
+
+   // Check to make sure the size of the domain doesn't cause potential issues
+   // with the remote device timer and the domain timer.
+   if ((device_timeout * sci_abstract_list_size(&fw_domain->remote_device_list))
+        > discover_timeout)
+      status = SCI_WARNING_TIMER_CONFLICT;
+
+   op_status = fw_domain->state_handlers->discover_handler(
+                  &fw_domain->parent, discover_timeout, device_timeout
+               );
+
+   // The status of the discover operation takes priority.
+   if (  (status == SCI_SUCCESS)
+      || (status != SCI_SUCCESS && op_status != SCI_SUCCESS) )
+   {
+      status = op_status;
+   }
+
+   return status;
+}
+
+// ---------------------------------------------------------------------------
+
+U32 scif_domain_get_suggested_discover_timeout(
+   SCI_DOMAIN_HANDLE_T   domain
+)
+{
+   U32 suggested_timeout = SCIF_DOMAIN_DISCOVER_TIMEOUT; //milli-seconds
+   return suggested_timeout;
+}
+
+// ---------------------------------------------------------------------------
+
+void scic_cb_port_stop_complete(
+   SCI_CONTROLLER_HANDLE_T  controller,
+   SCI_PORT_HANDLE_T        port,
+   SCI_STATUS               completion_status
+)
+{
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger((SCIF_SAS_DOMAIN_T*)sci_object_get_association(port)),
+      SCIF_LOG_OBJECT_DOMAIN,
+      "scic_cb_port_stop_complete(0x%x, 0x%x, 0x%x) enter\n",
+      controller, port, completion_status
+   ));
+}
+
+// ---------------------------------------------------------------------------
+
+void scic_cb_port_ready(
+   SCI_CONTROLLER_HANDLE_T  controller,
+   SCI_PORT_HANDLE_T        port
+)
+{
+   SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T*)
+                                   sci_object_get_association(port);
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_domain),
+      SCIF_LOG_OBJECT_DOMAIN,
+      "scic_cb_port_ready(0x%x, 0x%x) enter\n",
+      controller, port
+   ));
+
+   // The controller supplied with the port should match the controller
+   // saved in the domain.
+   ASSERT(sci_object_get_association(controller) == fw_domain->controller);
+
+   fw_domain->is_port_ready = TRUE;
+
+   fw_domain->state_handlers->port_ready_handler(&fw_domain->parent);
+}
+
+// ---------------------------------------------------------------------------
+
+void scic_cb_port_not_ready(
+   SCI_CONTROLLER_HANDLE_T  controller,
+   SCI_PORT_HANDLE_T        port,
+   U32                      reason_code
+)
+{
+   SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T*)
+                                   sci_object_get_association(port);
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_domain),
+      SCIF_LOG_OBJECT_DOMAIN,
+      "scic_cb_port_not_ready(0x%x, 0x%x) enter\n",
+      controller, port
+   ));
+
+   // The controller supplied with the port should match the controller
+   // saved in the domain.
+   ASSERT(sci_object_get_association(controller) == fw_domain->controller);
+
+   // There is no need to take action on the port reconfiguring since it is
+   // just a change of the port width.
+   if (reason_code != SCIC_PORT_NOT_READY_RECONFIGURING)
+   {
+      fw_domain->is_port_ready = FALSE;
+
+      fw_domain->state_handlers->port_not_ready_handler(
+                                    &fw_domain->parent, reason_code);
+   }
+}
+
+// ---------------------------------------------------------------------------
+
+void scic_cb_port_hard_reset_complete(
+   SCI_CONTROLLER_HANDLE_T  controller,
+   SCI_PORT_HANDLE_T        port,
+   SCI_STATUS               completion_status
+)
+{
+   SCIF_SAS_DOMAIN_T        * fw_domain = (SCIF_SAS_DOMAIN_T*)
+                                   sci_object_get_association(port);
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device;
+   SCI_FAST_LIST_ELEMENT_T  * element = fw_domain->request_list.list_head;
+   SCIF_SAS_TASK_REQUEST_T  * task_request = NULL;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_domain),
+      SCIF_LOG_OBJECT_DOMAIN,
+      "scic_cb_port_hard_reset_complete(0x%x, 0x%x, 0x%x) enter\n",
+      controller, port, completion_status
+   ));
+
+   while (element != NULL)
+   {
+      task_request = (SCIF_SAS_TASK_REQUEST_T*) sci_fast_list_get_object(element);
+      element = sci_fast_list_get_next(element);
+
+      if (scif_sas_task_request_get_function(task_request)
+             == SCI_SAS_HARD_RESET)
+      {
+         fw_device = task_request->parent.device;
+
+         if (fw_device->domain == fw_domain)
+         {
+            scic_remote_device_reset_complete(fw_device->core_object);
+
+            scif_cb_task_request_complete(
+               sci_object_get_association(controller),
+               fw_device,
+               task_request,
+               (SCI_TASK_STATUS) completion_status
+            );
+
+            break;
+         }
+      }
+   }
+}
+
+// ---------------------------------------------------------------------------
+
+void scic_cb_port_bc_change_primitive_recieved(
+   SCI_CONTROLLER_HANDLE_T  controller,
+   SCI_PORT_HANDLE_T        port,
+   SCI_PHY_HANDLE_T         phy
+)
+{
+   SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T*)
+                                   sci_object_get_association(port);
+
+   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)
+                                           sci_object_get_association(controller);
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_domain),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scic_cb_port_bc_change_primitive_recieved(0x%x, 0x%x, 0x%x) enter\n",
+      controller, port, phy
+   ));
+
+   if (fw_domain->broadcast_change_count == 0)
+   {  // Enable the BCN detection only if the bcn_count is zero. If bcn_count is
+      // not zero at this time, we won't enable BCN detection since all non-zero
+      // BCN_count means same to us. Furthermore, we avoid BCN storm by not
+      // always enabling the BCN_detection.
+      scic_port_enable_broadcast_change_notification(fw_domain->core_object);
+   }
+
+   fw_domain->broadcast_change_count++;
+
+   //if there is smp device on this domain that is in the middle of discover
+   //process or smp target reset, don't notify the driver layer.
+   if( ! scif_sas_domain_is_in_smp_activity(fw_domain) )
+      // Notify the user that there is, potentially, a change to the domain.
+      scif_cb_domain_change_notification(fw_controller, fw_domain);
+}
+
+// ---------------------------------------------------------------------------
+
+void scic_cb_port_bc_ses_primitive_recieved(
+   SCI_CONTROLLER_HANDLE_T  controller,
+   SCI_PORT_HANDLE_T        port,
+   SCI_PHY_HANDLE_T         phy
+)
+{
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(sci_object_get_association(port)),
+      SCIF_LOG_OBJECT_DOMAIN,
+      "scic_cb_port_bc_ses_primitive_received(0x%x, 0x%x, 0x%x) enter\n",
+      controller, port, phy
+   ));
+}
+
+// ---------------------------------------------------------------------------
+
+void scic_cb_port_bc_expander_primitive_recieved(
+   SCI_CONTROLLER_HANDLE_T  controller,
+   SCI_PORT_HANDLE_T        port,
+   SCI_PHY_HANDLE_T         phy
+)
+{
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(sci_object_get_association(port)),
+      SCIF_LOG_OBJECT_DOMAIN,
+      "scic_cb_port_bc_expander_primitive_received(0x%x, 0x%x, 0x%x) enter\n",
+      controller, port, phy
+   ));
+}
+
+// ---------------------------------------------------------------------------
+
+void scic_cb_port_bc_aen_primitive_recieved(
+   SCI_CONTROLLER_HANDLE_T  controller,
+   SCI_PORT_HANDLE_T        port,
+   SCI_PHY_HANDLE_T         phy
+)
+{
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(sci_object_get_association(port)),
+      SCIF_LOG_OBJECT_DOMAIN,
+      "scic_cb_port_bc_aen_primitive_received(0x%x, 0x%x, 0x%x) enter\n",
+      controller, port, phy
+   ));
+}
+
+// ---------------------------------------------------------------------------
+
+void scic_cb_port_link_up(
+   SCI_CONTROLLER_HANDLE_T  controller,
+   SCI_PORT_HANDLE_T        port,
+   SCI_PHY_HANDLE_T         phy
+)
+{
+   SCIF_SAS_DOMAIN_T        * fw_domain = (SCIF_SAS_DOMAIN_T*)
+                                 sci_object_get_association(port);
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(sci_object_get_association(port)),
+      SCIF_LOG_OBJECT_DOMAIN,
+      "scic_cb_port_link_up(0x%x, 0x%x, 0x%x) enter\n",
+      controller, port, phy
+   ));
+
+   scif_sas_domain_update_device_port_width(fw_domain, port);
+}
+
+// ---------------------------------------------------------------------------
+
+void scic_cb_port_link_down(
+   SCI_CONTROLLER_HANDLE_T  controller,
+   SCI_PORT_HANDLE_T        port,
+   SCI_PHY_HANDLE_T         phy
+)
+{
+   SCIF_SAS_DOMAIN_T        * fw_domain = (SCIF_SAS_DOMAIN_T*)
+                                 sci_object_get_association(port);
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(sci_object_get_association(port)),
+      SCIF_LOG_OBJECT_DOMAIN,
+      "scic_cb_port_link_down(0x%x, 0x%x, 0x%x) enter\n",
+      controller, port, phy
+   ));
+
+   scif_sas_domain_update_device_port_width(fw_domain, port);
+}
+
+//******************************************************************************
+//* P R O T E C T E D   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method constructs the framework's SAS domain object.  During
+ *        the construction process a linkage to the corresponding core port
+ *        object.
+ *
+ * @param[in]  domain This parameter specifies the domain object to be
+ *             constructed.
+ * @param[in]  domain_id This parameter specifies the ID for the domain
+ *             object.
+ * @param[in]  fw_controller This parameter specifies the controller managing
+ *             the domain being constructed.
+ *
+ * @return none
+ */
+void scif_sas_domain_construct(
+   SCIF_SAS_DOMAIN_T     * fw_domain,
+   U8                      domain_id,
+   SCIF_SAS_CONTROLLER_T * fw_controller
+)
+{
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_controller),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_INITIALIZATION,
+      "scif_sas_domain_construct(0x%x, 0x%x, 0x%x) enter\n",
+      fw_domain, domain_id, fw_controller
+   ));
+
+   sci_base_domain_construct(
+      &fw_domain->parent,
+      sci_base_object_get_logger(fw_controller),
+      scif_sas_domain_state_table
+   );
+
+   scif_sas_domain_initialize_state_logging(fw_domain);
+
+   sci_abstract_list_construct(
+      &fw_domain->remote_device_list, &fw_controller->free_remote_device_pool
+   );
+
+   // Retrieve the core's port object that directly corresponds to this
+   // domain.
+   scic_controller_get_port_handle(
+      fw_controller->core_object, domain_id, &fw_domain->core_object
+   );
+
+   // Set the association in the core port to this framework domain object.
+   sci_object_set_association(
+      (SCI_OBJECT_HANDLE_T) fw_domain->core_object, fw_domain
+   );
+
+   sci_fast_list_init(&fw_domain->request_list);
+
+   fw_domain->operation.timer = NULL;
+
+   fw_domain->is_port_ready      = FALSE;
+   fw_domain->device_start_count = 0;
+   fw_domain->controller         = fw_controller;
+   fw_domain->operation.status   = SCI_SUCCESS;
+   fw_domain->is_config_route_table_needed = FALSE;
+}
+
+/**
+ * @brief This method will terminate the requests outstanding in the core
+ *        based on the supplied criteria.
+ *        - if the all three parameters are specified then only the single
+ *          SCIF_SAS_REQUEST object is terminated.
+ *        - if only the SCIF_SAS_DOMAIN and SCIF_SAS_REMOTE_DEVICE are
+ *          specified, then all SCIF_SAS_REQUEST objects outstanding at
+ *          the device are terminated.  The one exclusion to this rule is
+ *          that the fw_requestor is not terminated.
+ *        - if only the SCIF_SAS_DOMAIN object is specified, then all
+ *          SCIF_SAS_REQUEST objects outstanding in the domain are
+ *          terminated.
+ *
+ * @param[in]  fw_domain This parameter specifies the domain in which to
+ *             terminate requests.
+ * @param[in]  fw_device This parameter specifies the remote device in
+ *             which to terminate requests.  This parameter can be NULL
+ *             as long as the fw_request parameter is NULL.  It is a
+ *             required parameter if the fw_request parameter is not NULL.
+ * @param[in]  fw_request This parameter specifies the request object to
+ *             be terminated.  This parameter can be NULL.
+ * @param[in]  fw_requestor This parameter specifies the task management
+ *             request that is responsible for the termination of requests.
+ *
+ * @return none
+ */
+void scif_sas_domain_terminate_requests(
+   SCIF_SAS_DOMAIN_T        * fw_domain,
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   SCIF_SAS_REQUEST_T       * fw_request,
+   SCIF_SAS_TASK_REQUEST_T  * fw_requestor
+)
+{
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_domain),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_TASK_MANAGEMENT,
+      "scif_sas_domain_terminate_requests(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
+      fw_domain, fw_device, fw_request, fw_requestor
+   ));
+
+   if (fw_request != NULL)
+   {
+      fw_request->terminate_requestor = fw_requestor;
+      fw_request->state_handlers->abort_handler(&fw_request->parent);
+   }
+   else
+   {
+      SCI_FAST_LIST_ELEMENT_T * element = fw_domain->request_list.list_head;
+      SCIF_SAS_REQUEST_T      * request = NULL;
+
+      // Cycle through the fast list of IO requests.  Terminate each
+      // oustanding requests that matches the criteria supplied by the
+      // caller.
+      while (element != NULL)
+      {
+         request = (SCIF_SAS_REQUEST_T*) sci_fast_list_get_object(element);
+         // The current element may be deleted from the list becasue of
+         // IO completion so advance to the next element early
+         element = sci_fast_list_get_next(element);
+
+         // Ensure we pass the supplied criteria before terminating the
+         // request.
+         if (
+               (fw_device == NULL)
+            || (
+                  (request->device == fw_device)
+               && (fw_requestor != (SCIF_SAS_TASK_REQUEST_T*) request)
+               )
+            )
+         {
+            if (
+                  (request->is_waiting_for_abort_task_set == FALSE) ||
+                  (request->terminate_requestor == NULL)
+               )
+            {
+               request->terminate_requestor = fw_requestor;
+               request->state_handlers->abort_handler(&request->parent);
+            }
+         }
+      }
+   }
+}
+
+/**
+ * @brief This method searches the domain object to find a
+ *        SCIF_SAS_REQUEST object associated with the supplied IO tag.
+ *
+ * @param[in]  fw_domain This parameter specifies the domain in which to
+ *             to find the request object.
+ * @param[in]  io_tag This parameter specifies the IO tag value for which
+ *             to locate the corresponding request.
+ *
+ * @return This method returns a pointer to the SCIF_SAS_REQUEST object
+ *         associated with the supplied IO tag.
+ * @retval NULL This value is returned if the IO tag does not resolve to
+ *         a request.
+ */
+SCIF_SAS_REQUEST_T * scif_sas_domain_get_request_by_io_tag(
+   SCIF_SAS_DOMAIN_T * fw_domain,
+   U16                 io_tag
+)
+{
+   SCI_FAST_LIST_ELEMENT_T * element    = fw_domain->request_list.list_head;
+   SCIF_SAS_IO_REQUEST_T   * io_request = NULL;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_domain),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_TASK_MANAGEMENT,
+      "scif_sas_domain_get_request_by_io_tag(0x%x, 0x%x) enter\n",
+      fw_domain, io_tag
+   ));
+
+   while (element != NULL)
+   {
+      io_request = (SCIF_SAS_IO_REQUEST_T*) sci_fast_list_get_object(element);
+
+      // Check to see if we located the request with an identical IO tag.
+      if (scic_io_request_get_io_tag(io_request->parent.core_object) == io_tag)
+         return &io_request->parent;
+
+      element = sci_fast_list_get_next(element);
+   }
+
+   return NULL;
+}
+
+/**
+ * @brief This method performs domain object initialization to be done
+ *        when the scif_controller_initialize() method is invoked.
+ *        This includes operation timeout creation.
+ *
+ * @param[in]  fw_domain This parameter specifies the domain object for
+ *             which to perform initialization.
+ *
+ * @return none
+ */
+void scif_sas_domain_initialize(
+   SCIF_SAS_DOMAIN_T * fw_domain
+)
+{
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_domain),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_INITIALIZATION,
+      "scif_sas_domain_initialize(0x%x) enter\n",
+      fw_domain
+   ));
+
+   // Create the timer for each domain.  It is too early in the process
+   // to allocate this during construction since the user didn't have
+   // a chance to set it's association.
+   if (fw_domain->operation.timer == 0)
+   {
+      fw_domain->operation.timer = scif_cb_timer_create(
+                                      fw_domain->controller,
+                                      scif_sas_domain_operation_timeout_handler,
+                                      fw_domain
+                                   );
+   }
+}
+
+/**
+ * @brief This method performs domain object handling for core remote
+ *        device start complete notifications.  Core remote device starts
+ *        and start completes are only done during discovery.  This could
+ *        ultimately be wrapped into a handler method on the domain (they
+ *        actually already exist).  This method will decrement the number
+ *        of device start operations ongoing and attempt to determine if
+ *        discovery is complete.
+ *
+ * @param[in]  fw_domain This parameter specifies the domain object for
+ *             which to perform initialization.
+ *
+ * @return none
+ */
+void scif_sas_domain_remote_device_start_complete(
+   SCIF_SAS_DOMAIN_T        * fw_domain,
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device
+)
+{
+   SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_domain),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_domain_remote_device_start_complete(0x%x, 0x%x) enter\n",
+      fw_domain, fw_device
+   ));
+
+   // If a device is being started/start completed, then we must be
+   // during discovery.
+   ASSERT(fw_domain->parent.state_machine.current_state_id
+          == SCI_BASE_DOMAIN_STATE_DISCOVERING);
+
+   scic_remote_device_get_protocols(fw_device->core_object, &dev_protocols);
+
+   // Decrement the number of devices being started and check to see
+   // if all have finished being started or failed as the case may be.
+   fw_domain->device_start_in_progress_count--;
+
+   if ( dev_protocols.u.bits.attached_smp_target )
+   {
+      if ( fw_device->containing_device == NULL )
+         //kick off the smp discover process if this expander is direct attached.
+         scif_sas_smp_remote_device_start_discover(fw_device);
+      else
+         //mark this device, the discover process of this device will start after
+         //its containing smp device finish discover.
+         fw_device->protocol_device.smp_device.scheduled_activity =
+            SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_DISCOVER;
+   }
+   else
+   {
+      fw_domain->state_handlers->device_start_complete_handler(
+         &fw_domain->parent, &fw_device->parent
+      );
+   }
+}
+
+
+/**
+ * @brief This methods check each smp device in this domain. If there is at
+ *        least one smp device in discover or target reset activity, this
+ *        domain is considered in smp activity. Note this routine is not
+ *        called on fast IO path.
+ *
+ * @param[in] fw_domain The framework domain object
+ *
+ * @return BOOL value to indicate whether a domain is in SMP activity.
+ */
+BOOL scif_sas_domain_is_in_smp_activity(
+   SCIF_SAS_DOMAIN_T        * fw_domain
+)
+{
+   SCI_ABSTRACT_ELEMENT_T * current_element =
+      sci_abstract_list_get_front(&fw_domain->remote_device_list);
+
+   SCIF_SAS_REMOTE_DEVICE_T * current_device;
+
+   while ( current_element != NULL )
+   {
+      SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;
+
+      current_device = (SCIF_SAS_REMOTE_DEVICE_T *)
+                       sci_abstract_list_get_object(current_element);
+
+      scic_remote_device_get_protocols(current_device->core_object,
+                                       &dev_protocols
+      );
+
+      if (dev_protocols.u.bits.attached_smp_target &&
+          scif_sas_smp_remote_device_is_in_activity(current_device))
+         return TRUE;
+
+      current_element =
+         sci_abstract_list_get_next(current_element);
+   }
+
+   return FALSE;
+}
+
+
+/**
+ * @brief This methods finds a expander attached device by searching the domain's
+ *        device list using connected expander device and expander phy id.
+ *
+ * @param[in] fw_domain The framework domain object
+ * @param[in] parent_device The expander device the target device attaches to.
+ * @param[in] expander_phy_id The expander phy id that the target device owns.
+ *
+ * @return found remote device or a NULL value if no device found.
+ */
+SCIF_SAS_REMOTE_DEVICE_T * scif_sas_domain_get_device_by_containing_device(
+   SCIF_SAS_DOMAIN_T        * fw_domain,
+   SCIF_SAS_REMOTE_DEVICE_T * containing_device,
+   U8                         expander_phy_id
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device;
+   SCI_ABSTRACT_ELEMENT_T * element = sci_abstract_list_get_front(
+                                         &fw_domain->remote_device_list
+                                      );
+
+   //parent device must not be NULL.
+   ASSERT(containing_device != NULL);
+
+   // Search the abstract list to see if there is a remote device meets the
+   // search condition.
+   while (element != NULL)
+   {
+      fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
+                  sci_abstract_list_get_object(element);
+
+      // Check to see if this is the device for which we are searching.
+      if (
+            (fw_device->containing_device == containing_device)
+         && (fw_device->expander_phy_identifier == expander_phy_id)
+         )
+      {
+         return fw_device;
+      }
+
+      element = sci_abstract_list_get_next(element);
+   }
+
+   return SCI_INVALID_HANDLE;
+}
+
+
+/**
+ * @brief This methods finds the first device that is in STOPPED state and its
+ *        connection_rate is still in SPINUP_HOLD(value 3).
+ *
+ * @param[in] fw_domain The framework domain object
+ *
+ * @return SCIF_SAS_REMOTE_DEVICE_T The device that is in SPINUP_HOLD or NULL.
+ */
+SCIF_SAS_REMOTE_DEVICE_T * scif_sas_domain_find_device_in_spinup_hold(
+   SCIF_SAS_DOMAIN_T        * fw_domain
+)
+{
+   SCI_ABSTRACT_ELEMENT_T   * current_element;
+   SCIF_SAS_REMOTE_DEVICE_T * current_device;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_domain),
+      SCIF_LOG_OBJECT_DOMAIN,
+      "scif_sas_domain_find_device_in_spinup_hold(0x%x) enter\n",
+      fw_domain
+   ));
+
+   //search throught domain's device list to find the first sata device on spinup_hold
+   current_element = sci_abstract_list_get_front(&fw_domain->remote_device_list);
+   while (current_element != NULL )
+   {
+      current_device = (SCIF_SAS_REMOTE_DEVICE_T *)
+                       sci_abstract_list_get_object(current_element);
+
+      //We must get the next element before we remove the current
+      //device. Or else, we will get wrong next_element, since the erased
+      //element has been put into free pool.
+      current_element = sci_abstract_list_get_next(current_element);
+
+      if ( sci_base_state_machine_get_state(&current_device->parent.state_machine) ==
+              SCI_BASE_REMOTE_DEVICE_STATE_STOPPED
+          && scic_remote_device_get_connection_rate(current_device->core_object) ==
+                SCI_SATA_SPINUP_HOLD )
+      {
+         return current_device;
+      }
+   }
+
+   return NULL;
+}
+
+
+/**
+ * @brief This methods finds the first device that has specific activity scheduled.
+ *
+ * @param[in] fw_domain The framework domain object
+ * @param[in] smp_activity A specified smp activity. The valid range is [1,5].
+ *
+ * @return SCIF_SAS_REMOTE_DEVICE_T The device that has specified smp activity scheduled.
+ */
+SCIF_SAS_REMOTE_DEVICE_T * scif_sas_domain_find_device_has_scheduled_activity(
+   SCIF_SAS_DOMAIN_T        * fw_domain,
+   U8                         smp_activity
+)
+{
+   SCI_ABSTRACT_ELEMENT_T * current_element =
+      sci_abstract_list_get_front(&fw_domain->remote_device_list);
+
+   SCIF_SAS_REMOTE_DEVICE_T * current_device;
+   SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;
+
+   //config route table activity has higher priority than discover activity.
+   while ( current_element != NULL )
+   {
+      current_device = (SCIF_SAS_REMOTE_DEVICE_T *)
+                       sci_abstract_list_get_object(current_element);
+
+      scic_remote_device_get_protocols(current_device->core_object,
+                                       &dev_protocols);
+
+      current_element =
+         sci_abstract_list_get_next(current_element);
+
+      if ( dev_protocols.u.bits.attached_smp_target
+          && current_device->protocol_device.smp_device.scheduled_activity ==
+                smp_activity)
+      {
+         return current_device;
+      }
+   }
+
+   return NULL;
+}
+
+
+/**
+ * @brief This methods finds the smp device that has is_config_route_table_scheduled
+ *        flag set to TRUE, and start config route table on it. If there is no
+ *        smp device scheduled to config route table, find the smp device has
+ *        is_discover_scheduled and start the smp discover process on them.
+ *
+ * @param[in] fw_domain The framework domain that to start smp discover process.
+ *
+ * @return NONE
+ */
+void scif_sas_domain_start_smp_activity(
+  SCIF_SAS_DOMAIN_T        * fw_domain
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * device_has_scheduled_activity = NULL;
+
+   //first, find device that has config route table activity scheduled.
+   //config route table activity has higher priority than Discover.
+   device_has_scheduled_activity =
+      scif_sas_domain_find_device_has_scheduled_activity(
+         fw_domain,
+         SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_CONFIG_ROUTE_TABLE
+      );
+
+   if (device_has_scheduled_activity != NULL)
+   {
+      scif_sas_smp_remote_device_configure_route_table(device_has_scheduled_activity);
+      device_has_scheduled_activity->protocol_device.smp_device.scheduled_activity =
+         SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_NONE;
+      return;
+   }
+
+   //if no device has config route table activity scheduled, search again, find
+   //device has discover activity scheduled.
+   device_has_scheduled_activity =
+      scif_sas_domain_find_device_has_scheduled_activity(
+         fw_domain,
+         SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_DISCOVER
+      );
+
+   if (device_has_scheduled_activity != NULL)
+      scif_sas_smp_remote_device_start_discover(device_has_scheduled_activity);
+}
+
+
+/**
+ * @brief This method starts domain's smp discover process from the top level expander.
+ *
+ * @param[in] fw_domain The framework domain that to start smp discover process.
+ @ @param[in] top_expander The top level expander device to start smp discover process.
+ *
+ * @return None
+ */
+void scif_sas_domain_start_smp_discover(
+   SCIF_SAS_DOMAIN_T        * fw_domain,
+   SCIF_SAS_REMOTE_DEVICE_T * top_expander
+)
+{
+   SCI_ABSTRACT_ELEMENT_T * current_element =
+       sci_abstract_list_get_front(&fw_domain->remote_device_list);
+
+   SCIF_SAS_REMOTE_DEVICE_T * current_device;
+
+   // something changed behind expander
+   // mark all the device behind expander to be NOT
+   // is_currently_discovered.
+   while ( current_element != NULL )
+   {
+      current_device = (SCIF_SAS_REMOTE_DEVICE_T *)
+                           sci_abstract_list_get_object(current_element);
+
+      current_device->is_currently_discovered = FALSE;
+
+      //reset all the devices' port witdh except the top expander.
+      if (current_device->containing_device != NULL)
+         current_device->device_port_width = 1;
+
+      current_element = sci_abstract_list_get_next(current_element);
+   }
+
+   //expander device itself should be set to is_currently_discovered.
+   top_expander->is_currently_discovered = TRUE;
+
+   //kick off the smp discover process.
+   scif_sas_smp_remote_device_start_discover(top_expander);
+}
+
+
+/**
+ * @brief This method continues domain's smp discover process and
+ *        may transit to READY state if all smp activities are done.
+ *
+ * @param[in] fw_domain The framework domain that to start smp discover process.
+ *
+ * @return None
+ */
+void scif_sas_domain_continue_discover(
+   SCIF_SAS_DOMAIN_T * fw_domain
+)
+{
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_domain),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_domain_continue_discover(0x%x) enter\n",
+      fw_domain
+   ));
+
+   if ( fw_domain->device_start_in_progress_count == 0
+       && !scif_sas_domain_is_in_smp_activity(fw_domain) )
+   {
+      //domain scrub the remote device list to see if there is a need
+      //to start smp discover on expander device. There may be no
+      //need to start any smp discover.
+      scif_sas_domain_start_smp_activity(fw_domain);
+
+      //In domain discovery timeout case, we cancel all
+      //the smp activities, and terminate all the smp requests, then
+      //this routine is called. But the smp request may not done
+      //terminated. We want to guard the domain trasitting to READY
+      //by checking outstanding smp request count. If there is outstanding
+      //smp request, the domain will not transit to READY. Later when
+      //the smp request is terminated at smp remote device, this routine
+      //will be called then the domain will transit to READY state.
+      if ( ! scif_sas_domain_is_in_smp_activity(fw_domain)
+          && scif_sas_domain_get_smp_request_count(fw_domain) == 0)
+      {
+         //before domain transit to READY state, domain has some clean up
+         //work to do, such like update domain's remote devcie list.
+         scif_sas_domain_finish_discover(fw_domain);
+      }
+   }
+}
+
+
+/**
+ * @brief This method finishes domain's smp discover process and
+ *        update domain's remote device list.
+ *
+ * @param[in] fw_domain The framework domain that's to finish smp discover process.
+ *
+ * @return None
+ */
+void scif_sas_domain_finish_discover(
+   SCIF_SAS_DOMAIN_T * fw_domain
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * current_device = NULL;
+   SCI_ABSTRACT_ELEMENT_T   * current_element = NULL;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_domain),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_domain_finish_discover(0x%x) enter\n",
+      fw_domain
+   ));
+
+   //need to scrub all the devices behind the expander. Check each
+   //device's discover_status. if the is_currently_discovered is FALSE, means
+   //the device is not been rediscovered. this device needs to be removed.
+   current_element = sci_abstract_list_get_front(&fw_domain->remote_device_list);
+   while (current_element != NULL )
+   {
+      current_device = (SCIF_SAS_REMOTE_DEVICE_T *)
+                          sci_abstract_list_get_object(current_element);
+
+      //We must get the next element before we remove the current
+      //device. Or else, we will get wrong next_element, since the erased
+      //element has been put into free pool.
+      current_element = sci_abstract_list_get_next(current_element);
+
+      if ( current_device->is_currently_discovered == FALSE )
+      {
+         // Notify the framework user of the device removal.
+         scif_cb_domain_device_removed(
+            fw_domain->controller, fw_domain, current_device
+         );
+      }
+   }
+
+   sci_base_state_machine_change_state(
+      &fw_domain->parent.state_machine, SCI_BASE_DOMAIN_STATE_READY
+   );
+}
+
+
+
+/**
+ * @brief This method remove an expander device and its child devices, in order to
+ *        deal with a detected illeagal phy connection.
+ *
+ * @param[in] fw_domain The domain that a expander belongs to.
+ * @param[in] fw_device The expander device to be removed.
+ *
+ * @return none.
+ */
+void scif_sas_domain_remove_expander_device(
+   SCIF_SAS_DOMAIN_T        * fw_domain,
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device
+)
+{
+   SCIF_SAS_SMP_REMOTE_DEVICE_T * smp_remote_device =
+      &fw_device->protocol_device.smp_device;
+
+   SCI_FAST_LIST_ELEMENT_T     * element = smp_remote_device->smp_phy_list.list_head;
+   SCIF_SAS_SMP_PHY_T          * curr_smp_phy = NULL;
+   SCIF_SAS_REMOTE_DEVICE_T    * current_device = NULL;
+
+   while (element != NULL)
+   {
+      curr_smp_phy = (SCIF_SAS_SMP_PHY_T*) sci_fast_list_get_object(element);
+      element = sci_fast_list_get_next(element);
+
+      if ( curr_smp_phy->attached_device_type != SMP_NO_DEVICE_ATTACHED
+          && curr_smp_phy->u.end_device != NULL )
+      {
+         if (curr_smp_phy->attached_device_type == SMP_END_DEVICE_ONLY)
+            current_device = curr_smp_phy->u.end_device;
+         else
+            current_device = curr_smp_phy->u.attached_phy->owning_device;
+
+         scif_cb_domain_device_removed(fw_domain->controller, fw_domain, current_device);
+      }
+   }
+
+   //remove device itself
+   scif_cb_domain_device_removed(fw_domain->controller, fw_domain, fw_device);
+}
+
+
+/**
+ * @brief This method searches the whole domain and finds all the smp devices to
+ *        cancel their smp activities if there is any.
+ *
+ * @param[in] fw_domain The domain that its smp activities are to be canceled.
+ *
+ * @return none.
+ */
+void scif_sas_domain_cancel_smp_activities(
+   SCIF_SAS_DOMAIN_T * fw_domain
+)
+{
+   SCI_ABSTRACT_ELEMENT_T * current_element =
+      sci_abstract_list_get_front(&fw_domain->remote_device_list);
+
+   SCIF_SAS_REMOTE_DEVICE_T * current_device;
+
+   //purge all the outstanding internal IOs in HPQ.
+   scif_sas_high_priority_request_queue_purge_domain(
+      &fw_domain->controller->hprq, fw_domain
+   );
+
+   while ( current_element != NULL )
+   {
+      SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;
+
+      current_device = (SCIF_SAS_REMOTE_DEVICE_T *)
+                       sci_abstract_list_get_object(current_element);
+
+      scic_remote_device_get_protocols(current_device->core_object,
+                                       &dev_protocols
+      );
+
+      if (dev_protocols.u.bits.attached_smp_target)
+      {
+         scif_sas_smp_remote_device_cancel_smp_activity(current_device);
+      }
+
+      current_element =
+         sci_abstract_list_get_next(current_element);
+   }
+}
+
+
+/**
+ * @brief This method searches the domain's request list and counts outstanding
+ *           smp IOs.
+ *
+ * @param[in] fw_domain The domain that its request list is to be searched.
+ *
+ * @return U8 The possible return value of this routine is 0 or 1.
+ */
+U8 scif_sas_domain_get_smp_request_count(
+   SCIF_SAS_DOMAIN_T * fw_domain
+)
+{
+   SCI_FAST_LIST_ELEMENT_T * element = fw_domain->request_list.list_head;
+   SCIF_SAS_REQUEST_T      * request = NULL;
+   U8                        count = 0;
+   SCIC_TRANSPORT_PROTOCOL   protocol;
+
+   // Cycle through the fast list of IO requests.  Terminate each
+   // oustanding requests that matches the criteria supplied by the
+   // caller.
+   while (element != NULL)
+   {
+      request = (SCIF_SAS_REQUEST_T*) sci_fast_list_get_object(element);
+      // The current element may be deleted from the list becasue of
+      // IO completion so advance to the next element early
+      element = sci_fast_list_get_next(element);
+
+      protocol = scic_io_request_get_protocol(request->core_object);
+
+      if ( protocol == SCIC_SMP_PROTOCOL)
+         count++;
+   }
+
+   return count;
+}
+
+
+/**
+ * @brief This method start clear affiliation activities for smp devices in
+ *           this domain.
+ *
+ * @param[in] fw_domain The domain that its smp devices are scheduled to clear
+ *                affiliation for all the EA SATA devices.
+ *
+ * @return none.
+ */
+void scif_sas_domain_start_clear_affiliation(
+   SCIF_SAS_DOMAIN_T * fw_domain
+)
+{
+   scif_sas_domain_schedule_clear_affiliation(fw_domain);
+   scif_sas_domain_continue_clear_affiliation(fw_domain);
+}
+
+
+/**
+ * @brief This method schedule clear affiliation activities for smp devices in
+ *           this domain.
+ *
+ * @param[in] fw_domain The domain that its smp devices are scheduled to clear
+ *                affiliation for all the EA SATA devices.
+ *
+ * @return none.
+ */
+void scif_sas_domain_schedule_clear_affiliation(
+   SCIF_SAS_DOMAIN_T * fw_domain
+)
+{
+   SCI_ABSTRACT_ELEMENT_T * current_element =
+      sci_abstract_list_get_front(&fw_domain->remote_device_list);
+
+   SCIF_SAS_REMOTE_DEVICE_T * current_device;
+   SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;
+
+   //config route table activity has higher priority than discover activity.
+   while ( current_element != NULL )
+   {
+      current_device = (SCIF_SAS_REMOTE_DEVICE_T *)
+                       sci_abstract_list_get_object(current_element);
+
+      scic_remote_device_get_protocols(current_device->core_object,
+                                       &dev_protocols);
+
+      current_element =
+         sci_abstract_list_get_next(current_element);
+
+      if ( dev_protocols.u.bits.attached_smp_target )
+      {
+         current_device->protocol_device.smp_device.scheduled_activity =
+            SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_CLEAR_AFFILIATION;
+      }
+   }
+}
+
+
+/**
+ * @brief This method carries clear affiliation activities for a smp devices in
+ *           this domain during controller stop process.
+ *
+ * @param[in] fw_domain The domain that its smp devices are to clear
+ *                affiliation for all the EA SATA devices.
+ *
+ * @return none.
+ */
+void scif_sas_domain_continue_clear_affiliation(
+   SCIF_SAS_DOMAIN_T * fw_domain
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * smp_device =
+      scif_sas_domain_find_device_has_scheduled_activity(
+         fw_domain,
+         SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_CLEAR_AFFILIATION
+      );
+
+   if (smp_device != NULL)
+      scif_sas_smp_remote_device_start_clear_affiliation(smp_device);
+   else
+   {
+      //This domain has done clear affiliation.
+      SCIF_SAS_CONTROLLER_T * fw_controller = fw_domain->controller;
+      fw_controller->current_domain_to_clear_affiliation++;
+
+      //let controller continue to clear affiliation on other domains.
+      scif_sas_controller_clear_affiliation(fw_domain->controller);
+   }
+}
+
+
+/**
+ * @brief This method releases resource for a framework domain.
+ *
+ * @param[in] fw_controller This parameter specifies the framework
+ *            controller, its associated domain's resources are to be released.
+ * @param[in] fw_domain This parameter specifies the framework
+ *            domain whose resources are to be released.
+ */
+void scif_sas_domain_release_resource(
+   SCIF_SAS_CONTROLLER_T * fw_controller,
+   SCIF_SAS_DOMAIN_T     * fw_domain
+)
+{
+   if (fw_domain->operation.timer != NULL)
+   {
+      scif_cb_timer_destroy(fw_controller, fw_domain->operation.timer);
+      fw_domain->operation.timer = NULL;
+   }
+}
+
+
+/**
+ * @brief This method finds the a EA device that has target reset scheduled.
+ *
+ * @param[in] fw_domain The framework domain object
+ *
+ * @return SCIF_SAS_REMOTE_DEVICE_T The EA device that has target reset scheduled.
+ */
+SCIF_SAS_REMOTE_DEVICE_T * scif_sas_domain_find_next_ea_target_reset(
+   SCIF_SAS_DOMAIN_T     * fw_domain
+)
+{
+   SCI_ABSTRACT_ELEMENT_T   * current_element;
+   SCIF_SAS_REMOTE_DEVICE_T * current_device;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_domain),
+      SCIF_LOG_OBJECT_DOMAIN,
+      "scif_sas_domain_find_next_ea_target_reset(0x%x) enter\n",
+      fw_domain
+   ));
+
+   //search throught domain's device list to find the first sata device on spinup_hold
+   current_element = sci_abstract_list_get_front(&fw_domain->remote_device_list);
+   while (current_element != NULL )
+   {
+      current_device = (SCIF_SAS_REMOTE_DEVICE_T *)
+                       sci_abstract_list_get_object(current_element);
+
+      current_element = sci_abstract_list_get_next(current_element);
+
+      if ( current_device->ea_target_reset_request_scheduled != NULL )
+      {
+         return current_device;
+      }
+   }
+
+   return NULL;
+}
+
+#if !defined(DISABLE_WIDE_PORTED_TARGETS)
+/**
+ * @brief This method update the direct attached device port width.
+ *
+ * @param[in] fw_domain The framework domain object
+ * @param[in] port The associated port object which recently has link up/down
+ *                 event happened.
+ *
+ * @return none
+ */
+void scif_sas_domain_update_device_port_width(
+   SCIF_SAS_DOMAIN_T * fw_domain,
+   SCI_PORT_HANDLE_T   port
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device;
+   SCIC_PORT_PROPERTIES_T     properties;
+   U8                         new_port_width = 0;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_domain),
+      SCIF_LOG_OBJECT_DOMAIN,
+      "scif_sas_domain_update_device_port_width(0x%x, 0x%x) enter\n",
+      fw_domain, port
+   ));
+
+   scic_port_get_properties(port, &properties);
+
+   fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)
+                  scif_domain_get_device_by_sas_address(
+                  fw_domain, &properties.remote.sas_address
+               );
+
+   // If the device already existed in the domain, it is a wide port SSP target,
+   // we need to update its port width.
+   if (fw_device != SCI_INVALID_HANDLE)
+   {
+      SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;
+      scic_remote_device_get_protocols(fw_device->core_object, &dev_protocols);
+
+      if (dev_protocols.u.bits.attached_ssp_target)
+      {
+         //Get accurate port width from port's phy mask for a DA device.
+         SCI_GET_BITS_SET_COUNT(properties.phy_mask, new_port_width);
+
+         scif_sas_remote_device_update_port_width(fw_device, new_port_width);
+      }
+   }
+}
+#endif //#if !defined(DISABLE_WIDE_PORTED_TARGETS)
+
+
+#ifdef SCI_LOGGING
+/**
+ * This method will turn on logging of domain state changes.
+ *
+ * @param[in] fw_domain The domain for which the state logging is to be turned
+ *       on.
+ */
+void scif_sas_domain_initialize_state_logging(
+   SCIF_SAS_DOMAIN_T *fw_domain
+)
+{
+   sci_base_state_machine_logger_initialize(
+      &fw_domain->parent.state_machine_logger,
+      &fw_domain->parent.state_machine,
+      &fw_domain->parent.parent,
+      scif_cb_logger_log_states,
+      "SCIF_SAS_DOMAIN_T", "base state machine",
+      SCIF_LOG_OBJECT_DOMAIN
+   );
+}
+
+/**
+ * This method will turn off logging of domain state changes.
+ *
+ * @param[in] fw_domain The domain for which the state logging is to be turned
+ *       off.
+ */
+void scif_sas_domain_deinitialize_state_logging(
+   SCIF_SAS_DOMAIN_T *fw_domain
+)
+{
+   sci_base_state_machine_logger_deinitialize(
+      &fw_domain->parent.state_machine_logger,
+      &fw_domain->parent.state_machine
+   );
+}
+#endif
diff --git a/sys/dev/disk/isci/scil/scif_sas_domain.h b/sys/dev/disk/isci/scil/scif_sas_domain.h
new file mode 100644
index 0000000..efe5157
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_domain.h
@@ -0,0 +1,327 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_domain.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIF_SAS_DOMAIN_H_
+#define _SCIF_SAS_DOMAIN_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains the protected interface structures, constants,
+ *        and methods for the SCIF_SAS_DOMAIN object.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_abstract_list.h>
+#include <dev/disk/isci/scil/sci_fast_list.h>
+#include <dev/disk/isci/scil/scif_domain.h>
+
+#include <dev/disk/isci/scil/sci_base_domain.h>
+#include <dev/disk/isci/scil/scif_sas_request.h>
+#include <dev/disk/isci/scil/scif_sas_task_request.h>
+#include <dev/disk/isci/scil/scif_sas_remote_device.h>
+
+
+extern SCI_BASE_DOMAIN_STATE_HANDLER_T scif_sas_domain_state_handler_table[];
+extern SCI_BASE_STATE_T scif_sas_domain_state_table[];
+
+#define PORT_HARD_RESET_TIMEOUT 1000 //1000 miliseconds
+
+#define SCIF_DOMAIN_DISCOVER_TIMEOUT 20000 // miliseconds
+
+/**
+ * @struct SCIF_SAS_DOMAIN
+ *
+ * @brief The SCI SAS Framework domain object abstracts the SAS domain
+ *        level behavior for the framework component.  Additionally,
+ *        it provides a higher level of abstraction for the core port
+ *        object.  There is a 1:1 correspondance between core ports and
+ *        framework domain objects.  Essentially, each core port provides
+ *        the access to the remote devices in the domain.
+ */
+typedef struct SCIF_SAS_DOMAIN
+{
+   /**
+    * The SCI_BASE_DOMAIN is the parent object for the SCIF_SAS_DOMAIN
+    * object.
+    */
+   SCI_BASE_DOMAIN_T  parent;
+
+   /**
+    * This field contains the handle for the SCI Core port object that
+    * is managed by this framework domain object.
+    */
+   SCI_PORT_HANDLE_T  core_object;
+
+   /**
+    * This field specifies the controller containing this domain object.
+    */
+   struct SCIF_SAS_CONTROLLER * controller;
+
+   /**
+    * This field references the list of state specific handler methods to
+    * be utilized for this domain instance.
+    */
+   SCI_BASE_DOMAIN_STATE_HANDLER_T * state_handlers;
+
+   /**
+    * This field contains references to all of the devices contained in
+    * this domain.
+    */
+   SCI_ABSTRACT_LIST_T  remote_device_list;
+
+   /**
+    * This field contains the list of all outstanding request (IO or
+    * management) in this domain.
+    */
+   SCI_FAST_LIST_T  request_list;
+
+   /**
+    * This field indicates whether the core port object is in a ready state
+    * or not.
+    */
+   BOOL  is_port_ready;
+
+   /**
+    * This field indicates the number of remote devices that have been
+    * started in this domain.
+    */
+   U32  device_start_count;
+
+   /**
+    * This field indicates the number of remote devices that are currently
+    * in the process of becoming ready.  This field is utilized to gate
+    * the transition back to the READY state for the domain.
+    */
+   U32  device_start_in_progress_count;
+
+   /**
+    * This field records how many broadcast change primitve are
+    * received and not processed yet.
+    */
+   U32  broadcast_change_count;
+
+   /**
+    * This fields indicates whether the expanders in this domain need to
+    * have there config route table configured by our driver. For expample,
+    * if we found the top level expander is a self-configuring expander and
+    * it is able to config others, all the expanders in this domain don't
+    * need to configure route table.
+    */
+   BOOL is_config_route_table_needed;
+
+   struct
+   {
+      /**
+       * This field provides the domain object a scratch area to indicate
+       * status of an ongoing operation.
+       */
+      SCI_STATUS  status;
+
+      /**
+       * This is the timer handle that is utilized to time the discovery
+       * or domain reset operations.
+       */
+      void * timer;
+
+      /**
+       * This field specifies the timeout value, in milliseconds, for the
+       * entire operation (discovery or reset).
+       */
+      U32 timeout;
+
+      /**
+       * This field specifies the timeout value, in milliseconds, for a
+       * single device.
+       */
+      U32 device_timeout;
+
+   } operation;
+
+} SCIF_SAS_DOMAIN_T;
+
+void scif_sas_domain_construct(
+   SCIF_SAS_DOMAIN_T          * fw_domain,
+   U8                           domain_id,
+   struct SCIF_SAS_CONTROLLER * fw_controller
+);
+
+void scif_sas_domain_terminate_requests(
+   SCIF_SAS_DOMAIN_T        * fw_domain,
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   SCIF_SAS_REQUEST_T       * fw_request,
+   SCIF_SAS_TASK_REQUEST_T  * fw_requestor
+);
+
+SCIF_SAS_REQUEST_T * scif_sas_domain_get_request_by_io_tag(
+   SCIF_SAS_DOMAIN_T * fw_domain,
+   U16                 io_tag
+);
+
+void scif_sas_domain_transition_to_stopped_state(
+   SCIF_SAS_DOMAIN_T * fw_domain
+);
+
+void scif_sas_domain_initialize(
+   SCIF_SAS_DOMAIN_T * fw_domain
+);
+
+void scif_sas_domain_remote_device_start_complete(
+   SCIF_SAS_DOMAIN_T        * fw_domain,
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device
+);
+
+BOOL scif_sas_domain_is_in_smp_activity(
+   SCIF_SAS_DOMAIN_T        * fw_domain
+);
+
+SCIF_SAS_REMOTE_DEVICE_T * scif_sas_domain_get_device_by_containing_device(
+   SCIF_SAS_DOMAIN_T        * fw_domain,
+   SCIF_SAS_REMOTE_DEVICE_T * containing_device,
+   U8                         expander_phy_id
+);
+
+SCIF_SAS_REMOTE_DEVICE_T * scif_sas_domain_find_device_in_spinup_hold(
+   SCIF_SAS_DOMAIN_T        * fw_domain
+);
+
+SCIF_SAS_REMOTE_DEVICE_T * scif_sas_domain_find_device_has_scheduled_activity(
+   SCIF_SAS_DOMAIN_T        * fw_domain,
+   U8                         smp_activity
+);
+
+void scif_sas_domain_start_smp_activity(
+  SCIF_SAS_DOMAIN_T        * fw_domain
+);
+
+void scif_sas_domain_remove_expander_device(
+   SCIF_SAS_DOMAIN_T        * fw_domain,
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device
+);
+
+void scif_sas_domain_start_smp_discover(
+   SCIF_SAS_DOMAIN_T        * fw_domain,
+   SCIF_SAS_REMOTE_DEVICE_T * top_expander
+);
+
+void scif_sas_domain_continue_discover(
+   SCIF_SAS_DOMAIN_T * fw_domain
+);
+
+void scif_sas_domain_finish_discover(
+   SCIF_SAS_DOMAIN_T * fw_domain
+);
+
+void scif_sas_domain_transition_to_discovering_state(
+   SCIF_SAS_DOMAIN_T * fw_domain
+);
+
+void scif_sas_domain_cancel_smp_activities(
+   SCIF_SAS_DOMAIN_T * fw_domain
+);
+
+U8 scif_sas_domain_get_smp_request_count(
+   SCIF_SAS_DOMAIN_T * fw_domain
+);
+
+void scif_sas_domain_schedule_clear_affiliation(
+   SCIF_SAS_DOMAIN_T * fw_domain
+);
+
+void scif_sas_domain_start_clear_affiliation(
+   SCIF_SAS_DOMAIN_T * fw_domain
+);
+
+void scif_sas_domain_continue_clear_affiliation(
+   SCIF_SAS_DOMAIN_T * fw_domain
+);
+
+void scif_sas_domain_release_resource(
+   struct SCIF_SAS_CONTROLLER * fw_controller,
+   SCIF_SAS_DOMAIN_T     * fw_domain
+);
+
+SCIF_SAS_REMOTE_DEVICE_T * scif_sas_domain_find_next_ea_target_reset(
+   SCIF_SAS_DOMAIN_T * fw_domain
+);
+
+#if !defined(DISABLE_WIDE_PORTED_TARGETS)
+void scif_sas_domain_update_device_port_width(
+   SCIF_SAS_DOMAIN_T     * fw_domain,
+   SCI_PORT_HANDLE_T      port
+);
+#else  //!defined(DISABLE_WIDE_PORTED_TARGETS)
+#define scif_sas_domain_update_device_port_width(domain, port)
+#endif //!defined(DISABLE_WIDE_PORTED_TARGETS)
+
+#ifdef SCI_LOGGING
+void scif_sas_domain_initialize_state_logging(
+   SCIF_SAS_DOMAIN_T *fw_domain
+);
+
+void scif_sas_domain_deinitialize_state_logging(
+   SCIF_SAS_DOMAIN_T *fw_domain
+);
+#else // SCI_LOGGING
+#define scif_sas_domain_initialize_state_logging(x)
+#define scif_sas_domain_deinitialize_state_logging(x)
+#endif // SCI_LOGGING
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIF_SAS_DOMAIN_H_
diff --git a/sys/dev/disk/isci/scil/scif_sas_domain_state_handlers.c b/sys/dev/disk/isci/scil/scif_sas_domain_state_handlers.c
new file mode 100644
index 0000000..a11e44f
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_domain_state_handlers.c
@@ -0,0 +1,1628 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_domain_state_handlers.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the state handler routines for each
+ *        of the domain states defined by the SCI_BASE_DOMAIN state
+ *        machine.
+ * @note
+ *        - The discover method must be synchronized with the
+ *          controller's completion handler.  The OS specific driver
+ *          component is responsible for ensuring this occurs.  If the
+ *          discovery method is called from within the call
+ *          tree of the completion routine, then no action is necessary.
+ */
+
+
+#include <dev/disk/isci/scil/scic_port.h>
+#include <dev/disk/isci/scil/scic_io_request.h>
+#include <dev/disk/isci/scil/scif_sas_logger.h>
+#include <dev/disk/isci/scil/scif_sas_domain.h>
+
+//******************************************************************************
+//* P R O T E C T E D   M E T H O D S
+//******************************************************************************
+
+//******************************************************************************
+//* S T A R T I N G   H A N D L E R S
+//******************************************************************************
+
+static
+SCI_STATUS scif_sas_domain_starting_port_ready_handler(
+   SCI_BASE_DOMAIN_T * domain
+)
+{
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(domain),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_domain_starting_port_ready_handler(0x%x) enter\n",
+      domain
+   ));
+
+   // The domain was previously completely stopped.  Now that the port is
+   // ready we can transition the domain to the ready state.
+   sci_base_state_machine_change_state(
+      &domain->state_machine, SCI_BASE_DOMAIN_STATE_READY
+   );
+
+   return SCI_SUCCESS;
+}
+
+//******************************************************************************
+//* R E A D Y   H A N D L E R S
+//******************************************************************************
+
+/**
+ * @brief This method provides READY state specific handling for
+ *        when a user attempts to discover a domain.
+ *
+ * @param[in]  domain This parameter specifies the domain object
+ *             on which the user is attempting to perform a discover
+ *             operation.
+ *
+ * @return This method returns an indication of whether the discover operation
+ *         succeeded.
+ * @retval SCI_SUCCESSS This value is returned when the discover operation
+ *         begins successfully.
+ */
+static
+SCI_STATUS scif_sas_domain_ready_discover_handler(
+   SCI_BASE_DOMAIN_T * domain,
+   U32                 op_timeout,
+   U32                 device_timeout
+)
+{
+   SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T *)domain;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(domain),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_domain_ready_discover_handler(0x%x, 0x%x, 0x%x) enter\n",
+      domain, op_timeout, device_timeout
+   ));
+
+   fw_domain->operation.timeout        = op_timeout;
+   fw_domain->operation.device_timeout = device_timeout;
+   fw_domain->operation.status         = SCI_SUCCESS;
+
+   scif_cb_timer_start(
+      fw_domain->controller,
+      fw_domain->operation.timer,
+      fw_domain->operation.timeout
+   );
+
+   scif_sas_domain_transition_to_discovering_state(fw_domain);
+
+   return fw_domain->operation.status;
+}
+
+/**
+ * @brief This method provides READY state processing for reception of a
+ *        port NOT ready notification from the core.
+ *
+ * @param[in]  domain This parameter specifies the domain object
+ *             on which the core port has just come ready.
+ *
+ * @return
+ */
+static
+SCI_STATUS scif_sas_domain_ready_port_not_ready_handler(
+   SCI_BASE_DOMAIN_T * domain,
+   U32                 reason_code
+)
+{
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(domain),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_domain_ready_port_not_ready_handler(0x%x, 0x%x) enter\n",
+      domain,
+      reason_code
+   ));
+
+   if (reason_code != SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED)
+   {
+      // Change to the STOPPING state to cause existing request
+      // completions to be terminated and devices removed.
+      sci_base_state_machine_change_state(
+         &domain->state_machine, SCI_BASE_DOMAIN_STATE_STOPPING
+      );
+   }
+
+   return SCI_SUCCESS;
+}
+
+/**
+ * @brief This method provides READY state specific handling for
+ *        when a user attempts to start an IO request.
+ *
+ * @param[in]  domain This parameter specifies the domain object
+ *             on which the user is attempting to perform a start IO
+ *             operation.
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object on which the user is attempting to perform a start IO
+ *             operation.
+ * @param[in]  io_request This parameter specifies the io request that is
+ *             being started.
+ *
+ * @return This method returns an indication of whether the start IO
+ *         operation succeeded.
+ * @retval SCI_SUCCESS This value is returned when the start IO operation
+ *         begins successfully.
+ */
+static
+SCI_STATUS scif_sas_domain_ready_start_io_handler(
+   SCI_BASE_DOMAIN_T        * domain,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request
+)
+{
+   SCIF_SAS_DOMAIN_T        * fw_domain  = (SCIF_SAS_DOMAIN_T*) domain;
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device  = (SCIF_SAS_REMOTE_DEVICE_T*)
+                                           remote_device;
+   SCIF_SAS_REQUEST_T       * fw_request = (SCIF_SAS_REQUEST_T*) io_request;
+   SCI_STATUS                 status;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(domain),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_IO_REQUEST,
+      "scif_sas_domain_ready_start_io_handler(0x%x, 0x%x, 0x%x) enter\n",
+      domain, remote_device, io_request
+   ));
+
+   status = fw_device->state_handlers->parent.start_io_handler(
+               &fw_device->parent, &fw_request->parent
+            );
+
+   if (status == SCI_SUCCESS)
+   {
+      // Add the IO to the list of outstanding requests on the domain.
+      sci_fast_list_insert_tail(
+         &fw_domain->request_list, &fw_request->list_element
+      );
+   }
+
+   return status;
+}
+
+/**
+ * @brief This method provides READY state specific handling for
+ *        when a user attempts to complete an IO request.
+ *
+ * @param[in]  domain This parameter specifies the domain object
+ *             on which the user is attempting to perform a complete IO
+ *             operation.
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object on which the user is attempting to perform a complete
+ *             IO operation.
+ * @param[in]  io_request This parameter specifies the io request that is
+ *             being completed.
+ *
+ * @return This method returns an indication of whether the complete IO
+ *         operation succeeded.
+ * @retval SCI_SUCCESS This value is returned when the complete IO operation
+ *         is successful.
+ */
+static
+SCI_STATUS scif_sas_domain_ready_complete_io_handler(
+   SCI_BASE_DOMAIN_T        * domain,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
+                                          remote_device;
+   SCIF_SAS_REQUEST_T       * fw_request= (SCIF_SAS_REQUEST_T*) io_request;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(domain),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_IO_REQUEST,
+      "scif_sas_domain_ready_complete_io_handler(0x%x, 0x%x, 0x%x) enter\n",
+      domain, remote_device, io_request
+   ));
+
+   // Remove the IO from the list of outstanding requests on the domain.
+   sci_fast_list_remove_element(&fw_request->list_element);
+
+   return fw_device->state_handlers->parent.complete_io_handler(
+             &fw_device->parent, &fw_request->parent
+          );
+}
+
+/**
+ * @brief This method provides READY state specific handling for
+ *        when a user attempts to continue an IO request.
+ *
+ * @param[in]  domain This parameter specifies the domain object
+ *             on which the user is attempting to perform a continue IO
+ *             operation.
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object on which the user is attempting to perform a start IO
+ *             operation.
+ * @param[in]  io_request This parameter specifies the io request that is
+ *             being started.
+ *
+ * @return This method returns an indication of whether the continue IO
+ *         operation succeeded.
+ * @retval SCI_SUCCESS This value is returned when the continue IO operation
+ *         begins successfully.
+ */
+static
+SCI_STATUS scif_sas_domain_ready_continue_io_handler(
+   SCI_BASE_DOMAIN_T        * domain,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request
+)
+{
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(domain),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_IO_REQUEST,
+      "scif_sas_domain_ready_continue_io_handler(0x%x, 0x%x, 0x%x) enter\n",
+      domain, remote_device, io_request
+   ));
+
+   /// @todo fix return code handling.
+   return SCI_FAILURE;
+}
+
+/**
+ * @brief This method provides READY state specific handling for
+ *        when a user attempts to start a task request.
+ *
+ * @param[in]  domain This parameter specifies the domain object
+ *             on which the user is attempting to perform a start task
+ *             operation.
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object on which the user is attempting to perform a start IO
+ *             operation.
+ * @param[in]  task_request This parameter specifies the task request that
+ *             is being started.
+ *
+ * @return This method returns an indication of whether the start task
+ *         operation succeeded.
+ * @retval SCI_SUCCESS This value is returned when the start task operation
+ *         begins successfully.
+ */
+static
+SCI_STATUS scif_sas_domain_ready_start_task_handler(
+   SCI_BASE_DOMAIN_T        * domain,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * task_request
+)
+{
+   SCIF_SAS_DOMAIN_T        * fw_domain  = (SCIF_SAS_DOMAIN_T*) domain;
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device  = (SCIF_SAS_REMOTE_DEVICE_T*)
+                                           remote_device;
+   SCIF_SAS_REQUEST_T       * fw_request = (SCIF_SAS_REQUEST_T*) task_request;
+   SCI_STATUS                 status;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(domain),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_TASK_MANAGEMENT,
+      "scif_sas_domain_ready_start_task_handler(0x%x, 0x%x, 0x%x) enter\n",
+      domain, remote_device, task_request
+   ));
+
+   status = fw_device->state_handlers->parent.start_task_handler(
+               &fw_device->parent, &fw_request->parent
+            );
+
+   if (status == SCI_SUCCESS)
+   {
+      // Add the task to the list of outstanding requests on the domain.
+      sci_fast_list_insert_tail(
+         &fw_domain->request_list, &fw_request->list_element
+      );
+   }
+
+   return status;
+}
+
+/**
+ * @brief This method provides READY state specific handling for
+ *        when a user attempts to complete a task request.
+ *
+ * @param[in]  domain This parameter specifies the domain object
+ *             on which the user is attempting to perform a complete task
+ *             operation.
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object on which the user is attempting to perform a start IO
+ *             operation.
+ * @param[in]  task_request This parameter specifies the task request that
+ *             is being started.
+ *
+ * @return This method returns an indication of whether the complete task
+ *         operation succeeded.
+ * @retval SCI_SUCCESS This value is returned when the complete task operation
+ *         begins successfully.
+ */
+static
+SCI_STATUS scif_sas_domain_ready_complete_task_handler(
+   SCI_BASE_DOMAIN_T        * domain,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * task_request
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device  = (SCIF_SAS_REMOTE_DEVICE_T*)
+                                           remote_device;
+   SCIF_SAS_REQUEST_T       * fw_request = (SCIF_SAS_REQUEST_T*) task_request;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(domain),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_TASK_MANAGEMENT,
+      "scif_sas_domain_ready_complete_task_handler(0x%x, 0x%x, 0x%x) enter\n",
+      domain, remote_device, task_request
+   ));
+
+   // Remove the IO from the list of outstanding requests on the domain.
+   sci_fast_list_remove_element(&fw_request->list_element);
+
+   return fw_device->state_handlers->parent.complete_task_handler(
+             &fw_device->parent, &fw_request->parent
+          );
+}
+
+
+/**
+ * @brief This method provides READY state specific handling for when a user
+ *        attempts to start a high priority IO request.
+ *
+ * @param[in]  domain This parameter specifies the domain object
+ *             on which the user is attempting to perform a start high priority
+ *             IO operation (which is exclusively for Phy Control hard reset).
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object on which the user is attempting to perform a start
+ *             high priority IO operation.
+ * @param[in]  io_request This parameter specifies the io request that is
+ *             being started.
+ *
+ * @return This method returns an indication of whether the start IO
+ *         operation succeeded.
+ * @retval SCI_SUCCESS This value is returned when the start IO operation
+ *         begins successfully.
+ */
+static
+SCI_STATUS scif_sas_domain_ready_start_high_priority_io_handler(
+   SCI_BASE_DOMAIN_T        * domain,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request
+)
+{
+   SCIF_SAS_DOMAIN_T        * fw_domain  = (SCIF_SAS_DOMAIN_T*) domain;
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device  = (SCIF_SAS_REMOTE_DEVICE_T*)
+                                           remote_device;
+   SCIF_SAS_REQUEST_T       * fw_request = (SCIF_SAS_REQUEST_T*) io_request;
+   SCI_STATUS                 status;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(domain),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_IO_REQUEST,
+      "scif_sas_domain_ready_start_high_priority_request_handler(0x%x, 0x%x, 0x%x) enter\n",
+      domain, remote_device, io_request
+   ));
+
+   status = fw_device->state_handlers->start_high_priority_io_handler(
+               &fw_device->parent, &fw_request->parent
+            );
+
+   if (status == SCI_SUCCESS)
+   {
+      // Add the IO to the list of outstanding requests on the domain.
+
+      // When domain is in READY state, this high priority io is likely
+      // a smp Phy Control or Discover request sent to parent device of
+      // a target device, which is to be Target Reset. This high priority
+      // IO's probably has already been added to the domain's list as a
+      // SCIF_SAS_TASK_REQUEST. We need to check if it is already on the
+      // list.
+
+      if ( ! sci_fast_list_is_on_this_list(
+                &fw_domain->request_list, &fw_request->list_element))
+
+         sci_fast_list_insert_tail(
+            &fw_domain->request_list, &fw_request->list_element
+         );
+   }
+
+   return status;
+}
+
+
+/**
+ * @brief This method provides READY state specific handling for
+ *        when a user attempts to complete an high priroity IO request.
+ *
+ * @param[in]  domain This parameter specifies the domain object
+ *             on which the user is attempting to perform a complete high
+ *             priority IO operation (which is exclusively for Phy Control
+ *             hard reset).
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object on which the user is attempting to perform a complete
+ *             IO operation.
+ * @param[in]  io_request This parameter specifies the io request that is
+ *             being completed.
+ *
+ * @return This method returns an indication of whether the complete IO
+ *         operation succeeded.
+ * @retval SCI_SUCCESS This value is returned when the complete IO operation
+ *         is successful.
+ */
+static
+SCI_STATUS scif_sas_domain_ready_complete_high_priority_io_handler(
+   SCI_BASE_DOMAIN_T        * domain,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request,
+   void                     * response_data,
+   SCI_IO_STATUS              completion_status
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
+                                          remote_device;
+   SCIF_SAS_REQUEST_T       * fw_request= (SCIF_SAS_REQUEST_T*) io_request;
+
+   SCIC_TRANSPORT_PROTOCOL    protocol;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(domain),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_IO_REQUEST,
+      "scif_sas_domain_ready_complete_high_priority_io_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
+      domain, remote_device, io_request, response_data
+   ));
+
+   protocol = scic_io_request_get_protocol(fw_request->core_object);
+
+   // If the request is an SMP HARD/LINK RESET request, then the request
+   // came through the task management path (partially).  As a result,
+   // the accounting for the request is managed in the task request
+   // completion path.  Thus, only change the domain request counter if
+   // the request is not an SMP target reset of some sort.
+   if (
+         (protocol != SCIC_SMP_PROTOCOL)
+      || (fw_device->protocol_device.smp_device.current_activity !=
+                SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_TARGET_RESET)
+      )
+   {
+      sci_fast_list_remove_element(&fw_request->list_element);
+   }
+
+   return fw_device->state_handlers->complete_high_priority_io_handler(
+             &fw_device->parent, &fw_request->parent, response_data, completion_status
+          );
+}
+
+//******************************************************************************
+//* S T O P P I N G   H A N D L E R S
+//******************************************************************************
+
+static
+SCI_STATUS scif_sas_domain_stopping_device_stop_complete_handler(
+   SCI_BASE_DOMAIN_T        * domain,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device
+)
+{
+   SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T *) domain;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(domain),
+      SCIF_LOG_OBJECT_DOMAIN,
+      "scif_sas_domain_stopping_device_stop_complete_handler(0x%x, 0x%x) enter\n",
+      domain, remote_device
+   ));
+
+   // Attempt to transition to the stopped state.
+   scif_sas_domain_transition_to_stopped_state(fw_domain);
+
+   return SCI_SUCCESS;
+}
+
+/**
+ * @brief This method provides STOPPING state specific handling for
+ *        when a user attempts to complete an IO request.
+ *
+ * @param[in]  domain This parameter specifies the domain object
+ *             on which the user is attempting to perform a complete IO
+ *             operation.
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object on which the user is attempting to perform a complete
+ *             IO operation.
+ * @param[in]  io_request This parameter specifies the io request that is
+ *             being completed.
+ *
+ * @return This method returns an indication of whether the complete IO
+ *         operation succeeded.
+ * @retval SCI_SUCCESS This value is returned when the complete IO operation
+ *         is successful.
+ */
+static
+SCI_STATUS scif_sas_domain_stopping_complete_io_handler(
+   SCI_BASE_DOMAIN_T        * domain,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request
+)
+{
+   SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T *) domain;
+   SCI_STATUS          status;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(domain),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_IO_REQUEST,
+      "scif_sas_domain_stopping_complete_io_handler(0x%x, 0x%x, 0x%x) enter\n",
+      domain, remote_device, io_request
+   ));
+
+   status = scif_sas_domain_ready_complete_io_handler(
+               domain, remote_device, io_request
+            );
+
+   // Attempt to transition to the stopped state.
+   scif_sas_domain_transition_to_stopped_state(fw_domain);
+
+   return status;
+}
+
+
+/**
+ * @brief This method provides STOPPING state specific handling for
+ *        when a user attempts to complete an IO request.
+ *
+ * @param[in]  domain This parameter specifies the domain object
+ *             on which the user is attempting to perform a complete IO
+ *             operation.
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object on which the user is attempting to perform a complete
+ *             IO operation.
+ * @param[in]  io_request This parameter specifies the io request that is
+ *             being completed.
+ *
+ * @return This method returns an indication of whether the complete IO
+ *         operation succeeded.
+ * @retval SCI_SUCCESS This value is returned when the complete IO operation
+ *         is successful.
+ */
+static
+SCI_STATUS scif_sas_domain_stopping_complete_high_priority_io_handler(
+   SCI_BASE_DOMAIN_T        * domain,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request,
+   void                     * response_data,
+   SCI_IO_STATUS              completion_status
+)
+{
+   SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T *) domain;
+   SCI_STATUS          status;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(domain),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_IO_REQUEST,
+      "scif_sas_domain_stopping_complete_io_handler(0x%x, 0x%x, 0x%x) enter\n",
+      domain, remote_device, io_request
+   ));
+
+   status = scif_sas_domain_ready_complete_high_priority_io_handler(
+               domain, remote_device, io_request, response_data, completion_status
+            );
+
+   // Attempt to transition to the stopped state.
+   scif_sas_domain_transition_to_stopped_state(fw_domain);
+
+   return status;
+}
+
+
+/**
+ * @brief This method provides STOPPING state specific handling for
+ *        when a user attempts to complete a task request.
+ *
+ * @param[in]  domain This parameter specifies the domain object
+ *             on which the user is attempting to perform a complete task
+ *             operation.
+ *
+ * @return This method returns an indication of whether the complete task
+ *         operation succeeded.
+ * @retval SCI_SUCCESS This value is returned when the complete task operation
+ *         begins successfully.
+ */
+static
+SCI_STATUS scif_sas_domain_stopping_complete_task_handler(
+   SCI_BASE_DOMAIN_T        * domain,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * task_request
+)
+{
+   SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T *) domain;
+   SCI_STATUS          status;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(domain),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_TASK_MANAGEMENT,
+      "scif_sas_domain_stopping_complete_task_handler(0x%x, 0x%x, 0x%x) enter\n",
+      domain, remote_device, task_request
+   ));
+
+   status = scif_sas_domain_ready_complete_task_handler(
+               domain, remote_device, task_request
+            );
+
+   // Attempt to transition to the stopped state.
+   scif_sas_domain_transition_to_stopped_state(fw_domain);
+
+   return SCI_SUCCESS;
+}
+
+//******************************************************************************
+//* D I S C O V E R I N G   H A N D L E R S
+//******************************************************************************
+
+/**
+ * @brief This method provides DISCOVERING state specific processing for
+ *        reception of a port NOT ready notification from the core.  A port
+ *        NOT ready notification forces the discovery operation to complete
+ *        in error.  Additionally, all IOs are aborted and devices removed.
+ *
+ * @param[in]  domain This parameter specifies the domain object
+ *             for which the core port is no longer ready.
+ *
+ * @return
+ */
+static
+SCI_STATUS scif_sas_domain_discovering_port_not_ready_handler(
+   SCI_BASE_DOMAIN_T * domain,
+   U32                 reason_code
+)
+{
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(domain),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_domain_discovering_port_not_ready_handler(0x%x, 0x%x) enter\n",
+      domain,
+      reason_code
+   ));
+
+   // Change to the STOPPING state to cause existing request
+   // completions to be terminated and devices removed.
+   sci_base_state_machine_change_state(
+      &domain->state_machine, SCI_BASE_DOMAIN_STATE_STOPPING
+   );
+
+   return SCI_SUCCESS;
+}
+
+static
+SCI_STATUS scif_sas_domain_discovering_device_start_complete_handler(
+   SCI_BASE_DOMAIN_T        * domain,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device
+)
+{
+   SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T *)domain;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(domain),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_domain_discovering_device_start_complete_handler(0x%x) enter\n",
+      domain, remote_device
+   ));
+
+   //domain will decide what's next step.
+   scif_sas_domain_continue_discover(fw_domain);
+
+   return SCI_SUCCESS;
+}
+
+// ---------------------------------------------------------------------------
+
+static
+SCI_STATUS scif_sas_domain_discovering_device_stop_complete_handler(
+   SCI_BASE_DOMAIN_T        * domain,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device
+)
+{
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(domain),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_domain_discovering_device_stop_complete_handler(0x%x) enter\n",
+      domain, remote_device
+   ));
+
+   return SCI_FAILURE;
+}
+
+
+/**
+ * @brief This method provides DISCOVERING state specific handling for when a user
+ *        attempts to start a high priority IO request.
+ *
+ * @param[in]  domain This parameter specifies the domain object
+ *             on which the user is attempting to perform a start IO
+ *             operation.
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object on which the user is attempting to perform a start IO
+ *             operation.
+ * @param[in]  io_request This parameter specifies the io request that is
+ *             being started.
+ *
+ * @return This method returns an indication of whether the start IO
+ *         operation succeeded.
+ * @retval SCI_SUCCESS This value is returned when the start IO operation
+ *         begins successfully.
+ */
+static
+SCI_STATUS scif_sas_domain_discovering_start_high_priority_io_handler(
+   SCI_BASE_DOMAIN_T        * domain,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request
+)
+{
+   SCIF_SAS_DOMAIN_T        * fw_domain  = (SCIF_SAS_DOMAIN_T*) domain;
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device  = (SCIF_SAS_REMOTE_DEVICE_T*)
+                                           remote_device;
+   SCIF_SAS_REQUEST_T       * fw_request = (SCIF_SAS_REQUEST_T*) io_request;
+   SCI_STATUS                 status;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(domain),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_IO_REQUEST,
+      "scif_sas_domain_discovery_start_high_priority_request_handler(0x%x, 0x%x, 0x%x) enter\n",
+      domain, remote_device, io_request
+   ));
+
+   status = fw_device->state_handlers->start_high_priority_io_handler(
+               &fw_device->parent, &fw_request->parent
+            );
+
+   if (status == SCI_SUCCESS)
+   {
+      // Add the IO to the list of outstanding requests on the domain.
+
+      // It is possible this high priority IO's has already been added to
+      // the domain's list as a SCIF_SAS_TASK_REQUEST. We need to check
+      // if it is already on the list.
+      if ( ! sci_fast_list_is_on_this_list(
+               &fw_domain->request_list, &fw_request->list_element))
+
+         sci_fast_list_insert_tail(
+            &fw_domain->request_list, &fw_request->list_element
+         );
+   }
+
+   return status;
+}
+
+
+/**
+ * @brief This method provides DISCOVERING state specific handling for
+ *        when a user attempts to complete an IO request.  User IOs are
+ *        allowed to be completed during discovery.
+ *
+ * @param[in]  domain This parameter specifies the domain object
+ *             on which the user is attempting to perform a complete IO
+ *             operation.
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object on which the user is attempting to perform a complete
+ *             IO operation.
+ * @param[in]  io_request This parameter specifies the io request that is
+ *             being completed.
+ *
+ * @return This method returns an indication of whether the complete IO
+ *         operation succeeded.
+ * @retval SCI_SUCCESS This value is returned when the complete IO operation
+ *         is successful.
+ */
+static
+SCI_STATUS scif_sas_domain_discovering_complete_io_handler(
+   SCI_BASE_DOMAIN_T        * domain,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request
+)
+{
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(domain),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_IO_REQUEST,
+      "scif_sas_domain_discovering_complete_io_handler(0x%x, 0x%x, 0x%x) enter\n",
+      domain, remote_device, io_request
+   ));
+
+   return scif_sas_domain_ready_complete_io_handler(
+             domain, remote_device, io_request
+          );
+}
+
+/**
+ * @brief This method provides DISCOVERING state specific handling for
+ *        when a user attempts to complete an high priroity IO request.  User
+ *        IOs are allowed to be completed during discovery.
+ *
+ * @param[in]  domain This parameter specifies the domain object
+ *             on which the user is attempting to perform a complete IO
+ *             operation.
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object on which the user is attempting to perform a complete
+ *             IO operation.
+ * @param[in]  io_request This parameter specifies the io request that is
+ *             being completed.
+ *
+ * @return This method returns an indication of whether the complete IO
+ *         operation succeeded.
+ * @retval SCI_SUCCESS This value is returned when the complete IO operation
+ *         is successful.
+ */
+static
+SCI_STATUS scif_sas_domain_discovering_complete_high_priority_io_handler(
+   SCI_BASE_DOMAIN_T        * domain,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request,
+   void                     * response_data,
+   SCI_IO_STATUS              completion_status
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
+                                          remote_device;
+   SCIF_SAS_REQUEST_T       * fw_request= (SCIF_SAS_REQUEST_T*) io_request;
+
+   SCIC_TRANSPORT_PROTOCOL    protocol;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(domain),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_IO_REQUEST,
+      "scif_sas_domain_discovering_complete_high_priority_io_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
+      domain, remote_device, io_request, response_data
+   ));
+
+   protocol = scic_io_request_get_protocol(fw_request->core_object);
+
+   // Remove the IO from the list of outstanding requests on the domain.
+
+   // If the request is an SMP HARD/LINK RESET request, then the request
+   // came through the task management path (partially).  As a result,
+   // the accounting for the request is managed in the task request
+   // completion path.  Thus, only change the domain request counter if
+   // the request is not an SMP target reset of some sort.
+   if (
+         (protocol != SCIC_SMP_PROTOCOL)
+      || (fw_device->protocol_device.smp_device.current_activity !=
+                SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_TARGET_RESET)
+   )
+   {
+      sci_fast_list_remove_element(&fw_request->list_element);
+   }
+
+   return fw_device->state_handlers->complete_high_priority_io_handler(
+             &fw_device->parent, &fw_request->parent, response_data, completion_status
+          );
+}
+
+
+/**
+ * @brief This method provides DISCOVERING state specific handling for
+ *        when the framework attempts to complete an IO request.  Internal
+ *        Framework IOs allowed to be continued during discovery.
+ *
+ * @param[in]  domain This parameter specifies the domain object
+ *             on which the user is attempting to perform a continue IO
+ *             operation.
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object on which the user is attempting to perform a continue
+ *             IO operation.
+ * @param[in]  io_request This parameter specifies the io request that is
+ *             being continued.
+ *
+ * @return This method returns an indication of whether the continue IO
+ *         operation succeeded.
+ * @retval SCI_SUCCESS This value is returned when the continue IO operation
+ *         is successful.
+ */
+static
+SCI_STATUS scif_sas_domain_discovering_continue_io_handler(
+   SCI_BASE_DOMAIN_T        * domain,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request
+)
+{
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(domain),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_IO_REQUEST,
+      "scif_sas_domain_discovering_continue_io_handler(0x%x, 0x%x, 0x%x) enter\n",
+      domain, remote_device, io_request
+   ));
+
+   /// @todo fix return code handling.
+   return SCI_FAILURE;
+}
+
+
+/**
+ * @brief This method provides handling when a user attempts to start
+ *        a task on a domain in DISCOVER state, only hard reset is allowed.
+ *
+ * @param[in]  domain This parameter specifies the domain object
+ *             on which the user is attempting to perform a start task
+ *             operation.
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object on which the user is attempting to perform a start IO
+ *             operation.
+ * @param[in]  task_request This parameter specifies the task request that
+ *             is being started.
+ *
+ * @return This method returns a status of start task operations
+ * @retval SCI_FAILURE_INVALID_STATE This value is returned for any tasks,
+ *         except for HARD RESET.
+ */
+static
+SCI_STATUS scif_sas_domain_discovering_start_task_handler(
+   SCI_BASE_DOMAIN_T        * domain,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * task_request
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
+                                          remote_device;
+   SCIF_SAS_TASK_REQUEST_T  * fw_task = (SCIF_SAS_TASK_REQUEST_T*)task_request;
+
+   //Only let target reset go through.
+   if (scif_sas_task_request_get_function(fw_task)
+             == SCI_SAS_HARD_RESET)
+   {
+      //If the domain is in the middle of smp DISCOVER process,
+      //interrupt it. After target reset is done, resume the smp DISCOVERY.
+      scif_sas_domain_cancel_smp_activities(fw_device->domain);
+
+      return scif_sas_domain_ready_start_task_handler(domain, remote_device, task_request);
+   }
+   else{
+      SCIF_LOG_WARNING((
+         sci_base_object_get_logger(domain),
+         SCIF_LOG_OBJECT_DOMAIN,
+         "Domain:0x%x Device:0x%x State:0x%x start task message invalid\n",
+         domain, remote_device,
+         sci_base_state_machine_get_state(&domain->state_machine)
+      ));
+
+      return SCI_FAILURE_INVALID_STATE;
+   }
+}
+
+
+/**
+ * @brief This method provides DISCOVERING state specific handling for
+ *        when a user attempts to complete a task request.  User task
+ *        management requests are allowed to be completed during discovery.
+ *
+ * @param[in]  domain This parameter specifies the domain object
+ *             on which the user is attempting to perform a complete IO
+ *             operation.
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object on which the user is attempting to perform a complete
+ *             IO operation.
+ * @param[in]  task_request This parameter specifies the task request that
+ *             is being completed.
+ *
+ * @return This method returns an indication of whether the complete task
+ *         management operation succeeded.
+ * @retval SCI_SUCCESS This value is returned when the complete task request
+ *         is successful.
+ */
+static
+SCI_STATUS scif_sas_domain_discovering_complete_task_handler(
+   SCI_BASE_DOMAIN_T        * domain,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * task_request
+)
+{
+   SCI_STATUS status;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(domain),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_TASK_MANAGEMENT,
+      "scif_sas_domain_discovering_complete_task_handler(0x%x, 0x%x, 0x%x) enter\n",
+      domain, remote_device, task_request
+   ));
+
+   status = scif_sas_domain_ready_complete_task_handler(
+               domain, remote_device, task_request
+            );
+
+   return status;
+}
+
+//******************************************************************************
+//* D E F A U L T   H A N D L E R S
+//******************************************************************************
+
+/**
+ * @brief This method provides default handling (i.e. returns an error)
+ *        when a user attempts to discover a domain and a discovery
+ *        operation is not allowed.
+ *
+ * @param[in]  domain This parameter specifies the domain object
+ *             on which the user is attempting to perform an discover
+ *             operation.
+ * @param[in]  op_timeout This parameter specifies the timeout
+ *             (in milliseconds) for the entire discovery operation.
+ *             This timeout value should be some multiple of the
+ *             individual device_timeout value.
+ * @param[in]  device_timeout This parameter specifies the timeout
+ *             (in milliseconds) for an individual device being discovered
+ *             and configured during this operation.
+ *
+ * @return This method returns an indication that discovery operations
+ *         are not allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+static
+SCI_STATUS scif_sas_domain_default_discover_handler(
+   SCI_BASE_DOMAIN_T * domain,
+   U32                 op_timeout,
+   U32                 device_timeout
+)
+{
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger((SCIF_SAS_DOMAIN_T *)domain),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "Domain:0x%x State:0x%x requested to discover in invalid state\n",
+      domain,
+      sci_base_state_machine_get_state(&domain->state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * @brief This method provides default processing for reception of a port
+ *        ready notification from the core.
+ *
+ * @param[in]  domain This parameter specifies the domain object
+ *             on which the core port has just come ready.
+ *
+ * @return
+ */
+static
+SCI_STATUS scif_sas_domain_default_port_ready_handler(
+   SCI_BASE_DOMAIN_T * domain
+)
+{
+   SCIF_LOG_INFO((
+      sci_base_object_get_logger(domain),
+      SCIF_LOG_OBJECT_DOMAIN,
+      "Domain:0x%x State:0x%x port now ready\n",
+      domain,
+      sci_base_state_machine_get_state(&domain->state_machine)
+   ));
+
+   return SCI_SUCCESS;
+}
+
+/**
+ * @brief This method provides default processing for reception of a port
+ *        NOT ready notification from the core.
+ *
+ * @param[in]  domain This parameter specifies the domain object
+ *             on which the core port has just come ready.
+ *
+ * @return
+ */
+static
+SCI_STATUS scif_sas_domain_default_port_not_ready_handler(
+   SCI_BASE_DOMAIN_T * domain,
+   U32                 reason_code
+)
+{
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger(domain),
+      SCIF_LOG_OBJECT_DOMAIN,
+      "Domain:0x%x State:0x%x Port Not Ready 0x%x in invalid state\n",
+      domain,
+      sci_base_state_machine_get_state(&domain->state_machine),
+      reason_code
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * @brief This method provides default handling (i.e. returns an error)
+ *        when a user attempts to start an IO on a domain and a start
+ *        IO operation is not allowed.
+ *
+ * @param[in]  domain This parameter specifies the domain object
+ *             on which the user is attempting to perform a start IO
+ *             operation.
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object on which the user is attempting to perform a start IO
+ *             operation.
+ * @param[in]  io_request This parameter specifies the io request that is
+ *             being started.
+ *
+ * @return This method returns an indication that start IO operations
+ *         are not allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+static
+SCI_STATUS scif_sas_domain_default_start_io_handler(
+   SCI_BASE_DOMAIN_T        * domain,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request
+)
+{
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger(domain),
+      SCIF_LOG_OBJECT_DOMAIN,
+      "Domain:0x%x Device:0x%x State:0x%x start IO message invalid\n",
+      domain, remote_device,
+      sci_base_state_machine_get_state(&domain->state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * @brief This method provides default handling (i.e. returns an error)
+ *        when a user attempts to complete an IO on a domain and a
+ *        complete IO operation is not allowed.
+ *
+ * @param[in]  domain This parameter specifies the domain object
+ *             on which the user is attempting to perform a complete IO
+ *             operation.
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object on which the user is attempting to perform a complete IO
+ *             operation.
+ * @param[in]  io_request This parameter specifies the io request that is
+ *             being completed.
+ *
+ * @return This method returns an indication that complete IO operations
+ *         are not allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+static
+SCI_STATUS scif_sas_domain_default_complete_io_handler(
+   SCI_BASE_DOMAIN_T        * domain,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request
+)
+{
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger(domain),
+      SCIF_LOG_OBJECT_DOMAIN,
+      "Domain:0x%x Device:0x%x State:0x%x complete IO message invalid\n",
+      domain, remote_device,
+      sci_base_state_machine_get_state(&domain->state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+
+/**
+ * @brief This method provides default handling (i.e. returns an error)
+ *        when a user attempts to complete an IO on a domain and a
+ *        complete IO operation is not allowed.
+ *
+ * @param[in]  domain This parameter specifies the domain object
+ *             on which the user is attempting to perform a complete IO
+ *             operation.
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object on which the user is attempting to perform a complete IO
+ *             operation.
+ * @param[in]  io_request This parameter specifies the io request that is
+ *             being completed.
+ *
+ * @return This method returns an indication that complete IO operations
+ *         are not allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+static
+SCI_STATUS scif_sas_domain_default_complete_high_priority_io_handler(
+   SCI_BASE_DOMAIN_T        * domain,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request,
+   void                     * response_data,
+   SCI_IO_STATUS              completion_status
+)
+{
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger(domain),
+      SCIF_LOG_OBJECT_DOMAIN,
+      "Domain:0x%x Device:0x%x State:0x%x complete IO message invalid\n",
+      domain, remote_device,
+      sci_base_state_machine_get_state(&domain->state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * @brief This method provides default handling (i.e. returns an error)
+ *        when a user attempts to continue an IO on a domain and a
+ *        continue IO operation is not allowed.
+ *
+ * @param[in]  domain This parameter specifies the domain object
+ *             on which the user is attempting to perform a continue IO
+ *             operation.
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object on which the user is attempting to perform a start IO
+ *             operation.
+ * @param[in]  io_request This parameter specifies the io request that is
+ *             being started.
+ *
+ * @return This method returns an indication that continue IO operations
+ *         are not allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+static
+SCI_STATUS scif_sas_domain_default_continue_io_handler(
+   SCI_BASE_DOMAIN_T        * domain,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request
+)
+{
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger(domain),
+      SCIF_LOG_OBJECT_DOMAIN,
+      "Domain:0x%x Device:0x%x State:0x%x contineu IO message invalid\n",
+      domain, remote_device,
+      sci_base_state_machine_get_state(&domain->state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * @brief This method provides default handling (i.e. returns an error)
+ *        when a user attempts to start a task on a domain and a start
+ *        task operation is not allowed.
+ *
+ * @param[in]  domain This parameter specifies the domain object
+ *             on which the user is attempting to perform a start task
+ *             operation.
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object on which the user is attempting to perform a start IO
+ *             operation.
+ * @param[in]  task_request This parameter specifies the task request that
+ *             is being started.
+ *
+ * @return This method returns an indication that start task operations
+ *         are not allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+static
+SCI_STATUS scif_sas_domain_default_start_task_handler(
+   SCI_BASE_DOMAIN_T        * domain,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * task_request
+)
+{
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger(domain),
+      SCIF_LOG_OBJECT_DOMAIN,
+      "Domain:0x%x Device:0x%x State:0x%x start task message invalid\n",
+      domain, remote_device,
+      sci_base_state_machine_get_state(&domain->state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * @brief This method provides default handling (i.e. returns an error)
+ *        when a user attempts to complete a task on a domain and a
+ *        complete task operation is not allowed.
+ *
+ * @param[in]  domain This parameter specifies the domain object
+ *             on which the user is attempting to perform a complete task
+ *             operation.
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object on which the user is attempting to perform a start IO
+ *             operation.
+ * @param[in]  task_request This parameter specifies the task request that
+ *             is being started.
+ *
+ * @return This method returns an indication that complete task operations
+ *         are not allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+static
+SCI_STATUS scif_sas_domain_default_complete_task_handler(
+   SCI_BASE_DOMAIN_T        * domain,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * task_request
+)
+{
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger(domain),
+      SCIF_LOG_OBJECT_DOMAIN,
+      "Domain:0x%x Device:0x%x State:0x%x complete task message invalid\n",
+      domain, remote_device,
+      sci_base_state_machine_get_state(&domain->state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * @brief This method provides default handling (i.e. returns an error)
+ *        when a remote device start operation completes in a state.
+ *
+ * @param[in]  domain This parameter specifies the domain object
+ *             on which the remote device start operation is completing.
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             for which the start operation is completing.
+ *
+ * @return This method returns an indication that start operation
+ *         completion is not allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+static
+SCI_STATUS scif_sas_domain_default_device_start_complete_handler(
+   SCI_BASE_DOMAIN_T        * domain,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device
+)
+{
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger(domain),
+      SCIF_LOG_OBJECT_DOMAIN,
+      "Domain:0x%x Device:0x%x State:0x%x device stop complete message invalid\n",
+      domain, remote_device,
+      sci_base_state_machine_get_state(&domain->state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * @brief This method provides default handling (i.e. returns an error)
+ *        when a remote device stop operation completes in a state.
+ *
+ * @param[in]  domain This parameter specifies the domain object
+ *             on which the remote device stop operation is completing.
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             for which the stop operation is completing.
+ *
+ * @return This method returns an indication that stop operation
+ *         completion is not allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+static
+SCI_STATUS scif_sas_domain_default_device_stop_complete_handler(
+   SCI_BASE_DOMAIN_T        * domain,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device
+)
+{
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger(domain),
+      SCIF_LOG_OBJECT_DOMAIN,
+      "Domain:0x%x Device:0x%x State:0x%x device stop complete message invalid\n",
+      domain, remote_device,
+      sci_base_state_machine_get_state(&domain->state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * @brief This method provides default handling (i.e. returns an error)
+ *        when sci user try to destruct a remote device of this domain.
+ *
+ * @param[in]  domain This parameter specifies the domain object
+ *             on which the remote device is to be destructed.
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             to be destructed.
+ *
+ * @return This method returns an indication that device destruction
+ *         is not allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+static
+SCI_STATUS scif_sas_domain_default_device_destruct_handler(
+   SCI_BASE_DOMAIN_T        * domain,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device
+)
+{
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger(domain),
+      SCIF_LOG_OBJECT_DOMAIN,
+      "Domain:0x%x Device:0x%x State:0x%x device destruct in invalid state\n",
+      domain, remote_device,
+      sci_base_state_machine_get_state(&domain->state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+
+/**
+ * @brief This method provides handling when sci user destruct a remote
+ *        device of this domain in discovering state. Mainly the device
+ *        is removed from domain's remote_device_list.
+ *
+ * @param[in]  domain This parameter specifies the domain object
+ *             on which the remote device is to be destructed.
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             to be destructed.
+ *
+ * @return This method returns a status of the device destruction.
+ * @retval SCI_SUCCESS This value is returned when a remote device is
+ *         successfully removed from domain.
+ */
+static
+SCI_STATUS scif_sas_domain_discovering_device_destruct_handler(
+   SCI_BASE_DOMAIN_T        * domain,
+   SCI_BASE_REMOTE_DEVICE_T * remote_device
+)
+{
+   SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T *)domain;
+
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger(domain),
+      SCIF_LOG_OBJECT_DOMAIN,
+      "Domain:0x%x Device:0x%x State:0x%x device destruct in domain DISCOVERING state\n",
+      domain, remote_device,
+      sci_base_state_machine_get_state(&domain->state_machine)
+   ));
+
+   //remove the remote device from domain's remote_device_list
+   sci_abstract_list_erase(
+      &(fw_domain->remote_device_list),
+      remote_device
+   );
+
+   return SCI_SUCCESS;
+}
+
+
+#define scif_sas_domain_stopped_discover_handler \
+        scif_sas_domain_ready_discover_handler
+
+#define scif_sas_domain_default_start_high_priority_io_handler \
+        scif_sas_domain_default_start_io_handler
+
+
+SCI_BASE_DOMAIN_STATE_HANDLER_T
+   scif_sas_domain_state_handler_table[SCI_BASE_DOMAIN_MAX_STATES] =
+{
+   // SCI_BASE_DOMAIN_STATE_INITIAL
+   {
+      scif_sas_domain_default_discover_handler,
+      scif_sas_domain_default_port_ready_handler,
+      scif_sas_domain_default_port_not_ready_handler,
+      scif_sas_domain_default_device_start_complete_handler,
+      scif_sas_domain_default_device_stop_complete_handler,
+      scif_sas_domain_default_device_destruct_handler,
+      scif_sas_domain_default_start_io_handler,
+      scif_sas_domain_default_start_high_priority_io_handler,
+      scif_sas_domain_default_complete_io_handler,
+      scif_sas_domain_default_complete_high_priority_io_handler,
+      scif_sas_domain_default_continue_io_handler,
+      scif_sas_domain_default_start_task_handler,
+      scif_sas_domain_default_complete_task_handler
+   },
+   // SCI_BASE_DOMAIN_STATE_STARTING
+   {
+      scif_sas_domain_default_discover_handler,
+      scif_sas_domain_starting_port_ready_handler,
+      scif_sas_domain_default_port_not_ready_handler,
+      scif_sas_domain_default_device_start_complete_handler,
+      scif_sas_domain_default_device_stop_complete_handler,
+      scif_sas_domain_default_device_destruct_handler,
+      scif_sas_domain_default_start_io_handler,
+      scif_sas_domain_default_start_high_priority_io_handler,
+      scif_sas_domain_default_complete_io_handler,
+      scif_sas_domain_default_complete_high_priority_io_handler,
+      scif_sas_domain_default_continue_io_handler,
+      scif_sas_domain_default_start_task_handler,
+      scif_sas_domain_default_complete_task_handler
+   },
+   // SCI_BASE_DOMAIN_STATE_READY
+   {
+      scif_sas_domain_ready_discover_handler,
+      scif_sas_domain_default_port_ready_handler,
+      scif_sas_domain_ready_port_not_ready_handler,
+      scif_sas_domain_default_device_start_complete_handler,
+      scif_sas_domain_default_device_stop_complete_handler,
+      scif_sas_domain_default_device_destruct_handler,
+      scif_sas_domain_ready_start_io_handler,
+      scif_sas_domain_ready_start_high_priority_io_handler,
+      scif_sas_domain_ready_complete_io_handler,
+      scif_sas_domain_ready_complete_high_priority_io_handler,
+      scif_sas_domain_ready_continue_io_handler,
+      scif_sas_domain_ready_start_task_handler,
+      scif_sas_domain_ready_complete_task_handler
+   },
+   // SCI_BASE_DOMAIN_STATE_STOPPING
+   {
+      scif_sas_domain_default_discover_handler,
+      scif_sas_domain_default_port_ready_handler,
+      scif_sas_domain_default_port_not_ready_handler,
+      scif_sas_domain_default_device_start_complete_handler,
+      scif_sas_domain_stopping_device_stop_complete_handler,
+      scif_sas_domain_default_device_destruct_handler,
+      scif_sas_domain_default_start_io_handler,
+      scif_sas_domain_default_start_high_priority_io_handler,
+      scif_sas_domain_stopping_complete_io_handler,
+      scif_sas_domain_stopping_complete_high_priority_io_handler,
+      scif_sas_domain_default_continue_io_handler,
+      scif_sas_domain_default_start_task_handler,
+      scif_sas_domain_stopping_complete_task_handler
+   },
+   // SCI_BASE_DOMAIN_STATE_STOPPED
+   {
+      scif_sas_domain_stopped_discover_handler,
+      scif_sas_domain_default_port_ready_handler,
+      scif_sas_domain_default_port_not_ready_handler,
+      scif_sas_domain_default_device_start_complete_handler,
+      scif_sas_domain_default_device_stop_complete_handler,
+      scif_sas_domain_default_device_destruct_handler,
+      scif_sas_domain_default_start_io_handler,
+      scif_sas_domain_default_start_high_priority_io_handler,
+      scif_sas_domain_default_complete_io_handler,
+      scif_sas_domain_default_complete_high_priority_io_handler,
+      scif_sas_domain_default_continue_io_handler,
+      scif_sas_domain_default_start_task_handler,
+      scif_sas_domain_default_complete_task_handler
+   },
+   // SCI_BASE_DOMAIN_STATE_DISCOVERING
+   {
+      scif_sas_domain_default_discover_handler,
+      scif_sas_domain_default_port_ready_handler,
+      scif_sas_domain_discovering_port_not_ready_handler,
+      scif_sas_domain_discovering_device_start_complete_handler,
+      scif_sas_domain_discovering_device_stop_complete_handler,
+      scif_sas_domain_discovering_device_destruct_handler,  //
+      scif_sas_domain_default_start_io_handler,
+      scif_sas_domain_discovering_start_high_priority_io_handler,
+      scif_sas_domain_discovering_complete_io_handler,
+      scif_sas_domain_discovering_complete_high_priority_io_handler, //
+      scif_sas_domain_discovering_continue_io_handler,
+      scif_sas_domain_discovering_start_task_handler,
+      scif_sas_domain_discovering_complete_task_handler
+   }
+};
diff --git a/sys/dev/disk/isci/scil/scif_sas_domain_states.c b/sys/dev/disk/isci/scil/scif_sas_domain_states.c
new file mode 100644
index 0000000..6018eb0
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_domain_states.c
@@ -0,0 +1,610 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_domain_states.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the entrance and exit methods for each
+ *        of the domain states defined by the SCI_BASE_DOMAIN state
+ *        machine.
+ */
+
+#include <dev/disk/isci/scil/intel_sas.h>
+#include <dev/disk/isci/scil/scic_port.h>
+
+#include <dev/disk/isci/scil/scif_sas_logger.h>
+#include <dev/disk/isci/scil/scif_sas_domain.h>
+#include <dev/disk/isci/scil/scif_sas_controller.h>
+#include <dev/disk/isci/scil/scic_controller.h>
+
+//******************************************************************************
+//* P R O T E C T E D    M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method will attempt to transition to the stopped state.
+ *        The transition will only occur if the criteria for transition is
+ *        met (i.e. all IOs are complete and all devices are stopped).
+ *
+ * @param[in]  fw_domain This parameter specifies the domain in which to
+ *             to attempt to perform the transition.
+ *
+ * @return none
+ */
+void scif_sas_domain_transition_to_stopped_state(
+   SCIF_SAS_DOMAIN_T * fw_domain
+)
+{
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_domain),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_domain_transition_to_stopped_state(0x%x) enter\n",
+      fw_domain
+   ));
+
+   // If IOs are quiesced, and all remote devices are stopped,
+   // then transition directly to the STOPPED state.
+   if (  (fw_domain->request_list.element_count == 0)
+      && (fw_domain->device_start_count == 0) )
+   {
+      SCIF_LOG_INFO((
+         sci_base_object_get_logger(fw_domain),
+         SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+         "Domain:0x%x immediate transition to STOPPED\n",
+         fw_domain
+      ));
+
+      sci_base_state_machine_change_state(
+         &fw_domain->parent.state_machine, SCI_BASE_DOMAIN_STATE_STOPPED
+      );
+   }
+}
+
+
+/**
+ * @brief This method is called upon entrance to all states where the
+ *        previous state may have been the DISCOVERING state.
+ *        We issue the scif_cb_domain_discovery_complete() notification
+ *        from this method, assuming pre-requisites are met, as opposed
+ *        to in the exit handler of the DISCOVERING state, so that the
+ *        appropriate state handlers are in place should the user decide
+ *        to call scif_domain_discover() again.
+ *
+ * @param[in]  fw_domain This parameter specifies the domain for which
+ *             the state transition has occurred.
+ *
+ * @return none
+ */
+static
+void scif_sas_domain_transition_from_discovering_state(
+   SCIF_SAS_DOMAIN_T * fw_domain
+)
+{
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_domain),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_domain_transition_from_discovering_state(0x%x) enter\n",
+      fw_domain
+   ));
+
+   if (fw_domain->parent.state_machine.previous_state_id
+       == SCI_BASE_DOMAIN_STATE_DISCOVERING)
+   {
+      scif_sas_controller_restore_interrupt_coalescence(fw_domain->controller);
+
+      scif_cb_timer_stop(fw_domain->controller, fw_domain->operation.timer);
+
+      scif_cb_domain_discovery_complete(
+         fw_domain->controller, fw_domain, fw_domain->operation.status
+      );
+   }
+}
+
+
+/**
+ * @brief This method is called upon entrance to DISCOVERING state. Right before
+ *           transitioning to DISCOVERING state, we temporarily change interrupt
+ *           coalescence scheme.
+ *
+ * @param[in]  fw_domain This parameter specifies the domain for which
+ *             the state transition has occurred.
+ *
+ * @return none
+ */
+void scif_sas_domain_transition_to_discovering_state(
+   SCIF_SAS_DOMAIN_T * fw_domain
+)
+{
+   scif_sas_controller_save_interrupt_coalescence(fw_domain->controller);
+
+   sci_base_state_machine_change_state(
+      &fw_domain->parent.state_machine, SCI_BASE_DOMAIN_STATE_DISCOVERING
+   );
+}
+
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        INITIAL state.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_DOMAIN object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_domain_initial_state_enter(
+   SCI_BASE_OBJECT_T * object
+)
+{
+   SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T *)object;
+
+   SET_STATE_HANDLER(
+      fw_domain,
+      scif_sas_domain_state_handler_table,
+      SCI_BASE_DOMAIN_STATE_INITIAL
+   );
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_domain),
+      SCIF_LOG_OBJECT_DOMAIN,
+      "scif_sas_domain_initial_state_enter(0x%x) enter\n",
+      fw_domain
+   ));
+}
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        STARTING state.  This includes setting the state handlers and
+ *        checking to see if the core port has already become READY.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_DOMAIN object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_domain_starting_state_enter(
+   SCI_BASE_OBJECT_T * object
+)
+{
+   SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T *)object;
+
+   SET_STATE_HANDLER(
+      fw_domain,
+      scif_sas_domain_state_handler_table,
+      SCI_BASE_DOMAIN_STATE_STARTING
+   );
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_domain),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_domain_starting_state_enter(0x%x) enter\n",
+      fw_domain
+   ));
+
+   scif_sas_domain_transition_from_discovering_state(fw_domain);
+
+   // If we entered the STARTING state and the core port is actually ready,
+   // then directly transition into the READY state.  This can occur
+   // if we were in the middle of discovery when the port failed
+   // (causing a transition to STOPPING), then before reaching STOPPED
+   // the port becomes ready again.
+   if (fw_domain->is_port_ready == TRUE)
+   {
+      sci_base_state_machine_change_state(
+         &fw_domain->parent.state_machine, SCI_BASE_DOMAIN_STATE_READY
+      );
+   }
+}
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        READY state.  If the transition into this state came from:
+ *        - the STARTING state, then alert the user via a
+ *          scif_cb_domain_change_notification() that the domain
+ *          has at least 1 device ready for discovery.
+ *        - the DISCOVERING state, then alert the user that
+ *          discovery is complete via the
+ *          scif_cb_domain_discovery_complete() notification that
+ *          discovery is finished.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_DOMAIN object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_domain_ready_state_enter(
+   SCI_BASE_OBJECT_T * object
+)
+{
+   SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T *)object;
+
+   SET_STATE_HANDLER(
+      fw_domain,
+      scif_sas_domain_state_handler_table,
+      SCI_BASE_DOMAIN_STATE_READY
+   );
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_domain),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_domain_ready_state_enter(0x%x) enter\n",
+      fw_domain
+   ));
+
+   if (fw_domain->parent.state_machine.previous_state_id
+       == SCI_BASE_DOMAIN_STATE_STARTING)
+   {
+      scif_cb_domain_ready(fw_domain->controller, fw_domain);
+
+      // Only indicate the domain change notification if the previous
+      // state was the STARTING state.  We issue the notification here
+      // as opposed to exit of the STARTING state so that the appropriate
+      // state handlers are in place should the user call
+      // scif_domain_discover() from scif_cb_domain_change_notification()
+      scif_cb_domain_change_notification(fw_domain->controller, fw_domain);
+   }
+   else if (fw_domain->parent.state_machine.previous_state_id
+            == SCI_BASE_DOMAIN_STATE_DISCOVERING)
+   {
+      //if domain discovery timed out, we will NOT go back to discover even
+      //the broadcast change count is not zero. Instead we finish the discovery
+      //back to user. User can check the operation status and decide to
+      //retry discover all over again.
+      if (fw_domain->operation.status == SCI_FAILURE_TIMEOUT)
+         fw_domain->broadcast_change_count = 0;
+
+      // Check the broadcast change count to determine if discovery
+      // is indeed complete.
+      if (fw_domain->broadcast_change_count == 0)
+      {
+         scif_sas_domain_transition_from_discovering_state(fw_domain);
+         scif_cb_domain_ready(fw_domain->controller, fw_domain);
+      }
+      else
+      {
+         // The broadcast change count indicates something my have
+         // changed in the domain, while a discovery was ongoing.
+         // Thus, we should start discovery over again.
+         sci_base_state_machine_change_state(
+            &fw_domain->parent.state_machine, SCI_BASE_DOMAIN_STATE_DISCOVERING
+         );
+      }
+
+      // Enable the BCN because underneath hardware may disabled any further
+      // BCN.
+      scic_port_enable_broadcast_change_notification(fw_domain->core_object);
+   }
+}
+
+/**
+ * @brief This method implements the actions taken when exiting the
+ *        READY state.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_DOMAIN object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_domain_ready_state_exit(
+   SCI_BASE_OBJECT_T * object
+)
+{
+   SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T *)object;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_domain),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_domain_ready_state_exit(0x%x) enter\n",
+      fw_domain
+   ));
+
+   scif_cb_domain_not_ready(fw_domain->controller, fw_domain);
+}
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        STOPPING state.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_DOMAIN object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_domain_stopping_state_enter(
+   SCI_BASE_OBJECT_T * object
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device;
+   SCIF_SAS_DOMAIN_T        * fw_domain = (SCIF_SAS_DOMAIN_T *)object;
+   SCI_ABSTRACT_ELEMENT_T   * element   = sci_abstract_list_get_front(
+                                             &fw_domain->remote_device_list
+                                          );
+
+   SET_STATE_HANDLER(
+      fw_domain,
+      scif_sas_domain_state_handler_table,
+      SCI_BASE_DOMAIN_STATE_STOPPING
+   );
+
+   // This must be invoked after the state handlers are set to ensure
+   // appropriate processing will occur if the user attempts to perform
+   // additional actions.
+   scif_sas_domain_transition_from_discovering_state(fw_domain);
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_domain),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_domain_stopping_state_enter(0x%x) enter\n",
+      fw_domain
+   ));
+
+   scif_sas_high_priority_request_queue_purge_domain(
+      &fw_domain->controller->hprq, fw_domain
+   );
+
+   // Search the domain's list of devices and put them all in the STOPPING
+   // state.
+   while (element != NULL)
+   {
+      fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
+                  sci_abstract_list_get_object(element);
+
+      // This method will stop the core device.  The core will terminate
+      // all IO requests currently outstanding.
+      fw_device->state_handlers->parent.stop_handler(&fw_device->parent);
+
+      element = sci_abstract_list_get_next(element);
+   }
+
+   // Attempt to transition to the stopped state.
+   scif_sas_domain_transition_to_stopped_state(fw_domain);
+}
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        STOPPED state.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_DOMAIN object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_domain_stopped_state_enter(
+   SCI_BASE_OBJECT_T * object
+)
+{
+   SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T *)object;
+
+   SET_STATE_HANDLER(
+      fw_domain,
+      scif_sas_domain_state_handler_table,
+      SCI_BASE_DOMAIN_STATE_STOPPED
+   );
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_domain),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_domain_stopped_state_enter(0x%x) enter\n",
+      fw_domain
+   ));
+
+   // A hot unplug of the direct attached device has occurred.  Thus,
+   // notify the user. Note, if the controller is not in READY state,
+   // mostly likely the controller is in STOPPING or STOPPED state,
+   // meaning the controller is in the process of stopping, we should
+   // not call back to user in the middle of controller stopping.
+   if(fw_domain->controller->parent.state_machine.current_state_id
+         == SCI_BASE_CONTROLLER_STATE_READY)
+      scif_cb_domain_change_notification(fw_domain->controller, fw_domain);
+}
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        DISCOVERING state.  This includes determining from which
+ *        state we entered.  If we entered from stopping that some sort
+ *        of hot-remove of the port occurred.  In the hot-remove case
+ *        all devices should be in the STOPPED state already and, as
+ *        a result, are removed from the domain with a notification sent
+ *        to the framework user.
+ *
+ * @note This method currently only handles hot-insert/hot-remove of
+ *       direct attached SSP devices.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_DOMAIN object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_domain_discovering_state_enter(
+   SCI_BASE_OBJECT_T * object
+)
+{
+   SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T *)object;
+
+   SET_STATE_HANDLER(
+      fw_domain,
+      scif_sas_domain_state_handler_table,
+      SCI_BASE_DOMAIN_STATE_DISCOVERING
+   );
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_domain),
+      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_domain_discovering_state_enter(0x%x) enter\n",
+      fw_domain
+   ));
+
+   fw_domain->broadcast_change_count = 0;
+
+   // Did the domain just go through a port not ready action?  If it did,
+   // then we will be entering from the STOPPED state.
+   if (fw_domain->parent.state_machine.previous_state_id
+       != SCI_BASE_DOMAIN_STATE_STOPPED)
+   {
+      SCIF_SAS_REMOTE_DEVICE_T * remote_device;
+      SCIC_PORT_PROPERTIES_T     properties;
+
+      scic_port_get_properties(fw_domain->core_object, &properties);
+
+      // If the device has not yet been added to the domain, then
+      // inform the user that the device is new.
+      remote_device = (SCIF_SAS_REMOTE_DEVICE_T *)
+                      scif_domain_get_device_by_sas_address(
+                         fw_domain, &properties.remote.sas_address
+                      );
+      if (remote_device == SCI_INVALID_HANDLE)
+      {
+         // simply notify the user of the new DA device and be done
+         // with discovery.
+         scif_cb_domain_da_device_added(
+            fw_domain->controller,
+            fw_domain,
+            &properties.remote.sas_address,
+            &properties.remote.protocols
+         );
+      }
+      else
+      {
+         if(properties.remote.protocols.u.bits.smp_target)
+            //kick off the smp discover process.
+            scif_sas_domain_start_smp_discover(fw_domain, remote_device);
+      }
+   }
+   else  //entered from STOPPED state.
+   {
+      SCI_ABSTRACT_ELEMENT_T * current_element =
+             sci_abstract_list_get_front(&(fw_domain->remote_device_list) );
+
+      SCIF_SAS_REMOTE_DEVICE_T * fw_device;
+
+      while (current_element != NULL)
+      {
+         fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)
+                     sci_abstract_list_get_object(current_element);
+
+         ASSERT(fw_device->parent.state_machine.current_state_id
+                == SCI_BASE_REMOTE_DEVICE_STATE_STOPPED);
+
+         current_element =
+            sci_abstract_list_get_next(current_element);
+
+         SCIF_LOG_INFO((
+            sci_base_object_get_logger(fw_domain),
+            SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+            "Controller:0x%x Domain:0x%x Device:0x%x removed\n",
+            fw_domain->controller, fw_domain, fw_device
+         ));
+
+         // Notify the framework user of the device removal.
+         scif_cb_domain_device_removed(
+            fw_domain->controller, fw_domain, fw_device
+         );
+      }
+
+      ASSERT(fw_domain->request_list.element_count == 0);
+      ASSERT(sci_abstract_list_size(&fw_domain->remote_device_list) == 0);
+
+      sci_base_state_machine_change_state(
+         &fw_domain->parent.state_machine, SCI_BASE_DOMAIN_STATE_STARTING
+      );
+   }
+}
+
+SCI_BASE_STATE_T scif_sas_domain_state_table[SCI_BASE_DOMAIN_MAX_STATES] =
+{
+   {
+      SCI_BASE_DOMAIN_STATE_INITIAL,
+      scif_sas_domain_initial_state_enter,
+      NULL,
+   },
+   {
+      SCI_BASE_DOMAIN_STATE_STARTING,
+      scif_sas_domain_starting_state_enter,
+      NULL,
+   },
+   {
+      SCI_BASE_DOMAIN_STATE_READY,
+      scif_sas_domain_ready_state_enter,
+      scif_sas_domain_ready_state_exit,
+   },
+   {
+      SCI_BASE_DOMAIN_STATE_STOPPING,
+      scif_sas_domain_stopping_state_enter,
+      NULL,
+   },
+   {
+      SCI_BASE_DOMAIN_STATE_STOPPED,
+      scif_sas_domain_stopped_state_enter,
+      NULL,
+   },
+   {
+      SCI_BASE_DOMAIN_STATE_DISCOVERING,
+      scif_sas_domain_discovering_state_enter,
+      NULL,
+   }
+};
diff --git a/sys/dev/disk/isci/scil/scif_sas_high_priority_request_queue.c b/sys/dev/disk/isci/scil/scif_sas_high_priority_request_queue.c
new file mode 100644
index 0000000..21ed1e6
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_high_priority_request_queue.c
@@ -0,0 +1,159 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_high_priority_request_queue.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains all of method implementations specific to
+ *        the high priority request queue (HPRQ).  See the
+ *        scif_sas_high_priority_request_queue.h file for additional
+ *        information.
+ */
+
+#include <dev/disk/isci/scil/scif_sas_high_priority_request_queue.h>
+
+#include <dev/disk/isci/scil/scif_sas_logger.h>
+#include <dev/disk/isci/scil/scif_sas_io_request.h>
+#include <dev/disk/isci/scil/scif_sas_controller.h>
+
+/**
+ * @brief This method initializes the fields of the HPRQ.  It should be
+ *        called during the construction of the object containing or
+ *        utilizing it (i.e. SCIF_SAS_CONTROLLER).
+ *
+ * @param[in] fw_hprq This parameter specific the high priority request
+ *            queue object being constructed.
+ *
+ * @return none
+ */
+void scif_sas_high_priority_request_queue_construct(
+   SCIF_SAS_HIGH_PRIORITY_REQUEST_QUEUE_T * fw_hprq,
+   SCI_BASE_LOGGER_T                      * logger
+)
+{
+   SCIF_LOG_TRACE((
+      logger,
+      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_high_priority_request_queue_construct(0x%x,0x%x) enter\n",
+      fw_hprq, logger
+   ));
+
+   sci_base_object_construct((SCI_BASE_OBJECT_T*) &fw_hprq->lock, logger);
+   fw_hprq->lock.level = SCI_LOCK_LEVEL_NONE;
+
+   sci_pool_initialize(fw_hprq->pool);
+}
+
+/**
+ * @brief This method will ensure all internal requests destined for
+ *        devices contained in the supplied domain are properly removed
+ *        from the high priority request queue.
+ *
+ * @param[in] fw_hprq This parameter specifies the high priority request
+ *            queue object for which to attempt to remove elements.
+ * @param[in] fw_domain This parameter specifies the domain for which to
+ *            remove all high priority requests.
+ *
+ * @return none
+ */
+void scif_sas_high_priority_request_queue_purge_domain(
+   SCIF_SAS_HIGH_PRIORITY_REQUEST_QUEUE_T * fw_hprq,
+   SCIF_SAS_DOMAIN_T                      * fw_domain
+)
+{
+   SCIF_SAS_IO_REQUEST_T * fw_io;
+   POINTER_UINT            io_address;
+   U32                     index;
+   U32                     element_count;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(&fw_hprq->lock),
+      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_high_priority_request_queue_purge_domain(0x%x,0x%x) enter\n",
+      fw_hprq, fw_domain
+   ));
+
+   element_count = sci_pool_count(fw_hprq->pool);
+
+   scif_cb_lock_acquire(fw_domain->controller, &fw_hprq->lock);
+
+   for (index = 0; index < element_count; index++)
+   {
+      sci_pool_get(fw_hprq->pool, io_address);
+
+      fw_io = (SCIF_SAS_IO_REQUEST_T*) io_address;
+
+      // If the high priority request is not intended for this domain,
+      // then it can be left in the pool.
+      if (fw_io->parent.device->domain != fw_domain)
+      {
+         sci_pool_put(fw_hprq->pool, io_address);
+      }
+      else
+      {
+         if (fw_io->parent.is_internal)
+         {
+            SCIF_SAS_INTERNAL_IO_REQUEST_T * fw_internal_io =
+               (SCIF_SAS_INTERNAL_IO_REQUEST_T *)fw_io;
+
+            // The request was intended for a device in the domain.  Put it
+            // back in the pool of freely available internal request memory
+            // objects. The internal IO's timer is to be destoyed.
+            scif_sas_internal_io_request_destruct(fw_domain->controller, fw_internal_io);
+         }
+      }
+   }
+
+   scif_cb_lock_release(fw_domain->controller, &fw_hprq->lock);
+}
diff --git a/sys/dev/disk/isci/scil/scif_sas_high_priority_request_queue.h b/sys/dev/disk/isci/scil/scif_sas_high_priority_request_queue.h
new file mode 100644
index 0000000..59f1112
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_high_priority_request_queue.h
@@ -0,0 +1,123 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_high_priority_request_queue.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIF_SAS_HIGH_PRIORITY_REQUEST_QUEUE_H_
+#define _SCIF_SAS_HIGH_PRIORITY_REQUEST_QUEUE_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of method prototypes and type
+ *        definitions specific to the high priority request queue (HPRQ).
+ *        The HPRQ is the mechanism through which internal requests or
+ *        other important requests created by the framework are stored.
+ *        The HPRQ is checked during the scif_controller_start_io() path
+ *        and is given precedence over user supplied IO requests.
+ *        Additionally, when requests are created there is an attempt to
+ *        start them quickly.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/sci_base_object.h>
+#include <dev/disk/isci/scil/sci_pool.h>
+#include <dev/disk/isci/scil/scif_sas_domain.h>
+#include <dev/disk/isci/scil/scif_sas_internal_io_request.h>
+
+typedef struct SCIF_SAS_LOCK
+{
+   SCI_BASE_OBJECT_T parent;
+
+   SCI_LOCK_LEVEL    level;
+
+} SCIF_SAS_LOCK_T;
+
+/**
+ * @struct SCIF_SAS_HIGH_PRIORITY_REQUEST_QUEUE_T
+ *
+ * @brief This structure depicts the fields contain in the high
+ *        priority request queue (HPRQ) object.  The HPRQ is used
+ *        to store IO or task requests that need to be completed
+ *        in short order.
+ */
+typedef struct SCIF_SAS_HIGH_PRIORITY_REQUEST_QUEUE
+{
+   /**
+    * This field specifies the necessary lock information (e.g. level)
+    * that must be taken before items are added or removed from the
+    * queue.
+    */
+   SCIF_SAS_LOCK_T  lock;
+
+   SCI_POOL_CREATE(pool, POINTER_UINT, SCIF_SAS_MAX_INTERNAL_REQUEST_COUNT);
+
+} SCIF_SAS_HIGH_PRIORITY_REQUEST_QUEUE_T;
+
+void scif_sas_high_priority_request_queue_construct(
+   SCIF_SAS_HIGH_PRIORITY_REQUEST_QUEUE_T * fw_hprq,
+   SCI_BASE_LOGGER_T                      * logger
+);
+
+void scif_sas_high_priority_request_queue_purge_domain(
+   SCIF_SAS_HIGH_PRIORITY_REQUEST_QUEUE_T * fw_hprq,
+   SCIF_SAS_DOMAIN_T                      * fw_domain
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIF_SAS_HIGH_PRIORITY_REQUEST_QUEUE_H_
diff --git a/sys/dev/disk/isci/scil/scif_sas_internal_io_request.c b/sys/dev/disk/isci/scil/scif_sas_internal_io_request.c
new file mode 100644
index 0000000..9d95d7f
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_internal_io_request.c
@@ -0,0 +1,280 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_internal_io_request.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains the implementation of the
+ *        SCIF_SAS_INTERNAL_IO_REQUEST object.
+ */
+
+
+#include <dev/disk/isci/scil/scic_io_request.h>
+#include <dev/disk/isci/scil/scic_remote_device.h>
+#include <dev/disk/isci/scil/scic_user_callback.h>
+#include <dev/disk/isci/scil/scic_controller.h>
+#include <dev/disk/isci/scil/scic_task_request.h>
+#include <dev/disk/isci/scil/scif_user_callback.h>
+
+#include <dev/disk/isci/scil/scif_sas_controller.h>
+#include <dev/disk/isci/scil/scif_sas_domain.h>
+#include <dev/disk/isci/scil/scif_sas_remote_device.h>
+#include <dev/disk/isci/scil/scif_sas_io_request.h>
+#include <dev/disk/isci/scil/scif_sas_internal_io_request.h>
+#include <dev/disk/isci/scil/scif_sas_task_request.h>
+#include <dev/disk/isci/scil/scif_sas_stp_io_request.h>
+#include <dev/disk/isci/scil/scif_sas_logger.h>
+#include <dev/disk/isci/scil/scif_sas_smp_io_request.h>
+#include <dev/disk/isci/scil/sci_util.h>
+
+//******************************************************************************
+//* P U B L I C   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief this routine return all memory needed for an internal request, both
+ *        framework and core request.
+ *
+ * @return U32 size of all memory needed for an internal request
+ */
+U32 scif_sas_internal_request_get_object_size(
+   void
+)
+{
+   return MAX(
+            (sizeof(SCIF_SAS_INTERNAL_IO_REQUEST_T) + scic_io_request_get_object_size()),
+            (sizeof(SCIF_SAS_TASK_REQUEST_T) + scic_task_request_get_object_size())
+             );
+}
+
+
+/**
+ * @brief This method constructs an internal smp request.
+ *
+ * @param[in] fw_controller The framework controller
+ * @param[in] fw_device The smp device that the internal io targets to.
+ * @param[in] internal_io_memory The memory space for the internal io.
+ * @param[in] io_tag The io tag for the internl io to be constructed.
+ * @param[in] smp_command A pointer to the smp request data structure according
+ *       to SAS protocol.
+ *
+ * @return Indicate if the internal io was successfully constructed.
+ * @retval SCI_SUCCESS This value is returned if the internal io was
+ *         successfully constructed.
+ * @retval SCI_FAILURE This value is returned if the internal io was failed to
+ *         be constructed.
+ */
+SCI_STATUS scif_sas_internal_io_request_construct_smp(
+   SCIF_SAS_CONTROLLER_T       * fw_controller,
+   SCIF_SAS_REMOTE_DEVICE_T    * fw_device,
+   void                        * internal_io_memory,
+   U16                           io_tag,
+   SMP_REQUEST_T               * smp_command
+)
+{
+   SCIF_SAS_INTERNAL_IO_REQUEST_T * fw_internal_io  =
+     (SCIF_SAS_INTERNAL_IO_REQUEST_T*)internal_io_memory;
+
+   SCIF_SAS_IO_REQUEST_T * fw_io =
+     (SCIF_SAS_IO_REQUEST_T*)internal_io_memory;
+
+   SCI_STATUS status;
+
+   //call common smp request construct routine.
+   status = scif_sas_io_request_construct_smp(
+               fw_controller,
+               fw_device,
+               internal_io_memory,
+               (char *)internal_io_memory + sizeof(SCIF_SAS_INTERNAL_IO_REQUEST_T),
+               SCI_CONTROLLER_INVALID_IO_TAG,
+               smp_command,
+               NULL //there is no associated user io object.
+            );
+
+   //Codes below are all internal io related.
+   if (status == SCI_SUCCESS)
+   {
+      //set the is_internal flag
+      fw_io->parent.is_internal = TRUE;
+
+      if (fw_internal_io->internal_io_timer == NULL)
+      {
+         //create the timer for this internal request.
+         fw_internal_io->internal_io_timer =
+            scif_cb_timer_create(
+               (SCI_CONTROLLER_HANDLE_T *)fw_controller,
+               scif_sas_internal_io_request_timeout_handler,
+               (void*)fw_io
+            );
+      }
+      else
+      {
+         ASSERT (0);
+      }
+
+      //insert into high priority queue
+      if ( !sci_pool_full(fw_controller->hprq.pool) )
+      {
+         sci_pool_put(
+            fw_controller->hprq.pool, (POINTER_UINT) internal_io_memory
+         );
+      }
+      else
+      {
+         SCIF_LOG_ERROR((
+            sci_base_object_get_logger(fw_controller),
+            SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_REMOTE_DEVICE,
+            "scif_sas_internal_io_request_construct_smp, high priority queue full!\n"
+         ));
+
+         scif_sas_internal_io_request_destruct(fw_controller, fw_internal_io);
+
+         //return failure status.
+         return SCI_FAILURE_INSUFFICIENT_RESOURCES;
+      }
+   }
+
+   return status;
+}
+
+
+/**
+ * @brief This method constructs an internal smp request.
+ * @param[in] fw_io
+ *
+ * @return SCI_STATUS
+ */
+SCI_STATUS scif_sas_internal_io_request_construct_stp(
+   SCIF_SAS_INTERNAL_IO_REQUEST_T * fw_io
+)
+{
+   //TBD
+   return SCI_SUCCESS;
+}
+
+
+/**
+ * @brief This method handles the timeout situation for an internal io.
+ *
+ * @param[in] fw_internal_io The timed out IO.
+ *
+ * @return none
+ */
+void scif_sas_internal_io_request_timeout_handler(
+   void * fw_internal_io
+)
+{
+   SCIF_SAS_REQUEST_T * fw_request = (SCIF_SAS_REQUEST_T *)fw_internal_io;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_request),
+      SCIF_LOG_OBJECT_IO_REQUEST,
+      "scif_sas_internal_io_request_timeout_handler(0x%x) enter\n",
+      fw_internal_io
+   ));
+
+   fw_request->state_handlers->abort_handler(&fw_request->parent);
+}
+
+
+/**
+ * @brief This methods takes care of completion of an internal request about its
+ *        "internal" related feature, including the memory recycling and timer.
+ *
+ * @param[in] fw_controller The framework controller object.
+ * @param[in] fw_internal_io The internal io to be completed.
+ * @param[in] completion_status the completeion status by core and framework so
+ *       far.
+ *
+ * @return none
+ */
+void scif_sas_internal_io_request_complete(
+   SCIF_SAS_CONTROLLER_T          * fw_controller,
+   SCIF_SAS_INTERNAL_IO_REQUEST_T * fw_internal_io,
+   SCI_STATUS                       completion_status
+)
+{
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_controller),
+      SCIF_LOG_OBJECT_IO_REQUEST,
+      "scif_sas_internal_io_request_complete(0x%x, 0x%x, 0x%x) enter\n",
+       fw_controller, fw_internal_io, completion_status
+   ));
+
+   scif_cb_timer_stop(fw_controller, fw_internal_io->internal_io_timer);
+   scif_sas_internal_io_request_destruct(fw_controller, fw_internal_io);
+}
+
+
+/**
+ * @brief This methods takes care of destruction of an internal request about its
+ *        "internal" related feature, including the memory recycling and timer.
+ *
+ * @param[in] fw_controller The framework controller object.
+ * @param[in] fw_internal_io The internal io to be completed.
+ *
+ * @return none
+ */
+void scif_sas_internal_io_request_destruct(
+   SCIF_SAS_CONTROLLER_T          * fw_controller,
+   SCIF_SAS_INTERNAL_IO_REQUEST_T * fw_internal_io
+)
+{
+   if (fw_internal_io->internal_io_timer != NULL)
+   {
+      scif_cb_timer_destroy(fw_controller, fw_internal_io->internal_io_timer);
+      fw_internal_io->internal_io_timer = NULL;
+   }
+   scif_sas_controller_free_internal_request(fw_controller, fw_internal_io);
+}
diff --git a/sys/dev/disk/isci/scil/scif_sas_internal_io_request.h b/sys/dev/disk/isci/scil/scif_sas_internal_io_request.h
new file mode 100644
index 0000000..727cd8d
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_internal_io_request.h
@@ -0,0 +1,156 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_internal_io_request.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIF_SAS_INTERNAL_REQUEST_H_
+#define _SCIF_SAS_INTERNAL_REQUEST_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains the protected interface structures, constants,
+ *        and methods for the SCIF_SAS_INTERNAL_REQUEST object.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+
+#include <dev/disk/isci/scil/scif_io_request.h>
+#include <dev/disk/isci/scil/sci_base_request.h>
+#include <dev/disk/isci/scil/scif_sas_request.h>
+#include <dev/disk/isci/scil/scif_sas_io_request.h>
+#include <dev/disk/isci/scil/scif_sas_remote_device.h>
+#include <dev/disk/isci/scil/intel_sas.h>
+#include <dev/disk/isci/scil/sci_controller_constants.h>
+
+struct SCIF_SAS_CONTROLLER;
+
+/**
+ * This constant dictates the maximum number of internal framework
+ *  IO request objects.  These objects are used for internal SMP requests
+ *  and for NCQ error handling.
+ */
+#define SCIF_SAS_MAX_INTERNAL_REQUEST_COUNT (SCI_MAX_DOMAINS*4)
+
+/**
+ * This constant dictates the minimum number of internal framework
+ *  IO request objects when size-constrained.
+ */
+#define SCIF_SAS_MIN_INTERNAL_REQUEST_COUNT (SCI_MAX_DOMAINS)
+
+/*
+ * This constant indicates the timeout value of an internal IO request
+ * in mili-seconds.
+ */
+#define SCIF_SAS_INTERNAL_REQUEST_TIMEOUT   3000
+
+/**
+ * @struct SCIF_SAS_INTERNAL_IO_REQUEST
+ *
+ * @brief The SCIF_SAS_INTERNAL_IO_REQUEST object represents the internal SAS
+ *        IO request behavior for the framework component.
+ */
+typedef struct SCIF_SAS_INTERNAL_IO_REQUEST
+{
+   /**
+    * The SCIF_SAS_IO_REQUEST is the parent object for the
+    * SCIF_SAS_INTERNAL_IO_REQUEST object.
+    */
+   SCIF_SAS_IO_REQUEST_T  parent;
+
+   /**
+    * This field will be utilized only by internal IO to handle timeout
+    * situation.
+    */
+   void * internal_io_timer;
+
+}SCIF_SAS_INTERNAL_IO_REQUEST_T;
+
+
+U32 scif_sas_internal_request_get_object_size(
+   void
+);
+
+SCI_STATUS scif_sas_internal_io_request_construct_smp(
+   struct SCIF_SAS_CONTROLLER  * fw_controller,
+   SCIF_SAS_REMOTE_DEVICE_T    * fw_remote_device,
+   void                        * internal_io_memory,
+   U16                           io_tag,
+   SMP_REQUEST_T               * smp_command
+);
+
+SCI_STATUS scif_sas_internal_io_request_construct_stp(
+   SCIF_SAS_INTERNAL_IO_REQUEST_T * fw_io
+);
+
+void scif_sas_internal_io_request_timeout_handler(
+   void * fw_io
+);
+
+void scif_sas_internal_io_request_complete(
+   struct SCIF_SAS_CONTROLLER     * fw_controller,
+   SCIF_SAS_INTERNAL_IO_REQUEST_T * fw_io,
+   SCI_STATUS                       completion_status
+);
+
+void scif_sas_internal_io_request_destruct(
+   struct SCIF_SAS_CONTROLLER     * fw_controller,
+   SCIF_SAS_INTERNAL_IO_REQUEST_T * fw_internal_io
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIF_SAS_IO_REQUEST_H_
diff --git a/sys/dev/disk/isci/scil/scif_sas_io_request.c b/sys/dev/disk/isci/scil/scif_sas_io_request.c
new file mode 100644
index 0000000..067bf3e
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_io_request.c
@@ -0,0 +1,819 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_io_request.c,v 1.2 2012/02/09 17:50:24 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains the implementation of the SCIF_SAS_IO_REQUEST
+ *        object.
+ */
+
+
+#include <dev/disk/isci/scil/scic_io_request.h>
+#include <dev/disk/isci/scil/scic_remote_device.h>
+#include <dev/disk/isci/scil/scic_user_callback.h>
+#include <dev/disk/isci/scil/scic_controller.h>
+#include <dev/disk/isci/scil/scif_user_callback.h>
+
+#include <dev/disk/isci/scil/scif_sas_controller.h>
+#include <dev/disk/isci/scil/scif_sas_domain.h>
+#include <dev/disk/isci/scil/scif_sas_remote_device.h>
+#include <dev/disk/isci/scil/scif_sas_io_request.h>
+#include <dev/disk/isci/scil/scif_sas_task_request.h>
+#include <dev/disk/isci/scil/scif_sas_stp_io_request.h>
+#include <dev/disk/isci/scil/scif_sas_logger.h>
+#include <dev/disk/isci/scil/scif_sas_smp_io_request.h>
+#include <dev/disk/isci/scil/sci_fast_list.h>
+#include <dev/disk/isci/scil/sati.h>
+#include <dev/disk/isci/scil/intel_sat.h>
+#include <dev/disk/isci/scil/sati_translator_sequence.h>
+
+/**
+ * @brief This method represents common functionality for the
+ *        scif_io_request_construct() and scif_sas_io_request_continue()
+ *        methods.
+ *
+ * @return This method returns an indication as to whether the
+ *         construction succeeded.
+ */
+static
+SCI_STATUS scif_sas_io_request_construct(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   SCIF_SAS_IO_REQUEST_T    * fw_io,
+   U16                        io_tag,
+   void                     * user_io_request_object,
+   SCI_IO_REQUEST_HANDLE_T  * scif_io_request,
+   BOOL                       is_initial_construction
+)
+{
+   SCI_STATUS                         status;
+   SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;
+
+   scic_remote_device_get_protocols(fw_device->core_object, &dev_protocols);
+
+   //Currently, all the io requests sent to smp target are internal.
+   //so we fail all the external io toward to it.
+   //Todo: is there a better way to handle external io to smp target?
+   if (dev_protocols.u.bits.attached_smp_target)
+      return SCI_FAILURE_INVALID_REMOTE_DEVICE;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_IO_REQUEST,
+      "scif_sas_io_request_construct(0x%x,0x%x,0x%x,0x%x,0x%x,0x%x) enter\n",
+      fw_device, fw_io, io_tag, user_io_request_object, scif_io_request,
+      is_initial_construction
+   ));
+
+   // Initialize the users handle to the framework IO request.
+   *scif_io_request = fw_io;
+
+   // Construct the parent object first in order to ensure logging can
+   // function.
+   scif_sas_request_construct(
+      &fw_io->parent,
+      fw_device,
+      sci_base_object_get_logger(fw_device),
+      scif_sas_io_request_state_table
+   );
+
+   status = scic_io_request_construct(
+               fw_device->domain->controller->core_object,
+               fw_device->core_object,
+               io_tag,
+               fw_io,
+               ((U8 *)fw_io) + sizeof(SCIF_SAS_IO_REQUEST_T),
+               &fw_io->parent.core_object
+            );
+
+   if (status == SCI_SUCCESS)
+   {
+      // These associations must be set early for the core io request
+      // object construction to complete correctly as there will be
+      // callbacks into the user driver framework during core construction
+      sci_object_set_association(fw_io, user_io_request_object);
+      sci_object_set_association(fw_io->parent.core_object, fw_io);
+
+      // Perform protocol specific core IO request construction.
+      if (dev_protocols.u.bits.attached_ssp_target)
+         status = scic_io_request_construct_basic_ssp(fw_io->parent.core_object);
+      else if (dev_protocols.u.bits.attached_stp_target)
+      {
+         if (is_initial_construction == TRUE)
+               sati_sequence_construct(&fw_io->parent.stp.sequence);
+
+#if !defined(DISABLE_ATAPI)
+         if (!scic_remote_device_is_atapi(fw_device->core_object))
+         {
+#endif
+            status = scif_sas_stp_io_request_construct(fw_io);
+
+#if !defined(DISABLE_ATAPI)
+         }
+         else
+            status = scif_sas_stp_packet_io_request_construct(fw_io);
+#endif
+      }
+
+      sci_base_state_machine_logger_initialize(
+         &fw_io->parent.parent.state_machine_logger,
+         &fw_io->parent.parent.state_machine,
+         &fw_io->parent.parent.parent,
+         scif_cb_logger_log_states,
+         "SCIF_IO_REQUEST_T", "base_state_machine",
+         SCIF_LOG_OBJECT_IO_REQUEST
+      );
+   }
+
+   return status;
+}
+
+//******************************************************************************
+//* P U B L I C   M E T H O D S
+//******************************************************************************
+
+U32 scif_io_request_get_object_size(
+   void
+)
+{
+   return (sizeof(SCIF_SAS_IO_REQUEST_T) + scic_io_request_get_object_size());
+}
+
+// ----------------------------------------------------------------------------
+U32 scif_io_request_get_number_of_bytes_transferred(
+   SCI_IO_REQUEST_HANDLE_T  scif_io_request
+)
+{
+   SCIF_SAS_IO_REQUEST_T * fw_request = (SCIF_SAS_IO_REQUEST_T*) scif_io_request;
+
+   if(scic_io_request_get_protocol(scif_io_request_get_scic_handle(scif_io_request))
+       == SCIC_STP_PROTOCOL)
+   {
+      U16 sati_data_bytes_set =
+             sati_get_number_data_bytes_set(&(fw_request->parent.stp.sequence));
+
+      if (sati_data_bytes_set != 0)
+         return sati_data_bytes_set;
+      else
+      {
+#if !defined(DISABLE_ATAPI)
+         U8 sat_protocol = fw_request->parent.stp.sequence.protocol;
+         if ( sat_protocol & SAT_PROTOCOL_PACKET)
+            return
+               scif_sas_stp_packet_io_request_get_number_of_bytes_transferred(fw_request);
+         else
+#endif
+            return scic_io_request_get_number_of_bytes_transferred(
+                      scif_io_request_get_scic_handle(scif_io_request));
+      }
+   }
+   else
+   {
+      return scic_io_request_get_number_of_bytes_transferred(
+                scif_io_request_get_scic_handle(scif_io_request));
+   }
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scif_io_request_construct(
+   SCI_CONTROLLER_HANDLE_T      scif_controller,
+   SCI_REMOTE_DEVICE_HANDLE_T   scif_remote_device,
+   U16                          io_tag,
+   void                       * user_io_request_object,
+   void                       * io_request_memory,
+   SCI_IO_REQUEST_HANDLE_T    * scif_io_request
+)
+{
+   SCIF_SAS_IO_REQUEST_T    * fw_io     = (SCIF_SAS_IO_REQUEST_T*)
+                                          io_request_memory;
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
+                                          scif_remote_device;
+
+   return scif_sas_io_request_construct(
+             fw_device,
+             fw_io,
+             io_tag,
+             user_io_request_object,
+             scif_io_request,
+             TRUE
+          );
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scif_request_construct(
+   SCI_CONTROLLER_HANDLE_T      scif_controller,
+   SCI_REMOTE_DEVICE_HANDLE_T   scif_remote_device,
+   U16                          io_tag,
+   void                       * user_io_request_object,
+   void                       * io_request_memory,
+   SCI_IO_REQUEST_HANDLE_T    * scif_io_request
+)
+{
+   SCIF_SAS_IO_REQUEST_T    * fw_io     = (SCIF_SAS_IO_REQUEST_T*)
+                                          io_request_memory;
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
+                                          scif_remote_device;
+   SCI_STATUS                 status;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_IO_REQUEST,
+      "scif_io_request_construct(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x) enter\n",
+      scif_controller, scif_remote_device, io_tag, user_io_request_object,
+      io_request_memory, scif_io_request
+   ));
+
+   // Step 1: Create the scif io request.
+   // Initialize the users handle to the framework IO request.
+   *scif_io_request = fw_io;
+
+   // Construct the parent object first in order to ensure logging can
+   // function.
+   scif_sas_request_construct(
+      &fw_io->parent,
+      fw_device,
+      sci_base_object_get_logger(fw_device),
+      scif_sas_io_request_state_table
+   );
+
+   status = scic_io_request_construct(
+               (void *) ((SCIF_SAS_CONTROLLER_T *)scif_controller)->core_object,
+               (void *) fw_device->core_object,
+               io_tag,
+               fw_io,
+               (U8 *)io_request_memory + sizeof(SCIF_SAS_IO_REQUEST_T),
+               &fw_io->parent.core_object
+            );
+
+   if (status == SCI_SUCCESS)
+   {
+      // These associations must be set early for the core io request
+      // object construction to complete correctly as there will be
+      // callbacks into the user driver framework during core construction
+      sci_object_set_association(fw_io, user_io_request_object);
+      sci_object_set_association(fw_io->parent.core_object, fw_io);
+
+      sci_base_state_machine_logger_initialize(
+         &fw_io->parent.parent.state_machine_logger,
+         &fw_io->parent.parent.state_machine,
+         &fw_io->parent.parent.parent,
+         scif_cb_logger_log_states,
+         "SCIF_IO_REQUEST_T", "base_state_machine",
+         SCIF_LOG_OBJECT_IO_REQUEST
+      );
+   }
+
+   return status;
+}
+
+// ----------------------------------------------------------------------------
+
+SCI_STATUS scif_io_request_construct_with_core (
+   SCI_CONTROLLER_HANDLE_T      scif_controller,
+   SCI_REMOTE_DEVICE_HANDLE_T   scif_remote_device,
+   void                       * scic_io_request,
+   void                       * user_io_request_object,
+   void                       * io_request_memory,
+   SCI_IO_REQUEST_HANDLE_T    * scif_io_request
+)
+{
+   SCIF_SAS_IO_REQUEST_T    * fw_io     = (SCIF_SAS_IO_REQUEST_T*)
+                                          io_request_memory;
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
+                                          scif_remote_device;
+   SCI_STATUS                 status = SCI_SUCCESS;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_IO_REQUEST,
+      "scif_io_request_construct_pass_through(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
+      scif_remote_device, user_io_request_object,
+      io_request_memory, scif_io_request
+   ));
+
+   // Initialize the users handle to the framework IO request.
+   *scif_io_request = fw_io;
+
+   // Construct the parent object first in order to ensure logging can
+   // function.
+   scif_sas_request_construct(
+      &fw_io->parent,
+      fw_device,
+      sci_base_object_get_logger(fw_device),
+      scif_sas_io_request_state_table
+   );
+
+   fw_io->parent.core_object = scic_io_request;
+
+   //set association
+   sci_object_set_association(fw_io, user_io_request_object);
+   sci_object_set_association(fw_io->parent.core_object, fw_io);
+
+
+   sci_base_state_machine_logger_initialize(
+      &fw_io->parent.parent.state_machine_logger,
+      &fw_io->parent.parent.state_machine,
+      &fw_io->parent.parent.parent,
+      scif_cb_logger_log_states,
+      "SCIF_IO_REQUEST_T", "base_state_machine",
+      SCIF_LOG_OBJECT_IO_REQUEST
+   );
+
+   return status;
+}
+
+// ---------------------------------------------------------------------------
+
+void * scif_io_request_get_response_iu_address(
+   SCI_IO_REQUEST_HANDLE_T scif_io_request
+)
+{
+   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*)scif_io_request;
+
+   return (scic_io_request_get_response_iu_address(fw_io->parent.core_object ));
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_IO_REQUEST_HANDLE_T scif_io_request_get_scic_handle(
+   SCI_IO_REQUEST_HANDLE_T scif_io_request
+)
+{
+   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*) scif_io_request;
+   return fw_io->parent.core_object;
+}
+
+// ---------------------------------------------------------------------------
+
+void scic_cb_io_request_complete(
+   SCI_CONTROLLER_HANDLE_T     controller,
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
+   SCI_IO_REQUEST_HANDLE_T     io_request,
+   SCI_IO_STATUS               completion_status
+)
+{
+   SCI_STATUS                 status;
+   SCIF_SAS_CONTROLLER_T    * fw_controller = (SCIF_SAS_CONTROLLER_T*)
+                                      sci_object_get_association(controller);
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
+                                      sci_object_get_association(remote_device);
+   SCIF_SAS_REQUEST_T       * fw_request = (SCIF_SAS_REQUEST_T*)
+                                      sci_object_get_association(io_request);
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(controller),
+      SCIF_LOG_OBJECT_IO_REQUEST,
+      "scic_cb_io_request_complete(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
+      controller, remote_device, io_request, completion_status
+   ));
+
+   // Invoke the common completion handler routine.
+   // A non-successful return indicates we are not in a correct state to
+   // receive a completion notification for this request.
+   status = fw_request->state_handlers->complete_handler(&fw_request->parent);
+
+   // If the status indicates the completion handler was successful, then
+   // allow protocol specific completion processing to occur.
+   if (status == SCI_SUCCESS)
+   {
+      if (fw_request->protocol_complete_handler != NULL)
+      {
+         status = fw_request->protocol_complete_handler(
+                     fw_controller, fw_device, fw_request, (SCI_STATUS *)&completion_status
+                  );
+      }
+
+      // If this isn't an internal framework IO request, then simply pass the
+      // notification up to the SCIF user.
+      if ( status == SCI_SUCCESS )
+      {
+         if (fw_request->is_high_priority == FALSE)
+         {
+            if (fw_request->is_waiting_for_abort_task_set == FALSE)
+            {
+               scif_cb_io_request_complete(
+                  fw_controller, fw_device, fw_request, completion_status);
+            }
+            else
+            {
+               // do nothing - will complete the I/O when the abort task
+               //  set completes
+            }
+         }
+         else
+            scif_sas_controller_complete_high_priority_io(
+               fw_controller, fw_device, fw_request);
+      }
+      else if ( status == SCI_WARNING_SEQUENCE_INCOMPLETE )
+      {
+         scif_sas_io_request_continue(fw_controller, fw_device, fw_request);
+      }
+   }
+}
+
+// ---------------------------------------------------------------------------
+
+U32 scic_cb_io_request_get_transfer_length(
+   void * scic_user_io_request
+)
+{
+   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*)
+                                   scic_user_io_request;
+
+   return (scif_cb_io_request_get_transfer_length(
+             fw_io->parent.parent.parent.associated_object
+           ));
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_IO_REQUEST_DATA_DIRECTION scic_cb_io_request_get_data_direction(
+   void * scic_user_io_request
+)
+{
+   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*)
+                                   scic_user_io_request;
+
+   return (scif_cb_io_request_get_data_direction(
+             fw_io->parent.parent.parent.associated_object
+          ));
+}
+
+// ---------------------------------------------------------------------------
+#ifndef SCI_SGL_OPTIMIZATION_ENABLED
+void scic_cb_io_request_get_next_sge(
+   void * scic_user_io_request,
+   void * current_sge_address,
+   void **next_sge
+)
+{
+   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*)
+                                   scic_user_io_request;
+
+   scif_cb_io_request_get_next_sge(
+      fw_io->parent.parent.parent.associated_object,
+      current_sge_address,
+      next_sge
+   );
+}
+#endif
+
+// ---------------------------------------------------------------------------
+
+SCI_PHYSICAL_ADDRESS scic_cb_sge_get_address_field(
+   void * scic_user_io_request,
+   void * sge_address
+)
+{
+   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*)
+                                   scic_user_io_request;
+   return scif_cb_sge_get_address_field(
+             fw_io->parent.parent.parent.associated_object, sge_address
+          );
+}
+
+// ---------------------------------------------------------------------------
+
+U32 scic_cb_sge_get_length_field(
+   void * scic_user_io_request,
+   void * sge_address
+)
+{
+   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*)
+                                   scic_user_io_request;
+
+   return scif_cb_sge_get_length_field(
+             fw_io->parent.parent.parent.associated_object,
+             sge_address
+          );
+}
+
+// ---------------------------------------------------------------------------
+
+void * scic_cb_ssp_io_request_get_cdb_address(
+   void * scic_user_io_request
+)
+{
+   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*)
+                                   scic_user_io_request;
+
+   return scif_cb_io_request_get_cdb_address(
+             fw_io->parent.parent.parent.associated_object
+          );
+}
+
+// ---------------------------------------------------------------------------
+
+U32 scic_cb_ssp_io_request_get_cdb_length(
+   void * scic_user_io_request
+)
+{
+   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*)
+                                   scic_user_io_request;
+
+   return scif_cb_io_request_get_cdb_length(
+             fw_io->parent.parent.parent.associated_object
+          );
+}
+
+// ---------------------------------------------------------------------------
+
+#if !defined(DISABLE_ATAPI)
+void * scic_cb_stp_packet_io_request_get_cdb_address(
+   void * scic_user_io_request
+)
+{
+   SCIF_SAS_REQUEST_T * fw_request = (SCIF_SAS_REQUEST_T*)scic_user_io_request;
+
+   SATI_TRANSLATOR_SEQUENCE_T * sati_sequence = &fw_request->stp.sequence;
+
+   if (sati_sequence->state != SATI_SEQUENCE_STATE_INCOMPLETE)
+      return scif_cb_io_request_get_cdb_address(
+                fw_request->parent.parent.associated_object
+             );
+   else
+      return
+      &(sati_sequence->command_specific_data.sati_atapi_data.request_sense_cdb);
+}
+#endif
+
+// ---------------------------------------------------------------------------
+
+#if !defined(DISABLE_ATAPI)
+U32 scic_cb_stp_packet_io_request_get_cdb_length(
+   void * scic_user_io_request
+)
+{
+   SCIF_SAS_REQUEST_T * fw_request = (SCIF_SAS_REQUEST_T*)
+                                   scic_user_io_request;
+
+   SATI_TRANSLATOR_SEQUENCE_T * sati_sequence = &fw_request->stp.sequence;
+
+   if (sati_sequence->state != SATI_SEQUENCE_STATE_INCOMPLETE)
+      return scif_cb_io_request_get_cdb_length(
+                fw_request->parent.parent.associated_object
+             );
+   else
+      return SATI_ATAPI_REQUEST_SENSE_CDB_LENGTH;
+}
+#endif
+
+// ---------------------------------------------------------------------------
+
+U32 scic_cb_ssp_io_request_get_lun(
+   void * scic_user_io_request
+)
+{
+   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*)
+                                   scic_user_io_request;
+
+   return scif_cb_io_request_get_lun(
+             fw_io->parent.parent.parent.associated_object
+          );
+}
+
+// ---------------------------------------------------------------------------
+
+U32 scic_cb_ssp_io_request_get_task_attribute(
+   void * scic_user_io_request
+)
+{
+   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*)
+                                   scic_user_io_request;
+
+   return scif_cb_io_request_get_task_attribute(
+             fw_io->parent.parent.parent.associated_object
+          );
+}
+
+// ---------------------------------------------------------------------------
+
+U32 scic_cb_ssp_io_request_get_command_priority(
+   void * scic_user_io_request
+)
+{
+   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*)
+                                   scic_user_io_request;
+
+   return scif_cb_io_request_get_command_priority(
+             fw_io->parent.parent.parent.associated_object
+          );
+}
+
+// ---------------------------------------------------------------------------
+
+BOOL scic_cb_request_is_initial_construction(
+   void * scic_user_io_request
+)
+{
+   SCIF_SAS_REQUEST_T * fw_request = (SCIF_SAS_REQUEST_T*)
+                                   scic_user_io_request;
+   SCIF_SAS_REMOTE_DEVICE_T* fw_device = fw_request->device;
+
+   SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;
+   scic_remote_device_get_protocols(fw_device->core_object, &dev_protocols);
+
+   if (dev_protocols.u.bits.attached_stp_target
+       && fw_request->stp.sequence.state == SATI_SEQUENCE_STATE_INCOMPLETE)
+      return FALSE;
+
+   return TRUE;
+}
+
+
+//******************************************************************************
+//* P R O T E C T E D   M E T H O D S
+//******************************************************************************
+/**
+ * @brief This method constructs an scif sas smp request.
+ *
+ * @param[in] fw_controller The framework controller
+ * @param[in] fw_device The smp device that the smp request targets to.
+ * @param[in] fw_io_memory The memory space for the smp request.
+ * @param[in] core_io_memory The memory space for the core request.
+ * @param[in] io_tag The io tag for the internl io to be constructed.
+ * @param[in] smp_command A pointer to the smp request data structure according
+ *       to SAS protocol.
+ *
+ * @return Indicate if the internal io was successfully constructed.
+ * @retval SCI_SUCCESS This value is returned if the internal io was
+ *         successfully constructed.
+ * @retval SCI_FAILURE This value is returned if the internal io was failed to
+ *         be constructed.
+ */
+SCI_STATUS scif_sas_io_request_construct_smp(
+   SCIF_SAS_CONTROLLER_T       * fw_controller,
+   SCIF_SAS_REMOTE_DEVICE_T    * fw_device,
+   void                        * fw_io_memory,
+   void                        * core_io_memory,
+   U16                           io_tag,
+   SMP_REQUEST_T               * smp_command,
+   void                        * user_request_object
+)
+{
+   SCIF_SAS_IO_REQUEST_T * fw_io =
+     (SCIF_SAS_IO_REQUEST_T*)fw_io_memory;
+
+   SCI_STATUS status = SCI_SUCCESS;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_IO_REQUEST,
+      "scif_sas_io_request_construct_smp(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x) enter\n",
+      fw_controller,
+      fw_device,
+      fw_io_memory,
+      core_io_memory,
+      io_tag,
+      smp_command,
+      user_request_object
+   ));
+
+   // Construct the parent object first in order to ensure logging can
+   // function.
+   scif_sas_request_construct(
+      &fw_io->parent,
+      fw_device,
+      sci_base_object_get_logger(fw_controller),
+      scif_sas_io_request_state_table
+   );
+
+   status = scic_io_request_construct(
+               fw_device->domain->controller->core_object,
+               fw_device->core_object,
+               io_tag,
+               (void*)fw_io,
+               (U8 *)core_io_memory,
+               &fw_io->parent.core_object
+            );
+
+   if (status == SCI_SUCCESS)
+   {
+      //set object association.
+      sci_object_set_association(fw_io, user_request_object);
+      sci_object_set_association(fw_io->parent.core_object, fw_io);
+
+      scif_sas_smp_request_construct(&fw_io->parent, smp_command);
+
+      fw_io->parent.is_high_priority = TRUE;
+
+      sci_base_state_machine_logger_initialize(
+         &fw_io->parent.parent.state_machine_logger,
+         &fw_io->parent.parent.state_machine,
+         &fw_io->parent.parent.parent,
+         scif_cb_logger_log_states,
+         "SCIF_IO_REQUEST_T", "base_state_machine",
+         SCIF_LOG_OBJECT_IO_REQUEST
+      );
+   }
+
+   return status;
+}
+
+
+/**
+ * @brief This method continues a scif sas request.
+ *
+ * @param[in] fw_controller The framework controller
+ * @param[in] fw_device The device that the IO request targets to.
+ * @param[in] fw_request The IO request to be continued.
+ *
+ * @return Indicate if the internal io was successfully constructed.
+ * @retval SCI_SUCCESS This value is returned if the internal io was
+ *         successfully continued.
+ * @retval SCI_FAILURE This value is returned if the io was failed to
+ *         be continued.
+ */
+SCI_STATUS scif_sas_io_request_continue(
+   SCIF_SAS_CONTROLLER_T       * fw_controller,
+   SCIF_SAS_REMOTE_DEVICE_T    * fw_device,
+   SCIF_SAS_REQUEST_T          * fw_request
+)
+{
+   SCI_IO_REQUEST_HANDLE_T dummy_handle;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_request),
+      SCIF_LOG_OBJECT_IO_REQUEST,
+      "scif_sas_io_request_continue(0x%x, 0x%x, 0x%x) enter\n",
+      fw_controller,
+      fw_device,
+      fw_request
+   ));
+
+   //complete this io request in framework and core.
+   scif_controller_complete_io(fw_controller, fw_device, fw_request);
+
+   //construct next command in the sequence using the same memory. We pass
+   //a dummy pointer to let the framework user keep the pointer to this IO
+   //request untouched.
+   scif_sas_io_request_construct(
+      fw_device,
+      (SCIF_SAS_IO_REQUEST_T*)fw_request,
+      SCI_CONTROLLER_INVALID_IO_TAG,
+      (void *)sci_object_get_association(fw_request),
+      &dummy_handle,
+      FALSE
+   );
+
+   //start the new constructed IO.
+   return (SCI_STATUS)scif_controller_start_io(
+             (SCI_CONTROLLER_HANDLE_T) fw_controller,
+             (SCI_REMOTE_DEVICE_HANDLE_T) fw_device,
+             (SCI_IO_REQUEST_HANDLE_T) fw_request,
+             SCI_CONTROLLER_INVALID_IO_TAG
+          );
+}
diff --git a/sys/dev/disk/isci/scil/scif_sas_io_request.h b/sys/dev/disk/isci/scil/scif_sas_io_request.h
new file mode 100644
index 0000000..a4e2045
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_io_request.h
@@ -0,0 +1,151 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_io_request.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIF_SAS_IO_REQUEST_H_
+#define _SCIF_SAS_IO_REQUEST_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains the protected interface structures, constants,
+ *        and methods for the SCIF_SAS_IO_REQUEST object.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/scif_io_request.h>
+#include <dev/disk/isci/scil/sci_base_request.h>
+#include <dev/disk/isci/scil/scif_sas_request.h>
+#include <dev/disk/isci/scil/scif_sas_stp_io_request.h>
+#include <dev/disk/isci/scil/intel_sas.h>
+
+
+struct SCIF_SAS_CONTROLLER;
+struct SCIF_SAS_REMOTE_DEVICE;
+
+//Note 0xFF is the maximum possible value to IO_RETRY_LIMIT since the io_retry_count in
+//SCIF_SAS_IO_REQUEST is in type of U8.
+#define SCIF_SAS_IO_RETRY_LIMIT 0xFF
+
+/**
+ * @struct SCIF_SAS_IO_REQUEST
+ *
+ * @brief The SCI SAS Framework IO request object abstracts the SAS IO
+ *        level behavior for the framework component.  Additionally,
+ *        it provides a higher level of abstraction for the core IO request
+ *        object.
+ */
+typedef struct SCIF_SAS_IO_REQUEST
+{
+   /**
+    * The SCI_BASE_REQUEST is the parent object for the
+    * SCIF_SAS_IO_REQUEST object.
+    */
+   SCIF_SAS_REQUEST_T  parent;
+
+   /**
+    * This field specifies the number of bytes to be utilized for this
+    * IO request.  This field is utilized during internal IO requests.
+    */
+   U32  transfer_length;
+
+   /**
+    * This field keeps track of how many times an io got retried.
+    */
+   U8 retry_count;
+
+} SCIF_SAS_IO_REQUEST_T;
+
+extern SCI_BASE_STATE_T scif_sas_io_request_state_table[];
+extern SCI_BASE_REQUEST_STATE_HANDLER_T
+   scif_sas_io_request_state_handler_table[];
+
+SCI_STATUS scif_sas_io_request_constructed_start_handler(
+   SCI_BASE_REQUEST_T * io_request
+);
+
+SCI_STATUS scif_sas_io_request_constructed_abort_handler(
+   SCI_BASE_REQUEST_T * io_request
+);
+
+SCI_STATUS scif_sas_io_request_default_complete_handler(
+   SCI_BASE_REQUEST_T * io_request
+);
+
+SCI_STATUS scif_sas_io_request_default_destruct_handler(
+   SCI_BASE_REQUEST_T * io_request
+);
+
+SCI_STATUS scif_sas_io_request_construct_smp(
+   struct SCIF_SAS_CONTROLLER       * fw_controller,
+   struct SCIF_SAS_REMOTE_DEVICE    * fw_device,
+   void                             * fw_io_memory,
+   void                             * core_io_memory,
+   U16                                io_tag,
+   SMP_REQUEST_T                    * smp_command,
+   void                             * user_request_object
+);
+
+SCI_STATUS scif_sas_io_request_continue(
+   struct SCIF_SAS_CONTROLLER       * fw_controller,
+   struct SCIF_SAS_REMOTE_DEVICE    * fw_device,
+   SCIF_SAS_REQUEST_T               * fw_request
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIF_SAS_IO_REQUEST_H_
diff --git a/sys/dev/disk/isci/scil/scif_sas_io_request_state_handlers.c b/sys/dev/disk/isci/scil/scif_sas_io_request_state_handlers.c
new file mode 100644
index 0000000..8f92b4e
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_io_request_state_handlers.c
@@ -0,0 +1,415 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_io_request_state_handlers.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the method implementations pertaining
+ *        to the framework io request state handler methods.
+ */
+
+#include <dev/disk/isci/scil/scic_controller.h>
+#include <dev/disk/isci/scil/scif_sas_logger.h>
+#include <dev/disk/isci/scil/scif_sas_io_request.h>
+#include <dev/disk/isci/scil/scif_sas_remote_device.h>
+#include <dev/disk/isci/scil/scif_sas_domain.h>
+#include <dev/disk/isci/scil/scif_sas_controller.h>
+
+//******************************************************************************
+//* C O N S T R U C T E D   H A N D L E R S
+//******************************************************************************
+
+/**
+ * @brief This method provides CONSTRUCTED state specific handling for
+ *        when the user attempts to start the supplied IO request.
+ *
+ * @param[in] io_request This parameter specifies the IO request object
+ *            to be started.
+ *
+ * @return This method returns a value indicating if the IO request was
+ *         successfully started or not.
+ * @retval SCI_SUCCESS This return value indicates successful starting
+ *         of the IO request.
+ */
+SCI_STATUS scif_sas_io_request_constructed_start_handler(
+   SCI_BASE_REQUEST_T * io_request
+)
+{
+   return SCI_SUCCESS;
+}
+
+/**
+ * @brief This method provides CONSTRUCTED state specific handling for
+ *        when the user attempts to abort the supplied IO request.
+ *
+ * @param[in] io_request This parameter specifies the IO request object
+ *            to be aborted.
+ *
+ * @return This method returns a value indicating if the IO request was
+ *         successfully aborted or not.
+ * @retval SCI_SUCCESS This return value indicates successful aborting
+ *         of the IO request.
+ */
+SCI_STATUS scif_sas_io_request_constructed_abort_handler(
+   SCI_BASE_REQUEST_T * io_request
+)
+{
+   sci_base_state_machine_change_state(
+      &io_request->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED
+   );
+
+   return SCI_SUCCESS;
+}
+
+//******************************************************************************
+//* S T A R T E D   H A N D L E R S
+//******************************************************************************
+
+/**
+ * @brief This method provides STARTED state specific handling for
+ *        when the user attempts to abort the supplied IO request.
+ *
+ * @param[in] io_request This parameter specifies the IO request object
+ *            to be aborted.
+ *
+ * @return This method returns a value indicating if the aborting the
+ *         IO request was successfully started.
+ * @retval SCI_SUCCESS This return value indicates that the abort process
+ *         began successfully.
+ */
+static
+SCI_STATUS scif_sas_io_request_started_abort_handler(
+   SCI_BASE_REQUEST_T * io_request
+)
+{
+   SCIF_SAS_REQUEST_T * fw_request = (SCIF_SAS_REQUEST_T *) io_request;
+
+   sci_base_state_machine_change_state(
+      &io_request->state_machine, SCI_BASE_REQUEST_STATE_ABORTING
+   );
+
+   return fw_request->status;
+}
+
+/**
+ * @brief This method provides STARTED state specific handling for
+ *        when the user attempts to complete the supplied IO request.
+ *
+ * @param[in] io_request This parameter specifies the IO request object
+ *            to be completed.
+ *
+ * @return This method returns a value indicating if the completion of the
+ *         IO request was successful.
+ * @retval SCI_SUCCESS This return value indicates that the completion process
+ *         was successful.
+ */
+static
+SCI_STATUS scif_sas_io_request_started_complete_handler(
+   SCI_BASE_REQUEST_T * io_request
+)
+{
+   sci_base_state_machine_change_state(
+      &io_request->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED
+   );
+
+   return SCI_SUCCESS;
+}
+
+//******************************************************************************
+//* C O M P L E T E D   H A N D L E R S
+//******************************************************************************
+
+/**
+ * @brief This method provides COMPLETED state specific handling for
+ *        when the user attempts to destruct the supplied IO request.
+ *
+ * @param[in] io_request This parameter specifies the IO request object
+ *            to be destructed.
+ *
+ * @return This method returns a value indicating if the destruct
+ *         operation was successful.
+ * @retval SCI_SUCCESS This return value indicates that the destruct
+ *         was successful.
+ */
+static
+SCI_STATUS scif_sas_io_request_completed_destruct_handler(
+   SCI_BASE_REQUEST_T * io_request
+)
+{
+   sci_base_state_machine_change_state(
+      &io_request->state_machine, SCI_BASE_REQUEST_STATE_FINAL
+   );
+
+   sci_base_state_machine_logger_deinitialize(
+      &io_request->state_machine_logger,
+      &io_request->state_machine
+   );
+
+   return SCI_SUCCESS;
+}
+
+//******************************************************************************
+//* A B O R T I N G   H A N D L E R S
+//******************************************************************************
+
+/**
+ * @brief This method provides ABORTING state specific handlering for when the
+ *        user attempts to abort the supplied IO request.
+ *
+ * @param[in] io_request This parameter specifies the IO request object
+ *            to be completed.
+ *
+ * @return This method returns a value indicating if the completion
+ *         operation was successful.
+ * @retval SCI_SUCCESS This return value indicates that the abort operation
+ *         was successful.
+ */
+static
+SCI_STATUS scif_sas_io_request_aborting_abort_handler(
+   SCI_BASE_REQUEST_T * io_request
+)
+{
+   SCIF_SAS_IO_REQUEST_T * fw_request = (SCIF_SAS_IO_REQUEST_T *) io_request;
+
+   return scic_controller_terminate_request(
+             fw_request->parent.device->domain->controller->core_object,
+             fw_request->parent.device->core_object,
+             fw_request->parent.core_object
+          );
+}
+
+/**
+ * @brief This method provides ABORTING state specific handling for
+ *        when the user attempts to complete the supplied IO request.
+ *
+ * @param[in] io_request This parameter specifies the IO request object
+ *            to be completed.
+ *
+ * @return This method returns a value indicating if the completion
+ *         operation was successful.
+ * @retval SCI_SUCCESS This return value indicates that the completion
+ *         was successful.
+ */
+static
+SCI_STATUS scif_sas_io_request_aborting_complete_handler(
+   SCI_BASE_REQUEST_T * io_request
+)
+{
+   sci_base_state_machine_change_state(
+      &io_request->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED
+   );
+
+   return SCI_SUCCESS;
+}
+
+//******************************************************************************
+//* D E F A U L T   H A N D L E R S
+//******************************************************************************
+
+/**
+ * @brief This method provides DEFAULT handling for when the user
+ *        attempts to start the supplied IO request.
+ *
+ * @param[in] io_request This parameter specifies the IO request object
+ *            to be started.
+ *
+ * @return This method returns an indication that the start operation is
+ *         not allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+static
+SCI_STATUS scif_sas_io_request_default_start_handler(
+   SCI_BASE_REQUEST_T * io_request
+)
+{
+   SCIF_LOG_ERROR((
+      sci_base_object_get_logger((SCIF_SAS_IO_REQUEST_T *) io_request),
+      SCIF_LOG_OBJECT_IO_REQUEST,
+      "IoRequest:0x%x State:0x%x invalid state to start\n",
+      io_request,
+      sci_base_state_machine_get_state(
+         &((SCIF_SAS_IO_REQUEST_T *) io_request)->parent.parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * @brief This method provides DEFAULT handling for when the user
+ *        attempts to abort the supplied IO request.
+ *
+ * @param[in] io_request This parameter specifies the IO request object
+ *            to be aborted.
+ *
+ * @return This method returns an indication that the abort operation is
+ *         not allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+static
+SCI_STATUS scif_sas_io_request_default_abort_handler(
+   SCI_BASE_REQUEST_T * io_request
+)
+{
+   SCIF_LOG_ERROR((
+      sci_base_object_get_logger((SCIF_SAS_IO_REQUEST_T *) io_request),
+      SCIF_LOG_OBJECT_IO_REQUEST,
+      "IoRequest:0x%x State:0x%x invalid state to abort\n",
+      io_request,
+      sci_base_state_machine_get_state(
+         &((SCIF_SAS_IO_REQUEST_T *) io_request)->parent.parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * @brief This method provides DEFAULT handling for when the user
+ *        attempts to complete the supplied IO request.
+ *
+ * @param[in] io_request This parameter specifies the IO request object
+ *            to be completed.
+ *
+ * @return This method returns an indication that complete operation is
+ *         not allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+SCI_STATUS scif_sas_io_request_default_complete_handler(
+   SCI_BASE_REQUEST_T * io_request
+)
+{
+   SCIF_LOG_ERROR((
+      sci_base_object_get_logger((SCIF_SAS_IO_REQUEST_T *) io_request),
+      SCIF_LOG_OBJECT_IO_REQUEST,
+      "IoRequest:0x%x State:0x%x invalid state to complete\n",
+      io_request,
+      sci_base_state_machine_get_state(
+         &((SCIF_SAS_IO_REQUEST_T *) io_request)->parent.parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * @brief This method provides DEFAULT handling for when the user
+ *        attempts to destruct the supplied IO request.
+ *
+ * @param[in] io_request This parameter specifies the IO request object
+ *            to be destructed.
+ *
+ * @return This method returns an indication that destruct operation is
+ *         not allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+SCI_STATUS scif_sas_io_request_default_destruct_handler(
+   SCI_BASE_REQUEST_T * io_request
+)
+{
+   SCIF_LOG_ERROR((
+      sci_base_object_get_logger((SCIF_SAS_IO_REQUEST_T *) io_request),
+      SCIF_LOG_OBJECT_IO_REQUEST,
+      "IoRequest:0x%x State:0x%x invalid state to destruct.\n",
+      io_request,
+      sci_base_state_machine_get_state(
+         &((SCIF_SAS_IO_REQUEST_T *) io_request)->parent.parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+
+SCI_BASE_REQUEST_STATE_HANDLER_T scif_sas_io_request_state_handler_table[] =
+{
+   // SCI_BASE_REQUEST_STATE_INITIAL
+   {
+      scif_sas_io_request_default_start_handler,
+      scif_sas_io_request_default_abort_handler,
+      scif_sas_io_request_default_complete_handler,
+      scif_sas_io_request_default_destruct_handler
+   },
+   // SCI_BASE_REQUEST_STATE_CONSTRUCTED
+   {
+      scif_sas_io_request_constructed_start_handler,
+      scif_sas_io_request_constructed_abort_handler,
+      scif_sas_io_request_default_complete_handler,
+      scif_sas_io_request_default_destruct_handler
+   },
+   // SCI_BASE_REQUEST_STATE_STARTED
+   {
+      scif_sas_io_request_default_start_handler,
+      scif_sas_io_request_started_abort_handler,
+      scif_sas_io_request_started_complete_handler,
+      scif_sas_io_request_default_destruct_handler
+   },
+   // SCI_BASE_REQUEST_STATE_COMPLETED
+   {
+      scif_sas_io_request_default_start_handler,
+      scif_sas_io_request_default_abort_handler,
+      scif_sas_io_request_default_complete_handler,
+      scif_sas_io_request_completed_destruct_handler
+   },
+   // SCI_BASE_REQUEST_STATE_ABORTING
+   {
+      scif_sas_io_request_default_start_handler,
+      scif_sas_io_request_aborting_abort_handler,
+      scif_sas_io_request_aborting_complete_handler,
+      scif_sas_io_request_default_destruct_handler
+   },
+   // SCI_BASE_REQUEST_STATE_FINAL
+   {
+      scif_sas_io_request_default_start_handler,
+      scif_sas_io_request_default_abort_handler,
+      scif_sas_io_request_default_complete_handler,
+      scif_sas_io_request_default_destruct_handler
+   },
+};
diff --git a/sys/dev/disk/isci/scil/scif_sas_io_request_states.c b/sys/dev/disk/isci/scil/scif_sas_io_request_states.c
new file mode 100644
index 0000000..4071122
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_io_request_states.c
@@ -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 - 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: src/sys/dev/isci/scil/scif_sas_io_request_states.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the SCIF_SAS_IO_REQUEST object
+ *        state entrance and exit method implementations.
+ */
+
+#include <dev/disk/isci/scil/scic_controller.h>
+
+#include <dev/disk/isci/scil/scif_sas_io_request.h>
+#include <dev/disk/isci/scil/scif_sas_domain.h>
+#include <dev/disk/isci/scil/scif_sas_controller.h>
+#include <dev/disk/isci/scil/scif_sas_logger.h>
+
+//******************************************************************************
+//* P R O T E C T E D   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        INITIAL state.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_IO_REQUEST object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_io_request_initial_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *)object;
+
+   SET_STATE_HANDLER(
+      &fw_io->parent,
+      scif_sas_io_request_state_handler_table,
+      SCI_BASE_REQUEST_STATE_INITIAL
+   );
+
+   // Initial state is a transitional state to the constructed state
+   sci_base_state_machine_change_state(
+      &fw_io->parent.parent.state_machine, SCI_BASE_REQUEST_STATE_CONSTRUCTED
+   );
+}
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        CONSTRUCTED state.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_IO_REQUEST object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_io_request_constructed_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *)object;
+
+   SET_STATE_HANDLER(
+      &fw_io->parent,
+      scif_sas_io_request_state_handler_table,
+      SCI_BASE_REQUEST_STATE_CONSTRUCTED
+   );
+}
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        STARTED state.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_IO_REQUEST object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_io_request_started_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *)object;
+
+   SET_STATE_HANDLER(
+      &fw_io->parent,
+      scif_sas_io_request_state_handler_table,
+      SCI_BASE_REQUEST_STATE_STARTED
+   );
+}
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        COMPLETED state.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_IO_REQUEST object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_io_request_completed_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *)object;
+
+   SET_STATE_HANDLER(
+      &fw_io->parent,
+      scif_sas_io_request_state_handler_table,
+      SCI_BASE_REQUEST_STATE_COMPLETED
+   );
+}
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        ABORTING state.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_IO_REQUEST object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_io_request_aborting_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *)object;
+
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger(fw_io),
+      SCIF_LOG_OBJECT_IO_REQUEST | SCIF_LOG_OBJECT_TASK_MANAGEMENT,
+      "Domain:0x%x Device:0x%x IORequest:0x%x terminating\n",
+      fw_io->parent.device->domain, fw_io->parent.device, fw_io
+   ));
+
+   SET_STATE_HANDLER(
+      &fw_io->parent,
+      scif_sas_io_request_state_handler_table,
+      SCI_BASE_REQUEST_STATE_ABORTING
+   );
+
+   fw_io->parent.status = scif_sas_request_terminate_start(
+                             &fw_io->parent, fw_io->parent.core_object
+                          );
+}
+
+/**
+ * @brief This method implements the actions taken when exiting the
+ *        ABORTING state.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_IO_REQUEST object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_io_request_aborting_state_exit(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIF_SAS_REQUEST_T * fw_request = (SCIF_SAS_REQUEST_T *)object;
+   scif_sas_request_terminate_complete(fw_request);
+}
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        FINAL state.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_IO_REQUEST object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_io_request_final_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *)object;
+
+   SET_STATE_HANDLER(
+      &fw_io->parent,
+      scif_sas_io_request_state_handler_table,
+      SCI_BASE_REQUEST_STATE_FINAL
+   );
+}
+
+SCI_BASE_STATE_T scif_sas_io_request_state_table[SCI_BASE_REQUEST_MAX_STATES] =
+{
+   {
+      SCI_BASE_REQUEST_STATE_INITIAL,
+      scif_sas_io_request_initial_state_enter,
+      NULL
+   },
+   {
+      SCI_BASE_REQUEST_STATE_CONSTRUCTED,
+      scif_sas_io_request_constructed_state_enter,
+      NULL
+   },
+   {
+      SCI_BASE_REQUEST_STATE_STARTED,
+      scif_sas_io_request_started_state_enter,
+      NULL
+   },
+   {
+      SCI_BASE_REQUEST_STATE_COMPLETED,
+      scif_sas_io_request_completed_state_enter,
+      NULL
+   },
+   {
+      SCI_BASE_REQUEST_STATE_ABORTING,
+      scif_sas_io_request_aborting_state_enter,
+      scif_sas_io_request_aborting_state_exit
+   },
+   {
+      SCI_BASE_REQUEST_STATE_FINAL,
+      scif_sas_io_request_final_state_enter,
+      NULL
+   },
+};
diff --git a/sys/dev/disk/isci/scil/scif_sas_library.c b/sys/dev/disk/isci/scil/scif_sas_library.c
new file mode 100644
index 0000000..e31bae6
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_library.c
@@ -0,0 +1,267 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_library.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the method implementations for the
+ *        SCIF_SAS_LIBRARY object.
+ */
+
+
+#include <dev/disk/isci/scil/scic_library.h>
+#include <dev/disk/isci/scil/sci_pool.h>
+
+#include <dev/disk/isci/scil/scif_sas_library.h>
+#include <dev/disk/isci/scil/scif_sas_logger.h>
+#include <dev/disk/isci/scil/scif_sas_controller.h>
+
+
+/**
+ * This macro simply calculates the size of the framework library.  This
+ * includes the memory for each controller object.
+ */
+#define SCIF_LIBRARY_SIZE(max_controllers)                             \
+(                                                                      \
+   sizeof(SCIF_SAS_LIBRARY_T) +                                        \
+   (sizeof(SCIF_SAS_CONTROLLER_T) * (max_controllers))                 \
+)
+
+
+//******************************************************************************
+//* P U B L I C   M E T H O D S
+//******************************************************************************
+
+
+U32 scif_library_get_object_size(
+   U8 max_controller_count
+)
+{
+   return ( SCIF_LIBRARY_SIZE(max_controller_count) +
+            scic_library_get_object_size(max_controller_count) );
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_LIBRARY_HANDLE_T scif_library_construct(
+   void * library_memory,
+   U8     max_controller_count
+)
+{
+   SCI_STATUS status;
+   SCIF_SAS_LIBRARY_T * fw_library = (SCIF_SAS_LIBRARY_T *) library_memory;
+
+   // Just clear out the memory of the structure to be safe.
+   memset(fw_library, 0, scif_library_get_object_size(max_controller_count));
+
+   // Invoke the parent object constructor.
+   SCI_BASE_LIBRARY_CONSTRUCT(fw_library,
+                              &fw_library->parent,
+                              max_controller_count,
+                              struct SCIF_SAS_CONTROLLER,
+                              status);
+
+   // The memory for the framework controller objects start immediately
+   // after the library object.
+   fw_library->controllers = (SCIF_SAS_CONTROLLER_T*)
+                             ((U8*)library_memory + sizeof(SCIF_SAS_LIBRARY_T));
+
+   // Construct the core library.
+   fw_library->core_object = scic_library_construct(
+                                (U8 *)library_memory +
+                                SCIF_LIBRARY_SIZE(max_controller_count),
+                                max_controller_count
+                             );
+
+   // Ensure construction completed successfully for the core.
+   if (fw_library->core_object != SCI_INVALID_HANDLE)
+   {
+      // Set the association in the core library to this framework library.
+      sci_object_set_association(
+         (SCI_OBJECT_HANDLE_T) fw_library->core_object,
+         (void *) fw_library
+      );
+
+      return fw_library;
+   }
+
+   return SCI_INVALID_HANDLE;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scif_library_allocate_controller(
+   SCI_LIBRARY_HANDLE_T      library,
+   SCI_CONTROLLER_HANDLE_T * new_controller
+)
+{
+   SCI_STATUS  status;
+
+   // Ensure the user supplied a valid library handle.
+   if (library != SCI_INVALID_HANDLE)
+   {
+      SCIF_SAS_LIBRARY_T * fw_library = (SCIF_SAS_LIBRARY_T *) library;
+
+      // Allocate the framework library.
+      SCI_BASE_LIBRARY_ALLOCATE_CONTROLLER(fw_library, new_controller, &status);
+      if (status == SCI_SUCCESS)
+      {
+         SCIF_SAS_CONTROLLER_T * fw_controller;
+
+         // Allocate the core controller and save the handle in the framework
+         // controller object.
+         fw_controller = (SCIF_SAS_CONTROLLER_T*) *new_controller;
+
+         // Just clear out the memory of the structure to be safe.
+         memset(fw_controller, 0, sizeof(SCIF_SAS_CONTROLLER_T));
+
+         status = scic_library_allocate_controller(
+                     fw_library->core_object, &(fw_controller->core_object)
+                  );
+
+         // Free the framework controller if the core controller allocation
+         // failed.
+         if (status != SCI_SUCCESS)
+            scif_library_free_controller(library, fw_controller);
+      }
+
+      if (status != SCI_SUCCESS)
+      {
+         SCIF_LOG_WARNING((
+            sci_base_object_get_logger(fw_library),
+            SCIF_LOG_OBJECT_LIBRARY,
+            "Library:0x%x Status:0x%x controller allocation failed\n",
+            fw_library, status
+         ));
+      }
+   }
+   else
+      status = SCI_FAILURE_INVALID_PARAMETER_VALUE;
+
+   return status;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scif_library_free_controller(
+   SCI_LIBRARY_HANDLE_T     library,
+   SCI_CONTROLLER_HANDLE_T  controller
+)
+{
+   SCI_STATUS  status;
+
+   if ( (library != SCI_INVALID_HANDLE) && (controller != SCI_INVALID_HANDLE) )
+   {
+      SCI_STATUS              core_status;
+      SCIF_SAS_LIBRARY_T    * fw_library    = (SCIF_SAS_LIBRARY_T*) library;
+      SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
+
+      core_status = scic_library_free_controller(
+                       fw_library->core_object, fw_controller->core_object
+                    );
+
+      scif_sas_controller_destruct(fw_controller);
+
+      SCI_BASE_LIBRARY_FREE_CONTROLLER(
+         (SCIF_SAS_LIBRARY_T *) library,
+         controller,
+         SCIF_SAS_CONTROLLER_T,
+         &status
+      );
+
+      if ( (status == SCI_SUCCESS) && (core_status != SCI_SUCCESS) )
+         status = core_status;
+
+      if (status != SCI_SUCCESS)
+      {
+         SCIF_LOG_WARNING((
+            sci_base_object_get_logger(fw_library),
+            SCIF_LOG_OBJECT_LIBRARY,
+            "Library:0x%x Controller:0x%x Status:0x%x free controller failed\n",
+            fw_library, fw_controller, status
+         ));
+      }
+   }
+   else
+      status = SCI_FAILURE_INVALID_PARAMETER_VALUE;
+
+   return status;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_LIBRARY_HANDLE_T scif_library_get_scic_handle(
+   SCI_LIBRARY_HANDLE_T   scif_library
+)
+{
+   SCIF_SAS_LIBRARY_T * fw_library = (SCIF_SAS_LIBRARY_T*) scif_library;
+
+   return fw_library->core_object;
+}
+
+// ---------------------------------------------------------------------------
+
+#define SCIF_SAS_LIBRARY_MAX_TIMERS 32
+
+U16 scif_library_get_max_timer_count(
+   void
+)
+{
+   /// @todo Need to calculate the exact maximum number of timers needed.
+   return SCIF_SAS_LIBRARY_MAX_TIMERS + scic_library_get_max_timer_count();
+}
+
+//******************************************************************************
+//* P R O T E C T E D   M E T H O D S
+//******************************************************************************
diff --git a/sys/dev/disk/isci/scil/scif_sas_library.h b/sys/dev/disk/isci/scil/scif_sas_library.h
new file mode 100644
index 0000000..501fee9
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_library.h
@@ -0,0 +1,104 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_library.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIF_SAS_LIBRARY_H_
+#define _SCIF_SAS_LIBRARY_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains the protected interface structures, constants,
+ *        and methods for the SCIF_SAS_LIBRARY object.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_base_library.h>
+#include <dev/disk/isci/scil/scif_library.h>
+
+
+/**
+ * @struct SCIF_SAS_LIBRARY
+ *
+ * @brief The SCI SAS Framework library object acts as the root of the
+ *        containment hierarchy for all framework objects.
+ */
+typedef struct SCIF_SAS_LIBRARY
+{
+   /**
+    * The SCI_BASE_LIBRARY is the parent object for the SCIF_SAS_LIBRARY
+    * object.
+    */
+   SCI_BASE_LIBRARY_T  parent;
+
+   /**
+    * This field contains the handle for the SCI Core library object that
+    * is managed by the framework.
+    */
+   SCI_LIBRARY_HANDLE_T  core_object;
+
+   /**
+    * This field provides the library a reference to the controller objects
+    * being managed by this library.
+    */
+   struct SCIF_SAS_CONTROLLER * controllers;
+
+} SCIF_SAS_LIBRARY_T;
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIF_SAS_LIBRARY_H_
diff --git a/sys/dev/disk/isci/scil/scif_sas_logger.h b/sys/dev/disk/isci/scil/scif_sas_logger.h
new file mode 100644
index 0000000..df3d09c
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_logger.h
@@ -0,0 +1,93 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_logger.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIF_SAS_LOGGER_H_
+#define _SCIF_SAS_LOGGER_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the SCI SAS Framework specific logger
+ *        object methods.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/scif_logger.h>
+#include <dev/disk/isci/scil/scif_user_callback.h>
+
+#if defined (SCI_LOGGING)
+
+#define SCIF_LOG_ERROR(x)    scif_cb_logger_log_error x
+#define SCIF_LOG_WARNING(x)  scif_cb_logger_log_warning x
+#define SCIF_LOG_INFO(x)     scif_cb_logger_log_info x
+#define SCIF_LOG_TRACE(x)    scif_cb_logger_log_trace x
+#define SCIF_LOG_STATES(x)   scif_cb_logger_log_states x
+
+#else // defined (SCI_LOGGING)
+
+#define SCIF_LOG_ERROR(x)
+#define SCIF_LOG_WARNING(x)
+#define SCIF_LOG_INFO(x)
+#define SCIF_LOG_TRACE(x)
+#define SCIF_LOG_STATES(x)
+
+#endif // defined (SCI_LOGGING)
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIF_SAS_LOGGER_H_
diff --git a/sys/dev/disk/isci/scil/scif_sas_remote_device.c b/sys/dev/disk/isci/scil/scif_sas_remote_device.c
new file mode 100644
index 0000000..f45b2ae
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_remote_device.c
@@ -0,0 +1,792 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_remote_device.c,v 1.2 2012/02/07 17:45:11 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains the implementation of the SCIF_SAS_REMOTE_DEVICE
+ *        object.
+ */
+
+
+#include <dev/disk/isci/scil/scic_remote_device.h>
+#include <dev/disk/isci/scil/scic_port.h>
+#include <dev/disk/isci/scil/scic_user_callback.h>
+
+#include <dev/disk/isci/scil/scif_sas_logger.h>
+#include <dev/disk/isci/scil/scif_sas_remote_device.h>
+#include <dev/disk/isci/scil/scif_sas_stp_remote_device.h>
+#include <dev/disk/isci/scil/scif_sas_domain.h>
+#include <dev/disk/isci/scil/scif_sas_controller.h>
+#include <dev/disk/isci/scil/sci_controller.h>
+#include <dev/disk/isci/scil/sci_util.h>
+
+
+//******************************************************************************
+//* P U B L I C   M E T H O D S
+//******************************************************************************
+
+U32 scif_remote_device_get_object_size(
+   void
+)
+{
+   return ( sizeof(SCIF_SAS_REMOTE_DEVICE_T)
+          + scic_remote_device_get_object_size() );
+}
+
+// ---------------------------------------------------------------------------
+
+void scif_remote_device_construct(
+   SCI_DOMAIN_HANDLE_T          domain,
+   void                       * remote_device_memory,
+   SCI_REMOTE_DEVICE_HANDLE_T * new_scif_remote_device_handle
+)
+{
+   SCIF_SAS_DOMAIN_T        * fw_domain = (SCIF_SAS_DOMAIN_T *) domain;
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)
+                                          remote_device_memory;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_domain),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE,
+      "scif_remote_device_construct(0x%x, 0x%x, 0x%x) enter\n",
+      domain, remote_device_memory, new_scif_remote_device_handle
+   ));
+
+   memset(remote_device_memory, 0, sizeof(SCIF_SAS_REMOTE_DEVICE_T));
+
+   // The user's handle to the remote device evaluates to the memory
+   // address where the remote device object is stored.
+   *new_scif_remote_device_handle = remote_device_memory;
+
+   fw_device->domain                = fw_domain;
+   fw_device->destruct_when_stopped = FALSE;
+   //fw_device->parent.is_failed      = FALSE;
+   fw_device->operation_status      = SCI_SUCCESS;
+   fw_device->request_count         = 0;
+   fw_device->task_request_count    = 0;
+   fw_device->is_currently_discovered = TRUE;
+   fw_device->containing_device       = NULL;
+   fw_device->device_port_width       = 1;
+   fw_device->expander_phy_identifier = 0;
+   fw_device->destination_state       =
+      SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_UNSPECIFIED;
+   fw_device->ea_target_reset_request_scheduled = NULL;
+
+   // Construct the base object first in order to ensure logging can
+   // function.
+   sci_base_remote_device_construct(
+      &fw_device->parent,
+      sci_base_object_get_logger(fw_domain),
+      scif_sas_remote_device_state_table
+   );
+
+   sci_base_state_machine_construct(
+      &fw_device->starting_substate_machine,
+      &fw_device->parent.parent,
+      scif_sas_remote_device_starting_substate_table,
+      SCIF_SAS_REMOTE_DEVICE_STARTING_SUBSTATE_AWAIT_COMPLETE
+   );
+
+   sci_base_state_machine_construct(
+      &fw_device->ready_substate_machine,
+      &fw_device->parent.parent,
+      scif_sas_remote_device_ready_substate_table,
+      SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL
+   );
+
+   scif_sas_remote_device_initialize_state_logging(fw_device);
+
+   scic_remote_device_construct(
+      fw_domain->core_object,
+      ((U8*) remote_device_memory) + sizeof(SCIF_SAS_REMOTE_DEVICE_T),
+      &fw_device->core_object
+   );
+
+   // Set the association in the core object, so that we are able to
+   // determine our framework remote device object from the core remote
+   // device.
+   sci_object_set_association(fw_device->core_object, fw_device);
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scif_remote_device_da_construct(
+   SCI_REMOTE_DEVICE_HANDLE_T                   remote_device,
+   SCI_SAS_ADDRESS_T                          * sas_address,
+   SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T * protocols
+)
+{
+   SCI_STATUS                 status    = SCI_SUCCESS;
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)
+                                          remote_device;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE,
+      "scif_remote_device_da_construct(0x%x, 0x%x, 0x%x) enter\n",
+      remote_device, sas_address, protocols
+   ));
+
+   // Make sure the device hasn't already been constructed and added
+   // to the domain.
+   if (scif_domain_get_device_by_sas_address(fw_device->domain, sas_address)
+       == SCI_INVALID_HANDLE)
+   {
+      SCIC_PORT_PROPERTIES_T  properties;
+
+      scic_port_get_properties(fw_device->domain->core_object, &properties);
+
+      // Check to see if this is the direct attached device.
+      if (  (sas_address->low == properties.remote.sas_address.low)
+         && (sas_address->high == properties.remote.sas_address.high) )
+      {
+         //Get accurate port width from port's phy mask for a DA device.
+         SCI_GET_BITS_SET_COUNT(properties.phy_mask, fw_device->device_port_width);
+
+         status = scic_remote_device_da_construct(fw_device->core_object);
+      }
+      else
+         // Don't allow the user to construct a direct attached device
+         // if it's not a direct attached device.
+         status = SCI_FAILURE_UNSUPPORTED_PROTOCOL;
+   }
+   else
+      status = SCI_FAILURE_DEVICE_EXISTS;
+
+   if (status == SCI_SUCCESS)
+   {
+      // Add the device to the domain list.
+      sci_abstract_list_pushback(
+         &fw_device->domain->remote_device_list, fw_device
+      );
+
+      // If a SATA/STP device is connected, then construct it.
+      if (protocols->u.bits.stp_target)
+         scif_sas_stp_remote_device_construct(fw_device);
+      else if (protocols->u.bits.smp_target)
+         scif_sas_smp_remote_device_construct(fw_device);
+
+      SCIF_LOG_INFO((
+         sci_base_object_get_logger(fw_device),
+         SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+         "Domain:0x%x SasAddress:0x%x,0x%x remote device constructed\n",
+         fw_device->domain, sas_address->low, sas_address->high
+      ));
+
+      status = fw_device->state_handlers->parent.start_handler(
+                  &fw_device->parent
+               );
+   }
+   else
+   {
+      SCIF_LOG_WARNING((
+         sci_base_object_get_logger(fw_device),
+         SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+         "Domain:0x%x SasAddress:0x%x,0x%x Status:0x%x remote device construct failure\n",
+         fw_device->domain, sas_address->low, sas_address->high, status
+      ));
+   }
+
+   return status;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scif_remote_device_ea_construct(
+   SCI_REMOTE_DEVICE_HANDLE_T   remote_device,
+   SCI_REMOTE_DEVICE_HANDLE_T   containing_device,
+   SMP_RESPONSE_DISCOVER_T    * smp_response
+)
+{
+   SCI_SAS_ADDRESS_T        * sas_address;
+   SCI_STATUS                 status        = SCI_SUCCESS;
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device     = (SCIF_SAS_REMOTE_DEVICE_T *)
+                                              remote_device;
+   SCIF_SAS_REMOTE_DEVICE_T * fw_smp_device = (SCIF_SAS_REMOTE_DEVICE_T *)
+                                              containing_device;
+
+   fw_device->containing_device = fw_smp_device;
+   fw_device->expander_phy_identifier =
+      fw_smp_device->protocol_device.smp_device.current_activity_phy_index;
+
+   sas_address = &smp_response->attached_sas_address;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE,
+      "scif_remote_device_ea_construct(0x%x, 0x%x) enter\n",
+      remote_device, smp_response
+   ));
+
+   // Make sure the device hasn't already been constructed and added
+   // to the domain.
+   if (scif_domain_get_device_by_sas_address(fw_device->domain, sas_address)
+       == SCI_INVALID_HANDLE)
+   {
+      //for sata device, we need another routine. likely
+      //scif_remote_device_ea_sata_construct.
+      status = scic_remote_device_ea_construct(fw_device->core_object, smp_response);
+   }
+   else
+      status = SCI_FAILURE_DEVICE_EXISTS;
+
+   if (status == SCI_SUCCESS)
+   {
+      // Add the device to the domain list.
+      sci_abstract_list_pushback(
+         &fw_device->domain->remote_device_list, fw_device
+      );
+
+      if (smp_response->protocols.u.bits.attached_smp_target)
+         scif_sas_smp_remote_device_construct(fw_device);
+      else if (smp_response->protocols.u.bits.attached_stp_target)
+         scif_sas_stp_remote_device_construct(fw_device);
+
+      SCIF_LOG_INFO((
+         sci_base_object_get_logger(fw_device),
+         SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+         "Domain:0x%x SasAddress:0x%x,0x%x remote device constructed\n",
+         fw_device->domain, sas_address->low, sas_address->high
+      ));
+
+      //only start the device if the device is not a SATA disk on SPINUP_HOLD state.
+      if ( scic_remote_device_get_connection_rate(fw_device->core_object) !=
+              SCI_SATA_SPINUP_HOLD )
+      {
+          status = fw_device->state_handlers->parent.start_handler(
+                      &fw_device->parent
+                   );
+      }
+   }
+   else
+   {
+      SCIF_LOG_WARNING((
+         sci_base_object_get_logger(fw_device),
+         SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+         "Domain:0x%x SasAddress:0x%x,0x%x Status:0x%x remote device construct failure\n",
+         fw_device->domain, sas_address->low, sas_address->high, status
+      ));
+   }
+
+   return status;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scif_remote_device_destruct(
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
+                                          remote_device;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE,
+      "scif_remote_device_destruct(0x%x) enter\n",
+      remote_device
+   ));
+
+   //remove the device from domain's remote_device_list
+   fw_device->domain->state_handlers->device_destruct_handler(
+      &fw_device->domain->parent, &fw_device->parent
+   );
+
+   // The destruct process may not complete immediately, since the core
+   // remote device likely needs to be stopped first.  However, the user
+   // is not given a callback notification for destruction.
+   return fw_device->state_handlers->parent.destruct_handler(
+             &fw_device->parent
+          );
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_REMOTE_DEVICE_HANDLE_T scif_remote_device_get_scic_handle(
+   SCI_REMOTE_DEVICE_HANDLE_T  scif_remote_device
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
+                                          scif_remote_device;
+
+   if ( (fw_device == NULL) || (fw_device->core_object == SCI_INVALID_HANDLE) )
+      return SCI_INVALID_HANDLE;
+
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE,
+      "RemoteDevice:0x%x no associated core device found\n",
+      fw_device
+   ));
+
+   return fw_device->core_object;
+}
+
+// ---------------------------------------------------------------------------
+
+void scic_cb_remote_device_start_complete(
+   SCI_CONTROLLER_HANDLE_T    controller,
+   SCI_REMOTE_DEVICE_HANDLE_T remote_device,
+   SCI_STATUS                 completion_status
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
+                                      sci_object_get_association(remote_device);
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_REMOTE_DEVICE_CONFIG,
+      "scic_cb_remote_device_start_complete(0x%x, 0x%x, 0x%x) enter\n",
+      controller, remote_device, completion_status
+   ));
+
+   fw_device->state_handlers->start_complete_handler(
+      fw_device, completion_status
+   );
+}
+
+// ---------------------------------------------------------------------------
+
+void scic_cb_remote_device_stop_complete(
+   SCI_CONTROLLER_HANDLE_T    controller,
+   SCI_REMOTE_DEVICE_HANDLE_T remote_device,
+   SCI_STATUS                 completion_status
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
+                                      sci_object_get_association(remote_device);
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_REMOTE_DEVICE_CONFIG,
+      "scic_cb_remote_device_stop_complete(0x%x, 0x%x, 0x%x) enter\n",
+      controller, remote_device, completion_status
+   ));
+
+   fw_device->state_handlers->stop_complete_handler(
+      fw_device, completion_status
+   );
+}
+
+// ---------------------------------------------------------------------------
+
+void scic_cb_remote_device_ready(
+   SCI_CONTROLLER_HANDLE_T     controller,
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
+                                      sci_object_get_association(remote_device);
+
+   fw_device->state_handlers->ready_handler(fw_device);
+}
+
+// ---------------------------------------------------------------------------
+
+void scic_cb_remote_device_not_ready(
+   SCI_CONTROLLER_HANDLE_T     controller,
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
+   U32                         reason_code
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
+                                      sci_object_get_association(remote_device);
+
+   fw_device->state_handlers->not_ready_handler(fw_device,reason_code);
+}
+
+// ---------------------------------------------------------------------------
+
+U16 scif_remote_device_get_max_queue_depth(
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
+                                          remote_device;
+   SMP_DISCOVER_RESPONSE_PROTOCOLS_T  protocols;
+
+   scic_remote_device_get_protocols(fw_device->core_object, &protocols);
+
+   // If the target is a SATA/STP target, then determine the queue depth
+   // for either NCQ or for UDMA.
+   if (protocols.u.bits.attached_stp_target)
+   {
+      if (fw_device->protocol_device.stp_device.sati_device.capabilities
+          & SATI_DEVICE_CAP_NCQ_SUPPORTED_ENABLE)
+      {
+         return fw_device->protocol_device.stp_device.sati_device.ncq_depth;
+      }
+      else
+      {
+         // At the moment, we only allow a single UDMA request to be queued.
+         return 1;
+      }
+   }
+
+   // For SSP devices return a no maximum queue depth supported.
+   return SCIF_REMOTE_DEVICE_NO_MAX_QUEUE_DEPTH;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scif_remote_device_get_containing_device(
+   SCI_REMOTE_DEVICE_HANDLE_T          remote_device,
+   SCI_REMOTE_DEVICE_HANDLE_T        * containing_device
+)
+{
+   SCI_STATUS                 status      = SCI_FAILURE;
+   SCIF_SAS_REMOTE_DEVICE_T * this_device = (SCIF_SAS_REMOTE_DEVICE_T *)
+                                            remote_device;
+
+   if ( (this_device != NULL) && (containing_device != NULL) )
+   {
+      *containing_device = (SCI_REMOTE_DEVICE_HANDLE_T)(this_device->containing_device);
+      if (*containing_device != NULL)
+      {
+         status = SCI_SUCCESS;
+      }
+   }
+
+   return status;
+}
+
+// ---------------------------------------------------------------------------
+
+U32 scif_remote_device_get_started_io_count(
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * this_device = (SCIF_SAS_REMOTE_DEVICE_T *)
+                                            remote_device;
+
+   return this_device->request_count - this_device->task_request_count;
+}
+//******************************************************************************
+//* P R O T E C T E D   M E T H O D S
+//******************************************************************************
+
+/*
+void scif_sas_remote_device_failure(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device
+)
+{
+   fw_device->parent.is_failed = TRUE;
+   sci_base_state_machine_change_state(
+      &fw_device->parent.state_machine, SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
+   );
+}
+*/
+
+
+/**
+ * @brief This method retrieves info from Report Phy Sata response and
+ *        save the additional data for a SATA remote device, if necessary.
+ *
+ * @param[in] report_phy_sata_response SMP Report Phy Sata response
+ *
+ * @return none
+ */
+void scif_sas_remote_device_save_report_phy_sata_information(
+   SMP_RESPONSE_REPORT_PHY_SATA_T * report_phy_sata_response
+)
+{
+   //do nothing currently. Later, if needed, we will search the existed
+   //remote device by stp_sas_address, then save more information for
+   //that device off the report_phy_sata_response. This assumes the
+   //stp_sas_address from report_phy_sata response is the same sas address
+   //from discover response.
+
+   return;
+}
+
+/**
+ * @brief This method does target reset for DA or EA remote device.
+ *
+ * @param[in] fw_controller, the controller object the target device belongs
+ *            to.
+ * @param[in] fw_device, the target device to be hard reset.
+ * @param[in] fw_request, the scif task request object that asked for this
+ *            target reset.
+ */
+void scif_sas_remote_device_target_reset(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   SCIF_SAS_REQUEST_T       * fw_request
+)
+{
+   SCIF_LOG_INFO((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE,
+      "scif_sas_remote_device_target_reset! fw_device:0x%x fw_request:0x%x\n",
+      fw_device, fw_request
+   ));
+
+   if (fw_device->containing_device == NULL)
+   {
+      SCI_PORT_HANDLE_T port;
+
+      port = scif_domain_get_scic_port_handle(fw_device->domain);
+
+      //Direct attached device target reset.
+      //calling core to do port reset. The fw_request will not be used here.
+      scic_port_hard_reset(
+         port,
+         scic_remote_device_get_suggested_reset_timeout(fw_device->core_object)
+      );
+   }
+   else
+   {  //Expander attached device target reset.
+
+      if ( fw_device->containing_device->protocol_device.smp_device.current_activity
+              == SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_TARGET_RESET )
+      {
+         //The containing expander is in the middle of target resetting other of its
+         //remote disks. Flag this remote device to be target reset later.
+         SCIF_LOG_INFO((
+            sci_base_object_get_logger(fw_device),
+            SCIF_LOG_OBJECT_REMOTE_DEVICE,
+            "scif_sas_remote_device_target_reset DELAYED! fw_device:0x%x fw_request:0x%x\n",
+            fw_device, fw_request
+         ));
+
+         fw_device->ea_target_reset_request_scheduled = fw_request;
+         return;
+      }
+
+      //set current_activity and current_smp_request to expander device.
+      scif_sas_smp_remote_device_start_target_reset(
+         fw_device->containing_device, fw_device, fw_request);
+   }
+
+   scic_remote_device_reset(fw_device->core_object);
+}
+
+
+/**
+ * @brief This method completes target reset for DA or EA remote device.
+ *
+ * @param[in] fw_device, the target device to be hard reset.
+ * @param[in] fw_request, the scif task request object that asked for this
+ *            target reset.
+ * @param[in] completion_status
+ */
+void scif_sas_remote_device_target_reset_complete(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   SCIF_SAS_REQUEST_T       * fw_request,
+   SCI_STATUS                 completion_status
+)
+{
+   SCIF_LOG_INFO((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE,
+      "scif_sas_remote_device_target_reset_complete! "
+      "fw_device:0x%x fw_request:0x%x completion_status 0x%x\n",
+      fw_device, fw_request, completion_status
+   ));
+
+   scif_cb_task_request_complete(
+      fw_device->domain->controller,
+      fw_device,
+      fw_request,
+      (SCI_TASK_STATUS) completion_status
+   );
+
+   scic_remote_device_reset_complete(fw_device->core_object);
+
+   //For expander attached device done target reset.
+   if (fw_device->containing_device != NULL)
+   {
+      //search for all the devices in the domain to find other remote devices
+      //needs to be target reset.
+      SCIF_SAS_REMOTE_DEVICE_T * next_device;
+
+      scif_sas_smp_remote_device_clear(fw_device->containing_device);
+
+      if( (next_device = scif_sas_domain_find_next_ea_target_reset(fw_device->domain))
+              != NULL )
+      {
+         scif_sas_smp_remote_device_start_target_reset(
+            next_device->containing_device,
+            next_device,
+            next_device->ea_target_reset_request_scheduled
+         );
+
+         next_device->ea_target_reset_request_scheduled = NULL;
+      }
+      else
+      {
+         //if the domain is in the DISCOVER state, we should resume the DISCOVER.
+         if (fw_device->domain->parent.state_machine.current_state_id ==
+                SCI_BASE_DOMAIN_STATE_DISCOVERING)
+         {
+            SCIF_SAS_REMOTE_DEVICE_T * top_expander = fw_device->containing_device;
+
+            while(top_expander->containing_device != NULL)
+               top_expander = top_expander->containing_device;
+
+            scif_sas_domain_start_smp_discover(fw_device->domain, top_expander);
+         }
+         else
+         {
+            //Tell driver to kick off Discover process. If the domain is already
+            //in Discovery state, this discovery requst will not be carried on.
+            scif_cb_domain_change_notification(
+            fw_device->domain->controller, fw_device->domain );
+         }
+      }
+   }
+   else
+   {
+      //Tell driver to kick off Discover process. If the domain is already
+      //in Discovery state, this discovery requst will not be carried on.
+      scif_cb_domain_change_notification(
+         fw_device->domain->controller, fw_device->domain );
+   }
+}
+
+#if !defined(DISABLE_WIDE_PORTED_TARGETS)
+SCI_STATUS scif_sas_remote_device_update_port_width(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   U8                         new_port_width
+)
+{
+   SCIF_LOG_INFO((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE,
+      "scif_sas_remote_device_update_port_width (0x%x, 0x%x) enter\n",
+      fw_device, new_port_width
+   ));
+
+   fw_device->device_port_width = new_port_width;
+
+   //Don't Start a new update of port width if a device is already in
+   //UPDATING PORT WIDTH state.
+   if (fw_device->parent.state_machine.current_state_id == SCI_BASE_REMOTE_DEVICE_STATE_READY)
+   {
+      if (fw_device->device_port_width != 0)
+      {
+         //Change state to UPDATING_PORT_WIDTH
+         sci_base_state_machine_change_state(
+            &fw_device->parent.state_machine,
+            SCI_BASE_REMOTE_DEVICE_STATE_UPDATING_PORT_WIDTH
+         );
+      }
+
+      return SCI_SUCCESS;
+   }
+   else if (fw_device->parent.state_machine.current_state_id ==
+               SCI_BASE_REMOTE_DEVICE_STATE_STARTING)
+   {
+      fw_device->destination_state =
+         SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_UPDATING_PORT_WIDTH;
+   }
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+#endif //#if !defined(DISABLE_WIDE_PORTED_TARGETS)
+
+
+#ifdef SCI_LOGGING
+void scif_sas_remote_device_initialize_state_logging(
+   SCIF_SAS_REMOTE_DEVICE_T * remote_device
+)
+{
+   sci_base_state_machine_logger_initialize(
+      &remote_device->parent.state_machine_logger,
+      &remote_device->parent.state_machine,
+      &remote_device->parent.parent,
+      scif_cb_logger_log_states,
+      "SCIF_SAS_REMOTE_DEVICE_T", "base_state_machine",
+      SCIF_LOG_OBJECT_REMOTE_DEVICE
+   );
+
+   sci_base_state_machine_logger_initialize(
+      &remote_device->starting_substate_machine_logger,
+      &remote_device->starting_substate_machine,
+      &remote_device->parent.parent,
+      scif_cb_logger_log_states,
+      "SCIF_SAS_REMOTE_DEVICE_T", "starting substate machine",
+      SCIF_LOG_OBJECT_REMOTE_DEVICE
+   );
+
+   sci_base_state_machine_logger_initialize(
+      &remote_device->ready_substate_machine_logger,
+      &remote_device->ready_substate_machine,
+      &remote_device->parent.parent,
+      scif_cb_logger_log_states,
+      "SCIF_SAS_REMOTE_DEVICE_T", "ready substate machine",
+      SCIF_LOG_OBJECT_REMOTE_DEVICE
+   );
+}
+
+void scif_sas_remote_device_deinitialize_state_logging(
+   SCIF_SAS_REMOTE_DEVICE_T * remote_device
+)
+{
+   sci_base_state_machine_logger_deinitialize(
+      &remote_device->parent.state_machine_logger,
+      &remote_device->parent.state_machine
+   );
+
+   sci_base_state_machine_logger_deinitialize(
+      &remote_device->starting_substate_machine_logger,
+      &remote_device->starting_substate_machine
+   );
+
+   sci_base_state_machine_logger_deinitialize(
+      &remote_device->ready_substate_machine_logger,
+      &remote_device->ready_substate_machine
+   );
+}
+#endif // SCI_LOGGING
diff --git a/sys/dev/disk/isci/scil/scif_sas_remote_device.h b/sys/dev/disk/isci/scil/scif_sas_remote_device.h
new file mode 100644
index 0000000..d19a53a
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_remote_device.h
@@ -0,0 +1,501 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_remote_device.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIF_SAS_REMOTE_DEVICE_H_
+#define _SCIF_SAS_REMOTE_DEVICE_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains the protected interface structures, constants,
+ *        and methods for the SCIF_SAS_REMOTE_DEVICE object.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/scif_remote_device.h>
+
+#include <dev/disk/isci/scil/sci_base_remote_device.h>
+#include <dev/disk/isci/scil/sci_base_request.h>
+#include <dev/disk/isci/scil/sci_base_state_machine_logger.h>
+#include <dev/disk/isci/scil/scif_sas_stp_remote_device.h>
+#include <dev/disk/isci/scil/scif_sas_smp_remote_device.h>
+
+
+struct SCIF_SAS_DOMAIN;
+struct SCIF_SAS_REMOTE_DEVICE;
+struct SCIF_SAS_REQUEST;
+
+/**
+ * This constant indicates the number of milliseconds to wait for the core
+ * to start/stop it's remote device object.
+ */
+#define SCIF_SAS_REMOTE_DEVICE_CORE_OP_TIMEOUT 1000
+
+/**
+ * @enum _SCIF_SAS_REMOTE_DEVICE_STARTING_SUBSTATES
+ *
+ * @brief This enumeration depicts all the substates for the remote device's
+ *        starting substate machine.
+ */
+typedef enum _SCIF_SAS_REMOTE_DEVICE_STARTING_SUBSTATES
+{
+   /**
+    * This state indicates that the framework is waiting for the core to
+    * issue a scic_cb_remote_device_start_complete() notification.
+    */
+   SCIF_SAS_REMOTE_DEVICE_STARTING_SUBSTATE_AWAIT_COMPLETE,
+
+   /**
+    * This state indicates that the core has received the core's
+    * scic_cb_remote_device_start_complete() notification.
+    */
+   SCIF_SAS_REMOTE_DEVICE_STARTING_SUBSTATE_AWAIT_READY,
+
+   SCIF_SAS_REMOTE_DEVICE_STARTING_SUBSTATE_MAX_STATES
+
+} SCIF_SAS_REMOTE_DEVICE_STARTING_SUBSTATES;
+
+/**
+ * @enum _SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATES
+ *
+ * @brief This enumeration depicts all of the substates for the remote
+ *        device READY substate machine.
+ */
+typedef enum _SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATES
+{
+   /**
+    * The Operational sub-state indicates that the remote device object
+    * is capable of receiving and handling all request types.
+    */
+   SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL,
+
+   /**
+    * This substate indicates that core remote device is not ready.
+    * As a result, no new IO or Task Management requests are allowed.
+    */
+   SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_SUSPENDED,
+
+   /**
+    * This substate indicates that task management to this device is
+    * ongoing and new IO requests are not allowed.
+    */
+   SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_TASK_MGMT,
+
+   /**
+   * This substate indicates that core remote device is not ready due
+   *  to an NCQ error.  As a result, no new IO requests are allowed.
+   */
+   SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR,
+
+   SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_MAX_STATES
+
+} SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATES;
+
+struct SCIF_SAS_REMOTE_DEVICE;
+typedef void (*SCIF_SAS_REMOTE_DEVICE_COMPLETION_HANDLER_T)(
+   struct SCIF_SAS_REMOTE_DEVICE *,
+   SCI_STATUS
+);
+
+typedef void (*SCIF_SAS_REMOTE_DEVICE_HANDLER_T)(
+   struct SCIF_SAS_REMOTE_DEVICE *
+);
+
+typedef void (*SCIF_SAS_REMOTE_DEVICE_NOT_READY_HANDLER_T)(
+   struct SCIF_SAS_REMOTE_DEVICE *,
+   U32
+);
+
+/**
+ * @struct SCIF_SAS_REMOTE_DEVICE_STATE_HANDLER
+ *
+ * @brief This structure defines the state handler methods for states and
+ *        substates applicable for the framework remote device object.
+ */
+typedef struct SCIF_SAS_REMOTE_DEVICE_STATE_HANDLER
+{
+   SCI_BASE_REMOTE_DEVICE_STATE_HANDLER_T      parent;
+   SCIF_SAS_REMOTE_DEVICE_COMPLETION_HANDLER_T start_complete_handler;
+   SCIF_SAS_REMOTE_DEVICE_COMPLETION_HANDLER_T stop_complete_handler;
+   SCIF_SAS_REMOTE_DEVICE_HANDLER_T            ready_handler;
+   SCIF_SAS_REMOTE_DEVICE_NOT_READY_HANDLER_T  not_ready_handler;
+   SCI_BASE_REMOTE_DEVICE_REQUEST_HANDLER_T    start_high_priority_io_handler;
+   SCI_BASE_REMOTE_DEVICE_HIGH_PRIORITY_REQUEST_COMPLETE_HANDLER_T    complete_high_priority_io_handler;
+} SCIF_SAS_REMOTE_DEVICE_STATE_HANDLER_T;
+
+/**
+ * @struct SCIF_SAS_REMOTE_DEVICE
+ *
+ * @brief The SCI SAS Framework remote device object abstracts the SAS remote
+ *        device level behavior for the framework component.  Additionally,
+ *        it provides a higher level of abstraction for the core remote
+ *        device object.
+ */
+typedef struct SCIF_SAS_REMOTE_DEVICE
+{
+   /**
+    * The SCI_BASE_REMOTE_DEVICE is the parent object for the
+    * SCIF_SAS_REMOTE_DEVICE object.
+    */
+   SCI_BASE_REMOTE_DEVICE_T  parent;
+
+   /**
+    * This field contains the handle for the SCI Core remote device object
+    * that is managed by this framework controller.
+    */
+   SCI_REMOTE_DEVICE_HANDLE_T  core_object;
+
+   /**
+    * This field references the list of state specific handler methods to
+    * be utilized for this remote device instance.
+    */
+   SCIF_SAS_REMOTE_DEVICE_STATE_HANDLER_T * state_handlers;
+
+   /**
+    * This field specifies the state machine utilized to manage the
+    * starting remote device substate machine.
+    */
+   SCI_BASE_STATE_MACHINE_T starting_substate_machine;
+
+   /**
+    * This field specifies the state machine utilized to manage the
+    * starting remote device substate machine.
+    */
+   SCI_BASE_STATE_MACHINE_T ready_substate_machine;
+
+   union
+   {
+      /**
+       * This field specifies the information specific to SATA/STP device
+       * instances.  This field is not utilized for SSP/SMP.
+       */
+      SCIF_SAS_STP_REMOTE_DEVICE_T  stp_device;
+
+      /**
+       * This field specifies the information specific to SMP device instances.
+       * This field is not utilized for SSP/SATA/STP.
+       */
+      SCIF_SAS_SMP_REMOTE_DEVICE_T  smp_device;
+
+   }protocol_device;
+
+   /**
+    * This field indicates the domain object containing this remote device.
+    */
+   struct SCIF_SAS_DOMAIN * domain;
+
+   /**
+    * This field counts the number of requests (IO and task management)
+    * that are currently outstanding for this device.
+    */
+   U32 request_count;
+
+   /**
+    * This field counts the number of only task management request that are
+    * currently outstanding for this device.
+    */
+   U32 task_request_count;
+
+   /**
+    * This field is utilize to store the status value of various operations
+    * the can be executed on this remote device instance.
+    */
+   SCI_STATUS operation_status;
+
+   /**
+    * This field is utilize to indicate that the remote device should be
+    * destructed when it finally reaches the stopped state.  This will
+    * include destructing the core remote device as well.
+    */
+   BOOL  destruct_when_stopped;
+
+   /**
+    * This field marks a device state of being discovered or not, majorly used
+    * during re-discover procedure.
+    */
+   BOOL is_currently_discovered;
+
+   /**
+    * This filed stores the expander device this device connected to, only if this
+    * device is behind expander. So this field also served as a flag to tell if a
+    * device is a EA one.
+    */
+   struct SCIF_SAS_REMOTE_DEVICE * containing_device;
+
+   /**
+    * This field stores the expander phy identifier for an expander attached
+    * device. This field is only used by expander attached device.
+    */
+   U8 expander_phy_identifier;
+
+   /**
+    * This field stores the port width for a device. Most devices are narrow port
+    * device, their port width is 1. If a device is a wide port device, their
+    * port width is larger than 1.
+    */
+   U8 device_port_width;
+
+   /**
+    * This field stores the destination state for a remote device in UPDATING
+    * PORT WIDTH state. The possible destination states for a remote device in
+    * UPDATING_PORT_WIDTH state are READY or STOPPING.
+    */
+   U16 destination_state;
+
+   /**
+    * This field stores the scheduled/delayed EA target reset request.
+    */
+   struct SCIF_SAS_REQUEST * ea_target_reset_request_scheduled;
+
+   #ifdef SCI_LOGGING
+   /**
+    * This field is the observer of the base state machine for this device
+    * object.
+    */
+   SCI_BASE_OBSERVER_T base_state_machine_observer;
+
+   /**
+    * This field is the state machine logger of the startig substate machine for
+    * this device object.
+    */
+   SCI_BASE_STATE_MACHINE_LOGGER_T starting_substate_machine_logger;
+
+   /**
+    * This field is the state machine logger of the ready substate machine for
+    * this device object.
+    */
+   SCI_BASE_STATE_MACHINE_LOGGER_T ready_substate_machine_logger;
+   #endif // SCI_LOGGING
+
+} SCIF_SAS_REMOTE_DEVICE_T;
+
+extern SCI_BASE_STATE_T scif_sas_remote_device_state_table[];
+extern SCIF_SAS_REMOTE_DEVICE_STATE_HANDLER_T
+   scif_sas_remote_device_state_handler_table[];
+
+extern SCI_BASE_STATE_T scif_sas_remote_device_starting_substate_table[];
+extern SCIF_SAS_REMOTE_DEVICE_STATE_HANDLER_T
+   scif_sas_remote_device_starting_substate_handler_table[];
+
+extern SCI_BASE_STATE_T scif_sas_remote_device_ready_substate_table[];
+extern SCIF_SAS_REMOTE_DEVICE_STATE_HANDLER_T
+   scif_sas_remote_device_ready_substate_handler_table[];
+
+/**
+ * @enum
+ *
+ * This enumeration is used to define the end destination state for the
+ * framework remote device.
+ */
+enum SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE
+{
+   SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_UNSPECIFIED,
+   SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_READY,
+   SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_STOPPING,
+   SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_UPDATING_PORT_WIDTH
+};
+
+//******************************************************************************
+//* P R O T E C T E D   M E T H O D S
+//******************************************************************************
+void scif_sas_remote_device_save_report_phy_sata_information(
+   SMP_RESPONSE_REPORT_PHY_SATA_T * report_phy_sata_response
+);
+
+void scif_sas_remote_device_target_reset(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   struct SCIF_SAS_REQUEST  * fw_request
+);
+
+void scif_sas_remote_device_target_reset_complete(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   struct SCIF_SAS_REQUEST  * fw_request,
+   SCI_STATUS                 completion_status
+);
+
+#ifdef SCI_LOGGING
+void scif_sas_remote_device_initialize_state_logging(
+   SCIF_SAS_REMOTE_DEVICE_T * remote_device
+);
+
+void scif_sas_remote_device_deinitialize_state_logging(
+   SCIF_SAS_REMOTE_DEVICE_T * remote_device
+);
+#else // SCI_LOGGING
+#define scif_sas_remote_device_initialize_state_logging(x)
+#define scif_sas_remote_device_deinitialize_state_logging(x)
+#endif // SCI_LOGGING
+
+//******************************************************************************
+//* R E A D Y   O P E R A T I O N A L   S T A T E   H A N D L E R S
+//******************************************************************************
+
+SCI_STATUS scif_sas_remote_device_ready_operational_complete_io_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request
+);
+
+SCI_STATUS scif_sas_remote_device_ready_operational_complete_task_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * task_request
+);
+
+SCI_STATUS scif_sas_remote_device_ready_task_management_complete_task_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * task_request
+);
+
+//******************************************************************************
+//* D E F A U L T   S T A T E   H A N D L E R S
+//******************************************************************************
+
+SCI_STATUS scif_sas_remote_device_default_start_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device
+);
+
+SCI_STATUS scif_sas_remote_device_default_stop_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device
+);
+
+SCI_STATUS scif_sas_remote_device_default_reset_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device
+);
+
+SCI_STATUS scif_sas_remote_device_default_reset_complete_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device
+);
+
+SCI_STATUS scif_sas_remote_device_default_start_io_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request
+);
+
+void scif_sas_remote_device_default_start_complete_handler(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   SCI_STATUS                 completion_status
+);
+
+void scif_sas_remote_device_default_stop_complete_handler(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   SCI_STATUS                 completion_status
+);
+
+SCI_STATUS scif_sas_remote_device_default_destruct_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device
+);
+
+SCI_STATUS scif_sas_remote_device_default_complete_io_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request
+);
+
+SCI_STATUS scif_sas_remote_device_default_complete_high_priority_io_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request,
+   void                     * response_data,
+   SCI_IO_STATUS              completion_status
+);
+
+SCI_STATUS scif_sas_remote_device_default_continue_io_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request
+);
+
+SCI_STATUS scif_sas_remote_device_default_start_task_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * task_request
+);
+
+SCI_STATUS scif_sas_remote_device_default_complete_task_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * task_request
+);
+
+void scif_sas_remote_device_default_ready_handler(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device
+);
+
+void scif_sas_remote_device_default_not_ready_handler(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   U32                        reason_code
+);
+
+SCI_STATUS scif_sas_remote_device_ready_task_management_start_high_priority_io_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request
+);
+
+SCI_STATUS scif_sas_remote_device_ready_task_management_complete_high_priority_io_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request,
+   void                     * response_data,
+   SCI_IO_STATUS              completion_status
+);
+
+#if !defined(DISABLE_WIDE_PORTED_TARGETS)
+SCI_STATUS scif_sas_remote_device_update_port_width(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   U8                         new_port_width
+);
+#else // !defined(DISABLE_WIDE_PORTED_TARGETS)
+#define scif_sas_remote_device_update_port_width(device) SCI_FAILURE
+#endif //#if !defined(DISABLE_WIDE_PORTED_TARGETS)
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIF_SAS_REMOTE_DEVICE_H_
diff --git a/sys/dev/disk/isci/scil/scif_sas_remote_device_ready_substate_handlers.c b/sys/dev/disk/isci/scil/scif_sas_remote_device_ready_substate_handlers.c
new file mode 100644
index 0000000..74b18dc
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_remote_device_ready_substate_handlers.c
@@ -0,0 +1,777 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_remote_device_ready_substate_handlers.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the method implementations pertaining
+ *        to the framework remote device READY sub-state handler methods.
+ */
+
+#include <dev/disk/isci/scil/scic_remote_device.h>
+#include <dev/disk/isci/scil/scic_io_request.h>
+
+#include <dev/disk/isci/scil/scif_sas_logger.h>
+#include <dev/disk/isci/scil/scif_sas_remote_device.h>
+#include <dev/disk/isci/scil/scif_sas_domain.h>
+#include <dev/disk/isci/scil/scif_sas_task_request.h>
+#include <dev/disk/isci/scil/scif_sas_io_request.h>
+#include <dev/disk/isci/scil/scif_sas_internal_io_request.h>
+#include <dev/disk/isci/scil/scif_sas_controller.h>
+#include <dev/disk/isci/scil/sci_abstract_list.h>
+#include <dev/disk/isci/scil/intel_sat.h>
+#include <dev/disk/isci/scil/sci_controller.h>
+
+//******************************************************************************
+//* P R I V A T E   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method implements the behavior common to starting a task mgmt
+ *        request.  It will change the ready substate to task management.
+ *
+ * @param[in]  fw_device This parameter specifies the remote device for
+ *             which to complete a request.
+ * @param[in]  fw_task This parameter specifies the task management
+ *             request being started.
+ *
+ * @return This method returns a value indicating the status of the
+ *         start operation.
+ */
+static
+SCI_STATUS scif_sas_remote_device_start_task_request(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   SCIF_SAS_TASK_REQUEST_T  * fw_task
+)
+{
+   // Transition into the TASK MGMT substate if not already in it.
+   if (fw_device->ready_substate_machine.current_state_id
+       != SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_TASK_MGMT)
+   {
+      sci_base_state_machine_change_state(
+         &fw_device->ready_substate_machine,
+         SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_TASK_MGMT
+      );
+   }
+
+   fw_device->request_count++;
+   fw_device->task_request_count++;
+
+   return SCI_SUCCESS;
+}
+
+//******************************************************************************
+//* R E A D Y   O P E R A T I O N A L   H A N D L E R S
+//******************************************************************************
+
+/**
+ * @brief This method provides OPERATIONAL sub-state specific handling for
+ *        when the core remote device object issues a device not ready
+ *        notification.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object for which the notification occurred.
+ *
+ * @return none.
+ */
+static
+void scif_sas_remote_device_ready_operational_not_ready_handler(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   U32                        reason_code
+)
+{
+   if (reason_code == SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED)
+   {
+      sci_base_state_machine_change_state(
+         &fw_device->ready_substate_machine,
+         SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR
+      );
+   }
+   else
+   {
+      // Even though we are in the OPERATIONAL state, the core remote device is not
+      // ready.  As a result, we process user requests/events as if we were
+      // stopping the framework remote device.
+      sci_base_state_machine_change_state(
+         &fw_device->ready_substate_machine,
+         SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_SUSPENDED
+      );
+   }
+}
+
+/**
+ * @brief This method provides TASK MGMT sub-state specific handling for when
+ *        the core remote device object issues a device not ready notification.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object for which the notification occurred.
+ *
+ * @return none.
+ */
+static
+void scif_sas_remote_device_ready_task_management_not_ready_handler(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   U32                        reason_code
+)
+{
+   //do nothing. Don't need to go to suspended substate.
+}
+
+/**
+ * @brief This method provides OPERATIONAL sub-state specific handling for
+ *        when the remote device is being stopped by the framework.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object for which the stop operation is being requested.
+ *
+ * @return This method returns an indication as to whether the failure
+ *         operation completed successfully.
+ */
+static
+SCI_STATUS scif_sas_remote_device_ready_operational_stop_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)
+                                          remote_device;
+
+   sci_base_state_machine_change_state(
+      &fw_device->parent.state_machine, SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
+   );
+
+   return fw_device->operation_status;
+}
+
+/**
+ * @brief This method provides OPERATIONAL sub-state specific handling for
+ *        when the user attempts to destruct the remote device.  In
+ *        the READY state the framework must first stop the device
+ *        before destructing it.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object for which the framework is attempting to start.
+ *
+ * @return This method returns an indication as to whether the destruct
+ *         operation completed successfully.
+ */
+static
+SCI_STATUS scif_sas_remote_device_ready_operational_destruct_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)
+                                          remote_device;
+
+   fw_device->destruct_when_stopped = TRUE;
+
+   return (fw_device->state_handlers->parent.stop_handler(&fw_device->parent));
+}
+
+/**
+ * @brief This method provides OPERATIONAL sub-state specific handling for
+ *        when the remote device undergoes a failure condition.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object for which the failure condition occurred.
+ *
+ * @return This method returns an indication as to whether the failure
+ *         operation completed successfully.
+ */
+static
+SCI_STATUS scif_sas_remote_device_ready_operational_fail_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)
+                                          remote_device;
+
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE,
+      "RemoteDevice:0x%x ready device failed\n",
+      fw_device
+   ));
+
+   sci_base_state_machine_change_state(
+      &fw_device->parent.state_machine, SCI_BASE_REMOTE_DEVICE_STATE_FAILED
+   );
+
+   /// @todo Fix the return code handling.
+   return SCI_FAILURE;
+}
+
+/**
+ * @brief This method provides OPERATIONAL sub-state specific handling for
+ *        when a user attempts to start an IO request on a remote
+ *        device.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object on which the user is attempting to perform a start
+ *             IO operation.
+ * @param[in]  io_request This parameter specifies the IO request to be
+ *             started.
+ *
+ * @return This method returns an indication as to whether the IO request
+ *         started successfully.
+ */
+static
+SCI_STATUS scif_sas_remote_device_ready_operational_start_io_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
+                                          remote_device;
+   SCIF_SAS_IO_REQUEST_T    * fw_io     = (SCIF_SAS_IO_REQUEST_T*) io_request;
+   SCI_STATUS                 status;
+
+   status = fw_io->parent.state_handlers->start_handler(&fw_io->parent.parent);
+
+   if (status == SCI_SUCCESS)
+   {
+      fw_device->request_count++;
+   }
+
+   return status;
+}
+
+/**
+ * @brief This method provides OPERATIONAL sub-state specific handling for
+ *        when a user attempts to start an IO request on a remote
+ *        device.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object on which the user is attempting to perform a complete
+ *             IO operation.
+ * @param[in]  io_request This parameter specifies the IO request to
+ *             be completed.
+ *
+ * @return This method returns an indication as to whether the IO request
+ *         completed successfully.
+ */
+SCI_STATUS scif_sas_remote_device_ready_operational_complete_io_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
+                                          remote_device;
+   fw_device->request_count--;
+   return SCI_SUCCESS;
+}
+
+
+/**
+ * @brief This method provides OPERATIONAL sub-state specific handling for
+ *        when a user attempts to start an IO request on a remote
+ *        device.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object on which the user is attempting to perform a complete
+ *             IO operation.
+ * @param[in]  io_request This parameter specifies the IO request to
+ *             be completed.
+ *
+ * @return This method returns an indication as to whether the IO request
+ *         completed successfully.
+ */
+static
+SCI_STATUS scif_sas_remote_device_ready_operational_complete_high_priority_io_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request,
+   void                     * response_data,
+   SCI_IO_STATUS              completion_status
+)
+{
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger((SCIF_SAS_REMOTE_DEVICE_T *)remote_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE,
+      "RemoteDevice:0x%x State:0x%x invalid state to complete high priority IO\n",
+      remote_device,
+      sci_base_state_machine_get_state(
+         &((SCIF_SAS_REMOTE_DEVICE_T *)remote_device)->parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+
+/**
+ * @brief This method provides OPERATIONAL sub-state specific handling for when
+ *        the framework attempts to continue an IO request on a remote
+ *        device.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object on which the user is attempting to perform a continue
+ *             IO operation.
+ * @param[in]  io_request This parameter specifies the IO request to
+ *             be continued.
+ *
+ * @return This method returns an indication as to whether the IO request
+ *         completed successfully.
+ */
+static
+SCI_STATUS scif_sas_remote_device_ready_operational_continue_io_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request
+)
+{
+   /// @todo Fix the return code handling.
+   return SCI_FAILURE;
+}
+
+/**
+ * @brief This method provides OPERATIONAL sub-state specific handling for
+ *        when a user attempts to start a task management request on
+ *        a remote device.  This includes terminating all of the affected
+ *        ongoing IO requests (i.e. aborting them in the silicon) and then
+ *        issuing the task management request to the silicon.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object on which the user is attempting to perform a start
+ *             task operation.
+ * @param[in]  task_request This parameter specifies the task management
+ *             request to be started.
+ *
+ * @return This method returns an indication as to whether the task
+ *         management request started successfully.
+ */
+static
+SCI_STATUS scif_sas_remote_device_ready_operational_start_task_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * task_request
+)
+{
+   SCI_STATUS                 status     = SCI_FAILURE;
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device  = (SCIF_SAS_REMOTE_DEVICE_T*)
+                                           remote_device;
+   SCIF_SAS_TASK_REQUEST_T  * fw_task    = (SCIF_SAS_TASK_REQUEST_T*)
+                                           task_request;
+   U8 task_function =
+         scif_sas_task_request_get_function(fw_task);
+
+   SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;
+
+   scic_remote_device_get_protocols(fw_device->core_object, &dev_protocols);
+   if (   dev_protocols.u.bits.attached_ssp_target
+       || dev_protocols.u.bits.attached_stp_target)
+   {
+      // //NOTE: For STP/SATA targets we currently terminate all requests for
+      //       any type of task management.
+      if (  (task_function == SCI_SAS_ABORT_TASK_SET)
+         || (task_function == SCI_SAS_CLEAR_TASK_SET)
+         || (task_function == SCI_SAS_LOGICAL_UNIT_RESET)
+         || (task_function == SCI_SAS_I_T_NEXUS_RESET)
+         || (task_function == SCI_SAS_HARD_RESET) )
+      {
+         // Terminate all of the requests in the silicon for this device.
+         scif_sas_domain_terminate_requests(
+            fw_device->domain, fw_device, NULL, fw_task
+         );
+
+         status = scif_sas_remote_device_start_task_request(fw_device, fw_task);
+      }
+      else if (  (task_function == SCI_SAS_CLEAR_ACA)
+              || (task_function == SCI_SAS_QUERY_TASK)
+              || (task_function == SCI_SAS_QUERY_TASK_SET)
+              || (task_function == SCI_SAS_QUERY_ASYNCHRONOUS_EVENT) )
+      {
+       ASSERT(!dev_protocols.u.bits.attached_stp_target);
+         status = scif_sas_remote_device_start_task_request(fw_device, fw_task);
+      }
+      else if (task_function == SCI_SAS_ABORT_TASK)
+      {
+         SCIF_SAS_REQUEST_T * fw_request
+            = scif_sas_domain_get_request_by_io_tag(
+                 fw_device->domain, fw_task->io_tag_to_manage
+              );
+
+         // Determine if the request being aborted was found.
+         if (fw_request != NULL)
+         {
+            scif_sas_domain_terminate_requests(
+               fw_device->domain, fw_device, fw_request, fw_task
+            );
+
+            status = scif_sas_remote_device_start_task_request(
+                        fw_device, fw_task
+                     );
+         }
+         else
+            status = SCI_FAILURE_INVALID_IO_TAG;
+      }
+   }
+   else
+      status = SCI_FAILURE_UNSUPPORTED_PROTOCOL;
+
+   if (status != SCI_SUCCESS)
+   {
+      SCIF_LOG_ERROR((
+         sci_base_object_get_logger(fw_device),
+         SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_TASK_MANAGEMENT,
+         "Controller:0x%x TaskRequest:0x%x Status:0x%x start task failure\n",
+         fw_device, fw_task, status
+      ));
+   }
+
+   return status;
+}
+
+/**
+ * @brief This method provides OPERATIONAL sub-state specific handling for
+ *        when a user attempts to complete a task management request on
+ *        a remote device.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device object
+ *             on which the user is attempting to perform a complete task
+ *             operation.
+ * @param[in]  task_request This parameter specifies the task management
+ *             request to be completed.
+ *
+ * @return This method returns an indication as to whether the task
+ *         management request succeeded.
+ */
+SCI_STATUS scif_sas_remote_device_ready_operational_complete_task_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * task_request
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
+                                          remote_device;
+   fw_device->request_count--;
+   fw_device->task_request_count--;
+
+   return SCI_SUCCESS;
+}
+
+/**
+ * @brief This method provides OPERATIONAL sub-state specific handling for
+ *        when a user attempts to start a high priority IO request on a remote
+ *        device.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object on which the user is attempting to perform a start
+ *             IO operation.
+ * @param[in]  io_request This parameter specifies the IO request to be
+ *             started.
+ *
+ * @return This method returns an indication as to whether the IO request
+ *         started successfully.
+ */
+static
+SCI_STATUS scif_sas_remote_device_ready_operational_start_high_priority_io_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
+                                          remote_device;
+   SCIF_SAS_IO_REQUEST_T    * fw_io     = (SCIF_SAS_IO_REQUEST_T*) io_request;
+
+   SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;
+
+   scic_remote_device_get_protocols(fw_device->core_object, &dev_protocols);
+
+   if (dev_protocols.u.bits.attached_smp_target)
+   {
+      //transit to task management state for smp request phase.
+      if (fw_device->ready_substate_machine.current_state_id
+       != SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_TASK_MGMT)
+      {
+         sci_base_state_machine_change_state(
+            &fw_device->ready_substate_machine,
+            SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_TASK_MGMT
+         );
+      }
+   }
+
+   fw_device->request_count++;
+
+   return fw_io->parent.state_handlers->start_handler(&fw_io->parent.parent);
+}
+
+
+/**
+ * @brief This method provides TASK MANAGEMENT sub-state specific handling for
+ *        when a user attempts to complete a task management request on
+ *        a remote device.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device object
+ *             on which the user is attempting to perform a complete task
+ *             operation.
+ * @param[in]  task_request This parameter specifies the task management
+ *             request to be completed.
+ *
+ * @return This method returns an indication as to whether the task
+ *         management request succeeded.
+ */
+SCI_STATUS scif_sas_remote_device_ready_task_management_complete_task_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * task_request
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
+                                          remote_device;
+
+   SCIF_SAS_TASK_REQUEST_T * fw_task = (SCIF_SAS_TASK_REQUEST_T *)
+                                       task_request;
+
+   fw_device->request_count--;
+   fw_device->task_request_count--;
+
+   // All existing task management requests and all of the IO requests
+   // affectected by the task management request must complete before
+   // the remote device can transition back into the READY / OPERATIONAL
+   // state.
+   if (  (fw_device->task_request_count == 0)
+      && (fw_task->affected_request_count == 0) )
+   {
+      sci_base_state_machine_change_state(
+         &fw_device->ready_substate_machine,
+         SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL
+      );
+   }
+
+   return SCI_SUCCESS;
+}
+
+/**
+ * @brief This method provides SUSPENDED sub-state specific handling for
+ *        when the core remote device object issues a device ready
+ *        notification.  This effectively causes the framework remote
+ *        device to transition back into the OPERATIONAL state.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object for which the notification occurred.
+ *
+ * @return none.
+ */
+static
+void scif_sas_remote_device_ready_suspended_ready_handler(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device
+)
+{
+   sci_base_state_machine_change_state(
+      &fw_device->ready_substate_machine,
+      SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL
+   );
+}
+
+
+/**
+ * @brief This handler is currently solely used by smp remote device for
+ *        discovering.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object on which the user is attempting to perform a complete high
+ *             priority IO operation.
+ * @param[in]  io_request This parameter specifies the high priority IO request
+ *             to be completed.
+ *
+ * @return SCI_STATUS indicate whether the io complete successfully.
+ */
+SCI_STATUS
+scif_sas_remote_device_ready_task_management_complete_high_priority_io_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request,
+   void                     * response_data,
+   SCI_IO_STATUS              completion_status
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device  = (SCIF_SAS_REMOTE_DEVICE_T*)
+                                           remote_device;
+   SCIF_SAS_REQUEST_T       * fw_request = (SCIF_SAS_REQUEST_T*) io_request;
+   SCI_STATUS                 status     = SCI_SUCCESS;
+   SCIC_TRANSPORT_PROTOCOL    protocol;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(remote_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_IO_REQUEST,
+      "scif_sas_remote_device_ready_task_management_complete_high_priority_io_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
+      remote_device, io_request, response_data, completion_status
+   ));
+
+   fw_device->request_count--;
+
+   // we are back to ready operational sub state here.
+   sci_base_state_machine_change_state(
+      &fw_device->ready_substate_machine,
+      SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL
+   );
+
+   protocol = scic_io_request_get_protocol(fw_request->core_object);
+
+   // If this request was an SMP initiator request we created, then
+   // decode the response.
+   if (protocol == SCIC_SMP_PROTOCOL)
+   {
+      if (completion_status != SCI_IO_FAILURE_TERMINATED)
+      {
+         status = scif_sas_smp_remote_device_decode_smp_response(
+                     fw_device, fw_request, response_data, completion_status
+                  );
+      }
+      else
+         scif_sas_smp_remote_device_terminated_request_handler(fw_device, fw_request);
+   }
+   else
+   {
+      // Currently, there are only internal SMP requests.  So, default work
+      // is simply to clean up the internal request.
+      if (fw_request->is_internal == TRUE)
+      {
+         scif_sas_internal_io_request_complete(
+            fw_device->domain->controller,
+            (SCIF_SAS_INTERNAL_IO_REQUEST_T *)fw_request,
+            SCI_SUCCESS
+         );
+      }
+   }
+
+   return status;
+}
+
+
+SCIF_SAS_REMOTE_DEVICE_STATE_HANDLER_T
+scif_sas_remote_device_ready_substate_handler_table[] =
+{
+   // SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL
+   {
+      {
+         scif_sas_remote_device_default_start_handler,
+         scif_sas_remote_device_ready_operational_stop_handler,
+         scif_sas_remote_device_ready_operational_fail_handler,
+         scif_sas_remote_device_ready_operational_destruct_handler,
+         scif_sas_remote_device_default_reset_handler,
+         scif_sas_remote_device_default_reset_complete_handler,
+         scif_sas_remote_device_ready_operational_start_io_handler,
+         scif_sas_remote_device_ready_operational_complete_io_handler,
+         scif_sas_remote_device_ready_operational_continue_io_handler,
+         scif_sas_remote_device_ready_operational_start_task_handler,
+         scif_sas_remote_device_ready_operational_complete_task_handler
+      },
+      scif_sas_remote_device_default_start_complete_handler,
+      scif_sas_remote_device_default_stop_complete_handler,
+      scif_sas_remote_device_default_ready_handler,
+      scif_sas_remote_device_ready_operational_not_ready_handler,
+      scif_sas_remote_device_ready_operational_start_high_priority_io_handler,  //
+      scif_sas_remote_device_ready_operational_complete_high_priority_io_handler
+   },
+   // SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_SUSPENDED
+   {
+      {
+         scif_sas_remote_device_default_start_handler,
+         scif_sas_remote_device_ready_operational_stop_handler,
+         scif_sas_remote_device_ready_operational_fail_handler,
+         scif_sas_remote_device_ready_operational_destruct_handler,
+         scif_sas_remote_device_default_reset_handler,
+         scif_sas_remote_device_default_reset_complete_handler,
+         scif_sas_remote_device_default_start_io_handler,
+         scif_sas_remote_device_ready_operational_complete_io_handler,
+         scif_sas_remote_device_default_continue_io_handler,
+         scif_sas_remote_device_ready_operational_start_task_handler,
+         scif_sas_remote_device_ready_operational_complete_task_handler
+      },
+      scif_sas_remote_device_default_start_complete_handler,
+      scif_sas_remote_device_default_stop_complete_handler,
+      scif_sas_remote_device_ready_suspended_ready_handler,
+      scif_sas_remote_device_default_not_ready_handler,
+      scif_sas_remote_device_default_start_io_handler,
+      scif_sas_remote_device_ready_operational_complete_high_priority_io_handler
+   },
+   // SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_TASK_MGMT
+   {
+      {
+         scif_sas_remote_device_default_start_handler,
+         scif_sas_remote_device_ready_operational_stop_handler,
+         scif_sas_remote_device_ready_operational_fail_handler,
+         scif_sas_remote_device_ready_operational_destruct_handler,
+         scif_sas_remote_device_default_reset_handler,
+         scif_sas_remote_device_default_reset_complete_handler,
+         scif_sas_remote_device_default_start_io_handler,
+         scif_sas_remote_device_ready_operational_complete_io_handler,
+         scif_sas_remote_device_ready_operational_continue_io_handler,
+         scif_sas_remote_device_ready_operational_start_task_handler,
+         scif_sas_remote_device_ready_task_management_complete_task_handler
+      },
+      scif_sas_remote_device_default_start_complete_handler,
+      scif_sas_remote_device_default_stop_complete_handler,
+      scif_sas_remote_device_default_ready_handler,
+      scif_sas_remote_device_ready_task_management_not_ready_handler,
+      scif_sas_remote_device_ready_operational_start_high_priority_io_handler,
+      scif_sas_remote_device_ready_task_management_complete_high_priority_io_handler
+   },
+   // SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR
+   {
+      {
+         scif_sas_remote_device_default_start_handler,
+         scif_sas_remote_device_ready_operational_stop_handler,
+         scif_sas_remote_device_ready_operational_fail_handler,
+         scif_sas_remote_device_ready_operational_destruct_handler,
+         scif_sas_remote_device_default_reset_handler,
+         scif_sas_remote_device_default_reset_complete_handler,
+         scif_sas_remote_device_default_start_io_handler,
+         scif_sas_remote_device_ready_operational_complete_io_handler,
+         scif_sas_remote_device_default_continue_io_handler,
+         scif_sas_remote_device_ready_operational_start_task_handler,
+         scif_sas_remote_device_ready_operational_complete_task_handler
+      },
+      scif_sas_remote_device_default_start_complete_handler,
+      scif_sas_remote_device_default_stop_complete_handler,
+      scif_sas_remote_device_ready_suspended_ready_handler,
+      scif_sas_remote_device_default_not_ready_handler,
+      scif_sas_remote_device_default_start_io_handler,
+      scif_sas_remote_device_ready_operational_complete_high_priority_io_handler
+   },
+};
diff --git a/sys/dev/disk/isci/scil/scif_sas_remote_device_ready_substates.c b/sys/dev/disk/isci/scil/scif_sas_remote_device_ready_substates.c
new file mode 100644
index 0000000..2773670
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_remote_device_ready_substates.c
@@ -0,0 +1,288 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_remote_device_ready_substates.c,v 1.2 2012/02/09 17:50:24 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains the entrance and exit methods for the ready
+ *        sub-state machine states (OPERATIONAL, TASK_MGMT).
+ */
+
+#include <dev/disk/isci/scil/scif_sas_remote_device.h>
+#include <dev/disk/isci/scil/scif_sas_domain.h>
+#include <dev/disk/isci/scil/scif_sas_logger.h>
+#include <dev/disk/isci/scil/scif_sas_internal_io_request.h>
+#include <dev/disk/isci/scil/scif_sas_controller.h>
+#include <dev/disk/isci/scil/sci_controller.h>
+
+//******************************************************************************
+//* P R O T E C T E D   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        READY OPERATIONAL substate.  This includes setting the state
+ *        handler methods and issuing a scif_cb_remote_device_ready()
+ *        notification to the user.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_remote_device_ready_operational_substate_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
+
+   SET_STATE_HANDLER(
+      fw_device,
+      scif_sas_remote_device_ready_substate_handler_table,
+      SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL
+   );
+
+   SCIF_LOG_INFO((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_REMOTE_DEVICE_CONFIG,
+      "Domain:0x%x Device:0x%x device ready\n",
+      fw_device->domain, fw_device
+   ));
+
+   // Notify the user that the device has become ready.
+   scif_cb_remote_device_ready(
+      fw_device->domain->controller, fw_device->domain, fw_device
+   );
+}
+
+/**
+ * @brief This method implements the actions taken when exiting the
+ *        READY OPERATIONAL substate.  This method issues a
+ *        scif_cb_remote_device_not_ready() notification to the framework
+ *        user.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_remote_device_ready_operational_substate_exit(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
+
+   // Notify the user that the device has become ready.
+   scif_cb_remote_device_not_ready(
+      fw_device->domain->controller, fw_device->domain, fw_device
+   );
+}
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        READY SUSPENDED substate.  This includes setting the state
+ *        handler methods.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_remote_device_ready_suspended_substate_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
+
+   SET_STATE_HANDLER(
+      fw_device,
+      scif_sas_remote_device_ready_substate_handler_table,
+      SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_SUSPENDED
+   );
+}
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        READY TASK MGMT substate.  This includes setting the state
+ *        handler methods.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_remote_device_ready_taskmgmt_substate_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
+
+   SET_STATE_HANDLER(
+      fw_device,
+      scif_sas_remote_device_ready_substate_handler_table,
+      SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_TASK_MGMT
+   );
+}
+
+/**
+* @brief This method implements the actions taken when entering the
+*        READY NCQ ERROR substate.  This includes setting the state
+*        handler methods.
+*
+* @param[in]  object This parameter specifies the base object for which
+*             the state transition is occurring.  This is cast into a
+*             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
+*
+* @return none
+*/
+static
+void scif_sas_remote_device_ready_ncq_error_substate_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T         * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
+   SCI_STATUS                         status = SCI_SUCCESS;
+   SCI_TASK_REQUEST_HANDLE_T          handle;
+   SCIF_SAS_CONTROLLER_T            * fw_controller = fw_device->domain->controller;
+   SCIF_SAS_TASK_REQUEST_T          * fw_task_request;
+   SCIF_SAS_REQUEST_T               * fw_request;
+   void                             * internal_task_memory;
+   SCIF_SAS_DOMAIN_T                * fw_domain = fw_device->domain;
+   SCI_FAST_LIST_ELEMENT_T          * pending_request_element;
+   SCIF_SAS_REQUEST_T               * pending_request = NULL;
+
+   SET_STATE_HANDLER(
+      fw_device,
+      scif_sas_remote_device_ready_substate_handler_table,
+      SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR
+   );
+
+   internal_task_memory = scif_sas_controller_allocate_internal_request(fw_controller);
+   ASSERT(internal_task_memory != NULL);
+
+   fw_task_request = (SCIF_SAS_TASK_REQUEST_T*)internal_task_memory;
+
+   fw_request = &fw_task_request->parent;
+
+   //construct the scif io request
+   status = scif_sas_internal_task_request_construct(
+      fw_controller,
+      fw_device,
+      SCI_CONTROLLER_INVALID_IO_TAG,
+      (void *)fw_task_request,
+      &handle,
+      SCI_SAS_ABORT_TASK_SET
+   );
+
+   pending_request_element = fw_domain->request_list.list_head;
+
+   // Cycle through the fast list of IO requests.  Mark each request
+   //  pending to this remote device so that they are not completed
+   //  to the operating system when the request is terminated, but
+   //  rather when the abort task set completes.
+   while (pending_request_element != NULL)
+   {
+      pending_request =
+         (SCIF_SAS_REQUEST_T*) sci_fast_list_get_object(pending_request_element);
+
+      // The current element may be deleted from the list becasue of
+      // IO completion so advance to the next element early
+      pending_request_element = sci_fast_list_get_next(pending_request_element);
+
+      if (pending_request->device == fw_device)
+      {
+         pending_request->is_waiting_for_abort_task_set = TRUE;
+      }
+   }
+
+   scif_controller_start_task(
+      fw_controller,
+      fw_device,
+      fw_request,
+      SCI_CONTROLLER_INVALID_IO_TAG
+   );
+}
+
+SCI_BASE_STATE_T scif_sas_remote_device_ready_substate_table
+[SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_MAX_STATES] =
+{
+   {
+      SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL,
+      scif_sas_remote_device_ready_operational_substate_enter,
+      scif_sas_remote_device_ready_operational_substate_exit
+   },
+   {
+      SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_SUSPENDED,
+      scif_sas_remote_device_ready_suspended_substate_enter,
+      NULL
+   },
+   {
+      SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_TASK_MGMT,
+      scif_sas_remote_device_ready_taskmgmt_substate_enter,
+      NULL
+   },
+   {
+      SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR,
+      scif_sas_remote_device_ready_ncq_error_substate_enter,
+      NULL
+   }
+};
diff --git a/sys/dev/disk/isci/scil/scif_sas_remote_device_starting_substate_handlers.c b/sys/dev/disk/isci/scil/scif_sas_remote_device_starting_substate_handlers.c
new file mode 100644
index 0000000..d42455b
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_remote_device_starting_substate_handlers.c
@@ -0,0 +1,315 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_remote_device_starting_substate_handlers.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the method implementations pertaining
+ *        to the framework remote device STARTING sub-state handler methods.
+ *        The STARTING sub-state machine is responsible for ensuring that
+ *        all initialization and configuration for a particular remote
+ *        device is complete before transitioning to the READY state
+ *        (i.e. before allowing normal host IO).
+ */
+
+#include <dev/disk/isci/scil/scic_remote_device.h>
+
+#include <dev/disk/isci/scil/scif_sas_logger.h>
+#include <dev/disk/isci/scil/scif_sas_remote_device.h>
+#include <dev/disk/isci/scil/scif_sas_domain.h>
+#include <dev/disk/isci/scil/scif_sas_task_request.h>
+
+//******************************************************************************
+//* G E N E R A L   S T O P   H A N D L E R S
+//******************************************************************************
+
+/**
+ * @brief This method provides startig sub-state specific handling for
+ *        when the remote device is requested to stop.  This will occur
+ *        when there is a link failure during the starting operation.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object for which the failure condition occurred.
+ *
+ * @return This method returns an indication as to whether the failure
+ *         operation completed successfully.
+ */
+static
+SCI_STATUS
+scif_sas_remote_device_starting_state_general_stop_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)
+                                          remote_device;
+
+   SCIF_LOG_INFO((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE,
+      "RemoteDevice:0x%x starting device requested to stop\n",
+      fw_device
+   ));
+
+   fw_device->domain->device_start_in_progress_count--;
+
+   sci_base_state_machine_change_state(
+      &fw_device->parent.state_machine, SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
+   );
+
+   return SCI_SUCCESS;
+}
+
+//******************************************************************************
+//* A W A I T   C O M P L E T E   H A N D L E R S
+//******************************************************************************
+
+/**
+ * @brief This method provides AWAIT START COMPLETE sub-state specific
+ *        handling for when the remote device undergoes a failure
+ *        condition.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object for which the failure condition occurred.
+ *
+ * @return This method returns an indication as to whether the failure
+ *         operation completed successfully.
+ */
+static
+SCI_STATUS scif_sas_remote_device_starting_await_complete_fail_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)
+                                          remote_device;
+
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE,
+      "RemoteDevice:0x%x starting device failed, start complete not received\n",
+      fw_device
+   ));
+
+   sci_base_state_machine_change_state(
+      &fw_device->parent.state_machine, SCI_BASE_REMOTE_DEVICE_STATE_FAILED
+   );
+
+   return SCI_SUCCESS;
+}
+
+/**
+ * @brief This method provides AWAIT COMPLETE state specific handling for
+ *        when the core remote device object issues a device not ready
+ *        notification.  In the AWAIT COMPLETE state we do not inform
+ *        the framework user of the state change of the device, since the
+ *        user is unaware of the remote device start process.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object for which the notification occurred.
+ *
+ * @return none.
+ */
+static
+void scif_sas_remote_device_starting_await_complete_not_ready_handler(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   U32                        reason_code
+)
+{
+}
+
+/**
+ * @brief This method provides AWAIT START COMPLETE sub-state specific
+ *        handling for when the core provides a start complete notification
+ *        for the remote device.  If the start completion status indicates
+ *        a successful start, then the device is transitioned into the
+ *        READY state.  All other status cause a transition to the
+ *        FAILED state and a scif_cb_controller_error() notification
+ *        message to the framework user.
+ *
+ * @param[in]  fw_device This parameter specifies the remote device
+ *             object for which the notification has occurred.
+ *
+ * @return none.
+ */
+static
+void scif_sas_remote_device_starting_await_complete_start_complete_handler(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   SCI_STATUS                 completion_status
+)
+{
+   if (completion_status == SCI_SUCCESS)
+   {
+      /** @todo need to add support for resetting the device first.  This can
+                wait until 1.3. */
+      /** @todo Update to comprehend situations (i.e. SATA) where config is
+                needed. */
+
+      sci_base_state_machine_change_state(
+         &fw_device->starting_substate_machine,
+         SCIF_SAS_REMOTE_DEVICE_STARTING_SUBSTATE_AWAIT_READY
+      );
+   }
+   else
+   {
+      SCIF_LOG_WARNING((
+         sci_base_object_get_logger(fw_device),
+         SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_REMOTE_DEVICE_CONFIG,
+         "Device:0x%x Status:0x%x failed to start core device\n",
+         fw_device
+      ));
+
+      sci_base_state_machine_change_state(
+         &fw_device->parent.state_machine,
+         SCI_BASE_REMOTE_DEVICE_STATE_FAILED
+      );
+
+      // Something is seriously wrong.  Starting the core remote device
+      // shouldn't fail in anyway in this state.
+      scif_cb_controller_error(fw_device->domain->controller,
+              SCI_CONTROLLER_REMOTE_DEVICE_ERROR);
+   }
+}
+
+//******************************************************************************
+//* C O M P L E T E   H A N D L E R S
+//******************************************************************************
+
+/**
+ * @brief This method provides STARTING AWAIT READY sub-state specific
+ *        handling for when the core provides a device ready notification
+ *        for the remote device.  This essentially, causes a transition
+ *        of the framework remote device into the READY state.
+ *
+ * @param[in]  fw_device This parameter specifies the remote device
+ *             object for which the notification has occurred.
+ *
+ * @return none.
+ */
+static
+void scif_sas_remote_device_starting_await_ready_ready_handler(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device
+)
+{
+#if !defined(DISABLE_WIDE_PORTED_TARGETS)
+   if (fw_device->destination_state ==
+          SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_UPDATING_PORT_WIDTH)
+   {
+      {
+         sci_base_state_machine_change_state(
+            &fw_device->parent.state_machine,
+            SCI_BASE_REMOTE_DEVICE_STATE_UPDATING_PORT_WIDTH
+         );
+      }
+   }
+   else
+#endif
+   {
+      sci_base_state_machine_change_state(
+         &fw_device->parent.state_machine, SCI_BASE_REMOTE_DEVICE_STATE_READY
+      );
+   }
+
+#if !defined(DISABLE_WIDE_PORTED_TARGETS)
+   scif_sas_domain_remote_device_start_complete(fw_device->domain,fw_device);
+#endif
+}
+
+
+SCIF_SAS_REMOTE_DEVICE_STATE_HANDLER_T
+scif_sas_remote_device_starting_substate_handler_table[] =
+{
+   // SCIF_SAS_REMOTE_DEVICE_STARTING_SUBSTATE_AWAIT_COMPLETE
+   {
+      {
+         scif_sas_remote_device_default_start_handler,
+         scif_sas_remote_device_starting_state_general_stop_handler,
+         scif_sas_remote_device_starting_await_complete_fail_handler,
+         scif_sas_remote_device_default_destruct_handler,
+         scif_sas_remote_device_default_reset_handler,
+         scif_sas_remote_device_default_reset_complete_handler,
+         scif_sas_remote_device_default_start_io_handler,
+         scif_sas_remote_device_default_complete_io_handler,
+         scif_sas_remote_device_default_continue_io_handler,
+         scif_sas_remote_device_default_start_task_handler,
+         scif_sas_remote_device_default_complete_task_handler
+      },
+      scif_sas_remote_device_starting_await_complete_start_complete_handler,
+      scif_sas_remote_device_default_stop_complete_handler,
+      scif_sas_remote_device_default_ready_handler,
+      scif_sas_remote_device_starting_await_complete_not_ready_handler,
+      scif_sas_remote_device_default_start_io_handler,
+      scif_sas_remote_device_default_complete_high_priority_io_handler
+   },
+   // SCIF_SAS_REMOTE_DEVICE_STARTING_SUBSTATE_AWAIT_READY
+   {
+      {
+         scif_sas_remote_device_default_start_handler,
+         scif_sas_remote_device_starting_state_general_stop_handler,
+         scif_sas_remote_device_starting_await_complete_fail_handler,
+         scif_sas_remote_device_default_destruct_handler,
+         scif_sas_remote_device_default_reset_handler,
+         scif_sas_remote_device_default_reset_complete_handler,
+         scif_sas_remote_device_default_start_io_handler,
+         scif_sas_remote_device_default_complete_io_handler,
+         scif_sas_remote_device_default_continue_io_handler,
+         scif_sas_remote_device_default_start_task_handler,
+         scif_sas_remote_device_default_complete_task_handler
+      },
+      scif_sas_remote_device_default_start_complete_handler,
+      scif_sas_remote_device_default_stop_complete_handler,
+      scif_sas_remote_device_starting_await_ready_ready_handler,
+      scif_sas_remote_device_default_not_ready_handler,
+      scif_sas_remote_device_default_start_io_handler,
+      scif_sas_remote_device_default_complete_high_priority_io_handler
+   }
+};
diff --git a/sys/dev/disk/isci/scil/scif_sas_remote_device_starting_substates.c b/sys/dev/disk/isci/scil/scif_sas_remote_device_starting_substates.c
new file mode 100644
index 0000000..e413c4a
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_remote_device_starting_substates.c
@@ -0,0 +1,141 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_remote_device_starting_substates.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains the entrance and exit methods for the starting
+ *        sub-state machine states (AWAIT COMPELTE).  The starting sub-state
+ *        machine manages the steps necessary to initialize and configure
+ *        a remote device.
+ */
+
+#include <dev/disk/isci/scil/scif_sas_remote_device.h>
+#include <dev/disk/isci/scil/scif_sas_domain.h>
+#include <dev/disk/isci/scil/scif_sas_logger.h>
+
+
+//******************************************************************************
+//* P R O T E C T E D   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        STARTING AWAIT COMPLETE substate.  This includes setting the
+ *        state handler methods.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_remote_device_starting_await_complete_substate_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
+
+   SET_STATE_HANDLER(
+      fw_device,
+      scif_sas_remote_device_starting_substate_handler_table,
+      SCIF_SAS_REMOTE_DEVICE_STARTING_SUBSTATE_AWAIT_COMPLETE
+   );
+
+   fw_device->domain->device_start_in_progress_count++;
+   fw_device->domain->device_start_count++;
+}
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        STARTING COMPLETE substate.  This includes setting the
+ *        state handler methods.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_remote_device_starting_complete_substate_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
+
+   SET_STATE_HANDLER(
+      fw_device,
+      scif_sas_remote_device_starting_substate_handler_table,
+      SCIF_SAS_REMOTE_DEVICE_STARTING_SUBSTATE_AWAIT_READY
+   );
+}
+
+
+SCI_BASE_STATE_T
+scif_sas_remote_device_starting_substate_table
+[SCIF_SAS_REMOTE_DEVICE_STARTING_SUBSTATE_MAX_STATES] =
+{
+   {
+      SCIF_SAS_REMOTE_DEVICE_STARTING_SUBSTATE_AWAIT_COMPLETE,
+      scif_sas_remote_device_starting_await_complete_substate_enter,
+      NULL
+   },
+   {
+      SCIF_SAS_REMOTE_DEVICE_STARTING_SUBSTATE_AWAIT_READY,
+      scif_sas_remote_device_starting_complete_substate_enter,
+      NULL
+   }
+};
diff --git a/sys/dev/disk/isci/scil/scif_sas_remote_device_state_handlers.c b/sys/dev/disk/isci/scil/scif_sas_remote_device_state_handlers.c
new file mode 100644
index 0000000..ade5665
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_remote_device_state_handlers.c
@@ -0,0 +1,1159 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_remote_device_state_handlers.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the method implementations pertaining
+ *        to the framework remote device state handler methods.
+ */
+
+#include <dev/disk/isci/scil/scic_remote_device.h>
+
+#include <dev/disk/isci/scil/scif_sas_logger.h>
+#include <dev/disk/isci/scil/scif_sas_remote_device.h>
+#include <dev/disk/isci/scil/scif_sas_domain.h>
+#include <dev/disk/isci/scil/scif_sas_task_request.h>
+#include <dev/disk/isci/scil/scif_sas_internal_io_request.h>
+
+//******************************************************************************
+//* S T O P P E D   H A N D L E R S
+//******************************************************************************
+
+/**
+ * @brief This method provides STOPPED state specific handling for
+ *        when the framework attempts to start the remote device.  This
+ *        method attempts to transition the state machine into the
+ *        STARTING state.  If this is unsuccessful, then there is a direct
+ *        transition into the FAILED state.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object for which the framework is attempting to start.
+ *
+ * @return This method returns an indication as to whether the start
+ *         operating began successfully.
+ */
+static
+SCI_STATUS scif_sas_remote_device_stopped_start_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)
+                                          remote_device;
+
+   sci_base_state_machine_change_state(
+      &fw_device->parent.state_machine, SCI_BASE_REMOTE_DEVICE_STATE_STARTING
+   );
+
+   // Check to see if the state transition occurred without issue.
+   if (sci_base_state_machine_get_state(&fw_device->parent.state_machine)
+       == SCI_BASE_REMOTE_DEVICE_STATE_FAILED)
+   {
+      SCIF_LOG_WARNING((
+         sci_base_object_get_logger(fw_device),
+         SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+         "Domain:0x%x Device:0x%x Status:0x%x failed to start\n",
+         fw_device->domain, fw_device, fw_device->operation_status
+      ));
+   }
+
+   return fw_device->operation_status;
+}
+
+/**
+ * @brief This method provides STOPPED state specific handling for
+ *        when the user attempts to destruct the remote device.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object for which the framework is attempting to start.
+ *
+ * @return This method returns an indication as to whether the destruct
+ *         operation completed successfully.
+ */
+static
+SCI_STATUS scif_sas_remote_device_stopped_destruct_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device
+)
+{
+   SCI_STATUS                 status;
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)
+                                          remote_device;
+
+   SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;
+   scic_remote_device_get_protocols(fw_device->core_object, &dev_protocols);
+
+   //For smp device, need to clear its smp phy list first.
+   if(dev_protocols.u.bits.attached_smp_target)
+      scif_sas_smp_remote_device_removed(fw_device);
+
+   status = scic_remote_device_destruct(fw_device->core_object);
+   if (status == SCI_SUCCESS)
+   {
+      sci_base_state_machine_change_state(
+         &fw_device->parent.state_machine, SCI_BASE_REMOTE_DEVICE_STATE_FINAL
+      );
+
+      scif_sas_remote_device_deinitialize_state_logging(fw_device);
+   }
+   else
+   {
+      SCIF_LOG_ERROR((
+         sci_base_object_get_logger(fw_device),
+         SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_REMOTE_DEVICE_CONFIG,
+         "Device:0x%x Status:0x%x failed to destruct core device\n",
+         fw_device
+      ));
+   }
+
+   return status;
+}
+
+//******************************************************************************
+//* S T O P P I N G   H A N D L E R S
+//******************************************************************************
+
+/**
+ * @brief This method provides STOPPING state specific handling for
+ *        when the core remote device object issues a stop completion
+ *        notification.
+ *
+ * @note There is no need to ensure all IO/Task requests are complete
+ *       before transitioning to the STOPPED state.  The SCI Core will
+ *       ensure this is accomplished.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object for which the completion occurred.
+ * @param[in]  completion_status This parameter specifies the status
+ *             of the completion operation.
+ *
+ * @return none.
+ */
+static
+void scif_sas_remote_device_stopping_stop_complete_handler(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   SCI_STATUS                 completion_status
+)
+{
+   // Transition directly to the STOPPED state since the core ensures
+   // all IO/Tasks are complete.
+   sci_base_state_machine_change_state(
+      &fw_device->parent.state_machine,
+      SCI_BASE_REMOTE_DEVICE_STATE_STOPPED
+   );
+
+   if (completion_status != SCI_SUCCESS)
+   {
+      SCIF_LOG_ERROR((
+         sci_base_object_get_logger(fw_device),
+         SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_REMOTE_DEVICE_CONFIG,
+         "Device:0x%x Status:0x%x failed to stop core device\n",
+         fw_device, completion_status
+      ));
+
+      // Something is seriously wrong.  Stopping the core remote device
+      // shouldn't fail in anyway.
+      scif_cb_controller_error(fw_device->domain->controller,
+              SCI_CONTROLLER_REMOTE_DEVICE_ERROR);
+   }
+}
+
+/**
+ * @brief This method provides STOPPING state handling for high priority
+ *        IO requests, when the framework attempts to complete a high
+ *        priority request.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object for which to complete the high priority IO.
+ * @param[in]  io_request This parameter specifies the IO request to be
+ *             completed.
+ * @param[in]  response_data This parameter is ignored, since the device
+ *             is in the stopping state.
+ *
+ * @return This method always returns success.
+ */
+static
+SCI_STATUS scif_sas_remote_device_stopping_complete_high_priority_io_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request,
+   void                     * response_data,
+   SCI_IO_STATUS              completion_status
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)
+                                          remote_device;
+   SCIF_SAS_REQUEST_T       * fw_request = (SCIF_SAS_REQUEST_T *) io_request;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(remote_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_IO_REQUEST,
+      "scif_sas_remote_device_stopping_complete_high_priority_io_handler(0x%x,0x%x,0x%x) enter\n",
+      remote_device, io_request, response_data
+   ));
+
+   fw_device->request_count--;
+
+   if (fw_request->is_internal == TRUE)
+   {
+      scif_sas_internal_io_request_complete(
+         fw_device->domain->controller,
+         (SCIF_SAS_INTERNAL_IO_REQUEST_T *) io_request,
+         SCI_SUCCESS
+      );
+   }
+
+   return SCI_SUCCESS;
+}
+
+//******************************************************************************
+//* F A I L E D   H A N D L E R S
+//******************************************************************************
+
+/**
+ * @brief This method provides FAILED state specific handling for
+ *        when the remote device is being stopped by the framework.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object for which the stop operation is being requested.
+ *
+ * @return This method returns an indication as to whether the failure
+ *         operation completed successfully.
+ */
+static
+SCI_STATUS scif_sas_remote_device_failed_stop_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)
+                                          remote_device;
+
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE,
+      "RemoteDevice:0x%x stopping failed device\n",
+      fw_device
+   ));
+
+   sci_base_state_machine_change_state(
+      &fw_device->parent.state_machine, SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
+   );
+
+   /// @todo Fix the return code handling.
+   return SCI_FAILURE;
+}
+
+//******************************************************************************
+//* D E F A U L T   H A N D L E R S
+//******************************************************************************
+
+/**
+ * @brief This method provides default handling (i.e. returns an error);
+ *        when a user attempts to start a remote device and a start operation
+ *        is not allowed.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device object
+ *             on which the user is attempting to perform a start operation.
+ *
+ * @return This method returns an indication that start operations are not
+ *         allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+SCI_STATUS scif_sas_remote_device_default_start_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device
+)
+{
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger((SCIF_SAS_REMOTE_DEVICE_T *)remote_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_REMOTE_DEVICE_CONFIG,
+      "RemoteDevice:0x%x State:0x%x invalid state to start\n",
+      remote_device,
+      sci_base_state_machine_get_state(
+         &((SCIF_SAS_REMOTE_DEVICE_T *)remote_device)->parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * @brief This method provides default handling (i.e. returns an error);
+ *        when a user attempts to stop a remote device and a stop operation
+ *        is not allowed.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device object
+ *             on which the user is attempting to perform a stop operation.
+ *
+ * @return This method returns an indication that stop operations are not
+ *         allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+SCI_STATUS scif_sas_remote_device_default_stop_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device
+)
+{
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger((SCIF_SAS_REMOTE_DEVICE_T *)remote_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE,
+      "RemoteDevice:0x%x State:0x%x invalid state to stop\n",
+      remote_device,
+      sci_base_state_machine_get_state(
+         &((SCIF_SAS_REMOTE_DEVICE_T *)remote_device)->parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * @brief This method provides default handling (i.e. returns an error);
+ *        when there is an attempt to fail a remote device from an invalid
+ *        state.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object on which there is an attempt to fail the device.
+ *
+ * @return This method returns an indication that the fail transition is not
+ *         allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+static
+SCI_STATUS scif_sas_remote_device_default_fail_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device
+)
+{
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger((SCIF_SAS_REMOTE_DEVICE_T *)remote_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE,
+      "RemoteDevice:0x%x State:0x%x invalid state to fail device\n",
+      remote_device,
+      sci_base_state_machine_get_state(
+         &((SCIF_SAS_REMOTE_DEVICE_T *)remote_device)->parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * @brief This method provides default handling (i.e. returns an error);
+ *        when there is an attempt to destruct a remote device from an
+ *        invalid state.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object on which there is an attempt to fail the device.
+ *
+ * @return This method returns an indication that the fail transition is not
+ *         allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+SCI_STATUS scif_sas_remote_device_default_destruct_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device
+)
+{
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger((SCIF_SAS_REMOTE_DEVICE_T *)remote_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE,
+      "RemoteDevice:0x%x State:0x%x invalid state to destruct.\n",
+      remote_device,
+      sci_base_state_machine_get_state(
+         &((SCIF_SAS_REMOTE_DEVICE_T *)remote_device)->parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * @brief This method provides default handling (i.e. returns an error);
+ *        when there is an attempt to reset a remote device from an invalid
+ *        state.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object on which there is an attempt to fail the device.
+ *
+ * @return This method returns an indication that the fail transition is not
+ *         allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+SCI_STATUS scif_sas_remote_device_default_reset_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device
+)
+{
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger((SCIF_SAS_REMOTE_DEVICE_T *)remote_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE,
+      "RemoteDevice:0x%x State:0x%x invalid state to reset.\n",
+      remote_device,
+      sci_base_state_machine_get_state(
+         &((SCIF_SAS_REMOTE_DEVICE_T *)remote_device)->parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * @brief This method provides default handling (i.e. returns an error);
+ *        when there is an attempt to complete a reset to the remote device
+ *        from an invalid state.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object on which there is an attempt to fail the device.
+ *
+ * @return This method returns an indication that the fail transition is not
+ *         allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+SCI_STATUS scif_sas_remote_device_default_reset_complete_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device
+)
+{
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger((SCIF_SAS_REMOTE_DEVICE_T *)remote_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE,
+      "RemoteDevice:0x%x State:0x%x invalid state to complete reset.\n",
+      remote_device,
+      sci_base_state_machine_get_state(
+         &((SCIF_SAS_REMOTE_DEVICE_T *)remote_device)->parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * @brief This method provides default handling (i.e. returns an error);
+ *        when a user attempts to start an IO on a remote device and a start
+ *        IO operation is not allowed.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object on which the user is attempting to perform a start IO
+ *             operation.
+ * @param[in]  io_request This parameter specifies the IO request to be
+ *             started.
+ *
+ * @return This method returns an indication that start IO operations
+ *         are not allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+SCI_STATUS scif_sas_remote_device_default_start_io_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request
+)
+{
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger((SCIF_SAS_REMOTE_DEVICE_T *)remote_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE,
+      "RemoteDevice:0x%x State:0x%x invalid state to start IO.\n",
+      remote_device,
+      sci_base_state_machine_get_state(
+         &((SCIF_SAS_REMOTE_DEVICE_T *)remote_device)->parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * @brief This method provides default handling (i.e. returns an error);
+ *        when a user attempts to complete an IO on a remote device and a
+ *        complete IO operation is not allowed.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object on which the user is attempting to perform a complete
+ *             IO operation.
+ * @param[in]  io_request This parameter specifies the IO request to be
+ *             completed.
+ *
+ * @return This method returns an indication that complete IO operations
+ *         are not allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+SCI_STATUS scif_sas_remote_device_default_complete_io_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request
+)
+{
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger((SCIF_SAS_REMOTE_DEVICE_T *)remote_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE,
+      "RemoteDevice:0x%x State:0x%x invalid state to complete IO\n",
+      remote_device,
+      sci_base_state_machine_get_state(
+         &((SCIF_SAS_REMOTE_DEVICE_T *)remote_device)->parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+
+/**
+ * @brief This method provides default handling (i.e. returns an error);
+ *        when a user attempts to complete an IO on a remote device and a
+ *        complete IO operation is not allowed.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object on which the user is attempting to perform a start IO
+ *             operation.
+ * @param[in]  io_request This parameter specifies the IO request to be
+ *             started.
+ *
+ * @return This method returns an indication that complete IO operations
+ *         are not allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+SCI_STATUS scif_sas_remote_device_default_complete_high_priority_io_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request,
+   void                     * response_data,
+   SCI_IO_STATUS              completion_status
+)
+{
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger((SCIF_SAS_REMOTE_DEVICE_T *)remote_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE,
+      "RemoteDevice:0x%x State:0x%x invalid state to complete high priority IO\n",
+      remote_device,
+      sci_base_state_machine_get_state(
+         &((SCIF_SAS_REMOTE_DEVICE_T *)remote_device)->parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+
+/**
+ * @brief This method provides default handling (i.e. returns an error);
+ *        when a user attempts to continue an IO on a remote device and a
+ *        continue IO operation is not allowed.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object on which the user is attempting to perform a start IO
+ *             operation.
+ * @param[in]  io_request This parameter specifies the IO request to be
+ *             started.
+ *
+ * @return This method returns an indication that continue IO operations
+ *         are not allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+SCI_STATUS scif_sas_remote_device_default_continue_io_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request
+)
+{
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger((SCIF_SAS_REMOTE_DEVICE_T *)remote_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE,
+      "RemoteDevice:0x%x State:0x%x invalid state to continue IO\n",
+      remote_device,
+      sci_base_state_machine_get_state(
+         &((SCIF_SAS_REMOTE_DEVICE_T *)remote_device)->parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * @brief This method provides default handling (i.e. returns an error);
+ *        when a user attempts to start a task on a remote device and a
+ *        start task operation is not allowed.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device
+ *             object on which the user is attempting to perform a start
+ *             task operation.
+ * @param[in]  task_request This parameter specifies the task management
+ *             request to be started.
+ *
+ * @return This method returns an indication that start task operations
+ *         are not allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+SCI_STATUS scif_sas_remote_device_default_start_task_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * task_request
+)
+{
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger((SCIF_SAS_REMOTE_DEVICE_T *)remote_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_TASK_MANAGEMENT,
+      "RemoteDevice:0x%x State:0x%x invalid state to start task\n",
+      remote_device,
+      sci_base_state_machine_get_state(
+         &((SCIF_SAS_REMOTE_DEVICE_T *)remote_device)->parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * @brief This method provides default handling (i.e. returns an error);
+ *        when a user attempts to complete a task on a remote device and a
+ *        complete task operation is not allowed.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device object
+ *             on which the user is attempting to perform a complete task
+ *             operation.
+ * @param[in]  task_request This parameter specifies the task management
+ *             request to be completed.
+ *
+ * @return This method returns an indication that complete task operations
+ *         are not allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+SCI_STATUS scif_sas_remote_device_default_complete_task_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * task_request
+)
+{
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger((SCIF_SAS_REMOTE_DEVICE_T *)remote_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_TASK_MANAGEMENT,
+      "RemoteDevice:0x%x State:0x%x invalid state to complete task\n",
+      remote_device,
+      sci_base_state_machine_get_state(
+         &((SCIF_SAS_REMOTE_DEVICE_T *)remote_device)->parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * @brief This method provides default handling (i.e. returns an error);
+ *        for when the core issues a start completion notification and
+ *        such a notification isn't supported.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device object
+ *             for which the completion notification has occured.
+ * @param[in]  completion_status This parameter specifies the status
+ *             of the completion operation.
+ *
+ * @return none.
+ */
+void scif_sas_remote_device_default_start_complete_handler(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   SCI_STATUS                 completion_status
+)
+{
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE,
+      "RemoteDevice:0x%x State:0x%x invalid state to start complete\n",
+      fw_device,
+      sci_base_state_machine_get_state(&fw_device->parent.state_machine)
+   ));
+}
+
+/**
+ * @brief This method provides default handling (i.e. returns an error);
+ *        for when the core issues a stop completion notification and
+ *        such a notification isn't supported.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device object
+ *             for which the completion notification has occured.
+ * @param[in]  completion_status This parameter specifies the status
+ *             of the completion operation.
+ *
+ * @return none.
+ */
+void scif_sas_remote_device_default_stop_complete_handler(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   SCI_STATUS                 completion_status
+)
+{
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE,
+      "RemoteDevice:0x%x State:0x%x invalid state to stop complete\n",
+      fw_device,
+      sci_base_state_machine_get_state(&fw_device->parent.state_machine)
+   ));
+}
+
+/**
+ * @brief This method provides default handling (i.e. returns an error);
+ *        for when the core issues a ready notification and such a
+ *        notification isn't supported.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device object
+ *             for which the notification has occured.
+ *
+ * @return none.
+ */
+void scif_sas_remote_device_default_ready_handler(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device
+)
+{
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE,
+      "RemoteDevice:0x%x State:0x%x invalid state to handle ready\n",
+      fw_device,
+      sci_base_state_machine_get_state(&fw_device->parent.state_machine)
+   ));
+}
+
+/**
+ * @brief This method provides default handling (i.e. returns an error);
+ *        for when the core issues a not ready notification and such a
+ *        notification isn't supported.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device object
+ *             for which the notification has occured.
+ *
+ * @return none.
+ */
+void scif_sas_remote_device_default_not_ready_handler(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   U32                        reason_code
+)
+{
+   SCIF_LOG_WARNING((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE,
+      "RemoteDevice:0x%x State:0x%x invalid state to handle not ready\n",
+      fw_device,
+      sci_base_state_machine_get_state(&fw_device->parent.state_machine)
+   ));
+}
+
+#if !defined(DISABLE_WIDE_PORTED_TARGETS)
+/**
+ * @brief This method provides handling of device start complete duing
+ *        UPDATING_PORT_WIDTH state.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device object
+ *             which is start complete.
+ *
+ * @return none.
+ */
+static
+SCI_STATUS scif_sas_remote_device_updating_port_width_state_complete_io_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device,
+   SCI_BASE_REQUEST_T       * io_request
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
+                                          remote_device;
+   fw_device->request_count--;
+
+   //If the request count is zero, go ahead to update the RNC.
+   if (fw_device->request_count == 0 )
+   {
+      if (fw_device->destination_state == SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_STOPPING)
+      {
+         //if the destination state of this device change to STOPPING, no matter
+         //whether we need to update the port width, just make the device
+         //go to the STOPPING state, the device will be removed anyway.
+         sci_base_state_machine_change_state(
+            &fw_device->parent.state_machine,
+            SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
+         );
+      }
+      else
+      {
+         //stop the device, upon the stop complete callback, start the device again
+         //with the updated port width.
+         scic_remote_device_stop(
+            fw_device->core_object, SCIF_SAS_REMOTE_DEVICE_CORE_OP_TIMEOUT);
+      }
+   }
+
+   return SCI_SUCCESS;
+}
+
+
+/**
+ * @brief This method provides handling of device start complete duing
+ *        UPDATING_PORT_WIDTH state.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device object
+ *             which is start complete.
+ *
+ * @return none.
+ */
+static
+void scif_sas_remote_device_updating_port_width_state_start_complete_handler(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   SCI_STATUS                 completion_status
+)
+{
+   SCIF_LOG_INFO((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE,
+      "RemoteDevice:0x%x updating port width state start complete handler\n",
+      fw_device,
+      sci_base_state_machine_get_state(&fw_device->parent.state_machine)
+   ));
+
+   if ( fw_device->destination_state
+           == SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_STOPPING )
+   {
+      //if the destination state of this device change to STOPPING, no matter
+      //whether we need to update the port width again, just make the device
+      //go to the STOPPING state.
+      sci_base_state_machine_change_state(
+         &fw_device->parent.state_machine,
+         SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
+      );
+   }
+   else if ( scic_remote_device_get_port_width(fw_device->core_object)
+                != fw_device->device_port_width
+            && fw_device->device_port_width != 0)
+   {
+      scic_remote_device_stop(
+         fw_device->core_object,
+         SCIF_SAS_REMOTE_DEVICE_CORE_OP_TIMEOUT
+      );
+   }
+   else
+   {
+      //Port width updating succeeds. Transfer to destination state.
+      sci_base_state_machine_change_state(
+         &fw_device->parent.state_machine,
+         SCI_BASE_REMOTE_DEVICE_STATE_READY
+      );
+   }
+}
+
+/**
+ * @brief This method provides handling of device stop complete duing
+ *        UPDATING_PORT_WIDTH state.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device object
+ *             which is stop complete.
+ *
+ * @return none.
+ */
+static
+void scif_sas_remote_device_updating_port_width_state_stop_complete_handler(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   SCI_STATUS                 completion_status
+)
+{
+   SCIF_LOG_INFO((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE,
+      "RemoteDevice:0x%x updating port width state stop complete handler\n",
+      fw_device,
+      sci_base_state_machine_get_state(&fw_device->parent.state_machine)
+   ));
+
+   if ( fw_device->destination_state
+           == SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_STOPPING )
+   {
+      //Device directly transits to STOPPED STATE from UPDATING_PORT_WIDTH state,
+      fw_device->domain->device_start_count--;
+
+      //if the destination state of this device change to STOPPING, no matter
+      //whether we need to update the port width again, just make the device
+      //go to the STOPPED state.
+      sci_base_state_machine_change_state(
+         &fw_device->parent.state_machine,
+         SCI_BASE_REMOTE_DEVICE_STATE_STOPPED
+      );
+   }
+   else
+   {
+      scic_remote_device_set_port_width(
+         fw_device->core_object,
+         fw_device->device_port_width
+      );
+
+      //Device stop complete, means the RNC has been destructed. Now we need to
+      //start core device so the RNC with updated port width will be posted.
+      scic_remote_device_start(
+         fw_device->core_object, SCIF_SAS_REMOTE_DEVICE_CORE_OP_TIMEOUT);
+   }
+}
+
+/**
+ * @brief This method provides handling (i.e. returns an error);
+ *        when a user attempts to stop a remote device during the updating
+ *        port width state, it will record the destination state for this
+ *        device to be STOPPING, instead of usually READY state.
+ *
+ * @param[in]  remote_device This parameter specifies the remote device object
+ *             on which the user is attempting to perform a stop operation.
+ *
+ * @return This method always return SCI_SUCCESS.
+ */
+static
+SCI_STATUS scif_sas_remote_device_updating_port_width_state_stop_handler(
+   SCI_BASE_REMOTE_DEVICE_T * remote_device
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device =
+      (SCIF_SAS_REMOTE_DEVICE_T *)remote_device;
+
+   SCIF_LOG_INFO((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE,
+      "RemoteDevice:0x%x updating port width state stop handler\n",
+      fw_device,
+      sci_base_state_machine_get_state(&fw_device->parent.state_machine)
+   ));
+
+   //Can't stop the device right now. Remember the pending stopping request.
+   //When exit the UPDATING_PORT_WIDTH state, we will check this variable
+   //to decide which state to go.
+   fw_device->destination_state =
+      SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_STOPPING;
+
+   return SCI_SUCCESS;
+}
+
+#endif //#if !defined(DISABLE_WIDE_PORTED_TARGETS)
+
+#define scif_sas_remote_device_stopping_complete_io_handler   \
+        scif_sas_remote_device_ready_operational_complete_io_handler
+#define scif_sas_remote_device_stopping_complete_task_handler \
+        scif_sas_remote_device_ready_operational_complete_task_handler
+
+SCIF_SAS_REMOTE_DEVICE_STATE_HANDLER_T
+scif_sas_remote_device_state_handler_table[SCI_BASE_REMOTE_DEVICE_MAX_STATES] =
+{
+   // SCI_BASE_REMOTE_DEVICE_STATE_INITIAL
+   {
+      {
+         scif_sas_remote_device_default_start_handler,
+         scif_sas_remote_device_default_stop_handler,
+         scif_sas_remote_device_default_fail_handler,
+         scif_sas_remote_device_default_destruct_handler,
+         scif_sas_remote_device_default_reset_handler,
+         scif_sas_remote_device_default_reset_complete_handler,
+         scif_sas_remote_device_default_start_io_handler,
+         scif_sas_remote_device_default_complete_io_handler,
+         scif_sas_remote_device_default_continue_io_handler,
+         scif_sas_remote_device_default_start_task_handler,
+         scif_sas_remote_device_default_complete_task_handler
+      },
+      scif_sas_remote_device_default_start_complete_handler,
+      scif_sas_remote_device_default_stop_complete_handler,
+      scif_sas_remote_device_default_ready_handler,
+      scif_sas_remote_device_default_not_ready_handler,
+      scif_sas_remote_device_default_start_io_handler,
+      scif_sas_remote_device_default_complete_high_priority_io_handler
+   },
+   // SCI_BASE_REMOTE_DEVICE_STATE_STOPPED
+   {
+      {
+         scif_sas_remote_device_stopped_start_handler,
+         scif_sas_remote_device_default_stop_handler,
+         scif_sas_remote_device_default_fail_handler,
+         scif_sas_remote_device_stopped_destruct_handler,
+         scif_sas_remote_device_default_reset_handler,
+         scif_sas_remote_device_default_reset_complete_handler,
+         scif_sas_remote_device_default_start_io_handler,
+         scif_sas_remote_device_default_complete_io_handler,
+         scif_sas_remote_device_default_continue_io_handler,
+         scif_sas_remote_device_default_start_task_handler,
+         scif_sas_remote_device_default_complete_task_handler
+      },
+      scif_sas_remote_device_default_start_complete_handler,
+      scif_sas_remote_device_default_stop_complete_handler,
+      scif_sas_remote_device_default_ready_handler,
+      scif_sas_remote_device_default_not_ready_handler,
+      scif_sas_remote_device_default_start_io_handler,
+      scif_sas_remote_device_default_complete_high_priority_io_handler
+   },
+   // SCI_BASE_REMOTE_DEVICE_STATE_STARTING
+   {
+      {
+         scif_sas_remote_device_default_start_handler,
+         scif_sas_remote_device_default_stop_handler,
+         scif_sas_remote_device_default_fail_handler,
+         scif_sas_remote_device_default_destruct_handler,
+         scif_sas_remote_device_default_reset_handler,
+         scif_sas_remote_device_default_reset_complete_handler,
+         scif_sas_remote_device_default_start_io_handler,
+         scif_sas_remote_device_default_complete_io_handler,
+         scif_sas_remote_device_default_continue_io_handler,
+         scif_sas_remote_device_default_start_task_handler,
+         scif_sas_remote_device_default_complete_task_handler
+      },
+      scif_sas_remote_device_default_start_complete_handler,
+      scif_sas_remote_device_default_stop_complete_handler,
+      scif_sas_remote_device_default_ready_handler,
+      scif_sas_remote_device_default_not_ready_handler,
+      scif_sas_remote_device_default_start_io_handler,
+      scif_sas_remote_device_default_complete_high_priority_io_handler
+   },
+   // SCI_BASE_REMOTE_DEVICE_STATE_READY - see substate handlers
+   {
+      {
+         scif_sas_remote_device_default_start_handler,
+         scif_sas_remote_device_default_stop_handler,
+         scif_sas_remote_device_default_fail_handler,
+         scif_sas_remote_device_default_destruct_handler,
+         scif_sas_remote_device_default_reset_handler,
+         scif_sas_remote_device_default_reset_complete_handler,
+         scif_sas_remote_device_default_start_io_handler,
+         scif_sas_remote_device_default_complete_io_handler,
+         scif_sas_remote_device_default_continue_io_handler,
+         scif_sas_remote_device_default_start_task_handler,
+         scif_sas_remote_device_default_complete_task_handler
+      },
+      scif_sas_remote_device_default_start_complete_handler,
+      scif_sas_remote_device_default_stop_complete_handler,
+      scif_sas_remote_device_default_ready_handler,
+      scif_sas_remote_device_default_not_ready_handler,
+      scif_sas_remote_device_default_start_io_handler,
+      scif_sas_remote_device_default_complete_high_priority_io_handler
+   },
+   // SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
+   {
+      {
+         scif_sas_remote_device_default_start_handler,
+         scif_sas_remote_device_default_stop_handler,
+         scif_sas_remote_device_default_fail_handler,
+         scif_sas_remote_device_default_destruct_handler,
+         scif_sas_remote_device_default_reset_handler,
+         scif_sas_remote_device_default_reset_complete_handler,
+         scif_sas_remote_device_default_start_io_handler,
+         scif_sas_remote_device_stopping_complete_io_handler,
+         scif_sas_remote_device_default_continue_io_handler,
+         scif_sas_remote_device_default_start_task_handler,
+         scif_sas_remote_device_stopping_complete_task_handler
+      },
+      scif_sas_remote_device_default_start_complete_handler,
+      scif_sas_remote_device_stopping_stop_complete_handler,
+      scif_sas_remote_device_default_ready_handler,
+      scif_sas_remote_device_default_not_ready_handler,
+      scif_sas_remote_device_default_start_io_handler,
+      scif_sas_remote_device_stopping_complete_high_priority_io_handler
+   },
+   // SCI_BASE_REMOTE_DEVICE_STATE_FAILED
+   {
+      {
+         scif_sas_remote_device_default_start_handler,
+         scif_sas_remote_device_failed_stop_handler,
+         scif_sas_remote_device_default_fail_handler,
+         scif_sas_remote_device_default_destruct_handler,
+         scif_sas_remote_device_default_reset_handler,
+         scif_sas_remote_device_default_reset_complete_handler,
+         scif_sas_remote_device_default_start_io_handler,
+         scif_sas_remote_device_default_complete_io_handler,
+         scif_sas_remote_device_default_continue_io_handler,
+         scif_sas_remote_device_default_start_task_handler,
+         scif_sas_remote_device_default_complete_task_handler
+      },
+      scif_sas_remote_device_default_start_complete_handler,
+      scif_sas_remote_device_default_stop_complete_handler,
+      scif_sas_remote_device_default_ready_handler,
+      scif_sas_remote_device_default_not_ready_handler,
+      scif_sas_remote_device_default_start_io_handler,
+      scif_sas_remote_device_default_complete_high_priority_io_handler
+   },
+   // SCI_BASE_REMOTE_DEVICE_STATE_RESETTING - is unused by framework
+   {
+      {
+         scif_sas_remote_device_default_start_handler,
+         scif_sas_remote_device_default_stop_handler,
+         scif_sas_remote_device_default_fail_handler,
+         scif_sas_remote_device_default_destruct_handler,
+         scif_sas_remote_device_default_reset_handler,
+         scif_sas_remote_device_default_reset_complete_handler,
+         scif_sas_remote_device_default_start_io_handler,
+         scif_sas_remote_device_default_complete_io_handler,
+         scif_sas_remote_device_default_continue_io_handler,
+         scif_sas_remote_device_default_start_task_handler,
+         scif_sas_remote_device_default_complete_task_handler
+      },
+      scif_sas_remote_device_default_start_complete_handler,
+      scif_sas_remote_device_default_stop_complete_handler,
+      scif_sas_remote_device_default_ready_handler,
+      scif_sas_remote_device_default_not_ready_handler,
+      scif_sas_remote_device_default_start_io_handler,
+      scif_sas_remote_device_default_complete_high_priority_io_handler
+   },
+#if !defined(DISABLE_WIDE_PORTED_TARGETS)
+   // SCI_BASE_REMOTE_DEVICE_STATE_UPDATING_PORT_WIDTH
+   {
+      {
+         scif_sas_remote_device_default_start_handler,
+         scif_sas_remote_device_updating_port_width_state_stop_handler,
+         scif_sas_remote_device_default_fail_handler,
+         scif_sas_remote_device_default_destruct_handler,
+         scif_sas_remote_device_default_reset_handler,
+         scif_sas_remote_device_default_reset_complete_handler,
+         scif_sas_remote_device_default_start_io_handler,
+         scif_sas_remote_device_updating_port_width_state_complete_io_handler,
+         scif_sas_remote_device_default_continue_io_handler,
+         scif_sas_remote_device_default_start_task_handler,
+         scif_sas_remote_device_default_complete_task_handler
+      },
+      scif_sas_remote_device_updating_port_width_state_start_complete_handler,
+      scif_sas_remote_device_updating_port_width_state_stop_complete_handler,
+      scif_sas_remote_device_default_ready_handler,
+      scif_sas_remote_device_default_not_ready_handler,
+      scif_sas_remote_device_default_start_io_handler,
+      scif_sas_remote_device_default_complete_high_priority_io_handler
+   },
+#endif
+   // SCI_BASE_REMOTE_DEVICE_STATE_FINAL
+   {
+      {
+         scif_sas_remote_device_default_start_handler,
+         scif_sas_remote_device_default_stop_handler,
+         scif_sas_remote_device_default_fail_handler,
+         scif_sas_remote_device_default_destruct_handler,
+         scif_sas_remote_device_default_reset_handler,
+         scif_sas_remote_device_default_reset_complete_handler,
+         scif_sas_remote_device_default_start_io_handler,
+         scif_sas_remote_device_default_complete_io_handler,
+         scif_sas_remote_device_default_continue_io_handler,
+         scif_sas_remote_device_default_start_task_handler,
+         scif_sas_remote_device_default_complete_task_handler
+      },
+      scif_sas_remote_device_default_start_complete_handler,
+      scif_sas_remote_device_default_stop_complete_handler,
+      scif_sas_remote_device_default_ready_handler,
+      scif_sas_remote_device_default_not_ready_handler,
+      scif_sas_remote_device_default_start_io_handler,
+      scif_sas_remote_device_default_complete_high_priority_io_handler
+   }
+};
diff --git a/sys/dev/disk/isci/scil/scif_sas_remote_device_states.c b/sys/dev/disk/isci/scil/scif_sas_remote_device_states.c
new file mode 100644
index 0000000..68439c0
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_remote_device_states.c
@@ -0,0 +1,547 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_remote_device_states.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief
+ */
+
+#include <dev/disk/isci/scil/scic_remote_device.h>
+
+#include <dev/disk/isci/scil/scif_sas_remote_device.h>
+#include <dev/disk/isci/scil/scif_sas_domain.h>
+#include <dev/disk/isci/scil/scif_sas_logger.h>
+
+
+/**
+ * This constant indicates the number of milliseconds to wait for the core
+ * to start/stop it's remote device object.
+ */
+//#define SCIF_SAS_REMOTE_DEVICE_CORE_OP_TIMEOUT 1000
+
+//******************************************************************************
+//* P R O T E C T E D   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        INITIAL state.  This basically, causes an immediate transition
+ *        into the STOPPED state.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_remote_device_initial_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
+
+   SET_STATE_HANDLER(
+      fw_device,
+      scif_sas_remote_device_state_handler_table,
+      SCI_BASE_REMOTE_DEVICE_STATE_INITIAL
+   );
+
+   // Initial state is a transitional state to the stopped state
+   sci_base_state_machine_change_state(
+      &fw_device->parent.state_machine,
+      SCI_BASE_REMOTE_DEVICE_STATE_STOPPED
+   );
+}
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        STOPPED state.  This method updates the domains count of started
+ *        devices and will invoke the destruct method if this entrance into
+ *        the STOPPED state was due to a scif_remote_device_destruct()
+ *        call by the user.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_remote_device_stopped_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
+
+   SET_STATE_HANDLER(
+      fw_device,
+      scif_sas_remote_device_state_handler_table,
+      SCI_BASE_REMOTE_DEVICE_STATE_STOPPED
+   );
+
+   // There should be no outstanding requests for this device in the
+   // stopped state.
+   ASSERT(fw_device->request_count == 0);
+
+   // If we are entering the stopped state as a result of a destruct
+   // request, then let's perform the actual destruct operation now.
+   if (fw_device->destruct_when_stopped == TRUE)
+      fw_device->operation_status
+         = fw_device->state_handlers->parent.destruct_handler(
+              &fw_device->parent
+           );
+
+   /// @todo What should we do if this call fails?
+   fw_device->domain->state_handlers->device_stop_complete_handler(
+      &fw_device->domain->parent, &fw_device->parent
+   );
+}
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        STARTING state.  This method will attempt to start the core
+ *        remote device and will kick-start the starting sub-state machine
+ *        if no errors are encountered.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_remote_device_starting_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
+
+   SET_STATE_HANDLER(
+      fw_device,
+      scif_sas_remote_device_state_handler_table,
+      SCI_BASE_REMOTE_DEVICE_STATE_STARTING
+   );
+
+   SCIF_LOG_INFO((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_REMOTE_DEVICE_CONFIG,
+      "RemoteDevice:0x%x starting/configuring\n",
+      fw_device
+   ));
+
+   fw_device->destination_state =
+      SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_READY;
+
+   sci_base_state_machine_start(&fw_device->starting_substate_machine);
+
+   fw_device->operation_status = scic_remote_device_start(
+                                    fw_device->core_object,
+                                    SCIF_SAS_REMOTE_DEVICE_CORE_OP_TIMEOUT
+                                 );
+
+   if (fw_device->operation_status != SCI_SUCCESS)
+   {
+      fw_device->state_handlers->parent.fail_handler(&fw_device->parent);
+
+      // Something is seriously wrong.  Starting the core remote device
+      // shouldn't fail in anyway in this state.
+      scif_cb_controller_error(fw_device->domain->controller,
+              SCI_CONTROLLER_REMOTE_DEVICE_ERROR);
+   }
+}
+
+/**
+ * @brief This method implements the actions taken when exiting the
+ *        STARTING state.  Currently this method simply stops the
+ *        sub-state machine.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_remote_device_starting_state_exit(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
+
+   fw_device->destination_state =
+      SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_UNSPECIFIED;
+
+   // Transition immediately into the operational sub-state.
+   sci_base_state_machine_stop(&fw_device->starting_substate_machine);
+}
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        READY state.  Currently this method simply starts the
+ *        sub-state machine.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_remote_device_ready_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
+
+   // Transition immediately into the operational sub-state.
+   sci_base_state_machine_start(&fw_device->ready_substate_machine);
+
+#if defined(DISABLE_WIDE_PORTED_TARGETS)
+   scif_sas_domain_remote_device_start_complete(fw_device->domain,fw_device);
+#endif
+}
+
+/**
+ * @brief This method implements the actions taken when exiting the
+ *        READY state.  Currently this method simply stops the
+ *        sub-state machine.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_remote_device_ready_state_exit(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
+
+   // Transition immediately into the operational sub-state.
+   sci_base_state_machine_stop(&fw_device->ready_substate_machine);
+}
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        STOPPING state.  This includes: stopping the core remote device
+ *        and handling any errors that may occur.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_remote_device_stopping_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
+
+   SET_STATE_HANDLER(
+      fw_device,
+      scif_sas_remote_device_state_handler_table,
+      SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
+   );
+
+   fw_device->operation_status = scic_remote_device_stop(
+                                    fw_device->core_object,
+                                    SCIF_SAS_REMOTE_DEVICE_CORE_OP_TIMEOUT
+                                 );
+
+   // If there was a failure, then transition directly to the stopped state.
+   if (fw_device->operation_status != SCI_SUCCESS)
+   {
+      /**
+       * @todo We may want to consider adding handling to reset the
+       *       structure data for the framework and core devices here
+       *       in order to help aid recovery.
+       */
+
+      fw_device->state_handlers->stop_complete_handler(
+         fw_device, fw_device->operation_status
+      );
+   }
+}
+
+/**
+ * @brief This method implements the actions taken when exiting the
+ *        STOPPING state.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_remote_device_stopping_state_exit(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
+
+   // Let the domain know that the device has stopped
+   fw_device->domain->device_start_count--;
+}
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        FAILED state.  This includes setting the state handler methods
+ *        and issuing a scif_cb_remote_device_failed() notification to
+ *        the user.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_remote_device_failed_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
+
+   SET_STATE_HANDLER(
+      fw_device,
+      scif_sas_remote_device_state_handler_table,
+      SCI_BASE_REMOTE_DEVICE_STATE_FAILED
+   );
+
+   SCIF_LOG_INFO((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_REMOTE_DEVICE_CONFIG,
+      "Domain:0x%x Device:0x%x Status:0x%x device failed\n",
+      fw_device->domain, fw_device, fw_device->operation_status
+   ));
+
+   // Notify the user that the device has failed.
+   scif_cb_remote_device_failed(
+      fw_device->domain->controller,
+      fw_device->domain,
+      fw_device,
+      fw_device->operation_status
+   );
+
+   // Only call start_complete for the remote device if the device failed
+   // from the STARTING state.
+   if (fw_device->parent.state_machine.previous_state_id
+       == SCI_BASE_REMOTE_DEVICE_STATE_STARTING)
+      scif_sas_domain_remote_device_start_complete(fw_device->domain,fw_device);
+}
+
+/**
+ * @brief This method implements the actions taken when entering the RESETTING
+ *        state.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_remote_device_resetting_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+}
+
+#if !defined(DISABLE_WIDE_PORTED_TARGETS)
+/**
+ * @brief This method implements the actions taken when entering the UPDATING
+ *        PORT WIDTH state.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_remote_device_updating_port_width_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
+
+   SET_STATE_HANDLER(
+      fw_device,
+      scif_sas_remote_device_state_handler_table,
+      SCI_BASE_REMOTE_DEVICE_STATE_UPDATING_PORT_WIDTH
+   );
+
+   fw_device->destination_state = SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_READY;
+
+   //If the request count is zero, go ahead to update the RNC.
+   //If not, don't do anything for now. The IO complete handler of this state
+   //will update the RNC whenever the request count goes down to zero.
+   if (fw_device->request_count == 0)
+   {
+      //stop the device, upon the stop complete callback, start the device again
+      //with the updated port width.
+      scic_remote_device_stop(
+         fw_device->core_object, SCIF_SAS_REMOTE_DEVICE_CORE_OP_TIMEOUT);
+   }
+}
+
+
+/**
+ * @brief This method implements the actions taken when exiting the
+ *        STOPPING state.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_remote_device_updating_port_width_state_exit(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
+
+   fw_device->destination_state =
+      SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_UNSPECIFIED;
+}
+
+
+#endif //#if !defined(DISABLE_WIDE_PORTED_TARGETS)
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        FINAL state.  This includes setting the FINAL state handler
+ *        methods.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_remote_device_final_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
+
+   SET_STATE_HANDLER(
+      fw_device,
+      scif_sas_remote_device_state_handler_table,
+      SCI_BASE_REMOTE_DEVICE_STATE_FINAL
+   );
+}
+
+
+SCI_BASE_STATE_T
+   scif_sas_remote_device_state_table[SCI_BASE_REMOTE_DEVICE_MAX_STATES] =
+{
+   {
+      SCI_BASE_REMOTE_DEVICE_STATE_INITIAL,
+      scif_sas_remote_device_initial_state_enter,
+      NULL
+   },
+   {
+      SCI_BASE_REMOTE_DEVICE_STATE_STOPPED,
+      scif_sas_remote_device_stopped_state_enter,
+      NULL
+   },
+   {
+      SCI_BASE_REMOTE_DEVICE_STATE_STARTING,
+      scif_sas_remote_device_starting_state_enter,
+      scif_sas_remote_device_starting_state_exit
+   },
+   {
+      SCI_BASE_REMOTE_DEVICE_STATE_READY,
+      scif_sas_remote_device_ready_state_enter,
+      scif_sas_remote_device_ready_state_exit
+   },
+   {
+      SCI_BASE_REMOTE_DEVICE_STATE_STOPPING,
+      scif_sas_remote_device_stopping_state_enter,
+      scif_sas_remote_device_stopping_state_exit
+   },
+   {
+      SCI_BASE_REMOTE_DEVICE_STATE_FAILED,
+      scif_sas_remote_device_failed_state_enter,
+      NULL
+   },
+   {
+      SCI_BASE_REMOTE_DEVICE_STATE_RESETTING,
+      scif_sas_remote_device_resetting_state_enter,
+      NULL
+   },
+#if !defined(DISABLE_WIDE_PORTED_TARGETS)
+   {
+      SCI_BASE_REMOTE_DEVICE_STATE_UPDATING_PORT_WIDTH,
+      scif_sas_remote_device_updating_port_width_state_enter,
+      scif_sas_remote_device_updating_port_width_state_exit
+   },
+#endif //#if !defined(DISABLE_WIDE_PORTED_TARGETS)
+   {
+      SCI_BASE_REMOTE_DEVICE_STATE_FINAL,
+      scif_sas_remote_device_final_state_enter,
+      NULL
+   },
+};
diff --git a/sys/dev/disk/isci/scil/scif_sas_request.c b/sys/dev/disk/isci/scil/scif_sas_request.c
new file mode 100644
index 0000000..cd2fe31
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_request.c
@@ -0,0 +1,181 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_request.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains the implementation of the SCIF_SAS_REQUEST
+ *        object.  The SCIF_SAS_REQUEST object provides data and methods
+ *        that are common to both IO requests and task management requests.
+ */
+
+
+#include <dev/disk/isci/scil/scic_controller.h>
+
+#include <dev/disk/isci/scil/scif_sas_request.h>
+#include <dev/disk/isci/scil/scif_sas_task_request.h>
+#include <dev/disk/isci/scil/scif_sas_controller.h>
+#include <dev/disk/isci/scil/scif_sas_domain.h>
+#include <dev/disk/isci/scil/scif_sas_remote_device.h>
+
+#include <dev/disk/isci/scil/scif_sas_logger.h>
+
+//******************************************************************************
+//* P R O T E C T E D   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method constructs the SCIF_SAS_REQUEST object.
+ *
+ * @param[in] fw_request This parameter specifies the request object to
+ *            be constructed.
+ * @param[in] fw_device This parameter specifies the remote device object
+ *            to which this request is destined.
+ * @param[in] logger This parameter specifies the logger associated with
+ *            this base request object.
+ * @param[in] state_table This parameter specifies the table of state
+ *            definitions to be utilized for the request state machine.
+ *
+ * @return none
+ */
+void scif_sas_request_construct(
+   SCIF_SAS_REQUEST_T       * fw_request,
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   SCI_BASE_LOGGER_T        * logger,
+   SCI_BASE_STATE_T         * state_table
+)
+{
+   sci_base_request_construct(&fw_request->parent, logger, state_table);
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_request),
+      SCIF_LOG_OBJECT_TASK_MANAGEMENT,
+      "scif_sas_request_construct(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
+      fw_request, fw_device, logger, state_table
+   ));
+
+   fw_request->device                    = fw_device;
+   fw_request->is_internal               = FALSE;
+   fw_request->lun                       = 0;
+   fw_request->terminate_requestor       = NULL;
+   fw_request->protocol_complete_handler = NULL;
+   fw_request->is_high_priority          = FALSE;
+   fw_request->is_waiting_for_abort_task_set = FALSE;
+
+   sci_fast_list_element_init(fw_request, &fw_request->list_element);
+}
+
+/**
+ * @brief This method will request the SCI core to terminate the supplied
+ *        request.
+ *
+ * @param[in] fw_request This parameter specifies the request to be terminated.
+ * @param[in] core_request This parameter specifies the core request (IO or
+ *            task) to be terminated.
+ *
+ * @return This method returns the status of the core termination operation.
+ */
+SCI_STATUS scif_sas_request_terminate_start(
+   SCIF_SAS_REQUEST_T      * fw_request,
+   SCI_IO_REQUEST_HANDLE_T   core_request
+)
+{
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_request),
+      SCIF_LOG_OBJECT_TASK_MANAGEMENT,
+      "scif_sas_request_terminate_start(0x%x) enter\n",
+      fw_request
+   ));
+
+   // Only increment the affected request count if this request is being
+   // terminated at the behest of a task management request.
+   if (fw_request->terminate_requestor != NULL)
+      fw_request->terminate_requestor->affected_request_count++;
+
+   return scic_controller_terminate_request(
+             fw_request->device->domain->controller->core_object,
+             fw_request->device->core_object,
+             core_request
+          );
+}
+
+/**
+ * @brief This method will perform termination completion processing for
+ *        the supplied request.  This includes updated the affected
+ *        request count, if a task management request is what generated
+ *        this termination.  Also, this method will attempt to transition
+ *        to the READY OPERATIONAL state if this represents the last
+ *        affected request.
+ *
+ * @param[in] fw_request This parameter specifies the request for which to
+ *            perform termination completion processing.
+ *
+ * @return none
+ */
+void scif_sas_request_terminate_complete(
+   SCIF_SAS_REQUEST_T * fw_request
+)
+{
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_request),
+      SCIF_LOG_OBJECT_TASK_MANAGEMENT,
+      "scif_sas_request_terminate_complete(0x%x) enter\n",
+      fw_request
+   ));
+
+   // For requests that were terminated due to a task management request,
+   // check to see if the task management request has completed.
+   if (fw_request->terminate_requestor != NULL)
+      scif_sas_task_request_operation_complete(fw_request->terminate_requestor);
+}
diff --git a/sys/dev/disk/isci/scil/scif_sas_request.h b/sys/dev/disk/isci/scil/scif_sas_request.h
new file mode 100644
index 0000000..683e924
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_request.h
@@ -0,0 +1,220 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_request.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIF_SAS_REQUEST_H_
+#define _SCIF_SAS_REQUEST_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains the protected interface structures, constants,
+ *        and methods for the SCIF_SAS_REQUEST object.  This object provides
+ *        the common data and behavior to SAS IO and task management
+ *        request types.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sati_translator_sequence.h>
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/sci_status.h>
+#include <dev/disk/isci/scil/sci_fast_list.h>
+#include <dev/disk/isci/scil/sci_base_request.h>
+
+#define SCIF_SAS_RESPONSE_DATA_LENGTH 120
+
+struct SCIF_SAS_CONTROLLER;
+struct SCIF_SAS_REMOTE_DEVICE;
+struct SCIF_SAS_TASK_REQUEST;
+struct SCIF_SAS_REQUEST;
+
+typedef SCI_STATUS (*SCIF_SAS_REQUEST_COMPLETION_HANDLER_T)(
+   struct SCIF_SAS_CONTROLLER *,
+   struct SCIF_SAS_REMOTE_DEVICE *,
+   struct SCIF_SAS_REQUEST *,
+   SCI_STATUS *
+);
+
+/**
+ * @struct SCIF_SAS_STP_REQUEST
+ *
+ * @brief This structure contains all of the data specific to performing
+ *        SATA/STP IO and TASK requests.
+ */
+typedef struct SCIF_SAS_STP_REQUEST
+{
+   /**
+    * This field contains the translation information utilized by SATI.
+    * For more information on this field please refer to
+    * SATI_TRANSLATOR_SEQUENCE.
+    */
+   SATI_TRANSLATOR_SEQUENCE_T  sequence;
+
+   /**
+    * This field contains the ncq tag being utilized by this IO request.
+    * The NCQ tag value must be less than or equal to 31 (0 <= tag <= 31).
+    */
+   U8  ncq_tag;
+
+} SCIF_SAS_STP_REQUEST_T;
+
+/**
+ * @struct SCIF_SAS_REQUEST
+ *
+ * @brief The SCIF_SAS_REQUEST object abstracts the common SAS
+ *        IO & task management data and behavior for the framework component.
+ */
+typedef struct SCIF_SAS_REQUEST
+{
+   /**
+    * All SAS request types (IO or Task management) have the SCI base
+    * request as their parent object.
+    */
+   SCI_BASE_REQUEST_T  parent;
+
+   /**
+    * This field references the list of state specific handler methods to
+    * be utilized for this request instance.
+    */
+   SCI_BASE_REQUEST_STATE_HANDLER_T * state_handlers;
+
+   SCIF_SAS_REQUEST_COMPLETION_HANDLER_T protocol_complete_handler;
+
+   /**
+    * This field is utilized to communicate state information relating
+    * to this IO request and it's state transitions.
+    */
+   SCI_STATUS  status;
+
+   /**
+    * This field represents the remote device object to which this IO
+    * request is destined.
+    */
+   struct SCIF_SAS_REMOTE_DEVICE * device;
+
+   /**
+    * This field references the request object that has asked that this
+    * request be terminated.
+    */
+   struct SCIF_SAS_TASK_REQUEST * terminate_requestor;
+
+   /**
+    * This field provides list specific information that enables a request
+    * to be placed in a list.
+    */
+   SCI_FAST_LIST_ELEMENT_T  list_element;
+
+   /**
+    * This field indicates if the current request is one internally
+    * generated by the framework or if it is a user IO/task request.
+    */
+   BOOL is_internal;
+
+   /**
+    * This field indicates the current request is a high priority one.
+    * An internal request is always high priority. But an external request
+    * could be high priority.
+    */
+   BOOL is_high_priority;
+
+   /**
+    * This field indicates the current request should not be completed
+    * until a pending abort task set request is completed.  For NCQ errors,
+    * it will allow waiting until the read log ext data is returned to
+    * to determine how to fail/abort the pending ios.
+    */
+   BOOL is_waiting_for_abort_task_set;
+
+   /**
+    * This field indicates the logical unit (LUN) for the request.
+    * This field is utilized during internal IO requests.
+    */
+   U32  lun;
+
+   /**
+    * This field specifies sata specific data for the reqeust object.
+    * This data is only valid for SATA requests.
+    */
+   SCIF_SAS_STP_REQUEST_T  stp;
+
+   /**
+    * This field contains the handle for the SCI Core request object that is
+    * managed by this framework request.
+    */
+   SCI_IO_REQUEST_HANDLE_T  core_object;
+
+} SCIF_SAS_REQUEST_T;
+
+void scif_sas_request_construct(
+   SCIF_SAS_REQUEST_T            * fw_request,
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device,
+   SCI_BASE_LOGGER_T             * logger,
+   SCI_BASE_STATE_T              * state_table
+);
+
+SCI_STATUS scif_sas_request_terminate_start(
+   SCIF_SAS_REQUEST_T      * fw_request,
+   SCI_IO_REQUEST_HANDLE_T   core_request
+);
+
+void scif_sas_request_terminate_complete(
+   SCIF_SAS_REQUEST_T * fw_request
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIF_SAS_REQUEST_H_
diff --git a/sys/dev/disk/isci/scil/scif_sas_sati_binding.h b/sys/dev/disk/isci/scil/scif_sas_sati_binding.h
new file mode 100644
index 0000000..1a5f2ac
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_sati_binding.h
@@ -0,0 +1,252 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_sati_binding.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIF_SAS_SATI_BINDING_H_
+#define _SCIF_SAS_SATI_BINDING_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains the SATI (SCSI to ATA Translation Implementation)
+ *        callback implementations that can be implemented by the SCI
+ *        Framework (or core in some cases).
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/scif_user_callback.h>
+#include <dev/disk/isci/scil/scif_io_request.h>
+#include <dev/disk/isci/scil/scif_remote_device.h>
+#include <dev/disk/isci/scil/scic_user_callback.h>
+#include <dev/disk/isci/scil/scic_io_request.h>
+#include <dev/disk/isci/scil/scic_remote_device.h>
+//#include <dev/disk/isci/scil/scic_sds_request.h>
+//#include <dev/disk/isci/scil/scu_task_context.h>
+#include <dev/disk/isci/scil/sci_object.h>
+#include <dev/disk/isci/scil/scif_sas_request.h>
+#include <dev/disk/isci/scil/sci_base_memory_descriptor_list.h>
+#include <dev/disk/isci/scil/scif_sas_stp_remote_device.h>
+#include <dev/disk/isci/scil/scif_sas_remote_device.h>
+#include <dev/disk/isci/scil/scif_sas_domain.h>
+#include <dev/disk/isci/scil/scif_sas_controller.h>
+#include <dev/disk/isci/scil/scic_sds_request.h>
+#include <dev/disk/isci/sci_environment.h>
+
+// SATI callbacks fulfilled by the framework user.
+
+#define sati_cb_get_data_byte(scsi_io, byte_offset, value)                    \
+{                                                                             \
+   U8 * virtual_address = scif_cb_io_request_get_virtual_address_from_sgl(    \
+                             sci_object_get_association(scsi_io),(byte_offset)\
+                          );                                                  \
+   *(value) = *(virtual_address);                                             \
+}
+
+#define sati_cb_set_data_byte(scsi_io, byte_offset, value)                    \
+{                                                                             \
+   U8 * virtual_address = scif_cb_io_request_get_virtual_address_from_sgl(    \
+                             sci_object_get_association(scsi_io),(byte_offset)\
+                          );                                                  \
+   *(virtual_address) = value;                                                \
+}
+
+#define sati_cb_get_cdb_address(scsi_io) \
+   scif_cb_io_request_get_cdb_address(sci_object_get_association(scsi_io))
+
+#define sati_cb_get_cdb_length(scsi_io)  \
+   scif_cb_io_request_get_cdb_length(sci_object_get_association(scsi_io))
+
+#define sati_cb_get_data_direction(scsi_io, sati_data_direction)              \
+{                                                                             \
+   SCI_IO_REQUEST_DATA_DIRECTION sci_data_direction =                         \
+      scif_cb_io_request_get_data_direction(                                  \
+         sci_object_get_association(scsi_io)                                  \
+      );                                                                      \
+   if (sci_data_direction == SCI_IO_REQUEST_DATA_IN)                          \
+      *(sati_data_direction) = SATI_DATA_DIRECTION_IN;                        \
+   else if (sci_data_direction == SCI_IO_REQUEST_DATA_OUT)                    \
+      *(sati_data_direction) = SATI_DATA_DIRECTION_OUT;                       \
+   else if (sci_data_direction == SCI_IO_REQUEST_NO_DATA)                     \
+      *(sati_data_direction) = SATI_DATA_DIRECTION_NONE;                      \
+}
+
+#define sati_cb_get_lun(scsi_io) \
+   scif_cb_io_request_get_lun(sci_object_get_association(scsi_io))
+
+// SATI callbacks fulfilled by the framework.
+
+/**
+ * This method implements the functionality necessary to fulfill the
+ * SCSI-to-ATA Translation requirements.  It ensures that the SAS
+ * address for the remote device associated with the supplied IO
+ * is written into the sas_address parameter.
+ * For more information on the parameters utilized in this method,
+ * please refer to sati_cb_device_get_sas_address().
+ */
+#define sati_cb_device_get_sas_address(scsi_io, sas_address)               \
+{                                                                          \
+   SCIF_SAS_REQUEST_T* fw_request = (SCIF_SAS_REQUEST_T*)scsi_io;          \
+   SCI_REMOTE_DEVICE_HANDLE_T scic_device                                  \
+      = scif_remote_device_get_scic_handle(fw_request->device);            \
+   scic_remote_device_get_sas_address(scic_device, sas_address);           \
+}
+
+#define sati_cb_device_get_request_by_ncq_tag(scsi_io, ncq_tag, matching_req) \
+{                                                                          \
+   SCIF_SAS_REQUEST_T* fw_request = (SCIF_SAS_REQUEST_T*)scsi_io;          \
+   SCIF_SAS_REMOTE_DEVICE_T* fw_device = fw_request->device;               \
+   matching_req = scif_sas_stp_remote_device_get_request_by_ncq_tag(fw_device, ncq_tag);  \
+}
+
+#define sati_cb_io_request_complete(scsi_io, completion_status)            \
+{                                                                          \
+   SCIF_SAS_REQUEST_T* fw_request = (SCIF_SAS_REQUEST_T*)scsi_io;          \
+   SCIF_SAS_REMOTE_DEVICE_T* fw_device = fw_request->device;               \
+   SCIF_SAS_DOMAIN_T*  fw_domain = fw_device->domain;                      \
+   SCIF_SAS_CONTROLLER_T* fw_controller = fw_domain->controller;           \
+   scif_cb_io_request_complete(                                            \
+      fw_controller, fw_device, fw_request, completion_status              \
+   );                                                                      \
+}
+
+#define sati_cb_get_response_iu_address scif_io_request_get_response_iu_address
+#define sati_cb_get_task_function       scic_cb_ssp_task_request_get_function
+
+#define sati_cb_get_ata_data_address(the_ata_io)          \
+   scic_io_request_get_rx_frame(                          \
+      scif_io_request_get_scic_handle((the_ata_io)), 0    \
+   )
+
+#define sati_cb_get_h2d_register_fis_address(the_ata_io)  \
+   (U8*) scic_stp_io_request_get_h2d_reg_address(         \
+            scif_io_request_get_scic_handle((the_ata_io)) \
+         )
+
+#define sati_cb_get_d2h_register_fis_address(the_ata_io)  \
+   (U8*) scic_stp_io_request_get_d2h_reg_address(         \
+            scif_io_request_get_scic_handle((the_ata_io)) \
+         )
+
+#define sati_cb_allocate_dma_buffer(scsi_io, length, virt_address, phys_address_low, phys_address_high) \
+{                                                                 \
+   SCIF_SAS_REQUEST_T* fw_request = (SCIF_SAS_REQUEST_T*)scsi_io; \
+   SCI_PHYSICAL_MEMORY_DESCRIPTOR_T mde;                          \
+   SCI_PHYSICAL_ADDRESS phys_addr;                                \
+   mde.virtual_address = NULL;                                    \
+   sci_cb_make_physical_address(mde.physical_address, 0, 0);      \
+   sci_base_mde_construct(                                        \
+      &mde, 4, length, SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS    \
+   );                                                             \
+   scif_cb_controller_allocate_memory(                            \
+      fw_request->device->domain->controller, &mde                \
+   );                                                             \
+   scic_cb_io_request_get_physical_address(fw_request->device->domain->controller, \
+                                           NULL,                  \
+                                           mde.virtual_address,   \
+                                           &phys_addr);           \
+   *(virt_address)       = mde.virtual_address;                      \
+   *(phys_address_low)   = sci_cb_physical_address_lower(phys_addr); \
+   *(phys_address_high)  = sci_cb_physical_address_upper(phys_addr); \
+}
+
+#define sati_cb_free_dma_buffer(scsi_io, virt_address)         \
+{                                                                 \
+   SCIF_SAS_REQUEST_T* fw_request = (SCIF_SAS_REQUEST_T*)scsi_io; \
+   SCI_PHYSICAL_MEMORY_DESCRIPTOR_T mde;                          \
+   mde.virtual_address = virt_address;                         \
+   sci_cb_make_physical_address(mde.physical_address, 0, 0);      \
+   sci_base_mde_construct(                                        \
+      &mde, 4, 0, SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS         \
+   );                                                             \
+   scif_cb_controller_free_memory(                                \
+      fw_request->device->domain->controller, &mde                \
+   );                                                             \
+}
+
+#define sati_cb_sgl_next_sge(scsi_io, ata_io, current_sge, next_sge) \
+{ \
+   /* For now just 2 SGEs are supported. */ \
+   SCIC_SDS_REQUEST_T *scic_request; \
+   SCU_SGL_ELEMENT_PAIR_T *sgl_pair; \
+   scic_request = scif_io_request_get_scic_handle((scsi_io)); \
+   sgl_pair     = scic_sds_request_get_sgl_element_pair(scic_request, 0); \
+ \
+   if ((current_sge) == NULL) \
+   { \
+      *(next_sge) = &(sgl_pair->A); \
+   } \
+   else \
+   { \
+      *(next_sge) = &(sgl_pair->B); \
+   } \
+}
+
+#define sati_cb_sge_write(current_sge, phys_address_low, phys_address_high, byte_length) \
+{ \
+   SCU_SGL_ELEMENT_T * scu_sge = (SCU_SGL_ELEMENT_T*) (current_sge); \
+   scu_sge->address_upper      = (phys_address_high); \
+   scu_sge->address_lower      = (phys_address_low); \
+   scu_sge->length             = (byte_length); \
+   scu_sge->address_modifier   = 0; \
+}
+
+#define sati_cb_do_translate_response(request) \
+    (request)->stp.sequence.is_translate_response_required
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIF_SAS_SATI_BINDING_H_
diff --git a/sys/dev/disk/isci/scil/scif_sas_smp_activity_clear_affiliation.c b/sys/dev/disk/isci/scil/scif_sas_smp_activity_clear_affiliation.c
new file mode 100644
index 0000000..14ee740
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_smp_activity_clear_affiliation.c
@@ -0,0 +1,249 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_smp_activity_clear_affiliation.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains the methods for the SCIF_SAS_SMP_REMMOTE object's
+ *           clear affiliation activity.
+ */
+#include <dev/disk/isci/scil/sci_controller.h>
+#include <dev/disk/isci/scil/scif_sas_controller.h>
+#include <dev/disk/isci/scil/scif_sas_remote_device.h>
+#include <dev/disk/isci/scil/scif_sas_logger.h>
+
+#include <dev/disk/isci/scil/scif_sas_smp_remote_device.h>
+#include <dev/disk/isci/scil/scif_sas_smp_io_request.h>
+#include <dev/disk/isci/scil/intel_sas.h>
+#include <dev/disk/isci/scil/scic_io_request.h>
+#include <dev/disk/isci/scil/scic_remote_device.h>
+#include <dev/disk/isci/scil/scif_sas_smp_phy.h>
+
+//******************************************************************************
+//* P R I V A T E   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method finds the next smp phy (from the anchor_phy) that link to
+ *           a SATA end device.
+ *
+ * @param[in] fw_device the framework SMP device that is clearing affiliation for
+ *               its remote SATA devices'
+ *
+ * @return SCIF_SAS_SMP_PHY_T a smp phy, to which clear affiliation phy control command
+ *            is to be sent.
+ */
+static
+SCIF_SAS_SMP_PHY_T * scif_sas_smp_remote_device_find_next_smp_phy_link_to_sata(
+   SCIF_SAS_SMP_PHY_T * anchor_phy
+)
+{
+   SCI_FAST_LIST_ELEMENT_T  * element = &anchor_phy->list_element;
+   SCIF_SAS_SMP_PHY_T * curr_smp_phy = NULL;
+
+   while (element != NULL)
+   {
+      curr_smp_phy = (SCIF_SAS_SMP_PHY_T*) sci_fast_list_get_object(element);
+      element = sci_fast_list_get_next(element);
+
+      if (curr_smp_phy->attached_device_type == SMP_END_DEVICE_ONLY
+          && curr_smp_phy->u.end_device != NULL)
+      {
+         SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;
+         scic_remote_device_get_protocols(
+            curr_smp_phy->u.end_device->core_object, &dev_protocols);
+
+         if (dev_protocols.u.bits.attached_stp_target)
+            return curr_smp_phy;
+      }
+   }
+
+   return NULL;
+}
+
+//******************************************************************************
+//* P U B L I C   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method starts the clear affiliation activity for a
+ *           smp device's remote SATA devices.
+ *
+ * @param[in] fw_device the framework SMP device that is clearing affiliation for
+ *               its remote SATA devices.
+ *
+ * @return none
+ */
+void scif_sas_smp_remote_device_start_clear_affiliation(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device
+)
+{
+   SCIF_SAS_SMP_REMOTE_DEVICE_T * smp_device =
+      &fw_device->protocol_device.smp_device;
+
+   SCIF_SAS_SMP_PHY_T * phy_to_clear_affiliation = NULL;
+
+   if (smp_device->smp_phy_list.list_head != NULL)
+   {
+      phy_to_clear_affiliation =
+         scif_sas_smp_remote_device_find_next_smp_phy_link_to_sata(
+            (SCIF_SAS_SMP_PHY_T *)smp_device->smp_phy_list.list_head->object
+         );
+   }
+
+   if (phy_to_clear_affiliation != NULL)
+   {
+      smp_device->curr_clear_affiliation_phy = phy_to_clear_affiliation;
+
+      //set current activity
+      fw_device->protocol_device.smp_device.current_activity =
+         SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_CLEAR_AFFILIATION;
+
+      //Set current_smp_request to PHY CONTROL.
+      fw_device->protocol_device.smp_device.current_smp_request =
+         SMP_FUNCTION_PHY_CONTROL;
+
+      //reset discover_to_start flag.
+      fw_device->protocol_device.smp_device.scheduled_activity =
+         SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_NONE;
+
+      //build PHY Control (clear affiliation) to the phy.
+      scif_sas_smp_request_construct_phy_control(
+         fw_device->domain->controller,
+         fw_device,
+         PHY_OPERATION_CLEAR_AFFILIATION,
+         phy_to_clear_affiliation->phy_identifier,
+         NULL,
+         NULL
+      );
+
+      //issue DPC to start this request.
+      scif_cb_start_internal_io_task_schedule(
+         fw_device->domain->controller,
+         scif_sas_controller_start_high_priority_io,
+         fw_device->domain->controller
+      );
+   }
+   else
+      scif_sas_smp_remote_device_finish_clear_affiliation(fw_device);
+}
+
+
+/**
+ * @brief This method continues the clear affiliation activity for a
+ *           smp device's remote SATA devices.
+ *
+ * @param[in] fw_device the framework SMP device that is clearing affiliation for
+ *               its remote SATA devices.
+ *
+ * @return none
+ */
+void scif_sas_smp_remote_device_continue_clear_affiliation(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device
+)
+{
+   SCIF_SAS_SMP_REMOTE_DEVICE_T * smp_device =
+      &fw_device->protocol_device.smp_device;
+
+   //search from next immediate smp phy.
+   SCIF_SAS_SMP_PHY_T * phy_to_clear_affiliation = NULL;
+
+   if (smp_device->curr_clear_affiliation_phy->list_element.next != NULL)
+   {
+      phy_to_clear_affiliation =
+         scif_sas_smp_remote_device_find_next_smp_phy_link_to_sata(
+            smp_device->curr_clear_affiliation_phy->list_element.next->object
+         );
+   }
+
+   if (phy_to_clear_affiliation != NULL)
+   {
+      smp_device->curr_clear_affiliation_phy = phy_to_clear_affiliation;
+
+      //build PHY Control (clear affiliation) to the phy.
+      scif_sas_smp_request_construct_phy_control(
+         fw_device->domain->controller,
+         fw_device,
+         PHY_OPERATION_CLEAR_AFFILIATION,
+         phy_to_clear_affiliation->phy_identifier,
+         NULL,
+         NULL
+      );
+   }
+   else
+      scif_sas_smp_remote_device_finish_clear_affiliation(fw_device);
+}
+
+
+/**
+ * @brief This method finishes the clear affiliation activity for a
+ *           smp device's remote SATA devices. It then notify the domain it fihishes
+ *           the clear affiliation activity.
+ *
+ * @param[in] fw_device the framework SMP device that is clearing affiliation for
+ *               its remote SATA devices.
+ *
+ * @return none
+ */
+void scif_sas_smp_remote_device_finish_clear_affiliation(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device
+)
+{
+   SCIF_SAS_DOMAIN_T * fw_domain = fw_device->domain;
+
+   scif_sas_smp_remote_device_clear(fw_device);
+
+   //let domain continue to clear affiliation on other smp devices.
+   scif_sas_domain_continue_clear_affiliation(fw_domain);
+}
diff --git a/sys/dev/disk/isci/scil/scif_sas_smp_io_request.c b/sys/dev/disk/isci/scil/scif_sas_smp_io_request.c
new file mode 100644
index 0000000..2feedf0
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_smp_io_request.c
@@ -0,0 +1,598 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_smp_io_request.c,v 1.2 2012/02/07 17:45:11 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains the method implementations for the
+ *        SCIF_SAS_SMP_IO_REQUEST object.  The contents will implement SMP
+ *        specific functionality.
+ */
+
+#include <dev/disk/isci/scil/scif_sas_smp_io_request.h>
+#include <dev/disk/isci/scil/scif_sas_logger.h>
+#include <dev/disk/isci/scil/scif_sas_controller.h>
+#include <dev/disk/isci/scil/sci_controller.h>
+
+#include <dev/disk/isci/scil/sci_status.h>
+#include <dev/disk/isci/scil/scic_io_request.h>
+#include <dev/disk/isci/scil/scic_user_callback.h>
+
+#include <dev/disk/isci/scil/intel_sas.h>
+
+/**
+ * @brief This routine is to fill in the space given by core the SMP command
+ *        frame. Then it calls core's construction.
+ *
+ * @param[in] fw_io The smp io request to be constructed.
+ * @param[in] smp_command The SMP request filled according to SAS spec.
+ *
+ * @return none
+ */
+void scif_sas_smp_request_construct(
+   SCIF_SAS_REQUEST_T * fw_request,
+   SMP_REQUEST_T * smp_command
+)
+{
+   void * command_iu_address =
+      scic_io_request_get_command_iu_address(fw_request->core_object);
+
+   //copy the smp_command to the address;
+   memcpy( (char*) command_iu_address,
+           smp_command,
+           sizeof(SMP_REQUEST_T)
+          );
+
+   scic_io_request_construct_smp(fw_request->core_object);
+
+   fw_request->protocol_complete_handler
+      = NULL;
+}
+
+/**
+ * @brief This method will perform all of the construction common to all
+ *        SMP requests (e.g. filling in the frame type, zero-out memory,
+ *        etc.).
+ *
+ * @param[out] smp_request This parameter specifies the SMP request
+ *             structure containing the SMP request to be sent to the
+ *             SMP target.
+ * @param[in]  smp_function This parameter specifies the SMP function to
+ *             sent.
+ * @param[in]  smp_response_length This parameter specifies the length of
+ *             the response (in DWORDs) that will be returned for this
+ *             SMP request.
+ * @param[in]  smp_request_length This parameter specifies the length of
+ *             the request (in DWORDs) that will be sent.
+ */
+static
+void scif_sas_smp_protocol_request_construct(
+   SMP_REQUEST_T * smp_request,
+   U8              smp_function,
+   U8              smp_response_length,
+   U8              smp_request_length
+)
+{
+   memset((char*)smp_request, 0, sizeof(SMP_REQUEST_T));
+
+   smp_request->header.smp_frame_type            = SMP_FRAME_TYPE_REQUEST;
+   smp_request->header.function                  = smp_function;
+   smp_request->header.allocated_response_length = smp_response_length;
+   smp_request->header.request_length            = smp_request_length;
+}
+
+
+/**
+ * @brief This method will allocate the internal IO request object and
+ *        construct its contents based upon the supplied SMP request.
+ *
+ * @param[in] fw_controller This parameter specifies the controller object
+ *            from which to allocate the internal IO request.
+ * @param[in] fw_device This parameter specifies the remote device for
+ *            which the internal IO request is destined.
+ * @param[in] smp_request This parameter specifies the SMP request contents
+ *            to be sent to the SMP target.
+ *
+ * @return void * The address of built scif sas smp request.
+ */
+static
+void * scif_sas_smp_request_build(
+   SCIF_SAS_CONTROLLER_T    * fw_controller,
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   SMP_REQUEST_T            * smp_request,
+   void                     * external_request_object,
+   void                     * external_memory
+)
+{
+   if (external_memory != NULL && external_request_object != NULL)
+   {
+      scif_sas_io_request_construct_smp(
+         fw_controller,
+         fw_device,
+         external_memory,
+         (char *)external_memory + sizeof(SCIF_SAS_IO_REQUEST_T),
+         SCI_CONTROLLER_INVALID_IO_TAG,
+         smp_request,
+         external_request_object
+      );
+
+      return external_memory;
+   }
+   else
+   {
+      void * internal_io_memory;
+      internal_io_memory = scif_sas_controller_allocate_internal_request(fw_controller);
+      ASSERT(internal_io_memory != NULL);
+
+      if (internal_io_memory != NULL)
+      {
+         //construct, only when we got valid io memory.
+         scif_sas_internal_io_request_construct_smp(
+            fw_controller,
+            fw_device,
+            internal_io_memory,
+            SCI_CONTROLLER_INVALID_IO_TAG,
+            smp_request
+         );
+      }
+      else
+      {
+         SCIF_LOG_ERROR((
+            sci_base_object_get_logger(fw_controller),
+            SCIF_LOG_OBJECT_IO_REQUEST,
+            "scif_sas_smp_request_build, no memory available!\n"
+         ));
+      }
+
+      return internal_io_memory;
+   }
+}
+
+/**
+ * @brief construct a smp Report Genernal command to the fw_device.
+ *
+ * @param[in] fw_controller The framework controller object.
+ * @param[in] fw_device the framework device that the REPORT GENERAL command
+ *       targets to.
+ *
+ * @return void * address to the built scif sas smp request.
+ */
+void * scif_sas_smp_request_construct_report_general(
+   SCIF_SAS_CONTROLLER_T    * fw_controller,
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device
+)
+{
+   SMP_REQUEST_T smp_report_general;
+
+   // Build the REPORT GENERAL request.
+   scif_sas_smp_protocol_request_construct(
+      &smp_report_general,
+      SMP_FUNCTION_REPORT_GENERAL,
+      sizeof(SMP_RESPONSE_REPORT_GENERAL_T) / sizeof(U32),
+      0
+   );
+
+   smp_report_general.request.report_general.crc = 0;
+
+   SCIF_LOG_INFO((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_IO_REQUEST | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "SMP REPORT GENERAL -  Device:0x%x\n",
+      fw_device
+   ));
+
+   return scif_sas_smp_request_build(
+             fw_controller, fw_device, &smp_report_general, NULL, NULL);
+}
+
+/**
+ * @brief construct a SMP Report Manufacturer Info request to the fw_device.
+ *
+ * @param[in] fw_controller The framework controller object.
+ * @param[in] fw_device the framework device that the REPORT MANUFACTURER
+ *            INFO targets to.
+ *
+ * @return void * address to the built scif sas smp request.
+ */
+void * scif_sas_smp_request_construct_report_manufacturer_info(
+   SCIF_SAS_CONTROLLER_T    * fw_controller,
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device
+)
+{
+   SMP_REQUEST_T smp_report_manufacturer_info;
+
+   scif_sas_smp_protocol_request_construct(
+      &smp_report_manufacturer_info,
+      SMP_FUNCTION_REPORT_MANUFACTURER_INFORMATION,
+      sizeof(SMP_RESPONSE_REPORT_MANUFACTURER_INFORMATION_T) / sizeof(U32),
+      0
+   );
+
+   smp_report_manufacturer_info.request.report_general.crc = 0;
+
+   SCIF_LOG_INFO((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_IO_REQUEST | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "SMP REPORT MANUFACTURER_INFO -  Device:0x%x\n",
+      fw_device
+   ));
+
+   return scif_sas_smp_request_build(
+             fw_controller, fw_device, &smp_report_manufacturer_info, NULL, NULL
+          );
+}
+
+/**
+ * @brief construct a smp Discover command to the fw_device.
+ * @param[in] fw_controller The framework controller object.
+ * @param[in] fw_device the framework smp device that DISCOVER command targets
+ *       to.
+ * @param[in] phy_identifier The phy index the DISCOVER command targets to.
+ *
+ * @return void * address to the built scif sas smp request.
+ */
+void * scif_sas_smp_request_construct_discover(
+   SCIF_SAS_CONTROLLER_T    * fw_controller,
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   U8                         phy_identifier,
+   void                     * external_request_object,
+   void                     * external_memory
+)
+{
+   SMP_REQUEST_T smp_discover;
+
+   scif_sas_smp_protocol_request_construct(
+      &smp_discover,
+      SMP_FUNCTION_DISCOVER,
+      sizeof(SMP_RESPONSE_DISCOVER_T) / sizeof(U32),
+      sizeof(SMP_REQUEST_PHY_IDENTIFIER_T) / sizeof(U32)
+   );
+
+   smp_discover.request.discover.phy_identifier = phy_identifier;
+
+   SCIF_LOG_INFO((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_IO_REQUEST | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "SMP DISCOVER - Device:0x%x PhyId:0x%x\n",
+      fw_device, phy_identifier
+   ));
+
+   return scif_sas_smp_request_build(
+             fw_controller, fw_device, &smp_discover,
+             external_request_object, external_memory
+          );
+}
+
+
+/**
+ * @brief construct a smp REPORT PHY SATA command to the fw_device.
+ * @param[in] fw_controller The framework controller object.
+ * @param[in] fw_device the framework smp device that DISCOVER command targets
+ *       to.
+ * @param[in] phy_identifier The phy index the DISCOVER command targets to.
+ *
+ * @return void * address to the built scif sas smp request.
+ */
+void * scif_sas_smp_request_construct_report_phy_sata(
+   SCIF_SAS_CONTROLLER_T    * fw_controller,
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   U8                         phy_identifier
+)
+{
+   SMP_REQUEST_T report_phy_sata;
+
+   scif_sas_smp_protocol_request_construct(
+      &report_phy_sata,
+      SMP_FUNCTION_REPORT_PHY_SATA,
+      sizeof(SMP_RESPONSE_REPORT_PHY_SATA_T) / sizeof(U32),
+      sizeof(SMP_REQUEST_PHY_IDENTIFIER_T) / sizeof(U32)
+   );
+
+   report_phy_sata.request.report_phy_sata.phy_identifier = phy_identifier;
+
+   SCIF_LOG_INFO((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_IO_REQUEST | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "SMP REPORT PHY SATA - Device:0x%x PhyId:0x%x\n",
+      fw_device, phy_identifier
+   ));
+
+   return scif_sas_smp_request_build(
+             fw_controller, fw_device, &report_phy_sata, NULL, NULL);
+}
+
+
+/**
+ * @brief construct a smp REPORT PHY SATA command to the fw_device.
+ * @param[in] fw_controller The framework controller object.
+ * @param[in] fw_device the framework smp device that PHY CONTROL command
+ *       targets to.
+ * @param[in] phy_identifier The phy index the DISCOVER command targets to.
+ *
+ * @return void * address to the built scif sas smp request.
+ */
+void * scif_sas_smp_request_construct_phy_control(
+   SCIF_SAS_CONTROLLER_T    * fw_controller,
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   U8                         phy_operation,
+   U8                         phy_identifier,
+   void                     * external_request_object,
+   void                     * external_memory
+)
+{
+   SMP_REQUEST_T phy_control;
+
+   scif_sas_smp_protocol_request_construct(
+      &phy_control,
+      SMP_FUNCTION_PHY_CONTROL,
+      0,
+      sizeof(SMP_REQUEST_PHY_CONTROL_T) / sizeof(U32)
+   );
+
+   phy_control.request.phy_control.phy_operation = phy_operation;
+   phy_control.request.phy_control.phy_identifier = phy_identifier;
+
+   return scif_sas_smp_request_build(
+             fw_controller, fw_device, &phy_control,
+             external_request_object, external_memory
+          );
+}
+
+
+/**
+ * @brief construct a smp CONFIG ROUTE INFO command to the fw_device.
+ *
+ * @param[in] fw_controller The framework controller object.
+ * @param[in] fw_device the framework smp device that PHY CONTROL command
+ *       targets to.
+ * @param[in] phy_id The phy, whose route entry at route_index is to be configured.
+ * @param[in] route_index The index of a phy's route entry that is to be configured.
+ * @param[in] destination_sas_address A sas address for an route table entry
+ *
+ * @return void * address to the built scif sas smp request.
+ */
+void * scif_sas_smp_request_construct_config_route_info(
+   struct SCIF_SAS_CONTROLLER    * fw_controller,
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device,
+   U8                              phy_id,
+   U16                             route_index,
+   SCI_SAS_ADDRESS_T               destination_sas_address,
+   BOOL                            disable_expander_route_entry
+)
+{
+   SMP_REQUEST_T config_route_info;
+
+   scif_sas_smp_protocol_request_construct(
+      &config_route_info,
+      SMP_FUNCTION_CONFIGURE_ROUTE_INFORMATION,
+      0,
+      sizeof(SMP_REQUEST_CONFIGURE_ROUTE_INFORMATION_T) / sizeof(U32)
+   );
+
+   config_route_info.request.configure_route_information.phy_identifier = phy_id;
+   config_route_info.request.configure_route_information.expander_route_index_high =
+      ((route_index & 0xff00) >> 8);
+   config_route_info.request.configure_route_information.expander_route_index =
+      route_index & 0xff;
+   config_route_info.request.configure_route_information.routed_sas_address[0] =
+      destination_sas_address.high;
+   config_route_info.request.configure_route_information.routed_sas_address[1] =
+      destination_sas_address.low;
+
+   if (disable_expander_route_entry == TRUE)
+      config_route_info.request.configure_route_information.disable_route_entry = 1;
+
+   return scif_sas_smp_request_build(
+             fw_controller, fw_device, &config_route_info,
+             NULL, NULL
+          );
+}
+
+/**
+ * @brief This method retry the internal smp request.
+ *
+ * @param[in] fw_device This parameter specifies the remote device for
+ *            which the internal IO request is destined.
+ * @param[in] retry_count This parameter specifies how many times the
+ *            old smp request has been retried.
+ *
+ * @return none.
+ */
+SCI_STATUS scif_sas_smp_internal_request_retry(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device
+)
+{
+   SCIF_SAS_CONTROLLER_T * fw_controller;
+   SCIF_SAS_IO_REQUEST_T * new_io;
+   void                  * new_request_memory = NULL;
+   U8 retry_count = fw_device->protocol_device.smp_device.io_retry_count;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_IO_REQUEST | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_smp_internal_request_retry(0x%x, 0x%x) time %d!\n",
+      fw_device, retry_count
+   ));
+
+   fw_controller = fw_device->domain->controller;
+
+   switch (fw_device->protocol_device.smp_device.current_smp_request)
+   {
+      case SMP_FUNCTION_REPORT_GENERAL:
+         new_request_memory = scif_sas_smp_request_construct_report_general(
+            fw_controller, fw_device
+         );
+         break;
+
+      case SMP_FUNCTION_DISCOVER:
+         //We are retrying an internal io. So we are going to allocate
+         //a new memory from internal io memory pool.
+         new_request_memory = scif_sas_smp_request_construct_discover(
+            fw_controller, fw_device,
+            fw_device->protocol_device.smp_device.current_activity_phy_index,
+            NULL, NULL
+         );
+
+         break;
+
+      case SMP_FUNCTION_REPORT_PHY_SATA:
+         new_request_memory = scif_sas_smp_request_construct_report_phy_sata(
+            fw_controller, fw_device,
+            fw_device->protocol_device.smp_device.current_activity_phy_index
+         );
+         break;
+
+      default:
+         //unsupported case, TBD
+         break;
+   } //end of switch
+
+   if (new_request_memory != NULL)
+   {
+      //set the retry count to new built smp request.
+      new_io = (SCIF_SAS_IO_REQUEST_T *) new_request_memory;
+      new_io->retry_count = ++retry_count;
+
+      //need to schedule the DPC here.
+      scif_cb_start_internal_io_task_schedule(
+            fw_controller,
+            scif_sas_controller_start_high_priority_io,
+            fw_controller
+         );
+
+      return SCI_SUCCESS;
+   }
+   else
+      return SCI_FAILURE_INSUFFICIENT_RESOURCES;
+
+}
+
+/**
+ * @brief This method retry the external smp request.
+ *
+ * @param[in] fw_device This parameter specifies the remote device for
+ *            which the internal IO request is destined.
+ * @param[in] old_internal_io This parameter specifies the old smp request to be
+ *            retried.
+ *
+ * @return none.
+ */
+SCI_STATUS scif_sas_smp_external_request_retry(
+   SCIF_SAS_IO_REQUEST_T    * old_io
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = old_io->parent.device;
+   SCIF_SAS_CONTROLLER_T * fw_controller;
+   SCIF_SAS_IO_REQUEST_T * new_io;
+   void                  * new_request_memory = NULL;
+   U8                      retry_count = old_io->retry_count;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_IO_REQUEST | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_smp_external_request_retry(0x%x) time %d!\n",
+      old_io
+   ));
+
+   fw_controller = fw_device->domain->controller;
+
+   // Before we construct new io using the same memory, we need to
+   // remove the IO from the list of outstanding requests on the domain
+   // so that we don't damage the domain's fast list of request.
+   sci_fast_list_remove_element(&old_io->parent.list_element);
+
+   switch (fw_device->protocol_device.smp_device.current_smp_request)
+   {
+      case SMP_FUNCTION_DISCOVER:
+         //we are retrying an external io, we are going to reuse the
+         //old io's memory. new_request_memory is same as old_io.
+         new_request_memory = scif_sas_smp_request_construct_discover(
+            fw_controller, fw_device,
+            fw_device->protocol_device.smp_device.current_activity_phy_index,
+            (void *)sci_object_get_association(old_io),
+            (void *)old_io
+         );
+
+         break;
+
+      case SMP_FUNCTION_PHY_CONTROL:
+         //Phy Control command always uses external io memory.
+         new_request_memory = scif_sas_smp_request_construct_phy_control(
+            fw_controller, fw_device, PHY_OPERATION_HARD_RESET,
+            fw_device->protocol_device.smp_device.current_activity_phy_index,
+            (void *)sci_object_get_association(old_io),
+            (void *)old_io
+         );
+
+         break;
+
+      default:
+         //unsupported case, TBD
+         return SCI_FAILURE;
+   } //end of switch
+
+   //set the retry count to new built smp request.
+   new_io = (SCIF_SAS_IO_REQUEST_T *) new_request_memory;
+   new_io->retry_count = ++retry_count;
+
+   //put into the high priority queue.
+   sci_pool_put(fw_controller->hprq.pool, (POINTER_UINT) new_request_memory);
+
+   //schedule the DPC to start new io.
+   scif_cb_start_internal_io_task_schedule(
+      fw_controller, scif_sas_controller_start_high_priority_io, fw_controller
+   );
+
+   return SCI_SUCCESS;
+}
diff --git a/sys/dev/disk/isci/scil/scif_sas_smp_io_request.h b/sys/dev/disk/isci/scil/scif_sas_smp_io_request.h
new file mode 100644
index 0000000..5d5a8b8
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_smp_io_request.h
@@ -0,0 +1,138 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_smp_io_request.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIF_SAS_SMP_REQUEST_H_
+#define _SCIF_SAS_SMP_REQUEST_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains the protected interface structures, constants,
+ *        and methods for the SCIF_SAS_SMP_REQUEST object.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/intel_sas.h>
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/sci_status.h>
+#include <dev/disk/isci/scil/sci_base_request.h>
+
+struct SCIF_SAS_REQUEST;
+struct SCIF_SAS_IO_REQUEST;
+struct SCIF_SAS_CONTROLLER;
+struct SCIF_SAS_REMOTE_DEVICE;
+struct SCIF_SAS_INTERNAL_IO_REQUEST;
+
+void scif_sas_smp_request_construct(
+   struct SCIF_SAS_REQUEST * fw_io,
+   SMP_REQUEST_T * smp_command
+);
+
+void * scif_sas_smp_request_construct_report_general(
+   struct SCIF_SAS_CONTROLLER    * fw_controller,
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device
+);
+
+void * scif_sas_smp_request_construct_report_manufacturer_info(
+   struct SCIF_SAS_CONTROLLER    * fw_controller,
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device
+);
+
+void * scif_sas_smp_request_construct_discover(
+   struct SCIF_SAS_CONTROLLER    * fw_controller,
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device,
+   U8                              phy_identifier,
+   void                          * external_request_object,
+   void                          * external_memory
+);
+
+void * scif_sas_smp_request_construct_report_phy_sata(
+   struct SCIF_SAS_CONTROLLER    * fw_controller,
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device,
+   U8                              phy_identifier
+);
+
+void * scif_sas_smp_request_construct_phy_control(
+   struct SCIF_SAS_CONTROLLER    * fw_controller,
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device,
+   U8                         phy_operation,
+   U8                         phy_identifier,
+   void                     * external_request_object,
+   void                     * external_memory
+);
+
+void * scif_sas_smp_request_construct_config_route_info(
+   struct SCIF_SAS_CONTROLLER    * fw_controller,
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device,
+   U8                              phy_id,
+   U16                             route_index,
+   SCI_SAS_ADDRESS_T               destination_sas_Address,
+   BOOL                            disable_expander_route_entry
+);
+
+SCI_STATUS scif_sas_smp_internal_request_retry(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device
+);
+
+SCI_STATUS scif_sas_smp_external_request_retry(
+   struct SCIF_SAS_IO_REQUEST    * old_io
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif
diff --git a/sys/dev/disk/isci/scil/scif_sas_smp_phy.c b/sys/dev/disk/isci/scil/scif_sas_smp_phy.c
new file mode 100644
index 0000000..8f152f0
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_smp_phy.c
@@ -0,0 +1,334 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_smp_phy.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains the implementation of the SCIF_SAS_SMP_PHY
+ *        object.
+ */
+
+#include <dev/disk/isci/scil/scif_sas_controller.h>
+#include <dev/disk/isci/scil/scif_sas_smp_phy.h>
+#include <dev/disk/isci/scil/scif_sas_smp_remote_device.h>
+
+//******************************************************************************
+//*
+//*     P U B L I C   M E T H O D S
+//*
+//******************************************************************************
+
+/**
+ * @brief This routine constructs a smp phy object for an expander phy and insert
+ *           to owning expander device's smp_phy_list.
+ * @param[in] this_smp_phy The memory space to store a phy
+ * @param[in] owning_device The smp remote device that owns this smp phy.
+ * @param[in] expander_phy_id The expander phy id for this_smp_phy.
+ * @return None
+ */
+void scif_sas_smp_phy_construct(
+   SCIF_SAS_SMP_PHY_T       * this_smp_phy,
+   SCIF_SAS_REMOTE_DEVICE_T * owning_device,
+   U8                         expander_phy_id
+)
+{
+   memset(this_smp_phy, 0, sizeof(SCIF_SAS_SMP_PHY_T));
+
+   this_smp_phy->phy_identifier = expander_phy_id;
+   this_smp_phy->owning_device = owning_device;
+
+   sci_fast_list_element_init((this_smp_phy), (&this_smp_phy->list_element));
+
+   //insert to owning device's smp phy list.
+   sci_fast_list_insert_tail(
+      (&owning_device->protocol_device.smp_device.smp_phy_list),
+      (&this_smp_phy->list_element)
+   );
+}
+
+/**
+ * @brief This routine destructs a smp phy object for an expander phy and free the smp
+ *           phy to controller's smp phy memory.
+ * @param[in] this_smp_phy The smp phy to be destructed.
+ *
+ * @return None
+ */
+void scif_sas_smp_phy_destruct(
+   SCIF_SAS_SMP_PHY_T       * this_smp_phy
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * owning_device = this_smp_phy->owning_device;
+   SCIF_SAS_CONTROLLER_T * fw_controller = owning_device->domain->controller;
+
+   if ( ( this_smp_phy->attached_device_type == SMP_EDGE_EXPANDER_DEVICE
+         || this_smp_phy->attached_device_type == SMP_FANOUT_EXPANDER_DEVICE)
+       && this_smp_phy->u.attached_phy != NULL )
+   {
+      //update the counterpart phy from the other smp phy list.
+      this_smp_phy->u.attached_phy->attached_device_type = SMP_NO_DEVICE_ATTACHED;
+      this_smp_phy->u.attached_phy->u.attached_phy = NULL;
+   }
+
+   //remove curr_smp_phy
+   sci_fast_list_remove_element(&this_smp_phy->list_element);
+   scif_sas_controller_free_smp_phy(fw_controller, this_smp_phy);
+}
+
+
+/**
+ * @brief This routine save a smp phy information based on discover response.
+ *
+ * @param[in] this_smp_phy The memory space to store a phy
+ * @param[in] attached_device A possible direct attached device to this phy.
+ *
+ * @param[in] discover_response The smp DISCOVER response for this_smp_phy.
+ * @return None
+ */
+void scif_sas_smp_phy_save_information(
+   SCIF_SAS_SMP_PHY_T       * this_smp_phy,
+   SCIF_SAS_REMOTE_DEVICE_T * attached_device,
+   SMP_RESPONSE_DISCOVER_T  * discover_response
+)
+{
+   ASSERT (this_smp_phy->owning_device != NULL);
+   ASSERT (this_smp_phy->phy_identifier == discover_response->phy_identifier);
+
+   this_smp_phy->attached_device_type = (U8)discover_response->u2.sas1_1.attached_device_type;
+   this_smp_phy->routing_attribute = (U8)discover_response->routing_attribute;
+   this_smp_phy->attached_sas_address = discover_response->attached_sas_address;
+   this_smp_phy->config_route_table_index_anchor = 0;
+
+   if (this_smp_phy->attached_device_type != SMP_EDGE_EXPANDER_DEVICE
+       && this_smp_phy->attached_device_type != SMP_FANOUT_EXPANDER_DEVICE)
+   {
+      //note, end_device field could be an end device, or a NULL value, but can't be expander device.
+      this_smp_phy->u.end_device = attached_device;
+   }
+   else
+   {
+      //if attached device type is expander, we will set u.attached_phy later when the
+      //the attached expander finish its discover on attached_phy.
+      ;
+   }
+}
+
+/**
+ * @brief This routine constructs a smp phy object for an expander phy.
+ * @param[in] this_smp_phy The memory space to store a phy
+ * @param[in] owning_device The smp remote device that owns this smp phy.
+ * @param[in] discover_response The smp DISCOVER response for this_smp_phy.
+ *
+ * @return Whether a smp phy has an attached phy and the pair of phy are set
+ *            set to each other as attached phy successfully.
+ */
+SCI_STATUS scif_sas_smp_phy_set_attached_phy(
+   SCIF_SAS_SMP_PHY_T       * this_smp_phy,
+   U8                         attached_phy_identifier,
+   SCIF_SAS_REMOTE_DEVICE_T * attached_remote_device
+)
+{
+   //find the attached phy from its owning device by attached_phy_id.
+   SCIF_SAS_SMP_PHY_T * attached_smp_phy =
+      (SCIF_SAS_SMP_PHY_T *)scif_sas_smp_remote_device_find_smp_phy_by_id(
+          attached_phy_identifier,
+          &attached_remote_device->protocol_device.smp_device);
+
+   if (attached_smp_phy != NULL)
+   {
+      this_smp_phy->u.attached_phy = attached_smp_phy;
+      attached_smp_phy->u.attached_phy = this_smp_phy;
+
+      return SCI_SUCCESS;
+   }
+
+   return SCI_FAILURE;
+}
+
+
+/**
+ * @brief This method verify the routing attributes of a phy connection per
+ *        specification.
+ *
+ * @param[in] this_smp_phy One smp phy belongs to a smp phy connection.
+ * @param[in] attached_smp_phy One smp phy belongs to a smp phy connection.
+ *
+ * @return Whether routing attributes of a phy connection is legal.
+ * @retval SCI_SUCCESS indicates a good phy connection.
+ *         SCI_FAILURE indicates a illegal phy connection.
+ */
+SCI_STATUS scif_sas_smp_phy_verify_routing_attribute(
+   SCIF_SAS_SMP_PHY_T * this_smp_phy,
+   SCIF_SAS_SMP_PHY_T * attached_smp_phy
+)
+{
+   SCI_STATUS status = SCI_SUCCESS;
+
+   //expander phy with direct routing attribute can only connect to
+   //phy with direct routing attribute.
+   if ( this_smp_phy->routing_attribute == DIRECT_ROUTING_ATTRIBUTE
+         || attached_smp_phy->routing_attribute == DIRECT_ROUTING_ATTRIBUTE )
+   {
+      if ( (this_smp_phy->routing_attribute | attached_smp_phy->routing_attribute)
+           != DIRECT_ROUTING_ATTRIBUTE )
+         status = SCI_FAILURE;
+   }
+
+   if (this_smp_phy->routing_attribute == TABLE_ROUTING_ATTRIBUTE
+       && attached_smp_phy->routing_attribute == TABLE_ROUTING_ATTRIBUTE)
+   {
+      if ( ! this_smp_phy->owning_device->protocol_device.smp_device.is_table_to_table_supported
+         || !attached_smp_phy->owning_device->protocol_device.smp_device.is_table_to_table_supported )
+      status = SCI_FAILURE;
+   }
+
+   return status;
+}
+
+
+/**
+ * @brief This method find The next smp phy that is in the smp phy list and
+ *           resides in the same wide port as this_smp_phy.
+ *
+ * @param[in] this_smp_phy The smp phy whose neighbor phy that is in the same
+ *               same wide port is to be find.
+ *
+ * @return The next smp phy that is in the smp phy list and resides in the same
+ *            wide port as this_smp_phy.
+ */
+SCIF_SAS_SMP_PHY_T * scif_sas_smp_phy_find_next_phy_in_wide_port(
+   SCIF_SAS_SMP_PHY_T * this_smp_phy
+)
+{
+   SCI_FAST_LIST_ELEMENT_T * next_phy_element = sci_fast_list_get_next(
+      &(this_smp_phy->list_element) );
+
+   SCIF_SAS_SMP_PHY_T * next_phy;
+
+   while (next_phy_element != NULL)
+   {
+      next_phy = (SCIF_SAS_SMP_PHY_T *)sci_fast_list_get_object(next_phy_element);
+
+      next_phy_element = sci_fast_list_get_next( &(next_phy->list_element));
+
+      if (next_phy->attached_sas_address.high == this_smp_phy->attached_sas_address.high
+          &&next_phy->attached_sas_address.low == this_smp_phy->attached_sas_address.low)
+         return next_phy;
+   }
+
+   return NULL;
+}
+
+
+/**
+ * @brief This method find the smp phy that resides in the middle of the same
+ *        wide port as this_smp_phy.
+ *
+ * @param[in] this_smp_phy The smp phy who is the lowest order phy in a wide
+ *       port .
+ *
+ * @return The next smp phy that is in the smp phy list and resides in the same
+ *            wide port as this_smp_phy.
+ */
+SCIF_SAS_SMP_PHY_T * scif_sas_smp_phy_find_middle_phy_in_wide_port(
+   SCIF_SAS_SMP_PHY_T * this_smp_phy
+)
+{
+   SCIF_SAS_SMP_PHY_T * next_phy =
+      scif_sas_smp_phy_find_next_phy_in_wide_port(this_smp_phy);
+   SCIF_SAS_SMP_PHY_T * middle_phy = this_smp_phy;
+
+   //currently we assume a wide port could not be wider than X4. so the
+   //second phy is always the correct answer for x2, x3 or x4 wide port.
+   //For a narrow port, phy0 is the middle phy.
+   if (next_phy != NULL)
+   {
+      middle_phy = next_phy;
+      next_phy =
+         scif_sas_smp_phy_find_next_phy_in_wide_port(next_phy);
+   }
+
+   if (next_phy != NULL)
+      middle_phy = next_phy;
+
+   return middle_phy;
+}
+
+
+/**
+ * @brief This method find the smp phy that is the hishest order phy
+ *           in the same wide port as this_smp_phy.
+ *
+ * @param[in] this_smp_phy The smp phy who is the lowest order phy in a wide
+ *       port.
+ *
+ * @return The next smp phy that is in the smp phy list and resides in the same
+ *            wide port as this_smp_phy.
+ */
+SCIF_SAS_SMP_PHY_T * scif_sas_smp_phy_find_highest_phy_in_wide_port(
+   SCIF_SAS_SMP_PHY_T * this_smp_phy
+)
+{
+   SCIF_SAS_SMP_PHY_T * next_phy =
+      scif_sas_smp_phy_find_next_phy_in_wide_port(this_smp_phy);
+   SCIF_SAS_SMP_PHY_T * highest_phy = this_smp_phy;
+
+   while(next_phy != NULL )
+   {
+      highest_phy = next_phy;
+      next_phy =
+         scif_sas_smp_phy_find_next_phy_in_wide_port(next_phy);
+   }
+
+   return highest_phy;
+}
diff --git a/sys/dev/disk/isci/scil/scif_sas_smp_phy.h b/sys/dev/disk/isci/scil/scif_sas_smp_phy.h
new file mode 100644
index 0000000..c39b366
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_smp_phy.h
@@ -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.
+ *
+ * $FreeBSD: src/sys/dev/isci/scil/scif_sas_smp_phy.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIF_SAS_SMP_PHY_H_
+#define _SCIF_SAS_SMP_PHY_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains the protected interface structures, constants,
+ *        and methods for the SCIF_SAS_SMP_PHY object.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/scif_sas_remote_device.h>
+#include <dev/disk/isci/scil/sci_fast_list.h>
+
+struct SCIF_SAS_CONTROLLER;
+struct SCIF_SAS_SMP_PHY;
+struct SCIF_SAS_REMOTE_DEVICE;
+
+/**
+ * @struct SCIF_SAS_SMP_PHY
+ *
+ * @brief This structure stores data for a smp phy of a smp device (expander).
+ */
+typedef struct SCIF_SAS_SMP_PHY
+{
+   /**
+    * A smp phy can either connect to a end device or another smp phy,
+    * This two conditions are mutual exclusive.
+    */
+   union{
+      /**
+       * The attached smp phy. This field has valid meaning when
+       * attached_device_type is expander.
+       */
+      struct SCIF_SAS_SMP_PHY       * attached_phy;
+
+      /**
+       * The attached end device. This field has valid meaning when
+       * attached_device_type is end_device.
+       */
+      struct SCIF_SAS_REMOTE_DEVICE * end_device;
+   } u;
+
+   /**
+    * This field records the owning expander device this smp phy belongs to.
+    */
+   struct SCIF_SAS_REMOTE_DEVICE * owning_device;
+
+   /**
+    * The list element of this smp phy for the smp phy list of the ownig expander.
+    */
+   SCI_FAST_LIST_ELEMENT_T    list_element;
+
+   /**
+    * This field records the attached sas address, retrieved from a DISCOVER
+    * response. Zero value is valid.
+    */
+   SCI_SAS_ADDRESS_T          attached_sas_address;
+
+   /**
+    * This field records the attached device type, retrieved from a DISCOVER
+    * response.
+    */
+   U8                         attached_device_type;
+
+   /**
+    * This field records the routing attribute, retrieved from a DISCOVER
+    * response.
+    */
+   U8                         routing_attribute;
+
+   /**
+    * This field records the phy identifier of this smp phy, retrieved from a
+    * DISCOVER response.
+    */
+   U8                         phy_identifier;
+
+   /**
+    * this field stores the last route index for previous round of config
+    * route table activity on a smp phy within one DISCOVER process.
+    */
+   U16                        config_route_table_index_anchor;
+
+}SCIF_SAS_SMP_PHY_T;
+
+
+void scif_sas_smp_phy_construct(
+   SCIF_SAS_SMP_PHY_T            * this_smp_phy,
+   struct SCIF_SAS_REMOTE_DEVICE * owning_device,
+   U8                              expander_phy_id
+);
+
+void scif_sas_smp_phy_destruct(
+   SCIF_SAS_SMP_PHY_T       * this_smp_phy
+);
+
+void scif_sas_smp_phy_save_information(
+   SCIF_SAS_SMP_PHY_T            * this_smp_phy,
+   struct SCIF_SAS_REMOTE_DEVICE * attached_device,
+   SMP_RESPONSE_DISCOVER_T       * discover_response
+);
+
+SCI_STATUS scif_sas_smp_phy_set_attached_phy(
+   SCIF_SAS_SMP_PHY_T            * this_smp_phy,
+   U8                              attached_phy_identifier,
+   struct SCIF_SAS_REMOTE_DEVICE * attached_remote_device
+);
+
+SCI_STATUS scif_sas_smp_phy_verify_routing_attribute(
+   SCIF_SAS_SMP_PHY_T * this_smp_phy,
+   SCIF_SAS_SMP_PHY_T * attached_smp_phy
+);
+
+SCIF_SAS_SMP_PHY_T * scif_sas_smp_phy_find_next_phy_in_wide_port(
+   SCIF_SAS_SMP_PHY_T * this_smp_phy
+);
+
+SCIF_SAS_SMP_PHY_T * scif_sas_smp_phy_find_middle_phy_in_wide_port(
+   SCIF_SAS_SMP_PHY_T * this_smp_phy
+);
+
+SCIF_SAS_SMP_PHY_T * scif_sas_smp_phy_find_highest_phy_in_wide_port(
+   SCIF_SAS_SMP_PHY_T * this_smp_phy
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIF_SAS_SMP_PHY_H_
diff --git a/sys/dev/disk/isci/scil/scif_sas_smp_remote_device.c b/sys/dev/disk/isci/scil/scif_sas_smp_remote_device.c
new file mode 100644
index 0000000..551a4ca
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_smp_remote_device.c
@@ -0,0 +1,2621 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_smp_remote_device.c,v 1.3 2012/02/09 17:50:24 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains the methods for the SCIF_SAS_SMP_REMOTE_DEVICE object.
+ */
+#include <dev/disk/isci/scil/sci_controller.h>
+#include <dev/disk/isci/scil/scif_sas_controller.h>
+#include <dev/disk/isci/scil/scif_sas_remote_device.h>
+#include <dev/disk/isci/scil/scif_sas_logger.h>
+
+#include <dev/disk/isci/scil/scif_sas_smp_remote_device.h>
+#include <dev/disk/isci/scil/scif_sas_smp_io_request.h>
+#include <dev/disk/isci/scil/intel_sas.h>
+#include <dev/disk/isci/scil/scic_io_request.h>
+#include <dev/disk/isci/scil/scic_remote_device.h>
+#include <dev/disk/isci/scil/scif_sas_smp_phy.h>
+
+
+/**
+ * @brief This method resets all fields for a smp remote device. This is a
+ *        private method.
+ *
+ * @param[in] fw_device the framework SMP device that is being
+ *            constructed.
+ *
+ * @return none
+ */
+void scif_sas_smp_remote_device_clear(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device
+)
+{
+   //reset all fields in smp_device, indicate that the smp device is not
+   //in discovery process.
+   fw_device->protocol_device.smp_device.current_activity =
+      SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_NONE;
+
+   fw_device->protocol_device.smp_device.current_smp_request =
+      NOT_IN_SMP_ACTIVITY;
+
+   fw_device->protocol_device.smp_device.current_activity_phy_index = 0;
+
+   fw_device->protocol_device.smp_device.curr_config_route_index = 0;
+
+   fw_device->protocol_device.smp_device.config_route_smp_phy_anchor = NULL;
+
+   fw_device->protocol_device.smp_device.is_route_table_cleaned = FALSE;
+
+   fw_device->protocol_device.smp_device.curr_config_route_destination_smp_phy = NULL;
+
+   fw_device->protocol_device.smp_device.scheduled_activity =
+      SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_NONE;
+
+   fw_device->protocol_device.smp_device.io_retry_count = 0;
+
+   fw_device->protocol_device.smp_device.curr_clear_affiliation_phy = NULL;
+
+   if (fw_device->protocol_device.smp_device.smp_activity_timer != NULL)
+   {
+      //stop the timer
+      scif_cb_timer_stop(
+         fw_device->domain->controller,
+         fw_device->protocol_device.smp_device.smp_activity_timer
+      );
+
+      //destroy the timer
+      scif_cb_timer_destroy(
+         fw_device->domain->controller,
+         fw_device->protocol_device.smp_device.smp_activity_timer
+      );
+
+      fw_device->protocol_device.smp_device.smp_activity_timer = NULL;
+   }
+}
+
+
+/**
+ * @brief This method intializes a smp remote device.
+ *
+ * @param[in] fw_device the framework SMP device that is being
+ *            constructed.
+ *
+ * @return none
+ */
+void scif_sas_smp_remote_device_construct(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device
+)
+{
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE,
+      "scif_sas_smp_remote_device_construct(0x%x) enter\n",
+      fw_device
+   ));
+
+   fw_device->protocol_device.smp_device.number_of_phys = 0;
+   fw_device->protocol_device.smp_device.expander_route_indexes = 0;
+   fw_device->protocol_device.smp_device.is_table_to_table_supported = FALSE;
+   fw_device->protocol_device.smp_device.is_externally_configurable  = FALSE;
+   fw_device->protocol_device.smp_device.is_able_to_config_others    = FALSE;
+
+   sci_fast_list_init(&fw_device->protocol_device.smp_device.smp_phy_list);
+
+   scif_sas_smp_remote_device_clear(fw_device);
+}
+
+
+/**
+ * @brief This method decodes a smp response to this smp device and then
+ *        continue the smp discover process.
+ *
+ * @param[in] fw_device The framework device that a SMP response targets to.
+ * @param[in] fw_request The pointer to an smp request whose response
+ *       is to be decoded.
+ * @param[in] response_data The response data passed in.
+ *
+ * @return none
+ */
+SCI_STATUS scif_sas_smp_remote_device_decode_smp_response(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   SCIF_SAS_REQUEST_T       * fw_request,
+   void                     * response_data,
+   SCI_IO_STATUS              completion_status
+)
+{
+   SMP_RESPONSE_T * smp_response = (SMP_RESPONSE_T *)response_data;
+   SCI_STATUS       status       = SCI_FAILURE_UNSUPPORTED_INFORMATION_TYPE;
+
+   if (fw_device->protocol_device.smp_device.smp_activity_timer != NULL)
+   {
+      //if there is a timer being used, recycle it now. Since we may
+      //use the timer for other purpose next.
+      scif_cb_timer_destroy(
+         fw_device->domain->controller,
+         fw_device->protocol_device.smp_device.smp_activity_timer
+      );
+
+      fw_device->protocol_device.smp_device.smp_activity_timer = NULL;
+   }
+
+   //if Core set the status of this io to be RETRY_REQUIRED, we should
+   //retry the IO without even decode the response.
+   if (completion_status == SCI_IO_FAILURE_RETRY_REQUIRED)
+   {
+      scif_sas_smp_remote_device_continue_current_activity(
+         fw_device, fw_request, SCI_FAILURE_RETRY_REQUIRED
+      );
+
+      return SCI_FAILURE_RETRY_REQUIRED;
+   }
+
+   //check the current smp request, decide what's next smp request to issue.
+   switch (fw_device->protocol_device.smp_device.current_smp_request)
+   {
+      case SMP_FUNCTION_REPORT_GENERAL:
+      {
+         //interpret REPORT GENERAL response.
+         status = scif_sas_smp_remote_device_decode_report_general_response(
+            fw_device, smp_response
+         );
+
+         break;
+      }
+
+      case SMP_FUNCTION_REPORT_MANUFACTURER_INFORMATION:
+      {
+         // No need to perform any parsing.  Just want to see
+         // the information in a trace if necessary.
+         status = SCI_SUCCESS;
+         break;
+      }
+
+      case SMP_FUNCTION_DISCOVER:
+      {
+         if (fw_device->protocol_device.smp_device.current_activity ==
+                SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_DISCOVER)
+         {
+            //decode discover response
+            status = scif_sas_smp_remote_device_decode_initial_discover_response(
+                        fw_device, smp_response
+                     );
+         }
+         else if (fw_device->protocol_device.smp_device.current_activity ==
+                  SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_TARGET_RESET)
+         {
+            //decode discover response as a polling result for a remote device
+            //target reset.
+            status =
+               scif_sas_smp_remote_device_decode_target_reset_discover_response(
+                  fw_device, smp_response
+               );
+         }
+         else if (fw_device->protocol_device.smp_device.current_activity ==
+                SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_SATA_SPINUP_HOLD_RELEASE)
+         {
+            //decode discover response
+            status =
+               scif_sas_smp_remote_device_decode_spinup_hold_release_discover_response(
+                  fw_device, smp_response
+               );
+         }
+         else
+            ASSERT(0);
+         break;
+      }
+
+      case SMP_FUNCTION_REPORT_PHY_SATA:
+      {
+         //decode the report phy sata response.
+         status = scif_sas_smp_remote_device_decode_report_phy_sata_response(
+            fw_device, smp_response
+         );
+
+         break;
+      }
+
+      case SMP_FUNCTION_PHY_CONTROL:
+      {
+         if (fw_device->protocol_device.smp_device.current_activity ==
+                SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_DISCOVER)
+         {
+            //decode the phy control response.
+            status = scif_sas_smp_remote_device_decode_discover_phy_control_response(
+                        fw_device, smp_response
+                     );
+         }
+         else if (fw_device->protocol_device.smp_device.current_activity ==
+                     SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_TARGET_RESET)
+         {
+            //decode discover response as a polling result for a remote device
+            //target reset.
+            status = scif_sas_smp_remote_device_decode_target_reset_phy_control_response(
+                        fw_device, smp_response
+                     );
+         }
+         else if (fw_device->protocol_device.smp_device.current_activity ==
+                     SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_CLEAR_AFFILIATION)
+         {
+            //currently don't care about the status.
+            status = SCI_SUCCESS;
+         }
+         else
+            ASSERT(0);
+         break;
+      }
+
+      case SMP_FUNCTION_CONFIGURE_ROUTE_INFORMATION:
+      {
+         //Note, currently we don't expect any abnormal status from config route info response,
+         //but there is a possibility that we exceed the maximum route index. We will take care
+         //of errors later.
+         status = scif_sas_smp_remote_device_decode_config_route_info_response(
+                     fw_device, smp_response
+                  );
+         break;
+      }
+
+      default:
+         //unsupported case, TBD
+         status = SCI_FAILURE_UNSUPPORTED_INFORMATION_TYPE;
+         break;
+   } //end of switch
+
+   //Continue current activity based on response's decoding status.
+   scif_sas_smp_remote_device_continue_current_activity(
+      fw_device, fw_request, status
+   );
+
+   return status;
+}
+
+
+/**
+ * @brief This method decodes a smp Report Genernal response to this smp device
+ *        and then continue the smp discover process.
+ *
+ * @param[in] fw_device The framework device that the REPORT GENERAL command
+ *       targets to.
+ * @param[in] report_general_response The pointer to a report general response
+ *
+ * @return none
+ */
+SCI_STATUS scif_sas_smp_remote_device_decode_report_general_response(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   SMP_RESPONSE_T           * smp_response
+)
+{
+   SMP_RESPONSE_REPORT_GENERAL_T * report_general_response =
+      &smp_response->response.report_general;
+
+   SMP_RESPONSE_HEADER_T * response_header = &smp_response->header;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_smp_remote_device_decode_report_general_response(0x%x, 0x%x) enter\n",
+      fw_device, smp_response
+   ));
+
+   if (response_header->function_result != SMP_RESULT_FUNCTION_ACCEPTED)
+   {
+      /// @todo: more decoding work needed when the function_result is not
+      /// SMP_RESULT_FUNCTION_ACCEPTED. Retry might be the option for some
+      /// function result.
+      SCIF_LOG_ERROR((
+         sci_base_object_get_logger(fw_device),
+         SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+         "Report General function result(0x%x)\n",
+         response_header->function_result
+      ));
+
+      return SCI_FAILURE;
+   }
+
+   //get info from report general response.
+   fw_device->protocol_device.smp_device.number_of_phys =
+      (U8)report_general_response->number_of_phys;
+
+   //currently there is byte swap issue in U16 data.
+   fw_device->protocol_device.smp_device.expander_route_indexes =
+      ((report_general_response->expander_route_indexes & 0xff) << 8) |
+      ((report_general_response->expander_route_indexes & 0xff00) >> 8);
+
+   fw_device->protocol_device.smp_device.is_table_to_table_supported =
+      (BOOL)report_general_response->table_to_table_supported;
+
+   fw_device->protocol_device.smp_device.is_externally_configurable =
+      (BOOL)report_general_response->configurable_route_table;
+
+   fw_device->protocol_device.smp_device.is_able_to_config_others =
+      (BOOL)report_general_response->configures_others;
+
+   //If the top level expander of a domain is able to configure others,
+   //no config route table is needed in the domain. Or else,
+   //we'll let all the externally configurable expanders in the damain
+   //configure route table.
+   if (fw_device->containing_device == NULL
+       && ! fw_device->protocol_device.smp_device.is_able_to_config_others)
+      fw_device->domain->is_config_route_table_needed = TRUE;
+
+   //knowing number of phys this expander has, we can allocate all the smp phys for
+   //this expander now if it is not done already.
+   if (fw_device->protocol_device.smp_device.smp_phy_list.element_count == 0)
+      scif_sas_smp_remote_device_populate_smp_phy_list(fw_device);
+
+   if (report_general_response->configuring)
+      return SCI_FAILURE_RETRY_REQUIRED;
+
+   return SCI_SUCCESS;
+}
+
+
+/**
+ * @brief This method decodes a smp Discover response to this smp device
+ *        and then continue the smp discover process. This is only ever
+ *        called for the very first discover stage during a given domain
+ *        discovery process.
+ *
+ * @param[in] fw_device The framework device that the DISCOVER command
+ *       targets to.
+ * @param[in] discover_response The pointer to a DISCOVER response
+ *
+ * @return none
+ */
+SCI_STATUS scif_sas_smp_remote_device_decode_initial_discover_response(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   SMP_RESPONSE_T           * smp_response
+)
+{
+   SCIF_SAS_DOMAIN_T        * fw_domain = fw_device->domain;
+   SCI_SAS_ADDRESS_T          attached_device_address;
+   SCIF_SAS_REMOTE_DEVICE_T * attached_remote_device;
+   SMP_RESPONSE_DISCOVER_T  * discover_response =
+      &smp_response->response.discover;
+   SMP_RESPONSE_HEADER_T    * response_header = &smp_response->header;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_smp_remote_device_decode_initial_discover_response(0x%x, 0x%x) enter\n",
+      fw_device, smp_response
+   ));
+
+   if (response_header->function_result == SMP_RESULT_PHY_VACANT)
+   {
+      return SCI_SUCCESS;
+   }
+   else if (response_header->function_result != SMP_RESULT_FUNCTION_ACCEPTED)
+   {
+      /// @todo: more decoding work needed when the function_result is not
+      /// SMP_RESULT_FUNCTION_ACCEPTED. Retry might be the option for some
+      /// function result.
+      SCIF_LOG_ERROR((
+         sci_base_object_get_logger(fw_device),
+         SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+         "Discover function result(0x%x)\n",
+         response_header->function_result
+      ));
+
+      return SCI_FAILURE;
+   }
+
+   //only if there is target device attached. We don't add device that is
+   //initiator only.
+   if ( ( discover_response->u2.sas1_1.attached_device_type
+             != SMP_NO_DEVICE_ATTACHED )
+       && ( discover_response->protocols.u.bits.attached_ssp_target
+           || discover_response->protocols.u.bits.attached_stp_target
+           || discover_response->protocols.u.bits.attached_smp_target
+           || discover_response->protocols.u.bits.attached_sata_device ) )
+   {
+      attached_device_address = discover_response->attached_sas_address;
+
+      attached_remote_device = (SCIF_SAS_REMOTE_DEVICE_T *)
+         scif_domain_get_device_by_sas_address(
+            fw_domain, &attached_device_address
+         );
+
+      //need to check if the device already existed in the domian.
+      if (attached_remote_device != SCI_INVALID_HANDLE)
+      {
+#if !defined(DISABLE_WIDE_PORTED_TARGETS)
+         if ( attached_remote_device->is_currently_discovered == TRUE
+             && attached_remote_device != fw_device->containing_device )
+         {
+            //a downstream wide port target is found.
+            attached_remote_device->device_port_width++;
+         }
+         else
+#endif //#if !defined(DISABLE_WIDE_PORTED_TARGETS)
+         {
+            //The device already existed. Mark the device as discovered.
+            attached_remote_device->is_currently_discovered = TRUE;
+         }
+
+#if !defined(DISABLE_WIDE_PORTED_TARGETS)
+         if (attached_remote_device->device_port_width !=
+                scic_remote_device_get_port_width(attached_remote_device->core_object)
+             && discover_response->protocols.u.bits.attached_ssp_target
+            )
+         {
+            scif_sas_remote_device_update_port_width(
+               attached_remote_device, attached_remote_device->device_port_width);
+         }
+#endif //#if !defined(DISABLE_WIDE_PORTED_TARGETS)
+
+         if ( discover_response->protocols.u.bits.attached_smp_target
+             && attached_remote_device != fw_device->containing_device)
+         {
+            //another expander device is discovered. Its own smp discover will starts after
+            //this discover finishes.
+            attached_remote_device->protocol_device.smp_device.scheduled_activity =
+               SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_DISCOVER;
+         }
+      }
+      else
+      {
+         //report the discovery of a disk for all types of end device.
+         scif_cb_domain_ea_device_added(
+            fw_domain->controller, fw_domain, fw_device, discover_response
+         );
+
+         //get info from discover response to see what we found. And do
+         //extra work according to end device's protocol type.
+         if ( discover_response->protocols.u.bits.attached_ssp_target
+             || discover_response->protocols.u.bits.attached_smp_target)
+         {
+            //for SSP or SMP target, no extra work.
+            ;
+         }
+         else if (  (discover_response->protocols.u.bits.attached_stp_target)
+                 || (discover_response->protocols.u.bits.attached_sata_device) )
+         {
+            // We treat a SATA Device bit the same as an attached STP
+            // target.
+            discover_response->protocols.u.bits.attached_stp_target = 1;
+
+            //kick off REPORT PHY SATA to the same phy.
+            fw_device->protocol_device.smp_device.current_smp_request =
+               SMP_FUNCTION_REPORT_PHY_SATA;
+         }
+      }
+   }
+   else if( (discover_response->u2.sas1_1.negotiated_physical_link_rate == SCI_SATA_SPINUP_HOLD
+             || discover_response->u4.sas2.negotiated_physical_link_rate == SCI_SATA_SPINUP_HOLD)
+          &&(discover_response->protocols.u.bits.attached_stp_target
+             || discover_response->protocols.u.bits.attached_sata_device)
+          )
+   {
+      attached_remote_device = scif_sas_domain_get_device_by_containing_device(
+                                  fw_domain,
+                                  fw_device,
+                                  discover_response->phy_identifier
+                               );
+
+      if (attached_remote_device != SCI_INVALID_HANDLE)
+      {
+         //Here, the only reason a device already existed in domain but
+         //the initial discover rersponse shows it in SPINUP_HOLD, is that
+         //a device has been removed and coming back in SPINUP_HOLD before
+         //we detected. The possibility of this situation is very very rare.
+         //we need to remove the device then add it back using the new
+         //discover response.
+         scif_cb_domain_device_removed(
+            fw_domain->controller, fw_domain, attached_remote_device
+         );
+      }
+
+      discover_response->protocols.u.bits.attached_stp_target = 1;
+
+      //still report ea_device_added(). But this device will not be
+      //started during scif_remote_device_ea_construct().
+      scif_cb_domain_ea_device_added(
+         fw_domain->controller, fw_domain, fw_device, discover_response
+      );
+
+      //need to send Phy Control (RESET) to release the phy from spinup hold
+      //condition.
+      fw_device->protocol_device.smp_device.current_smp_request =
+         SMP_FUNCTION_PHY_CONTROL;
+   }
+
+   //update the smp phy info based on this DISCOVER response.
+   return scif_sas_smp_remote_device_save_smp_phy_info(
+             fw_device, discover_response);
+}
+
+
+/**
+ * @brief This method decodes a smp Report Phy Sata response to this
+ *        smp device and then continue the smp discover process.
+ *
+ * @param[in] fw_device The framework device that the REPORT PHY SATA
+ *       command targets to.
+ * @param[in] report_phy_sata_response The pointer to a REPORT PHY
+ *       SATA response
+ *
+ * @return none
+ */
+SCI_STATUS scif_sas_smp_remote_device_decode_report_phy_sata_response(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   SMP_RESPONSE_T           * smp_response
+)
+{
+   SMP_RESPONSE_REPORT_PHY_SATA_T * report_phy_sata_response =
+      &smp_response->response.report_phy_sata;
+
+   SMP_RESPONSE_HEADER_T * response_header = &smp_response->header;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_smp_remote_device_decode_report_phy_sata_response(0x%x, 0x%x) enter\n",
+      fw_device, smp_response
+   ));
+
+   if (response_header->function_result != SMP_RESULT_FUNCTION_ACCEPTED)
+   {
+      /// @todo: more decoding work needed when the function_result is not
+      /// SMP_RESULT_FUNCTION_ACCEPTED. Retry might be the option for some
+      /// function result.
+      SCIF_LOG_ERROR((
+         sci_base_object_get_logger(fw_device),
+         SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+         "Report Phy Sata function result(0x%x)\n",
+         response_header->function_result
+      ));
+
+      return SCI_FAILURE;
+   }
+
+   scif_sas_remote_device_save_report_phy_sata_information(
+      report_phy_sata_response
+   );
+
+   // continue the discover process.
+   fw_device->protocol_device.smp_device.current_smp_request =
+      SMP_FUNCTION_DISCOVER;
+
+   return SCI_SUCCESS;
+}
+
+
+/**
+ * @brief This method decodes a smp Phy Control response to this smp device and
+ *        then continue the smp TARGET RESET process.
+ *
+ * @param[in] fw_device The framework device that the Phy Control command
+ *       targets to.
+ * @param[in] smp_response The pointer to a Phy Control response
+ * @param[in] fw_io The scif IO request that associates to this smp response.
+ *
+ * @return none
+ */
+SCI_STATUS scif_sas_smp_remote_device_decode_target_reset_phy_control_response(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   SMP_RESPONSE_T           * smp_response
+)
+{
+   SMP_RESPONSE_HEADER_T * response_header = &smp_response->header;
+
+   SCI_STATUS status = SCI_SUCCESS;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_smp_remote_device_decode_target_reset_phy_control_response(0x%x, 0x%x) enter\n",
+      fw_device, smp_response
+   ));
+
+   if (response_header->function_result != SMP_RESULT_FUNCTION_ACCEPTED)
+   {
+      /// @todo: more decoding work needed when the function_result is not
+      /// SMP_RESULT_FUNCTION_ACCEPTED. Retry might be the option for some
+      /// function result.
+      SCIF_LOG_ERROR((
+         sci_base_object_get_logger(fw_device),
+         SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+         "Phy Control function unaccepted result(0x%x)\n",
+         response_header->function_result
+      ));
+
+      status = SCI_FAILURE_RETRY_REQUIRED;
+   }
+
+   // phy Control succeeded.
+   return status;
+}
+
+/**
+ * @brief This method decodes a smp Phy Control response to this smp device and
+ *        then continue the smp DISCOVER process.
+ *
+ * @param[in] fw_device The framework device that the Phy Control command
+ *       targets to.
+ * @param[in] smp_response The pointer to a Phy Control response
+ *
+ * @return Almost always SCI_SUCCESS
+ */
+SCI_STATUS scif_sas_smp_remote_device_decode_discover_phy_control_response(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   SMP_RESPONSE_T           * smp_response
+)
+{
+   SMP_RESPONSE_HEADER_T * response_header = &smp_response->header;
+
+   SCI_STATUS status = SCI_SUCCESS;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_smp_remote_device_decode_discover_phy_control_response(0x%x, 0x%x) enter\n",
+      fw_device, smp_response
+   ));
+
+   if (response_header->function_result != SMP_RESULT_FUNCTION_ACCEPTED)
+   {
+      /// @todo: more decoding work needed when the function_result is not
+      /// SMP_RESULT_FUNCTION_ACCEPTED. Retry might be the option for some
+      /// function result.
+      SCIF_LOG_ERROR((
+         sci_base_object_get_logger(fw_device),
+         SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+         "Phy Control function unaccepted result(0x%x)\n",
+         response_header->function_result
+      ));
+
+      return SCI_FAILURE_RETRY_REQUIRED;
+   }
+
+   // continue the discover process.
+   fw_device->protocol_device.smp_device.current_smp_request =
+      SMP_FUNCTION_DISCOVER;
+
+   // phy Control succeeded.
+   return status;
+}
+
+
+/**
+ * @brief This method decodes a smp Discover response to this smp device
+ *        and then continue the smp discover process.
+ *
+ * @param[in] fw_device The framework device that the DISCOVER command
+ *       targets to.
+ * @param[in] discover_response The pointer to a DISCOVER response
+ *
+ * @return none
+ */
+SCI_STATUS scif_sas_smp_remote_device_decode_target_reset_discover_response(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   SMP_RESPONSE_T           * smp_response
+)
+{
+   SCIF_SAS_DOMAIN_T  * fw_domain;
+   SCI_SAS_ADDRESS_T attached_device_address;
+   SMP_RESPONSE_DISCOVER_T * discover_response =
+      &smp_response->response.discover;
+
+   SMP_RESPONSE_HEADER_T * response_header = &smp_response->header;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_smp_remote_device_decode_target_reset_discover_response(0x%x, 0x%x) enter\n",
+      fw_device, smp_response
+   ));
+
+   if (response_header->function_result != SMP_RESULT_FUNCTION_ACCEPTED)
+   {
+      /// @todo: more decoding work needed when the function_result is not
+      /// SMP_RESULT_FUNCTION_ACCEPTED. Retry might be the option for some
+      /// function result.
+      SCIF_LOG_ERROR((
+         sci_base_object_get_logger(fw_device),
+         SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+         "Discover function result(0x%x)\n",
+         response_header->function_result
+      ));
+
+      return SCI_FAILURE_RETRY_REQUIRED;
+   }
+
+   //only if there is device attached.
+   if ( discover_response->u2.sas1_1.attached_device_type != SMP_NO_DEVICE_ATTACHED )
+   {
+      fw_domain = fw_device->domain;
+      attached_device_address = discover_response->attached_sas_address;
+
+      // the device should have already existed in the domian.
+      ASSERT(scif_domain_get_device_by_sas_address(
+                fw_domain,
+                &attached_device_address
+             ) != SCI_INVALID_HANDLE);
+      return SCI_SUCCESS;
+   }
+   else
+      return SCI_FAILURE_RETRY_REQUIRED;
+}
+
+/**
+ * @brief This method decodes a smp Discover response to this smp device
+ *        for SPINUP_HOLD_RELEASE activity. If a DISCOVER response says
+ *        SATA DEVICE ATTACHED and has a valid NPL value, we call fw_device's
+ *        start_handler(). But if a DISCOVER response still shows SPINUP
+ *        in NPL state, we need to return retry_required status
+ *
+ * @param[in] fw_device The framework device that the DISCOVER command
+ *       targets to.
+ * @param[in] discover_response The pointer to a DISCOVER response
+ *
+ * @return SCI_SUCCESS
+ *         SCI_FAILURE_RETRY_REQUIRED
+ */
+SCI_STATUS scif_sas_smp_remote_device_decode_spinup_hold_release_discover_response(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   SMP_RESPONSE_T           * smp_response
+)
+{
+   SMP_RESPONSE_DISCOVER_T * discover_response = &smp_response->response.discover;
+
+   SMP_RESPONSE_HEADER_T * response_header = &smp_response->header;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_smp_remote_device_decode_spinup_hold_release_discover_response(0x%x, 0x%x) enter\n",
+      fw_device, smp_response
+   ));
+
+   if (response_header->function_result != SMP_RESULT_FUNCTION_ACCEPTED)
+   {
+      /// @todo: more decoding work needed when the function_result is not
+      /// SMP_RESULT_FUNCTION_ACCEPTED. Retry might be the option for some
+      /// function result.
+      SCIF_LOG_ERROR((
+         sci_base_object_get_logger(fw_device),
+         SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+         "Discover function result(0x%x)\n",
+         response_header->function_result
+      ));
+
+      return SCI_FAILURE;
+   }
+
+   if ( discover_response->u2.sas1_1.attached_device_type != SMP_NO_DEVICE_ATTACHED )
+   {
+      if (discover_response->u2.sas1_1.negotiated_physical_link_rate != SCI_SATA_SPINUP_HOLD
+          && discover_response->u4.sas2.negotiated_physical_link_rate != SCI_SATA_SPINUP_HOLD
+          && ( discover_response->protocols.u.bits.attached_stp_target
+             ||discover_response->protocols.u.bits.attached_sata_device )
+         )
+      {
+         SCIF_SAS_REMOTE_DEVICE_T * target_device =
+            scif_sas_domain_get_device_by_containing_device(
+               fw_device->domain,
+               fw_device,
+               fw_device->protocol_device.smp_device.current_activity_phy_index
+            );
+
+         //Need to update the device's connection rate. Its connection rate was SPINIP_HOLD.
+         scic_remote_device_set_max_connection_rate(
+            target_device->core_object,
+            discover_response->u2.sas1_1.negotiated_physical_link_rate
+         );
+
+         //Need to update the smp phy info too.
+         scif_sas_smp_remote_device_save_smp_phy_info(
+             fw_device, discover_response);
+
+         //This device has already constructed, only need to call start_handler
+         //of this device here.
+         return target_device->state_handlers->parent.start_handler(
+                   &target_device->parent );
+      }
+      else
+         return SCI_FAILURE_RETRY_REQUIRED;
+   }
+   else
+      return SCI_FAILURE_RETRY_REQUIRED;
+}
+
+
+/**
+ * @brief This method decodes a smp CONFIG ROUTE INFO response to this smp
+ *        device and then continue to config route table.
+ *
+ * @param[in] fw_device The framework device that the CONFIG ROUTE INFO command
+ *       targets to.
+ * @param[in] smp_response The pointer to a CONFIG ROUTE INFO response
+ *
+ * @return none
+ */
+SCI_STATUS scif_sas_smp_remote_device_decode_config_route_info_response(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   SMP_RESPONSE_T           * smp_response
+)
+{
+   SMP_RESPONSE_HEADER_T * response_header = &smp_response->header;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_smp_remote_device_decode_config_route_info_response(0x%x, 0x%x) enter\n",
+      fw_device, smp_response
+   ));
+
+   if (response_header->function_result == SMP_RESULT_INDEX_DOES_NOT_EXIST)
+   {
+      //case of exceeding max route index. We need to remove the devices that are not
+      //able to be edit to route table. The destination config route smp phy
+      //is used to remove devices.
+      scif_sas_smp_remote_device_cancel_config_route_table_activity(fw_device);
+
+      return SCI_FAILURE_EXCEED_MAX_ROUTE_INDEX;
+   }
+   else if (response_header->function_result != SMP_RESULT_FUNCTION_ACCEPTED)
+   {
+      /// @todo: more decoding work needed when the function_result is not
+      /// SMP_RESULT_FUNCTION_ACCEPTED. Retry might be the option for some
+      /// function result.
+      SCIF_LOG_ERROR((
+         sci_base_object_get_logger(fw_device),
+         SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+         "Discover function result(0x%x)\n",
+         response_header->function_result
+      ));
+
+      return SCI_FAILURE;
+   }
+
+   return SCI_SUCCESS;
+}
+
+
+/**
+ * @brief This method starts the smp Discover process for an expander by
+ *        sending Report General request.
+ *
+ * @param[in] fw_device The framework smp device that a  command
+ *       targets to.
+ *
+ * @return none
+ */
+void scif_sas_smp_remote_device_start_discover(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device
+)
+{
+   SCIF_SAS_CONTROLLER_T * fw_controller = fw_device->domain->controller;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_smp_remote_device_start_discover(0x%x) enter\n",
+      fw_device
+   ));
+
+   //For safety, clear the device again, there may be some config route table
+   //related info are not cleared yet.
+   scif_sas_smp_remote_device_clear(fw_device);
+
+   //set current activity
+   fw_device->protocol_device.smp_device.current_activity =
+      SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_DISCOVER;
+
+   //Set current_smp_request to REPORT GENERAL.
+   fw_device->protocol_device.smp_device.current_smp_request =
+      SMP_FUNCTION_REPORT_GENERAL;
+
+   //reset discover_to_start flag.
+   fw_device->protocol_device.smp_device.scheduled_activity =
+      SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_NONE;
+
+   //build the first smp request Report Genernal.
+   scif_sas_smp_request_construct_report_general(fw_controller, fw_device);
+
+   //issue DPC to start this request.
+   scif_cb_start_internal_io_task_schedule(
+      fw_controller,
+      scif_sas_controller_start_high_priority_io,
+      fw_controller
+   );
+}
+
+
+/**
+ * @brief This method continues the smp Discover process.
+ *
+ * @param[in] fw_device The framework smp device that a DISCOVER command
+ *       targets to.
+ * @param[in] fw_request The pointer to an smp request whose response
+ *       has been decoded.
+ * @param[in] status The decoding status of the smp request's response
+ *
+ * @return none
+ */
+void scif_sas_smp_remote_device_continue_current_activity(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   SCIF_SAS_REQUEST_T       * fw_request,
+   SCI_STATUS                 status
+)
+{
+   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *)fw_request;
+   // save the retry count.
+   U8 io_retry_count = fw_io->retry_count;
+
+   if (fw_request->is_internal)
+   {
+      // Complete this internal io request now. We want to free this io before
+      // we create another SMP request, which is going to happen soon.
+      scif_sas_internal_io_request_complete(
+         fw_device->domain->controller,
+         (SCIF_SAS_INTERNAL_IO_REQUEST_T *)fw_request,
+         SCI_SUCCESS
+      );
+   }
+
+   if (fw_device->protocol_device.smp_device.current_activity ==
+      SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_DISCOVER)
+   {
+      if (status == SCI_SUCCESS)
+      {   //continue the discover process.
+         scif_sas_smp_remote_device_continue_discover(fw_device);
+      }
+      else if (status == SCI_FAILURE_RETRY_REQUIRED)
+      {
+         //Retry the smp request. Since we are in the middle of Discover
+         //process, all the smp requests are internal. A new smp request
+         //will be created for retry.
+         U32 retry_wait_duration = (SCIF_DOMAIN_DISCOVER_TIMEOUT / 2) / SCIF_SAS_IO_RETRY_LIMIT;
+
+         if (io_retry_count < SCIF_SAS_IO_RETRY_LIMIT)
+            scif_sas_smp_remote_device_retry_internal_io (
+               fw_device, io_retry_count, retry_wait_duration);
+         else
+            scif_sas_smp_remote_device_fail_discover(fw_device);
+      }
+      else if (status == SCI_FAILURE_ILLEGAL_ROUTING_ATTRIBUTE_CONFIGURATION)
+      {
+         //remove this expander device and its child devices. No need to
+         //continue the discover on this device.
+         scif_sas_domain_remove_expander_device(fw_device->domain, fw_device);
+
+         //continue the domain's smp discover.
+         scif_sas_domain_continue_discover(fw_device->domain);
+      }
+      else
+      {  //terminate the discover process.
+         scif_sas_smp_remote_device_fail_discover(fw_device);
+      }
+   }
+   else if (fw_device->protocol_device.smp_device.current_activity ==
+      SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_TARGET_RESET)
+   {
+      if (status == SCI_SUCCESS)
+      {   //continue the target reset process.
+         scif_sas_smp_remote_device_continue_target_reset(
+            fw_device, fw_request);
+      }
+      else if (status == SCI_FAILURE_RETRY_REQUIRED)
+      {
+         //Retry the same smp request. Since we are in the middle of Target
+         //reset process, all the smp requests are using external resource.
+         //We will use the exactly same memory to retry.
+         if (io_retry_count < SCIF_SAS_IO_RETRY_LIMIT)
+         {
+            if (fw_device->protocol_device.smp_device.smp_activity_timer == NULL)
+            {
+               //create the timer to wait before retry.
+               fw_device->protocol_device.smp_device.smp_activity_timer =
+                  scif_cb_timer_create(
+                  (SCI_CONTROLLER_HANDLE_T *)fw_device->domain->controller,
+                  (SCI_TIMER_CALLBACK_T)scif_sas_smp_external_request_retry,
+                  (void*)fw_request
+               );
+            }
+            else
+            {
+               ASSERT(0);
+            }
+
+            //start the timer to wait
+            scif_cb_timer_start(
+               (SCI_CONTROLLER_HANDLE_T)fw_device->domain->controller,
+               fw_device->protocol_device.smp_device.smp_activity_timer,
+               SMP_REQUEST_RETRY_WAIT_DURATION  //20 miliseconds
+            );
+         }
+         else
+            scif_sas_smp_remote_device_fail_target_reset(fw_device, fw_request);
+      }
+      else
+         //terminate the discover process.
+         scif_sas_smp_remote_device_fail_target_reset(fw_device, fw_request);
+   }
+   else if (fw_device->protocol_device.smp_device.current_activity ==
+      SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_SATA_SPINUP_HOLD_RELEASE)
+   {
+      SCIF_SAS_REMOTE_DEVICE_T * target_device =
+         scif_sas_domain_get_device_by_containing_device(
+            fw_device->domain,
+            fw_device,
+            fw_device->protocol_device.smp_device.current_activity_phy_index
+         );
+
+      if (status == SCI_SUCCESS)
+      {
+         //move on to next round of SPINUP_HOLD_REALSE activity.
+         scif_sas_smp_remote_device_sata_spinup_hold_release(fw_device);
+      }
+      else if (status == SCI_FAILURE_RETRY_REQUIRED)
+      {
+         U32 delay =
+            (scic_remote_device_get_suggested_reset_timeout(target_device->core_object) /
+                SCIF_SAS_IO_RETRY_LIMIT);
+
+         //Retry the smp request. Since we are in the middle of Discover
+         //process, all the smp requests are internal. A new smp request
+         //will be created for retry.
+         if (io_retry_count < SCIF_SAS_IO_RETRY_LIMIT)
+         {
+            scif_sas_smp_remote_device_retry_internal_io(
+               fw_device, io_retry_count, delay);
+         }
+         else //give up on this target device.
+         {
+            scif_sas_smp_remote_device_fail_target_spinup_hold_release(
+               fw_device , target_device);
+         }
+      }
+      else //give up on this target device.
+        scif_sas_smp_remote_device_fail_target_spinup_hold_release(
+           fw_device, target_device);
+   }
+   else if (fw_device->protocol_device.smp_device.current_activity ==
+      SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_CONFIG_ROUTE_TABLE)
+   {
+      SCI_FAST_LIST_ELEMENT_T * next_phy_element = sci_fast_list_get_next(
+         &(fw_device->protocol_device.smp_device.curr_config_route_destination_smp_phy->list_element) );
+
+      SCI_FAST_LIST_T * destination_smp_phy_list =
+          fw_device->protocol_device.smp_device.curr_config_route_destination_smp_phy->list_element.owning_list;
+
+      SCIF_SAS_SMP_PHY_T * next_phy_in_wide_port = NULL;
+
+      if (next_phy_element != NULL
+          && status != SCI_FAILURE_EXCEED_MAX_ROUTE_INDEX)
+      {
+         fw_device->protocol_device.smp_device.curr_config_route_index++;
+
+         fw_device->protocol_device.smp_device.curr_config_route_destination_smp_phy =
+            (SCIF_SAS_SMP_PHY_T *)sci_fast_list_get_object(next_phy_element);
+
+         // Update the anchor for config route index.
+         fw_device->protocol_device.smp_device.config_route_smp_phy_anchor->config_route_table_index_anchor =
+            fw_device->protocol_device.smp_device.curr_config_route_index;
+
+         scif_sas_smp_remote_device_configure_route_table(fw_device);
+      }
+      else if ( scif_sas_smp_remote_device_get_config_route_table_method(fw_device)
+                   == SCIF_SAS_CONFIG_ROUTE_TABLE_ALL_PHYS
+                && (next_phy_in_wide_port = scif_sas_smp_phy_find_next_phy_in_wide_port(
+                       fw_device->protocol_device.smp_device.config_route_smp_phy_anchor)
+                   )!= NULL
+              )
+      {
+         //config the other phy in the same wide port
+         fw_device->protocol_device.smp_device.config_route_smp_phy_anchor =
+            next_phy_in_wide_port;
+
+         fw_device->protocol_device.smp_device.current_activity_phy_index =
+            fw_device->protocol_device.smp_device.config_route_smp_phy_anchor->phy_identifier;
+
+         fw_device->protocol_device.smp_device.curr_config_route_destination_smp_phy =
+            sci_fast_list_get_head(destination_smp_phy_list);
+
+         if (fw_device->protocol_device.smp_device.config_route_smp_phy_anchor->config_route_table_index_anchor != 0)
+            fw_device->protocol_device.smp_device.curr_config_route_index =
+               fw_device->protocol_device.smp_device.config_route_smp_phy_anchor->config_route_table_index_anchor + 1;
+         else
+            fw_device->protocol_device.smp_device.curr_config_route_index = 0;
+
+         scif_sas_smp_remote_device_configure_route_table(fw_device);
+      }
+      else if ( fw_device->protocol_device.smp_device.is_route_table_cleaned == FALSE)
+      {
+         fw_device->protocol_device.smp_device.current_activity =
+            SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_CLEAN_ROUTE_TABLE;
+
+         scif_sas_smp_remote_device_clean_route_table(fw_device);
+      }
+      else
+      {
+         //set this device's activity to NON.
+         fw_device->protocol_device.smp_device.current_activity =
+            SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_NONE;
+
+         //we need to notify domain that this device finished config route table, domain
+         //may pick up other activities (i.e. Discover) for other expanders.
+         scif_sas_domain_continue_discover(fw_device->domain);
+      }
+   }
+   else if (fw_device->protocol_device.smp_device.current_activity ==
+               SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_CLEAN_ROUTE_TABLE)
+   {
+      scif_sas_smp_remote_device_clean_route_table(fw_device);
+   }
+   else if (fw_device->protocol_device.smp_device.current_activity ==
+               SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_CLEAR_AFFILIATION)
+   {
+      scif_sas_smp_remote_device_continue_clear_affiliation(fw_device);
+   }
+}
+
+
+/**
+ * @brief This method continues the smp Discover process.
+ *
+ * @param[in] fw_device The framework smp device that a DISCOVER command
+ *       targets to.
+ *
+ * @return none
+ */
+void scif_sas_smp_remote_device_continue_discover(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device
+)
+{
+   SCIF_SAS_DOMAIN_T * fw_domain = fw_device->domain;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_smp_remote_device_continue_discover(0x%x) enter\n",
+      fw_device
+   ));
+
+   switch (fw_device->protocol_device.smp_device.current_smp_request)
+   {
+      case SMP_FUNCTION_REPORT_GENERAL:
+         // send the REPORT MANUFACTURER_INFO request
+         fw_device->protocol_device.smp_device.current_smp_request =
+            SMP_FUNCTION_REPORT_MANUFACTURER_INFORMATION;
+
+         scif_sas_smp_request_construct_report_manufacturer_info(
+            fw_domain->controller, fw_device
+         );
+
+         break;
+
+      case SMP_FUNCTION_REPORT_MANUFACTURER_INFORMATION:
+         //send the first SMP DISCOVER request.
+         fw_device->protocol_device.smp_device.current_activity_phy_index = 0;
+         fw_device->protocol_device.smp_device.current_smp_request =
+            SMP_FUNCTION_DISCOVER;
+
+         scif_sas_smp_request_construct_discover(
+            fw_domain->controller,
+            fw_device,
+            fw_device->protocol_device.smp_device.current_activity_phy_index,
+            NULL, NULL
+         );
+         break;
+
+
+      case SMP_FUNCTION_DISCOVER:
+         fw_device->protocol_device.smp_device.current_activity_phy_index++;
+
+         if ( (fw_device->protocol_device.smp_device.current_activity_phy_index <
+                  fw_device->protocol_device.smp_device.number_of_phys) )
+         {
+            scif_sas_smp_request_construct_discover(
+               fw_domain->controller,
+               fw_device,
+               fw_device->protocol_device.smp_device.current_activity_phy_index,
+               NULL, NULL
+            );
+         }
+         else
+            scif_sas_smp_remote_device_finish_initial_discover(fw_device);
+         break;
+
+
+      case SMP_FUNCTION_REPORT_PHY_SATA:
+         scif_sas_smp_request_construct_report_phy_sata(
+            fw_device->domain->controller,
+            fw_device,
+            fw_device->protocol_device.smp_device.current_activity_phy_index
+         );
+
+         break;
+
+
+      case SMP_FUNCTION_PHY_CONTROL:
+         scif_sas_smp_request_construct_phy_control(
+            fw_device->domain->controller,
+            fw_device,
+            PHY_OPERATION_HARD_RESET,
+            fw_device->protocol_device.smp_device.current_activity_phy_index,
+            NULL,
+            NULL
+         );
+
+         break;
+
+      default:
+         break;
+   }
+}
+
+/**
+ * @brief This method finishes the initial smp DISCOVER process. There
+ *        may be a spinup_hold release phase following of initial discover,
+ *        depending on whether there are SATA device in the domain
+ *        in SATA_SPINUP_HOLD condition.
+ *
+ * @param[in] fw_device The framework smp device that finishes all the
+ *       DISCOVER requests.
+ *
+ * @return none
+ */
+void scif_sas_smp_remote_device_finish_initial_discover(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * device_in_sata_spinup_hold =
+      scif_sas_domain_find_device_in_spinup_hold(fw_device->domain);
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_smp_remote_device_finish_initial_discover(0x%x) enter\n",
+      fw_device
+   ));
+
+   if ( device_in_sata_spinup_hold != NULL )
+   {
+     //call the common private routine to reset all fields of this smp device.
+     scif_sas_smp_remote_device_clear(fw_device);
+
+     //Move on to next activity SPINUP_HOLD_RELEASE
+     fw_device->protocol_device.smp_device.current_activity =
+        SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_SATA_SPINUP_HOLD_RELEASE;
+
+      //create the timer to delay a little bit before going to
+      //sata spinup hold release activity.
+      if (fw_device->protocol_device.smp_device.smp_activity_timer == NULL)
+      {
+      fw_device->protocol_device.smp_device.smp_activity_timer =
+         scif_cb_timer_create(
+            (SCI_CONTROLLER_HANDLE_T *)fw_device->domain->controller,
+            (SCI_TIMER_CALLBACK_T)scif_sas_smp_remote_device_sata_spinup_hold_release,
+            (void*)fw_device
+         );
+      }
+      else
+      {
+         ASSERT (0);
+      }
+
+      scif_cb_timer_start(
+         (SCI_CONTROLLER_HANDLE_T)fw_device->domain->controller,
+         fw_device->protocol_device.smp_device.smp_activity_timer,
+         SMP_SPINUP_HOLD_RELEASE_WAIT_DURATION
+      );
+   }
+   else
+      scif_sas_smp_remote_device_finish_discover(fw_device);
+}
+
+
+/**
+ * @brief This method finishes the smp DISCOVER process.
+ *
+ * @param[in] fw_device The framework smp device that finishes all the
+ *       DISCOVER requests.
+ *
+ * @return none
+ */
+void scif_sas_smp_remote_device_finish_discover(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device
+)
+{
+   SCIF_SAS_DOMAIN_T * fw_domain = fw_device->domain;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_smp_remote_device_finish_discover(0x%x) enter\n",
+      fw_device
+   ));
+
+   if ( fw_domain->is_config_route_table_needed
+       && fw_device->protocol_device.smp_device.smp_phy_list.list_head != NULL)
+      scif_sas_smp_remote_device_configure_upstream_expander_route_info(fw_device);
+
+   //call the common private routine to reset all fields of this smp device.
+   scif_sas_smp_remote_device_clear(fw_device);
+
+#ifdef SCI_SMP_PHY_LIST_DEBUG_PRINT
+   scif_sas_smp_remote_device_print_smp_phy_list(fw_device);
+#endif
+
+   //notify domain this smp device's discover finishes, it's up to domain
+   //to continue the discover process in a bigger scope.
+   scif_sas_domain_continue_discover(fw_domain);
+}
+
+
+/**
+ * @brief This method continues the smp Target Reset (Phy Control) process.
+ *
+ * @param[in] fw_device The framework smp device that a smp reset targets to.
+ *
+ * @return none
+ */
+void scif_sas_smp_remote_device_continue_target_reset(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   SCIF_SAS_REQUEST_T       * fw_request
+)
+{
+   SCIF_SAS_CONTROLLER_T * fw_controller = fw_device->domain->controller;
+   SCIF_SAS_REMOTE_DEVICE_T * target_device =
+      scif_sas_domain_get_device_by_containing_device(
+         fw_device->domain,
+         fw_device,
+         fw_device->protocol_device.smp_device.current_activity_phy_index
+      );
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_smp_remote_device_continue_target_reset(0x%x, 0x%x) enter\n",
+      fw_device, fw_request
+   ));
+
+   if (fw_device->protocol_device.smp_device.current_smp_request ==
+          SMP_FUNCTION_PHY_CONTROL)
+   {
+      //query the core remote device to get suggested reset timeout value
+      //then scale down by factor of 8 to get the duration of the pause
+      //before sending out Discover command to poll.
+      U32 delay =
+         (scic_remote_device_get_suggested_reset_timeout(target_device->core_object)/8);
+
+      //create the timer to send Discover command polling target device's
+      //coming back.
+      if (fw_device->protocol_device.smp_device.smp_activity_timer == NULL)
+      {
+         fw_device->protocol_device.smp_device.smp_activity_timer =
+            scif_cb_timer_create(
+               (SCI_CONTROLLER_HANDLE_T *)fw_controller,
+               (SCI_TIMER_CALLBACK_T)scif_sas_smp_remote_device_target_reset_poll,
+               (void*)fw_request
+            );
+      }
+      else
+      {
+         ASSERT(0);
+      }
+
+      //start the timer
+      scif_cb_timer_start(
+         (SCI_CONTROLLER_HANDLE_T)fw_controller,
+         fw_device->protocol_device.smp_device.smp_activity_timer,
+         delay
+      );
+   }
+   else if (fw_device->protocol_device.smp_device.current_smp_request ==
+          SMP_FUNCTION_DISCOVER)
+   {
+      //tell target reset successful
+      scif_sas_remote_device_target_reset_complete(
+         target_device, fw_request, SCI_SUCCESS);
+   }
+}
+
+/**
+ * @brief This routine is invoked by timer or when 2 BCN are received
+ *        after Phy Control command. This routine will construct a
+ *        Discover command to the same expander phy to poll the target
+ *        device's coming back. This new request is then put into
+ *        high priority queue and will be started by a DPC soon.
+ *
+ * @param[in] fw_request The scif request for smp activities.
+ */
+void scif_sas_smp_remote_device_target_reset_poll(
+   SCIF_SAS_REQUEST_T       * fw_request
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = fw_request->device;
+   SCIF_SAS_CONTROLLER_T * fw_controller = fw_device->domain->controller;
+   void * new_command_handle;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_smp_remote_device_target_reset_poll(0x%x) enter\n",
+      fw_request
+   ));
+
+   // Before we construct new io using the same memory, we need to
+   // remove the IO from the list of outstanding requests on the domain
+   // so that we don't damage the domain's fast list of request.
+   sci_fast_list_remove_element(&fw_request->list_element);
+
+   fw_device->protocol_device.smp_device.current_smp_request =
+      SMP_FUNCTION_DISCOVER;
+
+   //sent smp discover request to poll on remote device's coming back.
+   //construct Discover command using the same memory as fw_request.
+   new_command_handle = scif_sas_smp_request_construct_discover(
+      fw_device->domain->controller,
+      fw_device,
+      fw_device->protocol_device.smp_device.current_activity_phy_index,
+      (void *)sci_object_get_association(fw_request),
+      (void *)fw_request
+   );
+
+   //put into the high priority queue.
+   sci_pool_put(fw_controller->hprq.pool, (POINTER_UINT) new_command_handle);
+
+   //schedule the DPC to start new Discover command.
+   scif_cb_start_internal_io_task_schedule(
+      fw_controller, scif_sas_controller_start_high_priority_io, fw_controller
+   );
+}
+
+
+/**
+ * @brief This method fails discover process.
+ *
+ * @param[in] fw_device The framework smp device that failed at current
+ *       activity.
+ *
+ * @return none
+ */
+void scif_sas_smp_remote_device_fail_discover(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device
+)
+{
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_smp_remote_device_fail_discover(0x%x) enter\n",
+      fw_device
+   ));
+
+   switch (fw_device->protocol_device.smp_device.current_smp_request)
+   {
+      case SMP_FUNCTION_REPORT_GENERAL:
+      case SMP_FUNCTION_REPORT_MANUFACTURER_INFORMATION:
+         scif_sas_smp_remote_device_finish_discover(fw_device);
+         break;
+
+      case SMP_FUNCTION_DISCOVER:
+      case SMP_FUNCTION_REPORT_PHY_SATA:
+         //Retry limit reached, we will continue to send DISCOVER to next phy.
+         fw_device->protocol_device.smp_device.current_smp_request =
+            SMP_FUNCTION_DISCOVER;
+
+         scif_sas_smp_remote_device_continue_discover(fw_device);
+         break;
+
+      default:
+         break;
+   }
+}
+
+
+/**
+ * @brief This method fails Target Reset.
+ *
+ * @param[in] fw_device The framework smp device that failed at current
+ *       activity.
+ * @param[in] fw_request The smp request created for target reset
+ *       using external resource.
+ *
+ * @return none
+ */
+void scif_sas_smp_remote_device_fail_target_reset(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   SCIF_SAS_REQUEST_T       * fw_request
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * target_device =
+      scif_sas_domain_get_device_by_containing_device(
+         fw_device->domain,
+         fw_device,
+         fw_device->protocol_device.smp_device.current_activity_phy_index
+      );
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_smp_remote_device_fail_target_reset(0x%x, 0x%x, 0x%x) enter\n",
+      fw_device, target_device, fw_request
+   ));
+
+   //tell target reset failed
+   scif_sas_remote_device_target_reset_complete(
+      target_device, fw_request, SCI_FAILURE);
+}
+
+/**
+ * @brief This method init or continue the SATA SPINUP_HOLD RELEASE activity.
+ * This function searches domain's device list, find a device in STOPPED STATE
+ * and its connection_rate is SPINIP, then send DISCOVER command to its expander
+ * phy id to poll. But if searching the domain's device list for SATA devices on
+ * SPINUP_HOLD finds no device, the activity SPINUP_HOLD_RELEASE is finished.
+ * We then call fw_domain->device_start_complete_handler() for this smp-device.
+ *
+ * @param[in] fw_device The framework smp device that is on SATA SPINUP_HOLD_RELEASE
+ *       activity.
+ *
+ * @return none
+ */
+void scif_sas_smp_remote_device_sata_spinup_hold_release(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device
+)
+{
+   SCIF_SAS_DOMAIN_T        * fw_domain = fw_device->domain;
+   SCIF_SAS_CONTROLLER_T    * fw_controller = fw_domain->controller;
+   SCIF_SAS_REMOTE_DEVICE_T * device_to_poll = NULL;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_smp_remote_device_sata_spinup_hold_release(0x%x) enter\n",
+      fw_device
+   ));
+
+   //search throught domain's device list to find a sata device on spinup_hold
+   //state to poll.
+   device_to_poll = scif_sas_domain_find_device_in_spinup_hold(fw_domain);
+
+   if (device_to_poll != NULL)
+   {
+      //send DISCOVER command to this device's expaner phy.
+      fw_device->protocol_device.smp_device.current_smp_request =
+         SMP_FUNCTION_DISCOVER;
+
+      fw_device->protocol_device.smp_device.current_activity_phy_index =
+        device_to_poll->expander_phy_identifier;
+
+      scif_sas_smp_request_construct_discover(
+         fw_domain->controller,
+         fw_device,
+         fw_device->protocol_device.smp_device.current_activity_phy_index,
+         NULL, NULL
+      );
+
+      //schedule the DPC to start new Discover command.
+      scif_cb_start_internal_io_task_schedule(
+         fw_controller, scif_sas_controller_start_high_priority_io, fw_controller
+      );
+   }
+   else //SATA SPINUP HOLD RELEASE activity is done.
+      scif_sas_smp_remote_device_finish_discover (fw_device);
+}
+
+
+/**
+ * @brief This method fail an action of SATA SPINUP_HOLD RELEASE on a single EA
+ *        SATA device. It will remove a remote_device object for a sata device
+ *        that fails to come out of spinup_hold.
+ *
+ * @param[in] fw_device The framework smp device that is on SATA SPINUP_HOLD_RELEASE
+ *       activity.
+ * @param[in] target_device The expander attached device failed being brought out
+ *       of SPINUP_HOLD state.
+ *
+ * @return none
+ */
+void scif_sas_smp_remote_device_fail_target_spinup_hold_release(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   SCIF_SAS_REMOTE_DEVICE_T * target_device
+)
+{
+   SCIF_SAS_DOMAIN_T * fw_domain = fw_device->domain;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_smp_remote_device_fail_target_spinup_hold_release(0x%x, 0x%x) enter\n",
+      fw_device, target_device
+   ));
+
+   //need to remove the device, since we have to give up on spinup_hold_release
+   //activity on this device.
+   scif_cb_domain_device_removed(
+      fw_domain->controller, fw_domain, target_device
+   );
+
+   //move on to next round of SPINUP_HOLD_REALSE activity.
+   scif_sas_smp_remote_device_sata_spinup_hold_release(fw_device);
+}
+
+
+/**
+ * @brief This method retry only internal IO for the smp device.
+ *
+ * @param[in] fw_device The framework smp device that has an smp request to retry.
+ * @param[in] io_retry_count current count for times the IO being retried.
+ * @param[in] delay The time delay before the io gets retried.
+ *
+ * @return none
+ */
+void scif_sas_smp_remote_device_retry_internal_io(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   U8                         io_retry_count,
+   U32                        delay
+)
+{
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_smp_remote_device_retry_internal_io(0x%x, 0x%x, 0x%x) enter\n",
+      fw_device, io_retry_count, delay
+   ));
+
+   fw_device->protocol_device.smp_device.io_retry_count =
+      io_retry_count;
+
+   //create the timer for poll target device's coming back.
+   if (fw_device->protocol_device.smp_device.smp_activity_timer == NULL)
+   {
+      fw_device->protocol_device.smp_device.smp_activity_timer =
+         scif_cb_timer_create(
+            (SCI_CONTROLLER_HANDLE_T *)fw_device->domain->controller,
+            (SCI_TIMER_CALLBACK_T)scif_sas_smp_internal_request_retry,
+            (void*)fw_device
+         );
+   }
+   else
+   {
+      ASSERT(0);
+   }
+   //start the timer for a purpose of waiting.
+   scif_cb_timer_start(
+      (SCI_CONTROLLER_HANDLE_T)fw_device->domain->controller,
+      fw_device->protocol_device.smp_device.smp_activity_timer,
+      delay
+   );
+}
+
+
+/**
+ * @brief This method indicates whether an expander device is in Discover
+ *        process.
+ *
+ * @param[in] fw_device The framework smp device.
+ *
+ * @return Whether an expander device is in the middle of discovery process.
+ */
+BOOL scif_sas_smp_remote_device_is_in_activity(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device
+)
+{
+   return(fw_device->protocol_device.smp_device.current_activity
+          != SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_NONE);
+}
+
+/**
+ * @brief This method search through the smp phy list of an expander to
+ *        find a smp phy by its phy id of the expander.
+ *
+ * @param[in] phy_identifier The search criteria.
+ * @param[in] smp_remote_device The expander that owns the smp phy list.
+ *
+ * @return The found smp phy or a NULL pointer to indicate no smp phy is found.
+ */
+SCIF_SAS_SMP_PHY_T * scif_sas_smp_remote_device_find_smp_phy_by_id(
+   U8                             phy_identifier,
+   SCIF_SAS_SMP_REMOTE_DEVICE_T * smp_remote_device
+)
+{
+   SCI_FAST_LIST_ELEMENT_T  * element = smp_remote_device->smp_phy_list.list_head;
+   SCIF_SAS_SMP_PHY_T * curr_smp_phy = NULL;
+
+   ASSERT(phy_identifier < smp_remote_device->smp_phy_list.number_of_phys);
+
+   while (element != NULL)
+   {
+      curr_smp_phy = (SCIF_SAS_SMP_PHY_T*) sci_fast_list_get_object(element);
+      element = sci_fast_list_get_next(element);
+
+      if (curr_smp_phy->phy_identifier == phy_identifier)
+         return curr_smp_phy;
+   }
+
+   return NULL;
+}
+
+/**
+ * @brief This method takes care of removing smp phy list of a smp devcie, which is
+ *           about to be removed.
+ *
+ * @param[in] fw_device The expander device that is about to be removed.
+ *
+ * @return none.
+ */
+void scif_sas_smp_remote_device_removed(
+   SCIF_SAS_REMOTE_DEVICE_T * this_device
+)
+{
+   SCIF_SAS_SMP_REMOTE_DEVICE_T * smp_remote_device =
+      &this_device->protocol_device.smp_device;
+
+   SCI_FAST_LIST_ELEMENT_T  * element = smp_remote_device->smp_phy_list.list_head;
+   SCIF_SAS_SMP_PHY_T * curr_smp_phy = NULL;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(this_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_smp_remote_device_removed(0x%x) enter\n",
+      this_device
+   ));
+
+   //remove all the smp phys in this device's smp_phy_list, and the conterpart smp phys
+   //in phy connections.
+   while (element != NULL)
+   {
+      curr_smp_phy = (SCIF_SAS_SMP_PHY_T*) sci_fast_list_get_object(element);
+      element = sci_fast_list_get_next(element);
+
+      scif_sas_smp_phy_destruct(curr_smp_phy);
+   }
+
+   this_device->protocol_device.smp_device.number_of_phys = 0;
+   this_device->protocol_device.smp_device.expander_route_indexes = 0;
+   this_device->protocol_device.smp_device.is_table_to_table_supported = FALSE;
+   this_device->protocol_device.smp_device.is_externally_configurable  = FALSE;
+   this_device->protocol_device.smp_device.is_able_to_config_others    = FALSE;
+
+   scif_sas_smp_remote_device_clear(this_device);
+}
+
+
+/**
+ * @brief This method takes care of terminated smp request to a smp device. The
+ *        terminated smp request is most likely timeout and being aborted. A timeout
+ *        maybe due to OPEN REJECT (NO DESTINATION).
+ *
+ * @param[in] fw_device The expander device that a timed out smp request towards to.
+ * @param[in] fw_request A failed smp request that is terminated by scic.
+ *
+ * @return none.
+ */
+void scif_sas_smp_remote_device_terminated_request_handler(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   SCIF_SAS_REQUEST_T       * fw_request
+)
+{
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_smp_remote_device_terminated_request_handler(0x%x, 0x%x) enter\n",
+      fw_device, fw_request
+   ));
+
+   scif_sas_smp_remote_device_decode_smp_response(
+      fw_device, fw_request, NULL, SCI_IO_FAILURE_RETRY_REQUIRED
+   );
+}
+
+
+/**
+ * @brief This method allocates and populates the smp phy list of a expander device.
+ *
+ * @param[in] fw_device The expander device, whose smp phy list is to be populated after
+ *                      getting REPORT GENERAL response.
+ *
+ * @return none.
+ */
+void scif_sas_smp_remote_device_populate_smp_phy_list(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device
+)
+{
+   SCIF_SAS_SMP_PHY_T * this_smp_phy = NULL;
+   U8                   expander_phy_id = 0;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_smp_remote_device_populate_smp_phy_list(0x%x) enter\n",
+      fw_device
+   ));
+
+   for ( expander_phy_id = 0;
+         expander_phy_id < fw_device->protocol_device.smp_device.number_of_phys;
+         expander_phy_id++ )
+   {
+      this_smp_phy =
+         scif_sas_controller_allocate_smp_phy(fw_device->domain->controller);
+
+      ASSERT( this_smp_phy != NULL );
+
+      if ( this_smp_phy != NULL )
+         scif_sas_smp_phy_construct(this_smp_phy, fw_device, expander_phy_id);
+   }
+}
+
+
+/**
+ * @brief This method updates a smp phy of a expander device based on DISCOVER response.
+ *
+ * @param[in] fw_device The expander device, one of whose smp phys is to be updated.
+ * @param[in] discover_response The smp DISCOVER response.
+ *
+ * @return SCI_STATUS If a smp phy pair between expanders has invalid routing attribute,
+ *                    return SCI_FAILURE_ILLEGAL_ROUTING_ATTRIBUTE_CONFIGURATION, otherwise,
+ *                    return SCI_SUCCESS
+ */
+SCI_STATUS scif_sas_smp_remote_device_save_smp_phy_info(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   SMP_RESPONSE_DISCOVER_T  * discover_response
+)
+{
+   SCI_STATUS status = SCI_SUCCESS;
+   SCIF_SAS_SMP_PHY_T * smp_phy = NULL;
+   SCIF_SAS_REMOTE_DEVICE_T * attached_device = NULL;
+
+    SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_smp_remote_device_save_smp_phy_info(0x%x, 0x%x) enter\n",
+      fw_device, discover_response
+   ));
+
+   smp_phy = scif_sas_smp_remote_device_find_smp_phy_by_id(
+                discover_response->phy_identifier,
+                &fw_device->protocol_device.smp_device
+             );
+
+   ASSERT( smp_phy != NULL );
+
+   //Note, attached_device could be NULL, not all the smp phy have to connected to a device.
+   attached_device = (SCIF_SAS_REMOTE_DEVICE_T *)
+      scif_domain_get_device_by_sas_address(
+         fw_device->domain, &discover_response->attached_sas_address);
+
+   scif_sas_smp_phy_save_information(
+      smp_phy, attached_device, discover_response);
+
+   //handle the special case of smp phys between expanders.
+   if ( discover_response->protocols.u.bits.attached_smp_target )
+   {
+       //this fw_device is a child expander, just found its parent expander.
+       //And there is no smp_phy constructed yet, record this phy connection.
+       if ( attached_device != NULL
+           && attached_device == fw_device->containing_device )
+       {
+          //record the smp phy info, for this phy connects to a upstream smp device.
+          //the connection of a pair of smp phys are completed.
+          status = scif_sas_smp_phy_set_attached_phy(
+                      smp_phy,
+                      discover_response->attached_phy_identifier,
+                      attached_device
+                   );
+
+          if (status == SCI_SUCCESS)
+          {
+             //check the routing attribute for this phy and its containing device's
+             //expander_phy_routing_attribute.
+             if ( scif_sas_smp_phy_verify_routing_attribute(
+                     smp_phy, smp_phy->u.attached_phy) != SCI_SUCCESS )
+                return SCI_FAILURE_ILLEGAL_ROUTING_ATTRIBUTE_CONFIGURATION;
+          }
+       }
+    }
+
+    return status;
+}
+
+#ifdef SCI_SMP_PHY_LIST_DEBUG_PRINT
+void scif_sas_smp_remote_device_print_smp_phy_list(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device
+)
+{
+   SCIF_SAS_SMP_REMOTE_DEVICE_T * smp_remote_device = &fw_device->protocol_device.smp_device;
+   SCI_FAST_LIST_ELEMENT_T  * element = smp_remote_device->smp_phy_list.list_head;
+   SCIF_SAS_SMP_PHY_T * curr_smp_phy = NULL;
+
+   SCIF_LOG_ERROR((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE,
+      "==========EXPANDER DEVICE (0x%x) smp phy list========== \n",
+      fw_device
+   ));
+
+   while (element != NULL)
+   {
+      curr_smp_phy = (SCIF_SAS_SMP_PHY_T*) sci_fast_list_get_object(element);
+      element = sci_fast_list_get_next(element);
+
+      //print every thing about a smp phy
+      SCIF_LOG_ERROR((
+         sci_base_object_get_logger(fw_device),
+         SCIF_LOG_OBJECT_REMOTE_DEVICE,
+         "SMP_PHY_%d (0x%x), attached device(0x%x), attached_sas_address(%x%x) attached_device_type(%d), routing_attribute(%d)\n",
+         curr_smp_phy->phy_identifier, curr_smp_phy,
+         curr_smp_phy->u.end_device,
+         curr_smp_phy->attached_sas_address.high, curr_smp_phy->attached_sas_address.low,
+         curr_smp_phy->attached_device_type,
+         curr_smp_phy->routing_attribute
+      ));
+   }
+}
+#endif
+
+
+/**
+ * @brief This method configure upstream expander(s)' (if there is any) route info.
+ *
+ * @param[in] this_device The expander device that is currently in discover process.
+ *
+ * @return none.
+ */
+void scif_sas_smp_remote_device_configure_upstream_expander_route_info(
+   SCIF_SAS_REMOTE_DEVICE_T * this_device
+)
+{
+   SCIF_SAS_REMOTE_DEVICE_T * curr_child_expander = this_device;
+   SCIF_SAS_REMOTE_DEVICE_T * curr_parent_expander =
+      scif_sas_remote_device_find_upstream_expander(this_device);
+
+   SCIF_SAS_REMOTE_DEVICE_T * curr_config_route_info_expander = NULL;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(this_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_smp_remote_device_configure_upstream_expander_route_info(0x%x) enter\n",
+      this_device
+   ));
+
+   //traverse back to find root device.
+   while(curr_parent_expander != NULL )
+   {
+      //must set destination_smp_phy outside of find_upstream_expander() using the device
+      //that is just about to finish the discovery.
+      curr_parent_expander->protocol_device.smp_device.curr_config_route_destination_smp_phy =
+         (SCIF_SAS_SMP_PHY_T*)sci_fast_list_get_object(
+             this_device->protocol_device.smp_device.smp_phy_list.list_head);
+
+      curr_child_expander = curr_parent_expander;
+      curr_parent_expander = scif_sas_remote_device_find_upstream_expander(curr_child_expander);
+   }
+
+   //found the root device: curr_child_expander. configure it and its downstream expander(s) till
+   //this_device or a self-configuring expander that configures others;
+   curr_config_route_info_expander = curr_child_expander;
+
+   while ( curr_config_route_info_expander != NULL
+          && curr_config_route_info_expander != this_device
+          && curr_config_route_info_expander->protocol_device.smp_device.scheduled_activity
+                == SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_NONE
+         )
+   {
+      if (curr_config_route_info_expander->protocol_device.smp_device.is_externally_configurable)
+      {
+         SCIF_SAS_SMP_PHY_T * phy_being_config =
+            curr_config_route_info_expander->protocol_device.smp_device.config_route_smp_phy_anchor;
+
+         curr_config_route_info_expander->protocol_device.smp_device.curr_config_route_index =
+            phy_being_config->config_route_table_index_anchor;
+
+         if (curr_config_route_info_expander->protocol_device.smp_device.curr_config_route_index != 0)
+            curr_config_route_info_expander->protocol_device.smp_device.curr_config_route_index++;
+
+         curr_config_route_info_expander->protocol_device.smp_device.scheduled_activity =
+            SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_CONFIG_ROUTE_TABLE;
+
+         //Find a downstream expander that has curr_config_route_destination_smp_phy.owning device
+         //same as curr_config_route_info_expander.
+         curr_config_route_info_expander = scif_sas_remote_device_find_downstream_expander(
+            curr_config_route_info_expander);
+      }
+      else if (curr_config_route_info_expander->protocol_device.smp_device.is_able_to_config_others)
+      {
+         //no need to config route table to this expander and its children.
+         //find its downstream expander and clear the planned config route table activity.
+         SCIF_SAS_REMOTE_DEVICE_T * curr_downstream_expander =
+            scif_sas_remote_device_find_downstream_expander(
+               curr_config_route_info_expander);
+
+         scif_sas_smp_remote_device_clear(curr_config_route_info_expander);
+
+         while ( curr_downstream_expander != NULL
+                && curr_downstream_expander != this_device )
+         {
+            scif_sas_smp_remote_device_clear(curr_downstream_expander);
+            curr_downstream_expander =
+               scif_sas_remote_device_find_downstream_expander(
+                  curr_config_route_info_expander);
+         }
+
+         break;
+      }
+      else
+      {
+         // current expander is a self-configuring expander, which is not externally
+         // configurable, and doesn't config others. we need to simply skip this expander.
+         curr_config_route_info_expander = scif_sas_remote_device_find_downstream_expander(
+            curr_config_route_info_expander);
+      }
+   }
+}
+
+/**
+ * @brief This method finds the immediate upstream expander of a given expander device.
+ *
+ * @param[in] this_device The given expander device, whose upstream expander is to be found.
+ *
+ * @return The immediate upstream expander. Or a NULL pointer if this_device is root already.
+ */
+SCIF_SAS_REMOTE_DEVICE_T * scif_sas_remote_device_find_upstream_expander(
+   SCIF_SAS_REMOTE_DEVICE_T * this_device
+)
+{
+   SCIF_SAS_SMP_REMOTE_DEVICE_T * smp_remote_device =
+      &this_device->protocol_device.smp_device;
+
+   SCIF_SAS_REMOTE_DEVICE_T    * upstream_expander = NULL;
+
+   SCI_FAST_LIST_ELEMENT_T     * element = smp_remote_device->smp_phy_list.list_head;
+   SCIF_SAS_SMP_PHY_T          * curr_smp_phy = NULL;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(this_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_smp_remote_device_configure_upstream_expander_route_info(0x%x) enter\n",
+      this_device
+   ));
+
+   while (element != NULL)
+   {
+      curr_smp_phy = (SCIF_SAS_SMP_PHY_T*) sci_fast_list_get_object(element);
+      element = sci_fast_list_get_next(element);
+
+      if ( curr_smp_phy->routing_attribute == SUBTRACTIVE_ROUTING_ATTRIBUTE
+          && ( curr_smp_phy->attached_device_type == SMP_EDGE_EXPANDER_DEVICE
+              || curr_smp_phy->attached_device_type == SMP_FANOUT_EXPANDER_DEVICE)
+          && curr_smp_phy->u.attached_phy != NULL
+          && curr_smp_phy->u.attached_phy->routing_attribute == TABLE_ROUTING_ATTRIBUTE )
+      {
+         //set the current_activity and current_config_route_index for that
+         //upstream expander.
+         upstream_expander = curr_smp_phy->u.attached_phy->owning_device;
+
+         upstream_expander->protocol_device.smp_device.current_smp_request =
+            SMP_FUNCTION_CONFIGURE_ROUTE_INFORMATION;
+
+         //if the upstream_expander's config route table method is config phy0 only or
+         //config all phys, the current activity phy is found.
+         upstream_expander->protocol_device.smp_device.config_route_smp_phy_anchor =
+            scif_sas_smp_remote_device_find_smp_phy_by_id(
+               curr_smp_phy->u.attached_phy->phy_identifier,
+               &(curr_smp_phy->u.attached_phy->owning_device->protocol_device.smp_device)
+            );
+
+         //if the upstream_expander's config route table method is config middle phy only
+         //config highest phy only, the current activity phy needs a update.
+         if ( scif_sas_smp_remote_device_get_config_route_table_method(upstream_expander)
+                 == SCIF_SAS_CONFIG_ROUTE_TABLE_MIDDLE_PHY_ONLY )
+         {
+            upstream_expander->protocol_device.smp_device.config_route_smp_phy_anchor =
+               scif_sas_smp_phy_find_middle_phy_in_wide_port (
+                  upstream_expander->protocol_device.smp_device.config_route_smp_phy_anchor
+               );
+         }
+         else if ( scif_sas_smp_remote_device_get_config_route_table_method(upstream_expander)
+                      == SCIF_SAS_CONFIG_ROUTE_TABLE_HIGHEST_PHY_ONLY )
+         {
+            upstream_expander->protocol_device.smp_device.config_route_smp_phy_anchor =
+               scif_sas_smp_phy_find_highest_phy_in_wide_port (
+                  upstream_expander->protocol_device.smp_device.config_route_smp_phy_anchor
+               );
+         }
+
+         upstream_expander->protocol_device.smp_device.current_activity_phy_index =
+            upstream_expander->protocol_device.smp_device.config_route_smp_phy_anchor->phy_identifier;
+
+         return upstream_expander;
+      }
+   }
+
+   return NULL;
+}
+
+
+/**
+ * @brief This method finds the immediate downstream expander of a given expander device.
+ *
+ * @param[in] this_device The given expander device, whose downstream expander is to be found.
+ *
+ * @return The immediate downstream expander. Or a NULL pointer if there is none.
+ */
+SCIF_SAS_REMOTE_DEVICE_T * scif_sas_remote_device_find_downstream_expander(
+   SCIF_SAS_REMOTE_DEVICE_T * this_device
+)
+{
+   SCIF_SAS_SMP_REMOTE_DEVICE_T * this_smp_remote_device =
+      &this_device->protocol_device.smp_device;
+
+   SCIF_SAS_REMOTE_DEVICE_T    * downstream_expander = NULL;
+
+   SCI_FAST_LIST_ELEMENT_T     * element = this_smp_remote_device->smp_phy_list.list_head;
+   SCIF_SAS_SMP_PHY_T          * curr_smp_phy = NULL;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(this_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_remote_device_find_downstream_expander(0x%x) enter\n",
+      this_device
+   ));
+
+   while (element != NULL)
+   {
+      curr_smp_phy = (SCIF_SAS_SMP_PHY_T*) sci_fast_list_get_object(element);
+      element = sci_fast_list_get_next(element);
+
+      if ( curr_smp_phy->routing_attribute == TABLE_ROUTING_ATTRIBUTE
+          && curr_smp_phy->attached_device_type == SMP_EDGE_EXPANDER_DEVICE
+          && curr_smp_phy->u.attached_phy != NULL)
+      {
+         //set the current_activity and current_config_route_index for that
+         //upstream expander.
+         downstream_expander = curr_smp_phy->u.attached_phy->owning_device;
+
+         if ( downstream_expander->protocol_device.smp_device.curr_config_route_destination_smp_phy != NULL
+             && downstream_expander->protocol_device.smp_device.curr_config_route_destination_smp_phy->owning_device ==
+                this_smp_remote_device->curr_config_route_destination_smp_phy->owning_device )
+            return downstream_expander;
+      }
+   }
+
+   return NULL;
+}
+
+
+/**
+ * @brief This method follows route table optimization rule to check if a destination_device
+ *        should be recorded in the device_being_config's route table
+ *
+ * @param[in] device_being_config The upstream expander device, whose route table is being configured.
+ * @param[in] destination_smp_phy A smp phy whose attached device is potentially to be
+ *               recorded in route table.
+ *
+ * @return BOOL This method returns TRUE if a destination_device should be recorded in route table.
+ *              This method returns FALSE if a destination_device need not to be recorded
+ *              in route table.
+ */
+BOOL scif_sas_smp_remote_device_do_config_route_info(
+   SCIF_SAS_REMOTE_DEVICE_T * device_being_config,
+   SCIF_SAS_SMP_PHY_T       * destination_smp_phy
+)
+{
+   SCI_SAS_ADDRESS_T device_being_config_sas_address;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(device_being_config),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_smp_remote_device_do_config_route_info(0x%x, 0x%x) enter\n",
+      device_being_config, destination_smp_phy
+   ));
+
+   scic_remote_device_get_sas_address(
+      device_being_config->core_object, &device_being_config_sas_address
+   );
+
+   //refer to SAS-2 spec 4.8.3, rule (b)
+   if ((destination_smp_phy->attached_sas_address.low == 0
+        && destination_smp_phy->attached_sas_address.high == 0)
+       && (destination_smp_phy->attached_device_type == SMP_NO_DEVICE_ATTACHED))
+   {
+      return FALSE;
+   }
+
+   //refer to SAS-2 spec 4.8.3, rule (c), self-referencing.
+   if (destination_smp_phy->attached_sas_address.high ==
+          device_being_config_sas_address.high
+       && destination_smp_phy->attached_sas_address.low ==
+             device_being_config_sas_address.low)
+   {
+      return FALSE;
+   }
+
+   //There will be no cases that falling into rule (a), (d), (e) to be excluded,
+   //based on our current mechanism of cofig route table.
+
+   return TRUE;
+}
+
+
+/**
+ * @brief This method configures device_being_config's route table for all the enclosed devices in
+ *           a downstream smp device, destination_device.
+ *
+ * @param[in] device_being_config The upstream expander device, whose route table is being configured.
+ *
+ * @return None
+ */
+void scif_sas_smp_remote_device_configure_route_table(
+   SCIF_SAS_REMOTE_DEVICE_T * device_being_config
+)
+{
+   //go through the smp phy list of this_device.
+   SCI_FAST_LIST_ELEMENT_T     * element =
+      &(device_being_config->protocol_device.smp_device.curr_config_route_destination_smp_phy->list_element);
+   SCIF_SAS_SMP_PHY_T          * curr_smp_phy = NULL;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(device_being_config),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_smp_remote_device_configure_route_table(0x%x) enter\n",
+      device_being_config
+   ));
+
+   device_being_config->protocol_device.smp_device.current_activity =
+      SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_CONFIG_ROUTE_TABLE;
+
+   while (element != NULL)
+   {
+      curr_smp_phy = (SCIF_SAS_SMP_PHY_T*) sci_fast_list_get_object(element);
+      element = sci_fast_list_get_next(element);
+
+      //check if this phy needs to be added to the expander's route table.
+      if (scif_sas_smp_remote_device_do_config_route_info(
+             device_being_config, curr_smp_phy) == TRUE )
+      {
+         SCIF_SAS_SMP_REMOTE_DEVICE_T * smp_remote_device =
+            &device_being_config->protocol_device.smp_device;
+
+         smp_remote_device->curr_config_route_destination_smp_phy =
+            curr_smp_phy;
+
+         //Then config this_device's route table entry at the phy and next route_index.
+         //send config_route_info using curr_smp_phy.phy_identifier and sas_address.
+         scif_sas_smp_request_construct_config_route_info(
+            device_being_config->domain->controller,
+            device_being_config,
+            smp_remote_device->current_activity_phy_index,
+            smp_remote_device->curr_config_route_index,
+            curr_smp_phy->attached_sas_address,
+            FALSE
+         );
+
+         //schedule the DPC.
+         scif_cb_start_internal_io_task_schedule(
+            device_being_config->domain->controller,
+            scif_sas_controller_start_high_priority_io,
+            device_being_config->domain->controller
+         );
+
+         //stop here, we need to wait for config route info's response then send
+         //the next one.
+         break;
+      }
+   }
+}
+
+
+/**
+ * @brief This method walks through an expander's route table to clean table
+ *           attribute phys' route entries. This routine finds one table entry
+ *           to clean and will be called repeatly till it finishes cleanning the
+ *           whole table.
+ *
+ * @param[in] fw_device The expander device, whose route table entry is to be cleaned.
+ *
+ * @return None.
+ */
+void scif_sas_smp_remote_device_clean_route_table(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device
+)
+{
+   SCIF_SAS_SMP_PHY_T * smp_phy_being_config;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_smp_remote_device_clean_route_table(0x%x) enter\n",
+      fw_device
+   ));
+
+   //from anchors, start to clean all the other route table entries.
+   fw_device->protocol_device.smp_device.curr_config_route_index++;
+
+   if ( fw_device->protocol_device.smp_device.curr_config_route_index >=
+           fw_device->protocol_device.smp_device.expander_route_indexes )
+   {
+      fw_device->protocol_device.smp_device.curr_config_route_index = 0;
+
+      do //find next table attribute PHY.
+      {
+         fw_device->protocol_device.smp_device.current_activity_phy_index++;
+         if (fw_device->protocol_device.smp_device.current_activity_phy_index ==
+                fw_device->protocol_device.smp_device.number_of_phys)
+            fw_device->protocol_device.smp_device.current_activity_phy_index=0;
+
+         //phy_index changed, so update the smp_phy_being_config.
+         smp_phy_being_config =
+            scif_sas_smp_remote_device_find_smp_phy_by_id(
+               fw_device->protocol_device.smp_device.current_activity_phy_index,
+               &(fw_device->protocol_device.smp_device)
+            );
+      } while( smp_phy_being_config->routing_attribute != TABLE_ROUTING_ATTRIBUTE );
+
+      if ( smp_phy_being_config->phy_identifier !=
+              fw_device->protocol_device.smp_device.config_route_smp_phy_anchor->phy_identifier)
+      {
+         if (smp_phy_being_config->config_route_table_index_anchor != 0)
+            fw_device->protocol_device.smp_device.curr_config_route_index =
+               smp_phy_being_config->config_route_table_index_anchor + 1;
+         else
+            fw_device->protocol_device.smp_device.curr_config_route_index = 0;
+      }
+   }
+
+   if ( !(fw_device->protocol_device.smp_device.current_activity_phy_index ==
+             fw_device->protocol_device.smp_device.config_route_smp_phy_anchor->phy_identifier
+          && fw_device->protocol_device.smp_device.curr_config_route_index == 0)
+      )
+   {
+      //clean this route entry.
+      scif_sas_smp_remote_device_clean_route_table_entry(fw_device);
+   }
+   else
+   {
+      fw_device->protocol_device.smp_device.is_route_table_cleaned = TRUE;
+
+      //set this device's activity to NON.
+      fw_device->protocol_device.smp_device.current_activity =
+         SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_NONE;
+
+      //we need to notify domain that this device finished config route table, domain
+      //may pick up other activities (i.e. Discover) for other expanders.
+      scif_sas_domain_continue_discover(fw_device->domain);
+   }
+}
+
+/**
+ * @brief This method cleans a device's route table antry.
+ *
+ * @param[in] fw_device The expander device, whose route table entry is to be cleaned.
+ *
+ * @return None.
+ */
+void scif_sas_smp_remote_device_clean_route_table_entry(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device
+)
+{
+   SCI_SAS_ADDRESS_T empty_sas_address;
+   SCIF_SAS_SMP_REMOTE_DEVICE_T * smp_remote_device =
+      &(fw_device->protocol_device.smp_device);
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_smp_remote_device_clean_route_table(0x%x) enter\n",
+      fw_device
+   ));
+
+   empty_sas_address.high = 0;
+   empty_sas_address.low = 0;
+
+   scif_sas_smp_request_construct_config_route_info(
+      fw_device->domain->controller,
+      fw_device,
+      smp_remote_device->current_activity_phy_index,
+      smp_remote_device->curr_config_route_index,
+      empty_sas_address,
+      TRUE
+   );
+
+   //schedule the DPC.
+   scif_cb_start_internal_io_task_schedule(
+      fw_device->domain->controller,
+      scif_sas_controller_start_high_priority_io,
+      fw_device->domain->controller
+   );
+}
+
+
+/**
+ * @brief This method handles the case of exceeding route index when config route table
+ *           for a device, by removing the attached device of current config route
+ *           destination smp phy and the rest of smp phys in the same smp phy list.
+ *
+ * @param[in] fw_device The expander device, whose route table to be edited but failed
+ *               with a SMP function result of INDEX DOES NOT EXIST.
+ *
+ * @return None.
+ */
+void scif_sas_smp_remote_device_cancel_config_route_table_activity(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device
+)
+{
+   //go through the rest of the smp phy list of destination device.
+   SCI_FAST_LIST_ELEMENT_T     * element =
+      &(fw_device->protocol_device.smp_device.curr_config_route_destination_smp_phy->list_element);
+   SCIF_SAS_SMP_PHY_T          * curr_smp_phy = NULL;
+   SCIF_SAS_REMOTE_DEVICE_T    * curr_attached_device = NULL;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_smp_remote_device_cancel_config_route_table_activity(0x%x) enter\n",
+      fw_device
+   ));
+
+   while (element != NULL)
+   {
+      curr_smp_phy = (SCIF_SAS_SMP_PHY_T*) sci_fast_list_get_object(element);
+      element = sci_fast_list_get_next(element);
+
+      //check if this phy needs to be added to the expander's route table but can't due to
+      //exceeding max route index.
+      if (scif_sas_smp_remote_device_do_config_route_info(
+             fw_device, curr_smp_phy) == TRUE )
+      {
+         //set the is_currently_discovered to FALSE for attached device. Then when
+         //domain finish discover, domain will remove this device.
+         curr_attached_device = (SCIF_SAS_REMOTE_DEVICE_T *)
+            scif_domain_get_device_by_sas_address(
+               fw_device->domain, &(curr_smp_phy->attached_sas_address));
+
+         if (curr_attached_device != NULL)
+            curr_attached_device->is_currently_discovered = FALSE;
+      }
+   }
+}
+
+
+/**
+ * @brief This method cancel current activity and terminate the outstanding internal IO
+ *           if there is one.
+ *
+ * @param[in] fw_device The expander device, whose smp activity is to be canceled.
+ *
+ * @return None.
+ */
+void scif_sas_smp_remote_device_cancel_smp_activity(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device
+)
+{
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
+      "scif_sas_smp_remote_device_cancel_smp_activity(0x%x) enter\n",
+      fw_device
+   ));
+
+   //Terminate all of the requests in the silicon for this device.
+   scif_sas_domain_terminate_requests(
+      fw_device->domain, fw_device, NULL, NULL
+   );
+
+   if (fw_device->protocol_device.smp_device.current_activity ==
+          SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_CONFIG_ROUTE_TABLE)
+      scif_sas_smp_remote_device_cancel_config_route_table_activity(fw_device);
+
+   //Clear the device to stop the smp sctivity.
+   scif_sas_smp_remote_device_clear(fw_device);
+}
+
+
+/**
+ * @brief This method tells the way to configure route table for a expander. The
+ *          possible ways are: configure phy 0's route table, configure middle
+ *          phy's route table, configure highest order phy's route table,
+ *          configure all phys.
+ *
+ * @param[in] fw_device The expander device, whose config route table method is
+ *               to be chosen.
+ *
+ * @return one in 4 possible options.
+ */
+U8 scif_sas_smp_remote_device_get_config_route_table_method(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device
+)
+{
+   U8 config_route_table_method;
+
+   //config_route_table_method = SCIF_SAS_CONFIG_ROUTE_TABLE_MIDDLE_PHY_ONLY;
+   config_route_table_method = SCIF_SAS_CONFIG_ROUTE_TABLE_ALL_PHYS;
+
+   return config_route_table_method;
+}
+
+
+/**
+ * @brief This method starts the EA target reset process by constructing
+ *           and starting a PHY CONTROL (hard reset) smp request.
+ *
+ * @param[in] expander_device The expander device, to which a PHY Control smp command is
+ *               sent.
+ * @param[in] target_device The expander attahced target device, to which the target reset
+ *               request is sent.
+ * @param[in] fw_request The target reset task request.
+ *
+ * @return none
+ */
+void scif_sas_smp_remote_device_start_target_reset(
+   SCIF_SAS_REMOTE_DEVICE_T * expander_device,
+   SCIF_SAS_REMOTE_DEVICE_T * target_device,
+   SCIF_SAS_REQUEST_T       * fw_request
+)
+{
+   SCIF_SAS_CONTROLLER_T * fw_controller = expander_device->domain->controller;
+
+   //set current_activity and current_smp_request to expander device.
+   expander_device->protocol_device.smp_device.current_activity =
+      SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_TARGET_RESET;
+   expander_device->protocol_device.smp_device.current_smp_request =
+      SMP_FUNCTION_PHY_CONTROL;
+   expander_device->protocol_device.smp_device.current_activity_phy_index =
+      target_device->expander_phy_identifier;
+
+   //A Phy Control smp request has been constructed towards parent device.
+   //Walk the high priority io path.
+   fw_controller->state_handlers->start_high_priority_io_handler(
+      (SCI_BASE_CONTROLLER_T*) fw_controller,
+      (SCI_BASE_REMOTE_DEVICE_T*) expander_device,
+      (SCI_BASE_REQUEST_T*) fw_request,
+      SCI_CONTROLLER_INVALID_IO_TAG
+   );
+}
diff --git a/sys/dev/disk/isci/scil/scif_sas_smp_remote_device.h b/sys/dev/disk/isci/scil/scif_sas_smp_remote_device.h
new file mode 100644
index 0000000..c44a0fd
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_smp_remote_device.h
@@ -0,0 +1,431 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_smp_remote_device.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIF_SAS_SMP_REMOTE_DEVICE_H_
+#define _SCIF_SAS_SMP_REMOTE_DEVICE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+
+#include <dev/disk/isci/scil/sci_fast_list.h>
+#include <dev/disk/isci/scil/scif_sas_smp_phy.h>
+
+/**
+ * @file
+ *
+ * @brief This file contains the protected interface structures, constants,
+ *        and methods for the SCIF_SAS_SMP_REMOTE_DEVICE object.
+ */
+
+struct SCIF_SAS_CONTROLLER;
+struct SCIF_SAS_REMOTE_DEVICE;
+struct SCIF_SAS_INTERNAL_IO_REQUEST;
+struct SCIF_SAS_REQUEST;
+struct SCIF_SAS_SMP_PHY;
+
+#define SMP_REQUEST_RETRY_WAIT_DURATION   20
+#define SMP_SPINUP_HOLD_RELEASE_WAIT_DURATION 100
+
+/**
+ * @name SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_CODES
+ *
+ * These constants depict the various SMP remote device activities.
+ */
+/*@{*/
+#define NOT_IN_SMP_ACTIVITY 0xff
+#define SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_NONE         0x0
+#define SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_DISCOVER     0x1
+#define SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_TARGET_RESET 0x2
+#define SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_SATA_SPINUP_HOLD_RELEASE 0x3
+#define SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_CONFIG_ROUTE_TABLE 0x4
+#define SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_CLEAN_ROUTE_TABLE 0x5
+#define SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_CLEAR_AFFILIATION 0x6
+/*@}*/
+
+
+
+/**
+ * @name SCIF_SAS_CONFIG_ROUTE_TABLE_OPTION_CODES
+ *
+ * These constants depict the various configure route table options.
+ */
+/*@{*/
+#define SCIF_SAS_CONFIG_ROUTE_TABLE_LOWEST_PHY_ONLY   0
+#define SCIF_SAS_CONFIG_ROUTE_TABLE_MIDDLE_PHY_ONLY   1
+#define SCIF_SAS_CONFIG_ROUTE_TABLE_HIGHEST_PHY_ONLY  2
+#define SCIF_SAS_CONFIG_ROUTE_TABLE_ALL_PHYS          3
+/*@}*/
+
+/**
+ * @struct SCIF_SAS_SMP_REMOTE_DEVICE
+ *
+ * @brief The SCIF_SAS_SMP_REMOTE_DEVICE stores data for smp remote devices
+ *        (expanders) discovering attached targets.
+ *
+ */
+typedef struct SCIF_SAS_SMP_REMOTE_DEVICE
+{
+   /**
+    * This field stores the current SMP request function in the discovering
+    * sequence.
+    */
+   U32 current_smp_request;
+
+   /**
+    * This field indicates a smp device is either in the middle of normal discover
+    * process or in the middle of resetting a expander attahced remote device.
+    */
+   U8 current_activity;
+
+   /**
+    * This field stores the current expander phy index for sending out SMP
+    * DISCOVER request.
+    */
+   U8 current_activity_phy_index;
+
+   /**
+    * This field stores the current route index to config route table for
+    * a phy.
+    */
+   U16 curr_config_route_index;
+
+   /**
+    * This field indicates whether a route table of an expander has been cleaned
+    * since a DISCOVER process starts.
+    */
+   BOOL is_route_table_cleaned;
+
+   /**
+    * This field stores the smp phy whose route entries are edited by sending
+    * CONFIG ROUTE INFO commands.
+    */
+   struct SCIF_SAS_SMP_PHY * config_route_smp_phy_anchor;
+
+   /*
+    * This field stores the current smp phy on a destination device's smp phy list whose
+    * attached device's sas address is to be edited into this smp device's route table.
+    * When one config route info response is processed, we can find the next smp phy to edit
+    * using this field's value.
+    */
+   struct SCIF_SAS_SMP_PHY * curr_config_route_destination_smp_phy;
+
+   /*
+    * This field stores the current smp phy to which a PHY CONTROL (clear affiliation)
+    * command is sent out.
+    */
+   struct SCIF_SAS_SMP_PHY * curr_clear_affiliation_phy;
+
+   /**
+    * This field is to indicate a smp activity for this smp device is
+    * to be started (not yet). The scheduled activity could be Discover or Config
+    * Route Table.
+    */
+   U8 scheduled_activity;
+
+   /**
+    * This timer is used for waiting before retrying a smp request, or before
+    * sending Discover request after Phy Control during Target Reset.
+    */
+   void * smp_activity_timer;
+
+   /**
+    * This field save the retry count for internal smp request. Since when
+    * an internal smp request gets retried, it has been destructed already.
+    */
+   U8 io_retry_count;
+
+   /**
+    * This field stores the number of phys for expander device found by decoding
+    * the SMP REPORT GENERAL response.
+    */
+   U8  number_of_phys;
+
+   /**
+    * This field indicates the maximum number of expander route indexes per phy for
+    * this expander device.
+    */
+   U16 expander_route_indexes;
+
+   /**
+    * This field indicates whether an expander device supports table-to-table
+    * connection.
+    */
+   BOOL is_table_to_table_supported;
+
+   /**
+    * This field indicates whether an expander device is externally configurable.
+    * If it is, it is not self-configuring and is not able to config others.
+    */
+   BOOL is_externally_configurable;
+
+   /**
+    * This field indicates whether an expander device is able to config others.
+    */
+   BOOL is_able_to_config_others;
+
+   /**
+    * This field contains the list of all smp phys that connect to another smp phy.
+    */
+   SCI_FAST_LIST_T smp_phy_list;
+
+}SCIF_SAS_SMP_REMOTE_DEVICE_T;
+
+void scif_sas_smp_remote_device_clear(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device
+);
+
+void scif_sas_smp_remote_device_construct(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device
+);
+
+SCI_STATUS scif_sas_smp_remote_device_decode_smp_response(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device,
+   struct SCIF_SAS_REQUEST       * fw_request,
+   void                          * response_data,
+   SCI_IO_STATUS                   completion_status
+);
+
+SCI_STATUS scif_sas_smp_remote_device_decode_report_general_response(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device,
+   SMP_RESPONSE_T                * smp_response
+);
+
+SCI_STATUS scif_sas_smp_remote_device_decode_initial_discover_response(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device,
+   SMP_RESPONSE_T                * smp_response
+);
+
+SCI_STATUS scif_sas_smp_remote_device_decode_report_phy_sata_response(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device,
+   SMP_RESPONSE_T                * smp_response
+);
+
+SCI_STATUS scif_sas_smp_remote_device_decode_target_reset_phy_control_response(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device,
+   SMP_RESPONSE_T           * smp_response
+);
+
+SCI_STATUS scif_sas_smp_remote_device_decode_discover_phy_control_response(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device,
+   SMP_RESPONSE_T           * smp_response
+);
+
+SCI_STATUS scif_sas_smp_remote_device_decode_target_reset_discover_response(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device,
+   SMP_RESPONSE_T           * smp_response
+);
+
+SCI_STATUS scif_sas_smp_remote_device_decode_spinup_hold_release_discover_response(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device,
+   SMP_RESPONSE_T           * smp_response
+);
+
+SCI_STATUS scif_sas_smp_remote_device_decode_config_route_info_response(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device,
+   SMP_RESPONSE_T           * smp_response
+);
+
+void scif_sas_smp_remote_device_start_discover(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device
+);
+
+void scif_sas_smp_remote_device_continue_discover(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device
+);
+
+void scif_sas_smp_remote_device_finish_initial_discover(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device
+);
+
+void scif_sas_smp_remote_device_finish_discover(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device
+);
+
+void scif_sas_smp_remote_device_continue_target_reset(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device,
+   struct SCIF_SAS_REQUEST       * fw_request
+);
+
+void scif_sas_smp_remote_device_fail_discover(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device
+);
+
+void scif_sas_smp_remote_device_fail_target_reset(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device,
+   struct SCIF_SAS_REQUEST       * fw_request
+);
+
+void scif_sas_smp_remote_device_continue_current_activity(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device,
+   struct SCIF_SAS_REQUEST       * fw_request,
+   SCI_STATUS                      status
+);
+
+void scif_sas_smp_remote_device_target_reset_poll(
+   struct SCIF_SAS_REQUEST       * fw_request
+);
+
+void scif_sas_smp_remote_device_sata_spinup_hold_release(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device
+);
+
+void scif_sas_smp_remote_device_fail_target_spinup_hold_release(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device,
+   struct SCIF_SAS_REMOTE_DEVICE * target_device
+);
+
+void scif_sas_smp_remote_device_retry_internal_io(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device,
+   U8                         io_retry_count,
+   U32                        delay
+);
+
+BOOL scif_sas_smp_remote_device_is_in_activity(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device
+);
+
+SCIF_SAS_SMP_PHY_T * scif_sas_smp_remote_device_find_smp_phy_by_id(
+   U8                                  phy_identifier,
+   struct SCIF_SAS_SMP_REMOTE_DEVICE * smp_remote_device
+);
+
+void scif_sas_smp_remote_device_removed(
+   struct SCIF_SAS_REMOTE_DEVICE * this_device
+);
+
+void scif_sas_smp_remote_device_terminated_request_handler(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device,
+   struct SCIF_SAS_REQUEST       * fw_request
+);
+
+void scif_sas_smp_remote_device_populate_smp_phy_list(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device
+);
+
+SCI_STATUS scif_sas_smp_remote_device_save_smp_phy_info(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device,
+   SMP_RESPONSE_DISCOVER_T       * discover_response
+);
+
+#ifdef SCI_SMP_PHY_LIST_DEBUG_PRINT
+void scif_sas_smp_remote_device_print_smp_phy_list(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device
+);
+#endif
+
+void scif_sas_smp_remote_device_configure_upstream_expander_route_info(
+   struct SCIF_SAS_REMOTE_DEVICE * this_device
+);
+
+struct SCIF_SAS_REMOTE_DEVICE * scif_sas_remote_device_find_upstream_expander(
+   struct SCIF_SAS_REMOTE_DEVICE * this_device
+);
+
+struct SCIF_SAS_REMOTE_DEVICE * scif_sas_remote_device_find_downstream_expander(
+   struct SCIF_SAS_REMOTE_DEVICE * this_device
+);
+
+BOOL scif_sas_smp_remote_device_do_config_route_info(
+   struct SCIF_SAS_REMOTE_DEVICE * device_being_config,
+   struct SCIF_SAS_SMP_PHY       * destination_smp_phy
+);
+
+void scif_sas_smp_remote_device_configure_route_table(
+   struct SCIF_SAS_REMOTE_DEVICE * device_being_config
+);
+
+void scif_sas_smp_remote_device_clean_route_table(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device
+);
+
+void scif_sas_smp_remote_device_clean_route_table_entry(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device
+);
+
+void scif_sas_smp_remote_device_cancel_config_route_table_activity(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device
+);
+
+void scif_sas_smp_remote_device_cancel_smp_activity(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device
+);
+
+U8 scif_sas_smp_remote_device_get_config_route_table_method(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device
+);
+
+void scif_sas_smp_remote_device_start_clear_affiliation(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device
+);
+
+void scif_sas_smp_remote_device_continue_clear_affiliation(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device
+);
+
+void scif_sas_smp_remote_device_finish_clear_affiliation(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device
+);
+
+void scif_sas_smp_remote_device_start_target_reset(
+   struct SCIF_SAS_REMOTE_DEVICE * expander_device,
+   struct SCIF_SAS_REMOTE_DEVICE * target_device,
+   struct SCIF_SAS_REQUEST       * fw_request
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIF_SAS_SMP_REMOTE_DEVICE_H_
diff --git a/sys/dev/disk/isci/scil/scif_sas_stp_io_request.c b/sys/dev/disk/isci/scil/scif_sas_stp_io_request.c
new file mode 100644
index 0000000..12373a5
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_stp_io_request.c
@@ -0,0 +1,621 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_stp_io_request.c,v 1.2 2012/02/09 17:50:24 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains the method implementations for the
+ *        SCIF_SAS_STP_IO_REQUEST object.  The contents will implement
+ *        SATA/STP specific functionality.
+ */
+
+#include <dev/disk/isci/scil/scif_sas_stp_io_request.h>
+#include <dev/disk/isci/scil/scif_sas_stp_remote_device.h>
+#include <dev/disk/isci/scil/scif_sas_logger.h>
+#include <dev/disk/isci/scil/scif_sas_controller.h>
+
+#include <dev/disk/isci/scil/sci_status.h>
+#include <dev/disk/isci/scil/scic_io_request.h>
+
+#include <dev/disk/isci/scil/sati.h>
+#include <dev/disk/isci/scil/sati_atapi.h>
+#include <dev/disk/isci/scil/intel_sat.h>
+#include <dev/disk/isci/scil/sati_util.h>
+#include <dev/disk/isci/scil/sati_callbacks.h>
+
+//******************************************************************************
+// P R I V A T E   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method provides SATA/STP CONSTRUCTED state specific handling
+ *        for when the user attempts to start the supplied IO request.  It
+ *        will allocate NCQ tags if necessary.
+ *
+ * @param[in] io_request This parameter specifies the IO request object
+ *            to be started.
+ *
+ * @return This method returns a value indicating if the IO request was
+ *         successfully started or not.
+ * @retval SCI_SUCCESS This return value indicates successful starting
+ *         of the IO request.
+ */
+static
+SCI_STATUS scif_sas_stp_io_request_constructed_start_handler(
+   SCI_BASE_REQUEST_T * io_request
+)
+{
+   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *) io_request;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(io_request),
+      SCIF_LOG_OBJECT_IO_REQUEST,
+      "scif_sas_stp_io_request_constructed_start_handler(0x%x) enter\n",
+      io_request
+   ));
+
+   if (fw_io->parent.stp.sequence.protocol == SAT_PROTOCOL_FPDMA)
+   {
+      SATA_FIS_REG_H2D_T * fis;
+
+      // For NCQ, we need to attempt to allocate an available tag.
+      fw_io->parent.stp.ncq_tag = scif_sas_stp_remote_device_allocate_ncq_tag(
+                                     fw_io->parent.device
+                                  );
+
+      if (fw_io->parent.stp.ncq_tag == SCIF_SAS_INVALID_NCQ_TAG)
+         return SCI_FAILURE_NO_NCQ_TAG_AVAILABLE;
+
+      // Set the NCQ tag in the host to device register FIS (upper 5 bits
+      // of the 8-bit sector count register).
+      fis = scic_stp_io_request_get_h2d_reg_address(fw_io->parent.core_object);
+      fis->sector_count = (fw_io->parent.stp.ncq_tag << 3);
+
+      // The Core also requires that we inform it separately regarding the
+      // NCQ tag for this IO.
+      scic_stp_io_request_set_ncq_tag(
+         fw_io->parent.core_object, fw_io->parent.stp.ncq_tag
+      );
+   }
+
+   return SCI_SUCCESS;
+}
+
+/**
+ * @brief This method provides SATA/STP CONSTRUCTED state specific handling
+ *        for when the user attempts to complete the supplied IO request.
+ *        This method will be invoked in the event the call to start the
+ *        core IO request fails for some reason.  In this situation, the
+ *        NCQ tag will be freed.
+ *
+ * @param[in] io_request This parameter specifies the IO request object
+ *            to be started.
+ *
+ * @return This method returns a value indicating if the IO request was
+ *         successfully started or not.
+ * @retval SCI_SUCCESS This return value indicates successful starting
+ *         of the IO request.
+ */
+static
+SCI_STATUS scif_sas_stp_io_request_constructed_complete_handler(
+   SCI_BASE_REQUEST_T * io_request
+)
+{
+   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *) io_request;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(io_request),
+      SCIF_LOG_OBJECT_IO_REQUEST,
+      "scif_sas_stp_io_request_constructed_complete_handler(0x%x) enter\n",
+      io_request
+   ));
+
+   if (fw_io->parent.stp.sequence.protocol == SAT_PROTOCOL_FPDMA)
+   {
+      // For NCQ, we need to return the tag back to the free pool.
+      if (fw_io->parent.stp.ncq_tag != SCIF_SAS_INVALID_NCQ_TAG)
+         scif_sas_stp_remote_device_free_ncq_tag(
+            fw_io->parent.device, fw_io->parent.stp.ncq_tag
+         );
+   }
+
+   return SCI_SUCCESS;
+}
+/**
+ * @brief This method provides SATA/STP STARTED state specific handling for
+ *        when the user attempts to complete the supplied IO request.
+ *        It will perform data/response translation and free NCQ tags
+ *        if necessary.
+ *
+ * @param[in] io_request This parameter specifies the IO request object
+ *            to be started.
+ *
+ * @return This method returns a value indicating if the IO request was
+ *         successfully completed or not.
+ */
+static
+SCI_STATUS scif_sas_stp_core_cb_io_request_complete_handler(
+   SCIF_SAS_CONTROLLER_T    * fw_controller,
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   SCIF_SAS_REQUEST_T       * fw_request,
+   SCI_STATUS               * completion_status
+)
+{
+   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *) fw_request;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_controller),
+      SCIF_LOG_OBJECT_IO_REQUEST,
+      "scif_sas_stp_core_cb_io_request_complete_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
+      fw_controller, fw_device, fw_request, *completion_status
+   ));
+
+   if (fw_io->parent.stp.sequence.protocol == SAT_PROTOCOL_FPDMA)
+      scif_sas_stp_remote_device_free_ncq_tag(
+         fw_request->device, fw_io->parent.stp.ncq_tag
+      );
+
+   // Translating the response is only necessary if:
+   // - some sort of error occurred resulting in having the error bit
+   //   set in the ATA status register and values to decode in the
+   //   ATA error register.
+   // - the command returns information in the register FIS itself,
+   //   which requires translation.
+   // - the request completed ok but the sequence requires a callback
+   //   to possibly continue the translation
+   if ((*completion_status == SCI_FAILURE_IO_RESPONSE_VALID) ||
+       ((sati_cb_do_translate_response(fw_request)) &&
+        (*completion_status != SCI_FAILURE_IO_TERMINATED)))
+   {
+      SATI_STATUS sati_status = sati_translate_command_response(
+                                   &fw_io->parent.stp.sequence, fw_io, fw_io
+                                );
+      if (sati_status == SATI_COMPLETE)
+         *completion_status = SCI_SUCCESS;
+      else if (sati_status == SATI_FAILURE_CHECK_RESPONSE_DATA)
+         *completion_status = SCI_FAILURE_IO_RESPONSE_VALID;
+      else if (sati_status == SATI_SEQUENCE_INCOMPLETE)
+      {
+         // The translation indicates that additional SATA requests are
+         // necessary to finish the original SCSI request.  As a result,
+         // do not complete the IO and begin the next stage of the
+         // translation.
+         return SCI_WARNING_SEQUENCE_INCOMPLETE;
+      }
+      else if (sati_status == SATI_COMPLETE_IO_DONE_EARLY)
+         *completion_status = SCI_SUCCESS_IO_DONE_EARLY;
+      else
+      {
+         // Something unexpected occurred during translation.  Fail the
+         // IO request to the user.
+         *completion_status = SCI_FAILURE;
+      }
+   }
+   else if (*completion_status != SCI_SUCCESS)
+   {
+      SCIF_LOG_INFO((
+         sci_base_object_get_logger(fw_controller),
+         SCIF_LOG_OBJECT_IO_REQUEST,
+         "Sequence Terminated(0x%x, 0x%x, 0x%x)\n",
+         fw_controller, fw_device, fw_request
+      ));
+
+      sati_sequence_terminate(&fw_io->parent.stp.sequence, fw_io, fw_io);
+   }
+
+   return SCI_SUCCESS;
+}
+
+#if !defined(DISABLE_ATAPI)
+/**
+ * @brief This method provides STP PACKET io request STARTED state specific handling for
+ *        when the user attempts to complete the supplied IO request.
+ *        It will perform data/response translation.
+ *
+ * @param[in] io_request This parameter specifies the IO request object
+ *            to be started.
+ *
+ * @return This method returns a value indicating if the IO request was
+ *         successfully completed or not.
+ */
+static
+SCI_STATUS scif_sas_stp_core_cb_packet_io_request_complete_handler(
+   SCIF_SAS_CONTROLLER_T    * fw_controller,
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   SCIF_SAS_REQUEST_T       * fw_request,
+   SCI_STATUS               * completion_status
+)
+{
+   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *) fw_request;
+   SATI_STATUS sati_status;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_controller),
+      SCIF_LOG_OBJECT_IO_REQUEST,
+      "scif_sas_stp_packet_core_cb_io_request_complete_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
+      fw_controller, fw_device, fw_request, *completion_status
+   ));
+
+   if (*completion_status == SCI_FAILURE_IO_RESPONSE_VALID)
+   {
+      sati_status = sati_atapi_translate_command_response(
+                       &fw_io->parent.stp.sequence, fw_io, fw_io
+                    );
+
+      if (sati_status == SATI_COMPLETE)
+         *completion_status = SCI_SUCCESS;
+      else if (sati_status == SATI_FAILURE_CHECK_RESPONSE_DATA)
+         *completion_status = SCI_FAILURE_IO_RESPONSE_VALID;
+      else if (sati_status == SATI_SEQUENCE_INCOMPLETE)
+      {
+         // The translation indicates that additional REQUEST SENSE command is
+         // necessary to finish the original SCSI request.  As a result,
+         // do not complete the IO and begin the next stage of the IO.
+         return SCI_WARNING_SEQUENCE_INCOMPLETE;
+      }
+      else
+      {
+         // Something unexpected occurred during translation.  Fail the
+         // IO request to the user.
+         *completion_status = SCI_FAILURE;
+      }
+   }
+   else if (*completion_status == SCI_SUCCESS &&
+        fw_request->stp.sequence.state == SATI_SEQUENCE_STATE_INCOMPLETE)
+   {
+      //The internal Request Sense command is completed successfully.
+      sati_atapi_translate_request_sense_response(
+         &fw_io->parent.stp.sequence, fw_io, fw_io
+      );
+
+      *completion_status = SCI_FAILURE_IO_RESPONSE_VALID;
+   }
+
+   return SCI_SUCCESS;
+}
+#endif // !defined(DISABLE_ATAPI)
+
+//******************************************************************************
+// P R O T E C T E D   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method will construct the SATA/STP specific IO request
+ *        object utilizing the SATI.
+ *
+ * @pre The scif_sas_request_construct() method should be invoked before
+ *      calling this method.
+ *
+ * @param[in,out] stp_io_request This parameter specifies the stp_io_request
+ *                to be constructed.
+ *
+ * @return Indicate if the construction was successful.
+ * @return SCI_FAILURE_NO_NCQ_TAG_AVAILABLE
+ * @return SCI_SUCCESS_IO_COMPLETE_BEFORE_START
+ * @return SCI_FAILURE_IO_RESPONSE_VALID
+ * @return SCI_FAILURE This return value indicates a change in the translator
+ *         where a new return code has been given, but is not yet understood
+ *         by this routine.
+ */
+SCI_STATUS scif_sas_stp_io_request_construct(
+   SCIF_SAS_IO_REQUEST_T * fw_io
+)
+{
+   SATI_STATUS                sati_status;
+   SCI_STATUS                 sci_status = SCI_FAILURE;
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device  = fw_io->parent.device;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_io),
+      SCIF_LOG_OBJECT_IO_REQUEST,
+      "scif_sas_stp_io_request_construct(0x%x) enter\n",
+      fw_io
+   ));
+
+   // The translator will indirectly invoke core methods to set the fields
+   // of the ATA register FIS inside of this method.
+   sati_status = sati_translate_command(
+                    &fw_io->parent.stp.sequence,
+                    &fw_device->protocol_device.stp_device.sati_device,
+                    fw_io,
+                    fw_io
+                 );
+
+   if (sati_status == SATI_SUCCESS)
+   {
+      // Allow the core to finish construction of the IO request.
+      sci_status = scic_io_request_construct_basic_sata(fw_io->parent.core_object);
+      fw_io->parent.state_handlers = &stp_io_request_constructed_handlers;
+      fw_io->parent.protocol_complete_handler
+         = scif_sas_stp_core_cb_io_request_complete_handler;
+   }
+   else if (sati_status == SATI_SUCCESS_SGL_TRANSLATED)
+   {
+      SCIC_IO_SATA_PARAMETERS_T parms;
+      parms.do_translate_sgl = FALSE;
+
+      // The translation actually already caused translation of the
+      // scatter gather list.  So, call into the core through an API
+      // that will not attempt to translate the SGL.
+      scic_io_request_construct_advanced_sata(
+                      fw_io->parent.core_object, &parms
+                   );
+      fw_io->parent.state_handlers = &stp_io_request_constructed_handlers;
+      fw_io->parent.protocol_complete_handler
+         = scif_sas_stp_core_cb_io_request_complete_handler;
+      // Done with translation
+      sci_status = SCI_SUCCESS;
+   }
+   else if (sati_status == SATI_COMPLETE)
+      sci_status = SCI_SUCCESS_IO_COMPLETE_BEFORE_START;
+   else if (sati_status == SATI_FAILURE_CHECK_RESPONSE_DATA)
+      sci_status = SCI_FAILURE_IO_RESPONSE_VALID;
+   else
+   {
+      SCIF_LOG_ERROR((
+         sci_base_object_get_logger(fw_io),
+         SCIF_LOG_OBJECT_IO_REQUEST,
+         "Unexpected SAT translation failure 0x%x\n",
+         fw_io
+      ));
+   }
+
+   return sci_status;
+}
+
+
+#if !defined(DISABLE_ATAPI)
+/**
+ * @brief This method will construct the STP PACKET protocol specific IO
+ *        request object.
+ *
+ * @pre The scif_sas_request_construct() method should be invoked before
+ *      calling this method.
+ *
+ * @param[in,out] fw_io This parameter specifies the stp packet io request
+ *                to be constructed.
+ *
+ * @return Indicate if the construction was successful.
+ * @return SCI_SUCCESS_IO_COMPLETE_BEFORE_START
+ * @return SCI_FAILURE_IO_RESPONSE_VALID
+ * @return SCI_FAILURE This return value indicates a change in the translator
+ *         where a new return code has been given, but is not yet understood
+ *         by this routine.
+ */
+SCI_STATUS scif_sas_stp_packet_io_request_construct(
+   SCIF_SAS_IO_REQUEST_T * fw_io
+)
+{
+   SATI_STATUS                sati_status;
+   SCI_STATUS                 sci_status = SCI_FAILURE;
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device  = fw_io->parent.device;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_io),
+      SCIF_LOG_OBJECT_IO_REQUEST,
+      "scif_sas_stp_packet_io_request_construct(0x%x) enter\n",
+      fw_io
+   ));
+
+   sati_status = sati_atapi_translate_command(
+                    &fw_io->parent.stp.sequence,
+                    &fw_device->protocol_device.stp_device.sati_device,
+                    fw_io,
+                    fw_io
+                 );
+
+   if (sati_status == SATI_SUCCESS)
+   {
+      // Allow the core to finish construction of the IO request.
+      sci_status = scic_io_request_construct_basic_sata(fw_io->parent.core_object);
+
+      fw_io->parent.protocol_complete_handler
+         = scif_sas_stp_core_cb_packet_io_request_complete_handler;
+   }
+   else if (sati_status == SATI_COMPLETE)
+      sci_status = SCI_SUCCESS_IO_COMPLETE_BEFORE_START;
+   else if (sati_status == SATI_FAILURE_CHECK_RESPONSE_DATA)
+      sci_status = SCI_FAILURE_IO_RESPONSE_VALID;
+   else
+   {
+      SCIF_LOG_ERROR((
+         sci_base_object_get_logger(fw_io),
+         SCIF_LOG_OBJECT_IO_REQUEST,
+         "Unexpected SAT ATAPI translation failure 0x%x\n",
+         fw_io
+      ));
+   }
+
+   return sci_status;
+}
+#endif
+
+
+#if !defined(DISABLE_ATAPI)
+/**
+ * @brief This method will get the number of bytes transferred in an packet IO.
+ *
+ * @param[in] fw_io This parameter specifies the stp packet io request whose
+ *                     actual transferred length is to be retrieved.
+ *
+ * @return Actual length of transferred data.
+ */
+U32 scif_sas_stp_packet_io_request_get_number_of_bytes_transferred(
+   SCIF_SAS_IO_REQUEST_T * fw_io
+)
+{
+   SCI_IO_REQUEST_HANDLE_T scic_io = scif_io_request_get_scic_handle(fw_io);
+   SCI_IO_STATUS io_status = scic_request_get_sci_status (scic_io);
+   U32 actual_data_length;
+
+   if (io_status == SCI_IO_FAILURE_RESPONSE_VALID)
+       actual_data_length = 0;
+   else if (io_status == SCI_IO_SUCCESS_IO_DONE_EARLY)
+   {
+      actual_data_length = sati_atapi_translate_number_of_bytes_transferred(
+         &fw_io->parent.stp.sequence, fw_io, fw_io);
+
+      if (actual_data_length == 0)
+         actual_data_length =
+            scic_io_request_get_number_of_bytes_transferred(scic_io);
+   }
+   else
+      actual_data_length =
+         scic_io_request_get_number_of_bytes_transferred(scic_io);
+
+   return actual_data_length;
+}
+#endif
+
+
+//******************************************************************************
+// P U B L I C   M E T H O D S
+//******************************************************************************
+
+BOOL scic_cb_io_request_do_copy_rx_frames(
+   void * scic_user_io_request
+)
+{
+   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*) scic_user_io_request;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_io),
+      SCIF_LOG_OBJECT_IO_REQUEST,
+      "scic_cb_io_request_do_copy_rx_frames(0x%x) enter\n",
+      fw_io
+   ));
+
+   // If the translation was a PIO DATA IN (i.e. read) and the request
+   // was actually a READ payload operation, then copy the data, since
+   // there will be SGL space allocated for the transfer.
+   if (fw_io->parent.stp.sequence.protocol == SAT_PROTOCOL_PIO_DATA_IN)
+   {
+      if (
+            (fw_io->parent.stp.sequence.type ==  SATI_SEQUENCE_ATA_PASSTHROUGH_12)
+         || (fw_io->parent.stp.sequence.type ==  SATI_SEQUENCE_ATA_PASSTHROUGH_16)
+         || (
+               (fw_io->parent.stp.sequence.type >= SATI_SEQUENCE_TYPE_READ_MIN)
+            && (fw_io->parent.stp.sequence.type <= SATI_SEQUENCE_TYPE_READ_MAX)
+            )
+         )
+      {
+           SCIF_LOG_TRACE((
+                 sci_base_object_get_logger(fw_io),
+                 SCIF_LOG_OBJECT_IO_REQUEST,
+                 "scic_cb_io_request_do_copy_rx_frames(0x%x) TRUE\n",
+                 fw_io
+              ));
+           return TRUE;
+      }
+   }
+
+   // For all other requests we leave the data in the core buffers.
+   // This allows the translation to translate without having to have
+   // separate space allocated into which to copy the data.
+   return FALSE;
+}
+
+// ---------------------------------------------------------------------------
+
+U8 scic_cb_request_get_sat_protocol(
+   void * scic_user_io_request
+)
+{
+   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*) scic_user_io_request;
+
+   return fw_io->parent.stp.sequence.protocol;
+}
+
+U8 *scic_cb_io_request_get_virtual_address_from_sgl(
+   void * scic_user_io_request,
+   U32    byte_offset
+)
+{
+   SCIF_SAS_REQUEST_T *fw_request =
+      (SCIF_SAS_REQUEST_T *) sci_object_get_association(scic_user_io_request);
+
+   return scif_cb_io_request_get_virtual_address_from_sgl(
+             sci_object_get_association(fw_request),
+             byte_offset
+          );
+}
+
+#ifdef ENABLE_OSSL_COPY_BUFFER
+void scic_cb_io_request_copy_buffer(
+   void * scic_user_io_request,
+   U8    *source_addr,
+   U32   offset,
+   U32   length
+)
+{
+   SCIF_SAS_REQUEST_T *fw_request =
+      (SCIF_SAS_REQUEST_T *)sci_object_get_association(scic_user_io_request);
+
+   return scif_cb_io_request_copy_buffer(
+             sci_object_get_association(fw_request),
+             source_addr,
+             offset,
+             length
+          );
+}
+#endif
+// ---------------------------------------------------------------------------
+
+SCI_BASE_REQUEST_STATE_HANDLER_T stp_io_request_constructed_handlers =
+{
+   scif_sas_stp_io_request_constructed_start_handler,
+   scif_sas_io_request_constructed_abort_handler,
+   scif_sas_stp_io_request_constructed_complete_handler,
+   scif_sas_io_request_default_destruct_handler
+};
diff --git a/sys/dev/disk/isci/scil/scif_sas_stp_io_request.h b/sys/dev/disk/isci/scil/scif_sas_stp_io_request.h
new file mode 100644
index 0000000..324dc28
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_stp_io_request.h
@@ -0,0 +1,100 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_stp_io_request.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIF_SAS_STP_IO_REQUEST_H_
+#define _SCIF_SAS_STP_IO_REQUEST_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains the protected interface structures, constants,
+ *        and methods for the SCIF_SAS_STP_IO_REQUEST object.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sati_translator_sequence.h>
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/sci_status.h>
+#include <dev/disk/isci/scil/sci_base_request.h>
+
+extern SCI_BASE_REQUEST_STATE_HANDLER_T stp_io_request_constructed_handlers;
+
+struct SCIF_SAS_IO_REQUEST;
+SCI_STATUS scif_sas_stp_io_request_construct(
+   struct SCIF_SAS_IO_REQUEST * fw_io
+);
+
+#if !defined(DISABLE_ATAPI)
+SCI_STATUS scif_sas_stp_packet_io_request_construct(
+   struct SCIF_SAS_IO_REQUEST * fw_io
+);
+#else // !defined(DISABLE_ATAPI)
+#define scif_sas_stp_packet_io_request_construct(fw_io) SCI_FAILURE
+#endif // !defined(DISABLE_ATAPI)
+
+#if !defined(DISABLE_ATAPI)
+U32 scif_sas_stp_packet_io_request_get_number_of_bytes_transferred(
+   struct SCIF_SAS_IO_REQUEST * fw_io
+);
+#else // !defined(DISABLE_ATAPI)
+#define scif_sas_stp_packet_io_request_get_number_of_bytes_transferred(fw_io) 0
+#endif // !defined(DISABLE_ATAPI)
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIF_SAS_STP_IO_REQUEST_H_
diff --git a/sys/dev/disk/isci/scil/scif_sas_stp_remote_device.c b/sys/dev/disk/isci/scil/scif_sas_stp_remote_device.c
new file mode 100644
index 0000000..fc9b5b9
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_stp_remote_device.c
@@ -0,0 +1,214 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_stp_remote_device.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains the protected interface structures, constants,
+ *        and methods for the SCIF_SAS_STP_REMOTE_DEVICE object.
+ */
+
+#include <dev/disk/isci/scil/scif_sas_stp_remote_device.h>
+#include <dev/disk/isci/scil/scif_sas_remote_device.h>
+#include <dev/disk/isci/scil/scif_sas_domain.h>
+#include <dev/disk/isci/scil/scif_sas_controller.h>
+#include <dev/disk/isci/scil/scif_sas_logger.h>
+#include <dev/disk/isci/scil/intel_sat.h>
+
+/**
+ * @brief This method performs SATA/STP specific construction of the
+ *        STP remote device object.
+ *
+ * @param[in] device This parameter specifies the STP remote device
+ *            object to be constructed.
+ *
+ * @return none
+ */
+void scif_sas_stp_remote_device_construct(
+   SCIF_SAS_REMOTE_DEVICE_T * device
+)
+{
+   sati_device_construct(
+      &device->protocol_device.stp_device.sati_device,
+      device->domain->controller->user_parameters.sas.is_sata_ncq_enabled,
+      (U8) device->domain->controller->user_parameters.sas.max_ncq_depth,
+      device->domain->controller->user_parameters.sas.ignore_fua
+   );
+
+   device->protocol_device.stp_device.s_active = 0;
+}
+
+/**
+ * @brief This method attempts to allocate a valid NCQ tag from the list
+ *        of available tags in the remote device.
+ *
+ * @todo Attempt to find a CLZ like instruction to optimize this routine
+ *       down into a few instructions.  I know there is one like it for IA.
+ *
+ * @param[in] fw_device This parameter specifies the remote device
+ *            for which to allocate an available NCQ tag.
+ *
+ * @return Return an available NCQ tag.
+ * @retval 0-31 These values indicate an available tag was successfully
+ *         allocated.
+ * @return SCIF_SAS_STP_INVALID_NCQ_TAG This value indicates that there are
+ *         no available NCQ tags.
+ */
+U8 scif_sas_stp_remote_device_allocate_ncq_tag(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device
+)
+{
+   U8  ncq_tag  = 0;
+   U32 tag_mask = 1;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_IO_REQUEST,
+      "scif_sas_stp_remote_device_allocate_ncq_tag(0x%x)\n",
+      fw_device
+   ));
+
+   // Try to find an unused NCQ tag.
+   while (  (fw_device->protocol_device.stp_device.s_active & tag_mask)
+         && (ncq_tag < fw_device->protocol_device.stp_device.sati_device.ncq_depth) )
+   {
+      tag_mask <<= 1;
+      ncq_tag++;
+   }
+
+   // Check to see if we were able to find an available NCQ tag.
+   if (ncq_tag < fw_device->protocol_device.stp_device.sati_device.ncq_depth)
+   {
+      SCIF_LOG_INFO((
+         sci_base_object_get_logger(fw_device),
+         SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_IO_REQUEST,
+         "RemoteDevice:0x%x NcqTag:0x%x successful NCQ TAG allocation\n",
+         fw_device, ncq_tag
+      ));
+
+      fw_device->protocol_device.stp_device.s_active |= tag_mask;
+      return ncq_tag;
+   }
+
+   SCIF_LOG_INFO((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_IO_REQUEST,
+      "RemoteDevice:0x%x unable to allocate NCQ TAG\n",
+      fw_device
+   ));
+
+   // All NCQ tags are in use.
+   return SCIF_SAS_INVALID_NCQ_TAG;
+}
+
+/**
+ * @brief This method removes the specified tag from the list of
+ *        outstanding tags.  It doesn't return any values.
+ *
+ * @param[in] fw_device This parameter specifies the remote device for
+ *            which to free an NCQ tag.
+ * @param[in] ncq_tag This parameter specifies the NCQ tag that is
+ *            to be freed.
+ *
+ * @return none
+ */
+void scif_sas_stp_remote_device_free_ncq_tag(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device,
+   U8                              ncq_tag
+)
+{
+   SCIF_LOG_INFO((
+      sci_base_object_get_logger(fw_device),
+      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_IO_REQUEST,
+      "RemoteDevice:0x%x NcqTag:0x%x freeing NCQ TAG\n",
+      fw_device, ncq_tag
+   ));
+
+   fw_device->protocol_device.stp_device.s_active &= ~(1 << ncq_tag);
+}
+
+struct SCIF_SAS_REQUEST *
+scif_sas_stp_remote_device_get_request_by_ncq_tag(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device,
+   U8                              ncq_tag
+)
+{
+   SCIF_SAS_DOMAIN_T                * fw_domain = fw_device->domain;
+   SCI_FAST_LIST_ELEMENT_T          * pending_request_element;
+   SCIF_SAS_REQUEST_T               * pending_request = NULL;
+   SCIF_SAS_REQUEST_T               * matching_request = NULL;
+
+   pending_request_element = fw_domain->request_list.list_head;
+
+   while (pending_request_element != NULL)
+   {
+      pending_request =
+         (SCIF_SAS_REQUEST_T*) sci_fast_list_get_object(pending_request_element);
+
+      // The current element may be deleted from the list becasue of
+      // IO completion so advance to the next element early
+      pending_request_element = sci_fast_list_get_next(pending_request_element);
+
+      if (
+            (pending_request->device == fw_device) &&
+            (pending_request->stp.sequence.protocol == SAT_PROTOCOL_FPDMA) &&
+            (pending_request->stp.ncq_tag == ncq_tag)
+         )
+      {
+         matching_request = pending_request;
+      }
+   }
+
+   return matching_request;
+}
diff --git a/sys/dev/disk/isci/scil/scif_sas_stp_remote_device.h b/sys/dev/disk/isci/scil/scif_sas_stp_remote_device.h
new file mode 100644
index 0000000..b622afb
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_stp_remote_device.h
@@ -0,0 +1,118 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_stp_remote_device.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIF_SAS_STP_REMOTE_DEVICE_H_
+#define _SCIF_SAS_STP_REMOTE_DEVICE_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains the protected interface structures, constants,
+ *        and methods for the SCIF_SAS_STP_REMOTE_DEVICE object.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sati_device.h>
+
+#define SCIF_SAS_INVALID_NCQ_TAG 0xFF
+
+/**
+ * @struct SCIF_SAS_STP_REMOTE_DEVICE
+ *
+ * @brief The SCI SAS STP Framework remote device object abstracts the SAS
+ *        SATA/STP remote device level behavior for the framework component.
+ */
+typedef struct SCIF_SAS_STP_REMOTE_DEVICE
+{
+   /**
+    * This field contains all of the data utilized by the SCSI-to-ATA
+    * Translation Implementation (SATI).
+    */
+   SATI_DEVICE_T  sati_device;
+
+   /**
+    * This field contains a list of free NCQ tags available for use in
+    * SATA Native Command Queuing (NCQ) requests.
+    */
+   U32 s_active;
+
+} SCIF_SAS_STP_REMOTE_DEVICE_T;
+
+struct SCIF_SAS_REMOTE_DEVICE;
+void scif_sas_stp_remote_device_construct(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device
+);
+
+U8 scif_sas_stp_remote_device_allocate_ncq_tag(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device
+);
+
+void scif_sas_stp_remote_device_free_ncq_tag(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device,
+   U8                              ncq_tag
+);
+
+struct SCIF_SAS_REQUEST *
+scif_sas_stp_remote_device_get_request_by_ncq_tag(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device,
+   U8                              ncq_tag
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIF_SAS_STP_REMOTE_DEVICE_H_
diff --git a/sys/dev/disk/isci/scil/scif_sas_stp_task_request.c b/sys/dev/disk/isci/scil/scif_sas_stp_task_request.c
new file mode 100644
index 0000000..8f115bb
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_stp_task_request.c
@@ -0,0 +1,264 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_stp_task_request.c,v 1.2 2012/02/09 17:50:24 jimharris Exp $
+ */
+
+#include <dev/disk/isci/scil/sati.h>
+#include <dev/disk/isci/scil/scif_sas_logger.h>
+#include <dev/disk/isci/scil/scif_sas_task_request.h>
+#include <dev/disk/isci/scil/scif_sas_controller.h>
+#include <dev/disk/isci/scil/scif_sas_remote_device.h>
+#include <dev/disk/isci/scil/scif_sas_stp_task_request.h>
+#include <dev/disk/isci/scil/scic_task_request.h>
+#include <dev/disk/isci/scil/scic_controller.h>
+
+/**
+ * @brief This method provides SATA/STP STARTED state specific handling for
+ *        when the user attempts to complete the supplied IO request.
+ *        It will perform data/response translation and free NCQ tags
+ *        if necessary.
+ *
+ * @param[in] io_request This parameter specifies the IO request object
+ *            to be started.
+ *
+ * @return This method returns a value indicating if the IO request was
+ *         successfully completed or not.
+ */
+static
+SCI_STATUS scif_sas_stp_core_cb_task_request_complete_handler(
+   SCIF_SAS_CONTROLLER_T    * fw_controller,
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   SCIF_SAS_REQUEST_T       * fw_request,
+   SCI_STATUS               * completion_status
+)
+{
+#if !defined(DISABLE_SATI_TASK_MANAGEMENT)
+   SCIF_SAS_TASK_REQUEST_T * fw_task = (SCIF_SAS_TASK_REQUEST_T *) fw_request;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_controller),
+      SCIF_LOG_OBJECT_TASK_MANAGEMENT,
+      "scif_sas_stp_core_cb_task_request_complete_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
+      fw_controller, fw_device, fw_request, *completion_status
+   ));
+
+   // Translating the response is only necessary if some sort of error
+   // occurred resulting in having the error bit set in the ATA status
+   // register and values to decode in the ATA error register.
+   if (  (*completion_status == SCI_SUCCESS)
+      || (*completion_status == SCI_FAILURE_IO_RESPONSE_VALID) )
+   {
+      SATI_STATUS sati_status = sati_translate_task_response(
+                                   &fw_task->parent.stp.sequence,
+                                   fw_task,
+                                   fw_task
+                                );
+
+      if (sati_status == SATI_COMPLETE)
+         *completion_status = SCI_SUCCESS;
+      else if (sati_status == SATI_FAILURE_CHECK_RESPONSE_DATA)
+         *completion_status = SCI_FAILURE_IO_RESPONSE_VALID;
+      else if (sati_status == SATI_SEQUENCE_INCOMPLETE)
+      {
+         // The translation indicates that additional SATA requests are
+         // necessary to finish the original SCSI request.  As a result,
+         // do not complete the IO and begin the next stage of the
+         // translation.
+         /// @todo multiple ATA commands are required, but not supported yet.
+         return SCI_FAILURE;
+      }
+      else
+      {
+         // Something unexpected occurred during translation.  Fail the
+         // IO request to the user.
+         *completion_status = SCI_FAILURE;
+      }
+   }
+   else  //A stp task request sometimes fails.
+   {
+      if (scif_sas_task_request_get_function(fw_task) == SCI_SAS_ABORT_TASK_SET)
+      {
+         scif_sas_stp_task_request_abort_task_set_failure_handler(
+            fw_device, fw_task);
+      }
+   }
+
+   return SCI_SUCCESS;
+#else // !defined(DISABLE_SATI_TASK_MANAGEMENT)
+   return SCI_FAILURE;
+#endif // !defined(DISABLE_SATI_TASK_MANAGEMENT)
+}
+
+/**
+ * @file
+ *
+ * @brief This file contains the method implementations for the
+ *        SCIF_SAS_STP_TASK_REQUEST object.  The contents will implement
+ *        SATA/STP specific functionality.
+ */
+SCI_STATUS scif_sas_stp_task_request_construct(
+   SCIF_SAS_TASK_REQUEST_T * fw_task
+)
+{
+   SCI_STATUS                 sci_status = SCI_FAILURE;
+
+#if !defined(DISABLE_SATI_TASK_MANAGEMENT)
+   SATI_STATUS                sati_status;
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device  = fw_task->parent.device;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_task),
+      SCIF_LOG_OBJECT_TASK_MANAGEMENT,
+      "scif_sas_stp_task_request_construct(0x%x) enter\n",
+      fw_task
+   ));
+
+   // The translator will indirectly invoke core methods to set the fields
+   // of the ATA register FIS inside of this method.
+   sati_status = sati_translate_task_management(
+                    &fw_task->parent.stp.sequence,
+                    &fw_device->protocol_device.stp_device.sati_device,
+                    fw_task,
+                    fw_task
+                 );
+
+   if (sati_status == SATI_SUCCESS)
+   {
+      sci_status = scic_task_request_construct_sata(fw_task->parent.core_object);
+      //fw_task->parent.state_handlers = &stp_io_request_constructed_handlers;
+      fw_task->parent.protocol_complete_handler =
+         scif_sas_stp_core_cb_task_request_complete_handler;
+   }
+   else
+   {
+      SCIF_LOG_ERROR((
+         sci_base_object_get_logger(fw_task),
+         SCIF_LOG_OBJECT_TASK_MANAGEMENT,
+         "Task 0x%x received unexpected SAT translation failure 0x%x\n",
+         fw_task, sati_status
+      ));
+   }
+#endif // !defined(DISABLE_SATI_TASK_MANAGEMENT)
+
+   return sci_status;
+}
+
+
+/**
+ * @brief This method provides handling for failed stp TASK MANAGEMENT
+ *           request.
+ *
+ * @param[in] fw_device This parameter specifies the target device the
+ *            task management request towards to.
+ * @param[in] fw_request This parameter specifies the failed task management
+ *            request.
+ * @param[in] completion_status This parameter sprecifies the completion
+ *            status of the task management request's core status.
+ *
+ * @return None.
+ */
+void scif_sas_stp_task_request_abort_task_set_failure_handler(
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
+   SCIF_SAS_TASK_REQUEST_T  * fw_task
+)
+{
+#if !defined(DISABLE_SATI_TASK_MANAGEMENT)
+   SCIF_SAS_DOMAIN_T         * fw_domain = fw_device->domain;
+   SCI_FAST_LIST_ELEMENT_T   * pending_request_element;
+   SCIF_SAS_REQUEST_T        * pending_request = NULL;
+
+   pending_request_element = fw_domain->request_list.list_head;
+
+   // Cycle through the list of IO requests. search all the
+   // outstanding IOs with "waiting for abort task set" flag,
+   // completes them now.
+   while (pending_request_element != NULL)
+   {
+      pending_request =
+         (SCIF_SAS_REQUEST_T*) sci_fast_list_get_object(pending_request_element);
+
+      // The current element may be deleted from the list becasue of
+      // IO completion so advance to the next element early
+      pending_request_element = sci_fast_list_get_next(pending_request_element);
+
+      if ( pending_request->device == fw_device
+           && pending_request->is_waiting_for_abort_task_set == TRUE )
+      {
+         //In case the pending_request is still in the middle of aborting.
+         //abort it again to the core.
+         SCI_STATUS abort_status;
+
+         //Reset the flag now since we are process the read log ext command now.
+         pending_request->is_waiting_for_abort_task_set = FALSE;
+
+         abort_status = scic_controller_terminate_request(
+                           fw_domain->controller->core_object,
+                           fw_device->core_object,
+                           pending_request->core_object
+                        );
+
+         if (abort_status == SCI_FAILURE_INVALID_STATE)
+         {
+            //the request must have not be in aborting state anymore, complete it now.
+            scif_cb_io_request_complete(
+               fw_domain->controller,
+               fw_device,
+               pending_request,
+               SCI_IO_FAILURE_TERMINATED
+            );
+         }
+         //otherwise, the abort succeeded. Since the waiting flag is cleared,
+         //the pending request will be completed later.
+      }
+   }
+#endif //#if !defined(DISABLE_SATI_TASK_MANAGEMENT)
+}
diff --git a/sys/dev/disk/isci/scil/scif_sas_stp_task_request.h b/sys/dev/disk/isci/scil/scif_sas_stp_task_request.h
new file mode 100644
index 0000000..dd1e0fa
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_stp_task_request.h
@@ -0,0 +1,105 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_stp_task_request.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIF_SAS_STP_TASK_REQUEST_H_
+#define _SCIF_SAS_STP_TASK_REQUEST_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains the protected interface structures, constants,
+ *        and methods for the SCIF_SAS_STP_TASK_REQUEST object.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sati_translator_sequence.h>
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/sci_status.h>
+
+/**
+ * @struct SCIF_SAS_STP_TASK_REQUEST
+ *
+ * @brief This structure contains all of the data specific to performing
+ *        SATA/STP IO requests.
+ */
+typedef struct SCIF_SAS_STP_TASK_REQUEST
+{
+   /**
+    * This field contains the translation information utilized by SATI.
+    * For more information on this field please refer to
+    * SATI_TRANSLATOR_SEQUENCE.
+    */
+   SATI_TRANSLATOR_SEQUENCE_T  sequence;
+
+} SCIF_SAS_STP_TASK_REQUEST_T;
+
+//extern SCI_BASE_REQUEST_STATE_HANDLER_T stp_io_request_constructed_handlers;
+
+struct SCIF_SAS_TASK_REQUEST;
+SCI_STATUS scif_sas_stp_task_request_construct(
+   struct SCIF_SAS_TASK_REQUEST * fw_task
+);
+
+void scif_sas_stp_task_request_abort_task_set_failure_handler(
+   struct SCIF_SAS_REMOTE_DEVICE * fw_device,
+   struct SCIF_SAS_TASK_REQUEST  * fw_task
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIF_SAS_STP_TASK_REQUEST_H_
diff --git a/sys/dev/disk/isci/scil/scif_sas_task_request.c b/sys/dev/disk/isci/scil/scif_sas_task_request.c
new file mode 100644
index 0000000..3783f5a
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_task_request.c
@@ -0,0 +1,479 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_task_request.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains the task management request object
+ *        (SCIF_SAS_TASK_REQUEST) method implementations.
+ */
+
+
+#include <dev/disk/isci/scil/intel_sas.h>
+
+#include <dev/disk/isci/scil/scic_task_request.h>
+#include <dev/disk/isci/scil/scic_remote_device.h>
+#include <dev/disk/isci/scil/scic_user_callback.h>
+#include <dev/disk/isci/scil/scic_controller.h>
+#include <dev/disk/isci/scil/scif_user_callback.h>
+
+#include <dev/disk/isci/scil/scif_sas_request.h>
+#include <dev/disk/isci/scil/scif_sas_task_request.h>
+#include <dev/disk/isci/scil/scif_sas_stp_task_request.h>
+#include <dev/disk/isci/scil/scif_sas_logger.h>
+#include <dev/disk/isci/scil/scif_sas_controller.h>
+#include <dev/disk/isci/scil/scif_sas_domain.h>
+#include <dev/disk/isci/scil/scif_sas_remote_device.h>
+#include <dev/disk/isci/scil/scif_sas_smp_io_request.h>
+
+//******************************************************************************
+//* P U B L I C   M E T H O D S
+//******************************************************************************
+
+U32 scif_task_request_get_object_size(
+   void
+)
+{
+   return (sizeof(SCIF_SAS_TASK_REQUEST_T) + scic_task_request_get_object_size());
+}
+
+// ---------------------------------------------------------------------------
+
+U8 scif_sas_task_request_get_function(
+   SCIF_SAS_TASK_REQUEST_T *fw_task
+)
+{
+   return fw_task->function;
+}
+
+// ---------------------------------------------------------------------------
+
+static
+SCI_STATUS scif_sas_task_request_generic_construct(
+   SCI_CONTROLLER_HANDLE_T      scif_controller,
+   SCI_REMOTE_DEVICE_HANDLE_T   scif_remote_device,
+   U16                          io_tag,
+   void                       * user_task_request_object,
+   void                       * task_request_memory,
+   SCI_TASK_REQUEST_HANDLE_T  * scif_task_request,
+   U8                           task_function
+)
+{
+   SCI_STATUS                 status;
+   SCIF_SAS_CONTROLLER_T    * fw_controller   = (SCIF_SAS_CONTROLLER_T*)
+                                                scif_controller;
+   SCIF_SAS_TASK_REQUEST_T  * fw_task         = (SCIF_SAS_TASK_REQUEST_T*)
+                                                task_request_memory;
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device       = (SCIF_SAS_REMOTE_DEVICE_T*)
+                                                scif_remote_device;
+   U8                       * core_request_memory;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_controller),
+      SCIF_LOG_OBJECT_TASK_MANAGEMENT,
+      "scif_task_request_construct(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x) enter\n",
+      scif_controller, scif_remote_device, io_tag, user_task_request_object,
+      task_request_memory, scif_task_request
+   ));
+
+   // Initialize the user's handle to the framework task request.
+   *scif_task_request = fw_task;
+
+   // initialize affected request count
+   fw_task->affected_request_count = 0;
+   fw_task->io_tag_to_manage = SCI_CONTROLLER_INVALID_IO_TAG;
+   fw_task->function = task_function;
+
+   if (task_function == SCI_SAS_HARD_RESET )
+   {
+      if (fw_device->containing_device != NULL )
+      {// Target Reset is for an expander attached device,
+       // go down to construct smp Phy Control request.
+         scif_sas_smp_request_construct_phy_control(
+            fw_controller,
+            fw_device->containing_device,
+            PHY_OPERATION_HARD_RESET,
+            fw_device->expander_phy_identifier,
+            user_task_request_object,
+            task_request_memory
+         );
+      }
+      else
+      {
+         scif_sas_request_construct(
+            &fw_task->parent,
+            fw_device,
+            sci_base_object_get_logger(fw_controller),
+            scif_sas_task_request_state_table
+         );
+
+         // If target reset is for a DA device, don't build task at all.
+         // Just set object association.
+         sci_object_set_association(fw_task, user_task_request_object);
+      }
+
+      return SCI_SUCCESS;
+   }
+
+   // Construct the parent object first in order to ensure logging can
+   // function.
+   scif_sas_request_construct(
+      &fw_task->parent,
+      fw_device,
+      sci_base_object_get_logger(fw_controller),
+      scif_sas_task_request_state_table
+   );
+
+   core_request_memory = (U8 *)task_request_memory + sizeof(SCIF_SAS_TASK_REQUEST_T);
+
+   status = scic_task_request_construct(
+               fw_controller->core_object,
+               fw_device->core_object,
+               io_tag,
+               fw_task,
+               core_request_memory,
+               &fw_task->parent.core_object
+            );
+
+   if (status == SCI_SUCCESS)
+   {
+      SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;
+
+      // These associations must be set early for the core io request
+      // object construction to complete correctly as there will be
+      // callbacks into the user driver framework during core construction
+      sci_object_set_association(fw_task, user_task_request_object);
+      sci_object_set_association(fw_task->parent.core_object, fw_task);
+
+      // Perform protocol specific core IO request construction.
+      scic_remote_device_get_protocols(fw_device->core_object, &dev_protocols);
+      if (dev_protocols.u.bits.attached_ssp_target)
+         status = scic_task_request_construct_ssp(fw_task->parent.core_object);
+      else if (dev_protocols.u.bits.attached_stp_target)
+         status = scif_sas_stp_task_request_construct(fw_task);
+      else
+         status = SCI_FAILURE_UNSUPPORTED_PROTOCOL;
+
+      if (status == SCI_SUCCESS)
+      {
+         sci_base_state_machine_logger_initialize(
+            &fw_task->parent.parent.state_machine_logger,
+            &fw_task->parent.parent.state_machine,
+            &fw_task->parent.parent.parent,
+            scif_cb_logger_log_states,
+            "SCIF_SAS_TASK_REQUEST_T", "base_state_machine",
+            SCIF_LOG_OBJECT_TASK_MANAGEMENT
+         );
+      }
+      else
+      {
+         SCIF_LOG_WARNING((
+            sci_base_object_get_logger(fw_task),
+            SCIF_LOG_OBJECT_TASK_MANAGEMENT,
+            "Device:0x%x TaskRequest:0x%x Function:0x%x construct failed\n",
+            fw_device, fw_task, scif_sas_task_request_get_function(fw_task)
+         ));
+      }
+   }
+
+   return status;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scif_sas_internal_task_request_construct(
+   SCI_CONTROLLER_HANDLE_T      scif_controller,
+   SCI_REMOTE_DEVICE_HANDLE_T   scif_remote_device,
+   U16                          io_tag,
+   void                       * task_request_memory,
+   SCI_TASK_REQUEST_HANDLE_T  * scif_task_request,
+   U8                           task_function
+)
+{
+   SCI_STATUS                 status;
+   SCIF_SAS_TASK_REQUEST_T *  fw_task;
+
+   status = scif_sas_task_request_generic_construct(
+               scif_controller,
+               scif_remote_device,
+               io_tag,
+               NULL,
+               task_request_memory,
+               scif_task_request,
+               task_function
+            );
+
+   fw_task = (SCIF_SAS_TASK_REQUEST_T *)task_request_memory;
+
+   fw_task->parent.is_internal = TRUE;
+
+   return status;
+}
+
+// ---------------------------------------------------------------------------
+
+SCI_STATUS scif_task_request_construct(
+   SCI_CONTROLLER_HANDLE_T      scif_controller,
+   SCI_REMOTE_DEVICE_HANDLE_T   scif_remote_device,
+   U16                          io_tag,
+   void                       * user_task_request_object,
+   void                       * task_request_memory,
+   SCI_TASK_REQUEST_HANDLE_T  * scif_task_request
+)
+{
+   SCI_STATUS  status;
+   U8          task_function =
+                scif_cb_task_request_get_function(user_task_request_object);
+
+   status = scif_sas_task_request_generic_construct(
+               scif_controller,
+               scif_remote_device,
+               io_tag,
+               user_task_request_object,
+               task_request_memory,
+               scif_task_request,
+               task_function
+            );
+
+   return status;
+}
+
+// ---------------------------------------------------------------------------
+
+void scif_sas_internal_task_request_destruct(
+   SCIF_SAS_TASK_REQUEST_T * fw_internal_task
+)
+{
+   SCIF_SAS_CONTROLLER_T * fw_controller =
+      fw_internal_task->parent.device->domain->controller;
+   scif_sas_controller_free_internal_request(fw_controller, fw_internal_task);
+}
+
+// ---------------------------------------------------------------------------
+
+void scic_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_SAS_CONTROLLER_T    * fw_controller = (SCIF_SAS_CONTROLLER_T*)
+                                         sci_object_get_association(controller);
+   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
+                                      sci_object_get_association(remote_device);
+   SCIF_SAS_TASK_REQUEST_T  * fw_task = (SCIF_SAS_TASK_REQUEST_T*)
+                                       sci_object_get_association(task_request);
+   SCI_STATUS                 status;
+
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_controller),
+      SCIF_LOG_OBJECT_TASK_MANAGEMENT,
+      "scic_cb_task_request_complete(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
+      controller, remote_device, task_request, completion_status
+   ));
+
+   status = fw_task->parent.state_handlers->complete_handler(
+               &fw_task->parent.parent
+            );
+
+   if (status == SCI_SUCCESS)
+   {
+      if (fw_task->parent.protocol_complete_handler != NULL)
+      {
+         status = fw_task->parent.protocol_complete_handler(
+            fw_controller, fw_device, &fw_task->parent, (SCI_STATUS *)&completion_status
+         );
+      }
+
+      if (status == SCI_SUCCESS)
+      {
+         SCIF_LOG_WARNING((
+            sci_base_object_get_logger(fw_task),
+            SCIF_LOG_OBJECT_TASK_MANAGEMENT,
+            "RemoteDevice:0x%x TaskRequest:0x%x Function:0x%x CompletionStatus:0x%x "
+            "completed\n",
+            fw_device, fw_task,
+            scif_sas_task_request_get_function(fw_task),
+            completion_status
+         ));
+
+         // If this isn't an internal framework IO request, then simply pass the
+         // notification up to the SCIF user.  Otherwise, immediately complete the
+         // task since there is no SCIF user to notify.
+         if (fw_task->parent.is_internal == FALSE)
+         {
+            scif_cb_task_request_complete(
+               fw_controller, fw_device, fw_task, completion_status
+            );
+         }
+         else
+         {
+            scif_controller_complete_task(
+               fw_controller,
+               fw_device,
+               fw_task
+            );
+         }
+      }
+   }
+}
+
+// ---------------------------------------------------------------------------
+
+U32 scic_cb_ssp_task_request_get_lun(
+   void * scic_user_task_request
+)
+{
+   SCIF_SAS_TASK_REQUEST_T * fw_task = (SCIF_SAS_TASK_REQUEST_T*)
+                                       scic_user_task_request;
+
+   fw_task->parent.lun = scif_cb_task_request_get_lun(
+                            fw_task->parent.parent.parent.associated_object
+                         );
+
+   return fw_task->parent.lun;
+}
+
+// ---------------------------------------------------------------------------
+
+U8 scic_cb_ssp_task_request_get_function(
+   void * scic_user_task_request
+)
+{
+   SCIF_SAS_TASK_REQUEST_T * fw_task = (SCIF_SAS_TASK_REQUEST_T*)
+                                       scic_user_task_request;
+
+   return scif_sas_task_request_get_function(fw_task);
+}
+
+// ---------------------------------------------------------------------------
+
+U16 scic_cb_ssp_task_request_get_io_tag_to_manage(
+   void * scic_user_task_request
+)
+{
+   SCIF_SAS_TASK_REQUEST_T * fw_task = (SCIF_SAS_TASK_REQUEST_T*)
+                                       scic_user_task_request;
+
+   fw_task->io_tag_to_manage
+      = scif_cb_task_request_get_io_tag_to_manage(
+           fw_task->parent.parent.parent.associated_object
+        );
+
+   return fw_task->io_tag_to_manage;
+}
+
+// ---------------------------------------------------------------------------
+
+void * scic_cb_ssp_task_request_get_response_data_address(
+   void * scic_user_task_request
+)
+{
+   SCIF_SAS_TASK_REQUEST_T * fw_task = (SCIF_SAS_TASK_REQUEST_T*)
+                                       scic_user_task_request;
+
+   return scif_cb_task_request_get_response_data_address(
+                fw_task->parent.parent.parent.associated_object
+          );
+}
+
+// ---------------------------------------------------------------------------
+
+U32 scic_cb_ssp_task_request_get_response_data_length(
+   void * scic_user_task_request
+)
+{
+   SCIF_SAS_TASK_REQUEST_T * fw_task = (SCIF_SAS_TASK_REQUEST_T*)
+                                       scic_user_task_request;
+
+   return scif_cb_task_request_get_response_data_length(
+             fw_task->parent.parent.parent.associated_object
+          );
+}
+
+//******************************************************************************
+//* P R O T E C T E D   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method performs functionality required after a task management
+ *        operation (either a task management request or a silicon task
+ *        termination) has finished.
+ *
+ * @param[in]  fw_task This parameter specifies the request that has
+ *             the operation completing.
+ *
+ * @return none
+ */
+void scif_sas_task_request_operation_complete(
+   SCIF_SAS_TASK_REQUEST_T * fw_task
+)
+{
+   SCIF_LOG_TRACE((
+      sci_base_object_get_logger(fw_task),
+      SCIF_LOG_OBJECT_TASK_MANAGEMENT,
+      "scif_sas_task_request_operation_complete(0x%x) enter\n",
+      fw_task
+   ));
+
+   fw_task->affected_request_count--;
+
+   SCIF_LOG_INFO((
+      sci_base_object_get_logger(fw_task),
+      SCIF_LOG_OBJECT_TASK_MANAGEMENT,
+      "TaskRequest:0x%x current affected request count:0x%x\n",
+      fw_task, fw_task->affected_request_count
+   ));
+}
diff --git a/sys/dev/disk/isci/scil/scif_sas_task_request.h b/sys/dev/disk/isci/scil/scif_sas_task_request.h
new file mode 100644
index 0000000..3722fb3
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_task_request.h
@@ -0,0 +1,142 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_task_request.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIF_SAS_TASK_REQUEST_H_
+#define _SCIF_SAS_TASK_REQUEST_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains the protected interface structures, constants,
+ *        and methods for the SCIF_SAS_TASK_REQUEST object.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sati_translator_sequence.h>
+#include <dev/disk/isci/scil/scif_task_request.h>
+#include <dev/disk/isci/scil/sci_base_request.h>
+#include <dev/disk/isci/scil/scif_sas_request.h>
+#include <dev/disk/isci/scil/scif_sas_internal_io_request.h>
+#include <dev/disk/isci/scil/intel_sas.h>
+
+/**
+ * @struct SCIF_SAS_TASK_REQUEST
+ *
+ * @brief The SCI SAS Framework Task request object abstracts the SAS task
+ *        management behavior for the framework component.  Additionally,
+ *        it provides a higher level of abstraction for the core task
+ *        request object.
+ */
+typedef struct SCIF_SAS_TASK_REQUEST
+{
+   /**
+    * The SCIF_SAS_REQUEST is the parent object for the
+    * SCIF_SAS_TASK_REQUEST object.
+    */
+   SCIF_SAS_REQUEST_T  parent;
+
+   /**
+    * This field contains the number of current requests affected by
+    * this task management request.  This number indicates all of the
+    * requests terminated in the silicon (including previous task requests).
+    */
+   U16  affected_request_count;
+
+   /**
+    * This field specifies the tag for the IO request or the tag to be
+    * managed for a task management request.
+    * This field is utilized during internal IO requests.
+    */
+   U16  io_tag_to_manage;
+
+   /**
+    * This field will be utilized to specify the task management function
+    * of this task request.
+    */
+   SCI_SAS_TASK_MGMT_FUNCTION_T function;
+
+} SCIF_SAS_TASK_REQUEST_T;
+
+extern SCI_BASE_STATE_T scif_sas_task_request_state_table[];
+extern SCI_BASE_REQUEST_STATE_HANDLER_T
+   scif_sas_task_request_state_handler_table[];
+
+void scif_sas_task_request_operation_complete(
+   SCIF_SAS_TASK_REQUEST_T * fw_task
+);
+
+U8 scif_sas_task_request_get_function(
+   SCIF_SAS_TASK_REQUEST_T * fw_task
+);
+
+SCI_STATUS scif_sas_internal_task_request_construct(
+   SCI_CONTROLLER_HANDLE_T      scif_controller,
+   SCI_REMOTE_DEVICE_HANDLE_T   scif_remote_device,
+   U16                          io_tag,
+   void                       * task_request_memory,
+   SCI_TASK_REQUEST_HANDLE_T  * scif_task_request,
+   U8                           task_function
+);
+
+void scif_sas_internal_task_request_destruct(
+   SCIF_SAS_TASK_REQUEST_T * fw_internal_task
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIF_SAS_TASK_REQUEST_H_
diff --git a/sys/dev/disk/isci/scil/scif_sas_task_request_state_handlers.c b/sys/dev/disk/isci/scil/scif_sas_task_request_state_handlers.c
new file mode 100644
index 0000000..b8b86ca
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_task_request_state_handlers.c
@@ -0,0 +1,402 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_task_request_state_handlers.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the method implementations pertaining
+ *        to the framework io request state handler methods.
+ */
+
+#include <dev/disk/isci/scil/scif_sas_logger.h>
+#include <dev/disk/isci/scil/scif_sas_task_request.h>
+
+//******************************************************************************
+//* C O N S T R U C T E D   H A N D L E R S
+//******************************************************************************
+
+/**
+ * @brief This method provides CONSTRUCTED state specific handling for
+ *        when the user attempts to start the supplied task request.
+ *
+ * @param[in] task_request This parameter specifies the task request object
+ *            to be started.
+ *
+ * @return This method returns a value indicating if the task request was
+ *         successfully started or not.
+ * @retval SCI_SUCCESS This return value indicates successful starting
+ *         of the task request.
+ */
+static
+SCI_STATUS scif_sas_task_request_constructed_start_handler(
+   SCI_BASE_REQUEST_T * task_request
+)
+{
+   sci_base_state_machine_change_state(
+      &task_request->state_machine, SCI_BASE_REQUEST_STATE_STARTED
+   );
+
+   return SCI_SUCCESS;
+}
+
+/**
+ * @brief This method provides CONSTRUCTED state specific handling for
+ *        when the user attempts to abort the supplied task request.
+ *
+ * @param[in] task_request This parameter specifies the task request object
+ *            to be aborted.
+ *
+ * @return This method returns a value indicating if the task request was
+ *         successfully aborted or not.
+ * @retval SCI_SUCCESS This return value indicates successful aborting
+ *         of the task request.
+ */
+static
+SCI_STATUS scif_sas_task_request_constructed_abort_handler(
+   SCI_BASE_REQUEST_T * task_request
+)
+{
+   sci_base_state_machine_change_state(
+      &task_request->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED
+   );
+
+   return SCI_SUCCESS;
+}
+
+//******************************************************************************
+//* S T A R T E D   H A N D L E R S
+//******************************************************************************
+
+/**
+ * @brief This method provides STARTED state specific handling for
+ *        when the user attempts to abort the supplied task request.
+ *
+ * @param[in] task_request This parameter specifies the task request object
+ *            to be aborted.
+ *
+ * @return This method returns a value indicating if the aborting the
+ *         task request was successfully started.
+ * @retval SCI_SUCCESS This return value indicates that the abort process
+ *         began successfully.
+ */
+static
+SCI_STATUS scif_sas_task_request_started_abort_handler(
+   SCI_BASE_REQUEST_T * task_request
+)
+{
+   SCIF_SAS_REQUEST_T * fw_request = (SCIF_SAS_REQUEST_T *) task_request;
+
+   sci_base_state_machine_change_state(
+      &task_request->state_machine, SCI_BASE_REQUEST_STATE_ABORTING
+   );
+
+   return fw_request->status;
+}
+
+/**
+ * @brief This method provides STARTED state specific handling for
+ *        when the user attempts to complete the supplied task request.
+ *
+ * @param[in] task_request This parameter specifies the task request object
+ *            to be completed.
+ *
+ * @return This method returns a value indicating if the completion of the
+ *         task request was successful.
+ * @retval SCI_SUCCESS This return value indicates that the completion process
+ *         was successful.
+ */
+static
+SCI_STATUS scif_sas_task_request_started_complete_handler(
+   SCI_BASE_REQUEST_T * task_request
+)
+{
+   sci_base_state_machine_change_state(
+      &task_request->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED
+   );
+
+   return SCI_SUCCESS;
+}
+
+//******************************************************************************
+//* C O M P L E T E D   H A N D L E R S
+//******************************************************************************
+
+/**
+ * @brief This method provides COMPLETED state specific handling for
+ *        when the user attempts to destruct the supplied task request.
+ *
+ * @param[in] task_request This parameter specifies the task request object
+ *            to be destructed.
+ *
+ * @return This method returns a value indicating if the destruct
+ *         operation was successful.
+ * @retval SCI_SUCCESS This return value indicates that the destruct
+ *         was successful.
+ */
+static
+SCI_STATUS scif_sas_task_request_completed_destruct_handler(
+   SCI_BASE_REQUEST_T * task_request
+)
+{
+   SCIF_SAS_REQUEST_T * fw_request = (SCIF_SAS_REQUEST_T *)task_request;
+
+   sci_base_state_machine_change_state(
+      &task_request->state_machine, SCI_BASE_REQUEST_STATE_FINAL
+   );
+
+   sci_base_state_machine_logger_deinitialize(
+      &task_request->state_machine_logger,
+      &task_request->state_machine
+   );
+
+   if (fw_request->is_internal == TRUE)
+   {
+      scif_sas_internal_task_request_destruct(
+         (SCIF_SAS_TASK_REQUEST_T *)fw_request
+      );
+   }
+
+   return SCI_SUCCESS;
+}
+
+//******************************************************************************
+//* A B O R T I N G   H A N D L E R S
+//******************************************************************************
+
+/**
+ * @brief This method provides ABORTING state specific handling for
+ *        when the user attempts to complete the supplied task request.
+ *
+ * @param[in] task_request This parameter specifies the task request object
+ *            to be completed.
+ *
+ * @return This method returns a value indicating if the completion
+ *         operation was successful.
+ * @retval SCI_SUCCESS This return value indicates that the completion
+ *         was successful.
+ */
+static
+SCI_STATUS scif_sas_task_request_aborting_complete_handler(
+   SCI_BASE_REQUEST_T * task_request
+)
+{
+   sci_base_state_machine_change_state(
+      &task_request->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED
+   );
+
+   return SCI_SUCCESS;
+}
+
+//******************************************************************************
+//* D E F A U L T   H A N D L E R S
+//******************************************************************************
+
+/**
+ * @brief This method provides DEFAULT handling for when the user
+ *        attempts to start the supplied task request.
+ *
+ * @param[in] task_request This parameter specifies the task request object
+ *            to be started.
+ *
+ * @return This method returns an indication that the start operation is
+ *         not allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+static
+SCI_STATUS scif_sas_task_request_default_start_handler(
+   SCI_BASE_REQUEST_T * task_request
+)
+{
+   SCIF_LOG_ERROR((
+      sci_base_object_get_logger((SCIF_SAS_TASK_REQUEST_T *) task_request),
+      SCIF_LOG_OBJECT_TASK_MANAGEMENT,
+      "TaskRequest:0x%x State:0x%x invalid state to start\n",
+      task_request,
+      sci_base_state_machine_get_state(
+         &((SCIF_SAS_TASK_REQUEST_T *) task_request)->parent.parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * @brief This method provides DEFAULT handling for when the user
+ *        attempts to abort the supplied task request.
+ *
+ * @param[in] task_request This parameter specifies the task request object
+ *            to be aborted.
+ *
+ * @return This method returns an indication that the abort operation is
+ *         not allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+static
+SCI_STATUS scif_sas_task_request_default_abort_handler(
+   SCI_BASE_REQUEST_T * task_request
+)
+{
+   SCIF_LOG_ERROR((
+      sci_base_object_get_logger((SCIF_SAS_TASK_REQUEST_T *) task_request),
+      SCIF_LOG_OBJECT_TASK_MANAGEMENT,
+      "TaskRequest:0x%x State:0x%x invalid state to abort\n",
+      task_request,
+      sci_base_state_machine_get_state(
+         &((SCIF_SAS_TASK_REQUEST_T *) task_request)->parent.parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * @brief This method provides DEFAULT handling for when the user
+ *        attempts to complete the supplied task request.
+ *
+ * @param[in] task_request This parameter specifies the task request object
+ *            to be completed.
+ *
+ * @return This method returns an indication that complete operation is
+ *         not allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+static
+SCI_STATUS scif_sas_task_request_default_complete_handler(
+   SCI_BASE_REQUEST_T * task_request
+)
+{
+   SCIF_LOG_ERROR((
+      sci_base_object_get_logger((SCIF_SAS_TASK_REQUEST_T *) task_request),
+      SCIF_LOG_OBJECT_TASK_MANAGEMENT,
+      "TaskRequest:0x%x State:0x%x invalid state to complete\n",
+      task_request,
+      sci_base_state_machine_get_state(
+         &((SCIF_SAS_TASK_REQUEST_T *) task_request)->parent.parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+/**
+ * @brief This method provides DEFAULT handling for when the user
+ *        attempts to destruct the supplied task request.
+ *
+ * @param[in] task_request This parameter specifies the task request object
+ *            to be destructed.
+ *
+ * @return This method returns an indication that destruct operation is
+ *         not allowed.
+ * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
+ */
+static
+SCI_STATUS scif_sas_task_request_default_destruct_handler(
+   SCI_BASE_REQUEST_T * task_request
+)
+{
+   SCIF_LOG_ERROR((
+      sci_base_object_get_logger((SCIF_SAS_TASK_REQUEST_T *) task_request),
+      SCIF_LOG_OBJECT_TASK_MANAGEMENT,
+      "TaskRequest:0x%x State:0x%x invalid state to destruct.\n",
+      task_request,
+      sci_base_state_machine_get_state(
+         &((SCIF_SAS_TASK_REQUEST_T *) task_request)->parent.parent.state_machine)
+   ));
+
+   return SCI_FAILURE_INVALID_STATE;
+}
+
+
+SCI_BASE_REQUEST_STATE_HANDLER_T scif_sas_task_request_state_handler_table[] =
+{
+   // SCI_BASE_REQUEST_STATE_INITIAL
+   {
+      scif_sas_task_request_default_start_handler,
+      scif_sas_task_request_default_abort_handler,
+      scif_sas_task_request_default_complete_handler,
+      scif_sas_task_request_default_destruct_handler
+   },
+   // SCI_BASE_REQUEST_STATE_CONSTRUCTED
+   {
+      scif_sas_task_request_constructed_start_handler,
+      scif_sas_task_request_constructed_abort_handler,
+      scif_sas_task_request_default_complete_handler,
+      scif_sas_task_request_default_destruct_handler
+   },
+   // SCI_BASE_REQUEST_STATE_STARTED
+   {
+      scif_sas_task_request_default_start_handler,
+      scif_sas_task_request_started_abort_handler,
+      scif_sas_task_request_started_complete_handler,
+      scif_sas_task_request_default_destruct_handler
+   },
+   // SCI_BASE_REQUEST_STATE_COMPLETED
+   {
+      scif_sas_task_request_default_start_handler,
+      scif_sas_task_request_default_abort_handler,
+      scif_sas_task_request_default_complete_handler,
+      scif_sas_task_request_completed_destruct_handler
+   },
+   // SCI_BASE_REQUEST_STATE_ABORTING
+   {
+      scif_sas_task_request_default_start_handler,
+      scif_sas_task_request_default_abort_handler,
+      scif_sas_task_request_aborting_complete_handler,
+      scif_sas_task_request_default_destruct_handler
+   },
+   // SCI_BASE_REQUEST_STATE_FINAL
+   {
+      scif_sas_task_request_default_start_handler,
+      scif_sas_task_request_default_abort_handler,
+      scif_sas_task_request_default_complete_handler,
+      scif_sas_task_request_default_destruct_handler
+   },
+};
diff --git a/sys/dev/disk/isci/scil/scif_sas_task_request_states.c b/sys/dev/disk/isci/scil/scif_sas_task_request_states.c
new file mode 100644
index 0000000..f5e20a2
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_task_request_states.c
@@ -0,0 +1,285 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_sas_task_request_states.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the SCIF_SAS_TASK_REQUEST object
+ *        state entrance and exit method implementations.
+ */
+
+#include <dev/disk/isci/scil/scif_sas_task_request.h>
+
+//******************************************************************************
+//* P R O T E C T E D   M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        INITIAL state.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_TASK_REQUEST object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_task_request_initial_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIF_SAS_TASK_REQUEST_T * fw_task = (SCIF_SAS_TASK_REQUEST_T *)object;
+
+   SET_STATE_HANDLER(
+      &fw_task->parent,
+      scif_sas_task_request_state_handler_table,
+      SCI_BASE_REQUEST_STATE_INITIAL
+   );
+
+   // Initial state is a transitional state to the constructed state
+   sci_base_state_machine_change_state(
+      &fw_task->parent.parent.state_machine, SCI_BASE_REQUEST_STATE_CONSTRUCTED
+   );
+}
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        CONSTRUCTED state.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_TASK_REQUEST object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_task_request_constructed_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIF_SAS_TASK_REQUEST_T * fw_task = (SCIF_SAS_TASK_REQUEST_T *)object;
+
+   SET_STATE_HANDLER(
+      &fw_task->parent,
+      scif_sas_task_request_state_handler_table,
+      SCI_BASE_REQUEST_STATE_CONSTRUCTED
+   );
+}
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        STARTED state.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_TASK_REQUEST object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_task_request_started_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIF_SAS_TASK_REQUEST_T * fw_task = (SCIF_SAS_TASK_REQUEST_T *)object;
+
+   SET_STATE_HANDLER(
+      &fw_task->parent,
+      scif_sas_task_request_state_handler_table,
+      SCI_BASE_REQUEST_STATE_STARTED
+   );
+
+   // Increment the affected request count to include the task performing
+   // the task management to ensure we don't complete the task request until
+   // all terminations and the task itself have completed.
+   fw_task->affected_request_count++;
+}
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        COMPLETED state.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_TASK_REQUEST object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_task_request_completed_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIF_SAS_TASK_REQUEST_T * fw_task = (SCIF_SAS_TASK_REQUEST_T *)object;
+
+   SET_STATE_HANDLER(
+      &fw_task->parent,
+      scif_sas_task_request_state_handler_table,
+      SCI_BASE_REQUEST_STATE_COMPLETED
+   );
+
+   // Check to see if the task management operation is now finished (i.e.
+   // all of the task terminations and the task management request are
+   // complete).
+   scif_sas_task_request_operation_complete(fw_task);
+}
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        ABORTING state.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_TASK_REQUEST object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_task_request_aborting_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIF_SAS_TASK_REQUEST_T * fw_task = (SCIF_SAS_TASK_REQUEST_T *)object;
+
+   SET_STATE_HANDLER(
+      &fw_task->parent,
+      scif_sas_task_request_state_handler_table,
+      SCI_BASE_REQUEST_STATE_ABORTING
+   );
+
+   /// @todo Is terminating a previously outstanding task request right?
+   fw_task->parent.status = scif_sas_request_terminate_start(
+                               &fw_task->parent, fw_task->parent.core_object
+                            );
+}
+
+/**
+ * @brief This method implements the actions taken when exiting the
+ *        ABORTING state.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_TASK_REQUEST object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_task_request_aborting_state_exit(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIF_SAS_REQUEST_T * fw_request = (SCIF_SAS_REQUEST_T *)object;
+   scif_sas_request_terminate_complete(fw_request);
+}
+
+/**
+ * @brief This method implements the actions taken when entering the
+ *        FINAL state.
+ *
+ * @param[in]  object This parameter specifies the base object for which
+ *             the state transition is occurring.  This is cast into a
+ *             SCIF_SAS_TASK_REQUEST object in the method implementation.
+ *
+ * @return none
+ */
+static
+void scif_sas_task_request_final_state_enter(
+   SCI_BASE_OBJECT_T *object
+)
+{
+   SCIF_SAS_TASK_REQUEST_T * fw_task = (SCIF_SAS_TASK_REQUEST_T *)object;
+
+   SET_STATE_HANDLER(
+      &fw_task->parent,
+      scif_sas_task_request_state_handler_table,
+      SCI_BASE_REQUEST_STATE_FINAL
+   );
+}
+
+
+SCI_BASE_STATE_T
+   scif_sas_task_request_state_table[SCI_BASE_REQUEST_MAX_STATES] =
+{
+   {
+      SCI_BASE_REQUEST_STATE_INITIAL,
+      scif_sas_task_request_initial_state_enter,
+      NULL
+   },
+   {
+      SCI_BASE_REQUEST_STATE_CONSTRUCTED,
+      scif_sas_task_request_constructed_state_enter,
+      NULL
+   },
+   {
+      SCI_BASE_REQUEST_STATE_STARTED,
+      scif_sas_task_request_started_state_enter,
+      NULL
+   },
+   {
+      SCI_BASE_REQUEST_STATE_COMPLETED,
+      scif_sas_task_request_completed_state_enter,
+      NULL
+   },
+   {
+      SCI_BASE_REQUEST_STATE_ABORTING,
+      scif_sas_task_request_aborting_state_enter,
+      scif_sas_task_request_aborting_state_exit
+   },
+   {
+      SCI_BASE_REQUEST_STATE_FINAL,
+      scif_sas_task_request_final_state_enter,
+      NULL
+   },
+};
diff --git a/sys/dev/disk/isci/scil/scif_sas_timer.c b/sys/dev/disk/isci/scil/scif_sas_timer.c
new file mode 100644
index 0000000..14473f1
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_sas_timer.c
@@ -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: src/sys/dev/isci/scil/scif_sas_timer.c,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+
+/**
+ * @file
+ *
+ * @brief This file contains core callback notificiations implemented by
+ *        the framework for timers.
+ */
+
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/scif_user_callback.h>
+#include <dev/disk/isci/scil/scic_user_callback.h>
+
+#include <dev/disk/isci/scil/scif_sas_controller.h>
+
+void * scic_cb_timer_create(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   SCI_TIMER_CALLBACK_T      timer_callback,
+   void                    * cookie
+)
+{
+   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)
+                                         sci_object_get_association(controller);
+
+   return scif_cb_timer_create(fw_controller, timer_callback, cookie);
+}
+
+// -----------------------------------------------------------------------------
+
+void scic_cb_timer_destroy(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   void                    * timer
+)
+{
+   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)
+                                         sci_object_get_association(controller);
+   if (timer != NULL)
+   {
+      scif_cb_timer_destroy(fw_controller, timer);
+      timer = NULL;
+   }
+}
+
+// -----------------------------------------------------------------------------
+
+void scic_cb_timer_start(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   void                    * timer,
+   U32                       milliseconds
+)
+{
+   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)
+                                         sci_object_get_association(controller);
+
+   scif_cb_timer_start(fw_controller, timer, milliseconds);
+}
+
+// -----------------------------------------------------------------------------
+
+void scic_cb_timer_stop(
+   SCI_CONTROLLER_HANDLE_T   controller,
+   void                    * timer
+)
+{
+   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)
+                                         sci_object_get_association(controller);
+
+   scif_cb_timer_stop(fw_controller, timer);
+}
diff --git a/sys/dev/disk/isci/scil/scif_task_request.h b/sys/dev/disk/isci/scil/scif_task_request.h
new file mode 100644
index 0000000..9d83d52
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_task_request.h
@@ -0,0 +1,128 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_task_request.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIF_TASK_REQUEST_H_
+#define _SCIF_TASK_REQUEST_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains the structures and interface methods that
+ *        can be referenced and used by the SCI user for the SCI task
+ *        management request object.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/sci_status.h>
+
+
+/**
+ * @brief This method simply returns the size required to construct an SCI
+ *        based task request object (includes core & framework object size).
+ *
+ * @return Retrun the size of the SCI task request object.
+ */
+U32 scif_task_request_get_object_size(
+   void
+);
+
+/**
+ * @brief This method is called by the SCIF user to construct a task
+ *        management request.  This method will construct a SCIC task request
+ *        internally.
+ *
+ * @note  The SCI framework implementation will create an association between
+ *        the user task request object and the framework task request object.
+ *
+ * @param[in]  scif_controller the handle to the framework controller object
+ *             for which to build an IO request.
+ * @param[in]  scif_remote_device This parameter specifies the framework
+ *             remote device with which this task request is to be associated.
+ * @param[in]  io_tag This parameter specifies the IO tag to be associated
+ *             with this request.  If SCI_CONTROLLER_INVALID_IO_TAG is
+ *             passed, then a copy of the request is built internally.  The
+ *             request will be copied into the actual controller request
+ *             memory when the IO tag is allocated internally during the
+ *             scif_controller_start_task() method.
+ * @param[in]  user_task_request_object This parameter specifies the user
+ *             task request to be utilized during task construction.  This task
+ *             pointer will become the associated object for the framework
+ *             task request object.
+ * @param[in]  task_request_memory This parameter specifies the memory
+ *             to be utilized in the construction of the framework task request.
+ * @param[in]  scif_task_request This parameter specifies the handle to be
+ *             utilized for all further interactions with this task request
+ *             object.
+ *
+ * @return Indicate if the controller successfully built the task request.
+ * @retval SCI_SUCCESS This value is returned if the task request was
+ *         successfully built.
+ */
+SCI_STATUS scif_task_request_construct(
+   SCI_CONTROLLER_HANDLE_T      scif_controller,
+   SCI_REMOTE_DEVICE_HANDLE_T   scif_remote_device,
+   U16                          io_tag,
+   void                       * user_task_request_object,
+   void                       * task_request_memory,
+   SCI_TASK_REQUEST_HANDLE_T  * scif_task_request
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIF_TASK_REQUEST_H_
diff --git a/sys/dev/disk/isci/scil/scif_user_callback.h b/sys/dev/disk/isci/scil/scif_user_callback.h
new file mode 100644
index 0000000..460387e
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scif_user_callback.h
@@ -0,0 +1,1048 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scif_user_callback.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCIF_USER_CALLBACK_H_
+#define _SCIF_USER_CALLBACK_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the interface methods/macros that must
+ *        be implemented by an SCI Framework user.
+ */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/sci_status.h>
+#include <dev/disk/isci/scil/sci_controller.h>
+#include <dev/disk/isci/scil/intel_sas.h>
+#include <dev/disk/isci/scil/sci_memory_descriptor_list.h>
+
+
+/**
+ * @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   controller,
+   SCI_TIMER_CALLBACK_T      timer_callback,
+   void                    * cookie
+);
+
+/**
+ * @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   controller,
+   void                    * timer
+);
+
+/**
+ * @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,
+   U32                       milliseconds
+);
+
+/**
+ * @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
+);
+
+/**
+ * @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 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
+);
+
+/**
+ * @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
+);
+
+/**
+ * @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
+);
+
+/**
+ * @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.
+ */
+U8 * scif_cb_io_request_get_virtual_address_from_sgl(
+   void * scif_user_io_request,
+   U32    byte_offset
+);
+
+#ifdef ENABLE_OSSL_COPY_BUFFER
+/**
+ * @brief This method is presently utilized in the PIO path,
+ *        copies from UF buffer to the SGL buffer. This method
+ *        can be served for other OS related copies.
+ *
+ * @param[in] 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] source addr. Address of UF buffer.
+ * @param[in] 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.
+ * @param[in] length.
+ *
+ * @return    None
+ */
+void scif_cb_io_request_copy_buffer(
+   void * scic_user_io_request,
+   U8   *source_addr,
+   U32   offset,
+   U32   length
+);
+#endif
+
+/**
+ * @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     controller,
+   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
+   SCI_IO_REQUEST_HANDLE_T     io_request,
+   SCI_IO_STATUS               completion_status
+);
+
+/**
+ * @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
+);
+
+/**
+ * @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.
+ */
+U32 scif_cb_io_request_get_transfer_length(
+   void * scif_user_io_request
+);
+
+/**
+ * @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
+);
+
+#ifndef SCI_SGL_OPTIMIZATION_ENABLED
+/**
+ * @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
+);
+#endif
+
+/**
+ * @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
+);
+
+/**
+ * @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.
+ */
+U32 scif_cb_sge_get_length_field(
+   void * scif_user_io_request,
+   void * sge_address
+);
+
+/**
+ * @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
+);
+
+/**
+ * @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.
+ */
+U32 scif_cb_io_request_get_cdb_length(
+   void * scif_user_io_request
+);
+
+/**
+ * @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.
+ */
+U32 scif_cb_io_request_get_lun(
+   void * scif_user_io_request
+);
+
+/**
+ * @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.
+ */
+U32 scif_cb_io_request_get_task_attribute(
+   void * scif_user_io_request
+);
+
+/**
+ * @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.
+ */
+U32 scif_cb_io_request_get_command_priority(
+   void * scif_user_io_request
+);
+
+/**
+ * @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?
+ */
+U32 scif_cb_task_request_get_lun(
+   void * scif_user_task_request
+);
+
+/**
+ * @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.
+ */
+U8 scif_cb_task_request_get_function(
+   void * scif_user_task_request
+);
+
+/**
+ * @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.
+ */
+U16 scif_cb_task_request_get_io_tag_to_manage(
+   void * scif_user_task_request
+);
+
+/**
+ * @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
+);
+
+/**
+ * @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.
+ */
+U32 scif_cb_task_request_get_response_data_length(
+   void * scif_user_task_request
+);
+
+/**
+ * @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,
+   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 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,
+   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 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,
+   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
+ *        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,
+   U32                   log_object_mask,
+   char                * log_message,
+   ...
+);
+
+
+/**
+ * @brief In this method the user is expected to log the supplied state
+ *        transition 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_states(
+   SCI_LOGGER_HANDLE_T   logger_object,
+   U32                   log_object_mask,
+   char                * log_message,
+   ...
+);
+
+
+/**
+ * @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
+);
+
+
+/**
+ * @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
+);
+
+/**
+ * @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
+);
+
+/**
+ * @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
+);
+
+/**
+ * @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
+);
+
+/**
+ * @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
+);
+
+/**
+ * @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
+);
+
+/**
+ * @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
+);
+
+
+
+/**
+ * @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 controller,
+   FUNCPTR                 start_internal_io_task_routine,
+   void                  * context
+);
+
+/**
+ * @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
+);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCIF_USER_CALLBACK_H_
diff --git a/sys/dev/disk/isci/scil/scu_bios_definitions.h b/sys/dev/disk/isci/scil/scu_bios_definitions.h
new file mode 100644
index 0000000..280c56e
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scu_bios_definitions.h
@@ -0,0 +1,1001 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scu_bios_definitions.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCU_BIOS_DEFINITIONS_H_
+#define _SCU_BIOS_DEFINITIONS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+/**
+ *  IMPORTANT NOTE:
+ *  This file can be used by an SCI Library based driver or
+ *  stand-alone where the library is excluded.  By excluding
+ *  the SCI Library, inclusion of OS specific header files can
+ *  be avoided.  For example, a BIOS utility probably does not
+ *  want to be bothered with inclusion of nested OS DDK include
+ *  files that are not necessary for its function.
+ *
+ *  To exclude the SCI Library, either uncomment the EXCLUDE_SCI_LIBRARY
+ *  #define statement in environment.h or define the statement as an input
+ *  to your compiler.
+ */
+
+#include <dev/disk/isci/environment.h>
+
+#ifndef EXCLUDE_SCI_LIBRARY
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/intel_sas.h>
+#include <dev/disk/isci/scil/sci_controller_constants.h>
+#endif /* EXCLUDE_SCI_LIBRARY */
+
+
+
+// For Intel Storage Controller Unit OEM Block
+#define SCI_OEM_PARAM_SIGNATURE     "ISCUOEMB"
+
+#define SCI_PREBOOT_SOURCE_INIT     (0x00)
+#define SCI_PREBOOT_SOURCE_OROM     (0x80)
+#define SCI_PREBOOT_SOURCE_EFI      (0x81)
+
+#define SCI_OEM_PARAM_VER_1_0       (0x10)
+#define SCI_OEM_PARAM_VER_1_1       (0x11)
+#define SCI_OEM_PARAM_VER_1_2       (0x12)
+#define SCI_OEM_PARAM_VER_1_3       (0x13)
+
+// current version
+#define SCI_OEM_PARAM_VER_CUR       SCI_OEM_PARAM_VER_1_3
+
+// port configuration mode
+#define SCI_BIOS_MODE_MPC   (0x00)
+#define SCI_BIOS_MODE_APC   (0x01)
+
+
+#ifndef SCI_MAX_PHYS
+#define SCI_MAX_PHYS (4)
+#endif
+
+#ifndef SCI_MAX_PORTS
+#define SCI_MAX_PORTS (4)
+#endif
+
+
+/**
+ * @struct SCI_BIOS_OEM_PARAM_BLOCK_HDR
+ *
+ * @brief This structure defines the OEM Parameter block header.
+ */
+typedef struct SCI_BIOS_OEM_PARAM_BLOCK_HDR
+{
+    /**
+     * This field contains the OEM Parameter Block Signature which is
+     * used by BIOS and driver software to identify that the memory location
+     * contains valid OEM Parameter data.  The value must be set to
+     * SCI_OEM_PARAM_SIGNATURE which is the string "ISCUOEMB" which
+     * stands for Intel Storage Controller Unit OEM Block.
+     */
+    U8 signature[8];
+    /**
+     * This field contains the size in bytes of the complete OEM
+     * Parameter Block, both header and payload hdr_length +
+     * (num_elements * element_length).
+     */
+    U16 total_block_length;
+    /**
+     * This field contains the size in bytes of the
+     * SCI_BIOS_OEM_PARAM_BLOCK_HDR. It also indicates the offset from
+     * the beginning of this data structure to where the actual
+     * parameter data payload begins.
+     */
+    U8 hdr_length;
+    /**
+     * This field contains the version info defining the structure
+     * of the OEM Parameter block.
+     */
+    U8  version;
+    /**
+     * This field contains a value indicating the preboot initialization
+     * method (Option ROM or UEFI driver) so that after OS transition,
+     * the OS driver can know the preboot method. OEMs who build a single
+     * flash image where the preboot method is unknown at manufacturing
+     * time should set this field to SCI_PREBOOT_SOURCE_INIT.  Then
+     * after the block is retrieved into host memory and under preboot
+     * driver control, the OROM or UEFI driver can set this field
+     * appropriately (SCI_PREBOOT_SOURCE_OROM and SCI_PREBOOT_SOURCE_EFI,
+     * respectively).
+     */
+    U8 preboot_source;
+    /**
+     * This field contains the number of parameter descriptor elements
+     * (i.e. controller_elements) following this header.  The number of
+     * elements corresponds to the number of SCU controller units contained
+     * in the platform:
+     *  controller_element[0] = SCU0
+     *  controller_element[1] = SCU1
+     */
+    U8 num_elements;
+    /**
+     * This field contains the size in bytes of the descriptor element(s)
+     * in the block.
+     */
+    U16 element_length;
+    /**
+     * Reserve fields for future use.
+     */
+    U8 reserved[8];
+
+} SCI_BIOS_OEM_PARAM_BLOCK_HDR_T;
+
+
+/**
+ * @struct SCIC_SDS_OEM_PARAMETERS VER 1.0
+ *
+ * @brief This structure delineates the various OEM parameters that must
+ * be set for the Intel SAS Storage Controller Unit (SCU).
+ */
+typedef struct SCI_BIOS_OEM_PARAM_ELEMENT
+{
+    /**
+     * Per SCU Controller Data
+     */
+    struct
+    {
+        /**
+         * This field indicates the port configuration mode for
+         * this controller:
+         *   Automatic Port Configuration(APC) or
+         *   Manual Port Configuration (MPC).
+         *
+         * APC means the Platform OEM expects SCI to configure
+         * SAS Ports automatically according to the discovered SAS
+         * Address pairs of the endpoints, wide and/or narrow.
+         *
+         * MPC means the Platform OEM manually defines wide or narrow
+         * connectors by apriori assigning PHYs to SAS Ports.
+         *
+         * By default, the mode type is APC
+         * in APC mode, if ANY of the phy mask is non-zero,
+         *    SCI_FAILURE_INVALID_PARAMETER_VALUE will be returned
+         *      from scic_oem_parameters_set AND the default oem
+         *      configuration will be applied
+         * in MPC mode, if ALL of the phy masks are zero,
+         *    SCI_FAILURE_INVALID_PARAMETER_VALUE will be returned
+         *      from scic_oem_parameters_set AND the default oem
+         *      configuration will be applied
+         */
+        U8  mode_type;
+
+        /**
+         * This field specifies the maximum number of direct attached
+         * devices the OEM will allow to have powered up simultaneously
+         * on this controller.  This allows the OEM to avoid exceeding
+         * power supply limits for this platform.  A value of zero
+         * indicates there are no restrictions.
+         */
+        U8  max_number_concurrent_device_spin_up;
+
+        /**
+         * This field indicates OEM's desired default
+         * Spread Spectrum Clocking (SSC) setting for Tx:
+         *   enabled     = 1
+         *   disabled    = 0
+         */
+        U8 do_enable_ssc;
+
+        U8 reserved;
+
+    } controller;
+
+    /**
+     * Per SAS Port data.
+     */
+    struct
+    {
+        /**
+         * This field specifies the phys to be contained inside a port.
+         * The bit position in the mask specifies the index of the phy
+         * to be contained in the port.  Multiple bits (i.e. phys)
+        * can be contained in a single port:
+        *      Bit 0 = This controller's PHY index 0     (0x01)
+        *      Bit 1 = This controller's PHY index 1     (0x02)
+        *      Bit 2 = This controller's PHY index 2     (0x04)
+        *      Bit 3 = This controller's PHY index 3     (0x08)
+        *
+        * Refer to the mode_type field for rules regarding APC and MPC mode.
+        * General rule: For APC mode phy_mask = 0
+        */
+        U8 phy_mask;
+
+    } ports[SCI_MAX_PORTS]; // Up to 4 Ports per SCU controller unit
+
+    /**
+     * Per PHY Parameter data.
+     */
+    struct
+    {
+        /**
+         * This field indicates the SAS Address that will be transmitted on
+         * this PHY index.  The field is defined as a union, however, the
+         * OEM should use the U8 array definition when encoding it to ensure
+         * correct byte ordering.
+         *
+         * NOTE: If using APC MODE, along with phy_mask being set to ZERO, the
+         * SAS Addresses for all PHYs within a controller group SHALL be the
+         * same.
+         */
+        union
+        {
+            /**
+             * The array should be stored in little endian order.  For example,
+             * if the desired SAS Address is 0x50010B90_0003538D, then it
+             * should be stored in the following manner:
+             *    array[0] = 0x90
+             *    array[1] = 0x0B
+             *    array[2] = 0x01
+             *    array[3] = 0x50
+             *    array[4] = 0x8D
+             *    array[5] = 0x53
+             *    array[6] = 0x03
+             *    array[7] = 0x00
+             */
+            U8 array[8];
+            /**
+             * This is the typedef'd version of the SAS Address used in
+             * the SCI Library.
+             */
+            SCI_SAS_ADDRESS_T  sci_format;
+
+        } sas_address;
+
+        /**
+         * These are the per PHY equalization settings associated with the the
+         * AFE XCVR Tx Amplitude and Equalization Control Register Set
+         * (0 thru 3).
+         *
+         * Operational Note: The following Look-Up-Table registers are engaged
+         * by the AFE block after the following:
+         *  - Software programs the Link Layer AFE Look Up Table Control
+         *    Registers (AFE_LUTCR).
+         *  - Software sets AFE XCVR Tx Control Register Tx Equalization
+         *    Enable bit.
+         */
+        /**
+         * AFE_TX_AMP_CTRL0.  This register is associated with AFE_LUTCR
+         * LUTSel=00b. It contains the Tx Equalization settings that will be
+         * used if a SATA 1.5Gbs or SATA 3.0Gbs device is direct-attached.
+         */
+        U32 afe_tx_amp_control0;
+
+        /**
+         * AFE_TX_AMP_CTRL1.  This register is associated with AFE_LUTCR
+         * LUTSel=01b. It contains the Tx Equalization settings that will
+         * be used if a SATA 6.0Gbs device is direct-attached.
+         */
+        U32 afe_tx_amp_control1;
+
+        /**
+         * AFE_TX_AMP_CTRL2.  This register is associated with AFE_LUTCR
+         * LUTSel=10b. It contains the Tx Equalization settings that will
+         * be used if a SAS 1.5Gbs or SAS 3.0Gbs device is direct-attached.
+         */
+        U32 afe_tx_amp_control2;
+
+        /**
+         * AFE_TX_AMP_CTRL3.  This register is associated with AFE_LUTCR
+         * LUTSel=11b. It contains the Tx Equalization settings that will
+         * be used if a SAS 6.0Gbs device is direct-attached.
+         */
+        U32 afe_tx_amp_control3;
+
+    } phys[SCI_MAX_PHYS];   // 4 PHYs per SCU controller unit
+
+} SCI_BIOS_OEM_PARAM_ELEMENT_T;
+
+/**
+ * @struct SCIC_SDS_OEM_PARAMETERS VER 1.1
+ *
+ * @brief This structure delineates the various OEM parameters that must
+ * be set for the Intel SAS Storage Controller Unit (SCU).
+ */
+typedef struct SCI_BIOS_OEM_PARAM_ELEMENT_v_1_1
+{
+    /**
+     * Per SCU Controller Data
+     */
+    struct
+    {
+        /**
+         * This field indicates the port configuration mode for
+         * this controller:
+         *   Automatic Port Configuration(APC) or
+         *   Manual Port Configuration (MPC).
+         *
+         * APC means the Platform OEM expects SCI to configure
+         * SAS Ports automatically according to the discovered SAS
+         * Address pairs of the endpoints, wide and/or narrow.
+         *
+         * MPC means the Platform OEM manually defines wide or narrow
+         * connectors by apriori assigning PHYs to SAS Ports.
+         *
+         * By default, the mode type is APC
+         * in APC mode, if ANY of the phy mask is non-zero,
+         *    SCI_FAILURE_INVALID_PARAMETER_VALUE will be returned
+         *      from scic_oem_parameters_set AND the default oem
+         *      configuration will be applied
+         * in MPC mode, if ALL of the phy masks are zero,
+         *    SCI_FAILURE_INVALID_PARAMETER_VALUE will be returned
+         *      from scic_oem_parameters_set AND the default oem
+         *      configuration will be applied
+         */
+        U8  mode_type;
+
+        /**
+         * This field specifies the maximum number of direct attached
+         * devices the OEM will allow to have powered up simultaneously
+         * on this controller.  This allows the OEM to avoid exceeding
+         * power supply limits for this platform.  A value of zero
+         * indicates there are no restrictions.
+         */
+        U8  max_number_concurrent_device_spin_up;
+
+        /**
+         * This bitfield indicates the OEM's desired default Tx
+         * Spread Spectrum Clocking (SSC) settings for SATA and SAS.
+         * NOTE: Default SSC Modulation Frequency is 31.5KHz.
+         *--------------------------------------------------------------------*/
+        /**
+         * NOTE: Max spread for SATA is +0 / -5000 PPM.
+         * Down-spreading SSC (only method allowed for SATA):
+         *  SATA SSC Tx Disabled                    = 0x0
+         *  SATA SSC Tx at +0 / -1419 PPM Spread    = 0x2
+         *  SATA SSC Tx at +0 / -2129 PPM Spread    = 0x3
+         *  SATA SSC Tx at +0 / -4257 PPM Spread    = 0x6
+         *  SATA SSC Tx at +0 / -4967 PPM Spread    = 0x7
+        */
+        U8 ssc_sata_tx_spread_level : 4;
+
+        /**
+         * SAS SSC Tx Disabled                     = 0x0
+         *
+         * NOTE: Max spread for SAS down-spreading +0 / -2300 PPM
+         * Down-spreading SSC:
+         *  SAS SSC Tx at +0 / -1419 PPM Spread     = 0x2
+         *  SAS SSC Tx at +0 / -2129 PPM Spread     = 0x3
+         *
+         * NOTE: Max spread for SAS center-spreading +2300 / -2300 PPM
+         * Center-spreading SSC:
+         *  SAS SSC Tx at +1064 / -1064 PPM Spread  = 0x3
+         *  SAS SSC Tx at +2129 / -2129 PPM Spread  = 0x6
+         */
+        U8 ssc_sas_tx_spread_level : 3;
+        /**
+         * NOTE: Refer to the SSC section of the SAS 2.x Specification
+         * for proper setting of this field. For standard SAS Initiator
+         * SAS PHY operation it should be 0 for Down-spreading.
+         * SAS SSC Tx spread type:
+         *  Down-spreading SSC      = 0
+         *  Center-spreading SSC    = 1
+         */
+        U8 ssc_sas_tx_type : 1;
+        /*--------------------------------------------------------------------*/
+
+        U8 reserved;
+
+    } controller;
+
+    /**
+     * Per SAS Port data.
+     */
+    struct
+    {
+        /**
+         * This field specifies the phys to be contained inside a port.
+         * The bit position in the mask specifies the index of the phy
+         * to be contained in the port.  Multiple bits (i.e. phys)
+        * can be contained in a single port:
+        *      Bit 0 = This controller's PHY index 0     (0x01)
+        *      Bit 1 = This controller's PHY index 1     (0x02)
+        *      Bit 2 = This controller's PHY index 2     (0x04)
+        *      Bit 3 = This controller's PHY index 3     (0x08)
+        *
+        * Refer to the mode_type field for rules regarding APC and MPC mode.
+        * General rule: For APC mode phy_mask = 0
+        */
+        U8 phy_mask;
+
+    } ports[SCI_MAX_PORTS]; // Up to 4 Ports per SCU controller unit
+
+    /**
+     * Per PHY Parameter data.
+     */
+    struct
+    {
+        /**
+         * This field indicates the SAS Address that will be transmitted on
+         * this PHY index.  The field is defined as a union, however, the
+         * OEM should use the U8 array definition when encoding it to ensure
+         * correct byte ordering.
+         *
+         * NOTE: If using APC MODE, along with phy_mask being set to ZERO, the
+         * SAS Addresses for all PHYs within a controller group SHALL be the
+         * same.
+         */
+        union
+        {
+            /**
+             * The array should be stored in little endian order.  For example,
+             * if the desired SAS Address is 0x50010B90_0003538D, then it
+             * should be stored in the following manner:
+             *    array[0] = 0x90
+             *    array[1] = 0x0B
+             *    array[2] = 0x01
+             *    array[3] = 0x50
+             *    array[4] = 0x8D
+             *    array[5] = 0x53
+             *    array[6] = 0x03
+             *    array[7] = 0x00
+             */
+            U8 array[8];
+            /**
+             * This is the typedef'd version of the SAS Address used in
+             * the SCI Library.
+             */
+            SCI_SAS_ADDRESS_T  sci_format;
+
+        } sas_address;
+
+        /**
+         * These are the per PHY equalization settings associated with the the
+         * AFE XCVR Tx Amplitude and Equalization Control Register Set
+         * (0 thru 3).
+         *
+         * Operational Note: The following Look-Up-Table registers are engaged
+         * by the AFE block after the following:
+         *  - Software programs the Link Layer AFE Look Up Table Control
+         *    Registers (AFE_LUTCR).
+         *  - Software sets AFE XCVR Tx Control Register Tx Equalization
+         *    Enable bit.
+         */
+        /**
+         * AFE_TX_AMP_CTRL0.  This register is associated with AFE_LUTCR
+         * LUTSel=00b. It contains the Tx Equalization settings that will be
+         * used if a SATA 1.5Gbs or SATA 3.0Gbs device is direct-attached.
+         */
+        U32 afe_tx_amp_control0;
+
+        /**
+         * AFE_TX_AMP_CTRL1.  This register is associated with AFE_LUTCR
+         * LUTSel=01b. It contains the Tx Equalization settings that will
+         * be used if a SATA 6.0Gbs device is direct-attached.
+         */
+        U32 afe_tx_amp_control1;
+
+        /**
+         * AFE_TX_AMP_CTRL2.  This register is associated with AFE_LUTCR
+         * LUTSel=10b. It contains the Tx Equalization settings that will
+         * be used if a SAS 1.5Gbs or SAS 3.0Gbs device is direct-attached.
+         */
+        U32 afe_tx_amp_control2;
+
+        /**
+         * AFE_TX_AMP_CTRL3.  This register is associated with AFE_LUTCR
+         * LUTSel=11b. It contains the Tx Equalization settings that will
+         * be used if a SAS 6.0Gbs device is direct-attached.
+         */
+        U32 afe_tx_amp_control3;
+
+    } phys[SCI_MAX_PHYS];   // 4 PHYs per SCU controller unit
+
+} SCI_BIOS_OEM_PARAM_ELEMENT_v_1_1_T;
+
+/**
+ * @struct SCIC_SDS_OEM_PARAMETERS VER 1.2
+ *
+ * @brief This structure delineates the various OEM parameters that must
+ * be set for the Intel SAS Storage Controller Unit (SCU).
+ */
+typedef struct SCI_BIOS_OEM_PARAM_ELEMENT_v_1_2
+{
+    /**
+     * Per SCU Controller Data
+     */
+    struct
+    {
+        /**
+         * This field indicates the port configuration mode for
+         * this controller:
+         *   Automatic Port Configuration(APC) or
+         *   Manual Port Configuration (MPC).
+         *
+         * APC means the Platform OEM expects SCI to configure
+         * SAS Ports automatically according to the discovered SAS
+         * Address pairs of the endpoints, wide and/or narrow.
+         *
+         * MPC means the Platform OEM manually defines wide or narrow
+         * connectors by apriori assigning PHYs to SAS Ports.
+         *
+         * By default, the mode type is APC
+         * in APC mode, if ANY of the phy mask is non-zero,
+         *    SCI_FAILURE_INVALID_PARAMETER_VALUE will be returned
+         *      from scic_oem_parameters_set AND the default oem
+         *      configuration will be applied
+         * in MPC mode, if ALL of the phy masks are zero,
+         *    SCI_FAILURE_INVALID_PARAMETER_VALUE will be returned
+         *      from scic_oem_parameters_set AND the default oem
+         *      configuration will be applied
+         */
+        U8  mode_type;
+
+        /**
+         * This field specifies the maximum number of direct attached
+         * devices the OEM will allow to have powered up simultaneously
+         * on this controller.  This allows the OEM to avoid exceeding
+         * power supply limits for this platform.  A value of zero
+         * indicates there are no restrictions.
+         */
+        U8  max_number_concurrent_device_spin_up;
+
+        /**
+         * This bitfield indicates the OEM's desired default Tx
+         * Spread Spectrum Clocking (SSC) settings for SATA and SAS.
+         * NOTE: Default SSC Modulation Frequency is 31.5KHz.
+         *--------------------------------------------------------------------*/
+        /**
+         * NOTE: Max spread for SATA is +0 / -5000 PPM.
+         * Down-spreading SSC (only method allowed for SATA):
+         *  SATA SSC Tx Disabled                    = 0x0
+         *  SATA SSC Tx at +0 / -1419 PPM Spread    = 0x2
+         *  SATA SSC Tx at +0 / -2129 PPM Spread    = 0x3
+         *  SATA SSC Tx at +0 / -4257 PPM Spread    = 0x6
+         *  SATA SSC Tx at +0 / -4967 PPM Spread    = 0x7
+        */
+        U8 ssc_sata_tx_spread_level : 4;
+
+        /**
+         * SAS SSC Tx Disabled                     = 0x0
+         *
+         * NOTE: Max spread for SAS down-spreading +0 / -2300 PPM
+         * Down-spreading SSC:
+         *  SAS SSC Tx at +0 / -1419 PPM Spread     = 0x2
+         *  SAS SSC Tx at +0 / -2129 PPM Spread     = 0x3
+         *
+         * NOTE: Max spread for SAS center-spreading +2300 / -2300 PPM
+         * Center-spreading SSC:
+         *  SAS SSC Tx at +1064 / -1064 PPM Spread  = 0x3
+         *  SAS SSC Tx at +2129 / -2129 PPM Spread  = 0x6
+         */
+        U8 ssc_sas_tx_spread_level : 3;
+        /**
+         * NOTE: Refer to the SSC section of the SAS 2.x Specification
+         * for proper setting of this field. For standard SAS Initiator
+         * SAS PHY operation it should be 0 for Down-spreading.
+         * SAS SSC Tx spread type:
+         *  Down-spreading SSC      = 0
+         *  Center-spreading SSC    = 1
+         */
+        U8 ssc_sas_tx_type : 1;
+
+        /**
+         * This field indicates length of the SAS/SATA cable between
+         * host and device.
+         * This field is used make relationship between analog parameters of
+         * the phy in the silicon and length of the cable.
+         * Supported length: "short"- up to 3m, "long"- more than 3m
+         * This is bit mask field:
+         *
+         * BIT:           7  6  5  4   3     2     1     0 (LSB)
+         * ASSIGNMENT:   <-><-><-><-><phy3><phy2><phy1><phy0>
+         *
+         * For short cable corresponding bit shall be reset,
+         * for long cable shall be set.
+         */
+        U8 long_cable_selection_mask;
+
+    } controller;
+
+    /**
+     * Per SAS Port data.
+     */
+    struct
+    {
+        /**
+         * This field specifies the phys to be contained inside a port.
+         * The bit position in the mask specifies the index of the phy
+         * to be contained in the port.  Multiple bits (i.e. phys)
+        * can be contained in a single port:
+        *      Bit 0 = This controller's PHY index 0     (0x01)
+        *      Bit 1 = This controller's PHY index 1     (0x02)
+        *      Bit 2 = This controller's PHY index 2     (0x04)
+        *      Bit 3 = This controller's PHY index 3     (0x08)
+        *
+        * Refer to the mode_type field for rules regarding APC and MPC mode.
+        * General rule: For APC mode phy_mask = 0
+        */
+        U8 phy_mask;
+
+    } ports[SCI_MAX_PORTS]; // Up to 4 Ports per SCU controller unit
+
+    /**
+     * Per PHY Parameter data.
+     */
+    struct
+    {
+        /**
+         * This field indicates the SAS Address that will be transmitted on
+         * this PHY index.  The field is defined as a union, however, the
+         * OEM should use the U8 array definition when encoding it to ensure
+         * correct byte ordering.
+         *
+         * NOTE: If using APC MODE, along with phy_mask being set to ZERO, the
+         * SAS Addresses for all PHYs within a controller group SHALL be the
+         * same.
+         */
+        union
+        {
+            /**
+             * The array should be stored in little endian order.  For example,
+             * if the desired SAS Address is 0x50010B90_0003538D, then it
+             * should be stored in the following manner:
+             *    array[0] = 0x90
+             *    array[1] = 0x0B
+             *    array[2] = 0x01
+             *    array[3] = 0x50
+             *    array[4] = 0x8D
+             *    array[5] = 0x53
+             *    array[6] = 0x03
+             *    array[7] = 0x00
+             */
+            U8 array[8];
+            /**
+             * This is the typedef'd version of the SAS Address used in
+             * the SCI Library.
+             */
+            SCI_SAS_ADDRESS_T  sci_format;
+
+        } sas_address;
+
+        /**
+         * These are the per PHY equalization settings associated with the the
+         * AFE XCVR Tx Amplitude and Equalization Control Register Set
+         * (0 thru 3).
+         *
+         * Operational Note: The following Look-Up-Table registers are engaged
+         * by the AFE block after the following:
+         *  - Software programs the Link Layer AFE Look Up Table Control
+         *    Registers (AFE_LUTCR).
+         *  - Software sets AFE XCVR Tx Control Register Tx Equalization
+         *    Enable bit.
+         */
+        /**
+         * AFE_TX_AMP_CTRL0.  This register is associated with AFE_LUTCR
+         * LUTSel=00b. It contains the Tx Equalization settings that will be
+         * used if a SATA 1.5Gbs or SATA 3.0Gbs device is direct-attached.
+         */
+        U32 afe_tx_amp_control0;
+
+        /**
+         * AFE_TX_AMP_CTRL1.  This register is associated with AFE_LUTCR
+         * LUTSel=01b. It contains the Tx Equalization settings that will
+         * be used if a SATA 6.0Gbs device is direct-attached.
+         */
+        U32 afe_tx_amp_control1;
+
+        /**
+         * AFE_TX_AMP_CTRL2.  This register is associated with AFE_LUTCR
+         * LUTSel=10b. It contains the Tx Equalization settings that will
+         * be used if a SAS 1.5Gbs or SAS 3.0Gbs device is direct-attached.
+         */
+        U32 afe_tx_amp_control2;
+
+        /**
+         * AFE_TX_AMP_CTRL3.  This register is associated with AFE_LUTCR
+         * LUTSel=11b. It contains the Tx Equalization settings that will
+         * be used if a SAS 6.0Gbs device is direct-attached.
+         */
+        U32 afe_tx_amp_control3;
+
+    } phys[SCI_MAX_PHYS];   // 4 PHYs per SCU controller unit
+
+} SCI_BIOS_OEM_PARAM_ELEMENT_v_1_2_T;
+
+/**
+ * @struct SCIC_SDS_OEM_PARAMETERS VER 1.3
+ *
+ * @brief This structure delineates the various OEM parameters that must
+ * be set for the Intel SAS Storage Controller Unit (SCU).
+ */
+typedef struct SCI_BIOS_OEM_PARAM_ELEMENT_v_1_3
+{
+    /**
+     * Per SCU Controller Data
+     */
+    struct
+    {
+        /**
+         * This field indicates the port configuration mode for
+         * this controller:
+         *   Automatic Port Configuration(APC) or
+         *   Manual Port Configuration (MPC).
+         *
+         * APC means the Platform OEM expects SCI to configure
+         * SAS Ports automatically according to the discovered SAS
+         * Address pairs of the endpoints, wide and/or narrow.
+         *
+         * MPC means the Platform OEM manually defines wide or narrow
+         * connectors by apriori assigning PHYs to SAS Ports.
+         *
+         * By default, the mode type is APC
+         * in APC mode, if ANY of the phy mask is non-zero,
+         *    SCI_FAILURE_INVALID_PARAMETER_VALUE will be returned
+         *      from scic_oem_parameters_set AND the default oem
+         *      configuration will be applied
+         * in MPC mode, if ALL of the phy masks are zero,
+         *    SCI_FAILURE_INVALID_PARAMETER_VALUE will be returned
+         *      from scic_oem_parameters_set AND the default oem
+         *      configuration will be applied
+         */
+        U8  mode_type;
+
+        /**
+         * This field specifies the maximum number of direct attached
+         * devices the OEM will allow to have powered up simultaneously
+         * on this controller.  This allows the OEM to avoid exceeding
+         * power supply limits for this platform.  A value of zero
+         * indicates there are no restrictions.
+         */
+        U8  max_number_concurrent_device_spin_up;
+
+        /**
+         * This bitfield indicates the OEM's desired default Tx
+         * Spread Spectrum Clocking (SSC) settings for SATA and SAS.
+         * NOTE: Default SSC Modulation Frequency is 31.5KHz.
+         *--------------------------------------------------------------------*/
+        /**
+         * NOTE: Max spread for SATA is +0 / -5000 PPM.
+         * Down-spreading SSC (only method allowed for SATA):
+         *  SATA SSC Tx Disabled                    = 0x0
+         *  SATA SSC Tx at +0 / -1419 PPM Spread    = 0x2
+         *  SATA SSC Tx at +0 / -2129 PPM Spread    = 0x3
+         *  SATA SSC Tx at +0 / -4257 PPM Spread    = 0x6
+         *  SATA SSC Tx at +0 / -4967 PPM Spread    = 0x7
+        */
+        U8 ssc_sata_tx_spread_level : 4;
+
+        /**
+         * SAS SSC Tx Disabled                     = 0x0
+         *
+         * NOTE: Max spread for SAS down-spreading +0 / -2300 PPM
+         * Down-spreading SSC:
+         *  SAS SSC Tx at +0 / -1419 PPM Spread     = 0x2
+         *  SAS SSC Tx at +0 / -2129 PPM Spread     = 0x3
+         *
+         * NOTE: Max spread for SAS center-spreading +2300 / -2300 PPM
+         * Center-spreading SSC:
+         *  SAS SSC Tx at +1064 / -1064 PPM Spread  = 0x3
+         *  SAS SSC Tx at +2129 / -2129 PPM Spread  = 0x6
+         */
+        U8 ssc_sas_tx_spread_level : 3;
+        /**
+         * NOTE: Refer to the SSC section of the SAS 2.x Specification
+         * for proper setting of this field. For standard SAS Initiator
+         * SAS PHY operation it should be 0 for Down-spreading.
+         * SAS SSC Tx spread type:
+         *  Down-spreading SSC      = 0
+         *  Center-spreading SSC    = 1
+         */
+        U8 ssc_sas_tx_type : 1;
+
+        /**
+         * This field indicates length of the SAS/SATA cable between
+         * host and device.
+         * This field is used make relationship between analog parameters of
+         * the phy in the silicon and length of the cable.
+         * Supported cable attenuation levels:
+         * "short"- up to 3m, "medium"-3m to 6m, and "long"- more than 6m
+         * This is bit mask field:
+         *
+         * BIT:      (MSB) 7     6     5     4
+         * ASSIGNMENT:   <phy3><phy2><phy1><phy0>  - Medium cable length assignment
+         * BIT:            3     2     1     0  (LSB)
+         * ASSIGNMENT:   <phy3><phy2><phy1><phy0>  - Long cable length assignment
+         *
+         * BITS 7-4 are set when the cable length is assigned to medium
+         * BITS 3-0 are set when the cable length is assigned to long
+         * The BIT positions are clear when the cable length is assigned to short
+         * Setting the bits for both long and medium cable length is undefined.
+         *
+         * A value of 0x84 would assign
+         *    phy3 - medium
+         *    phy2 - long
+         *    phy1 - short
+         *    phy0 - short
+         */
+        U8 cable_selection_mask;
+
+    } controller;
+
+    /**
+     * Per SAS Port data.
+     */
+    struct
+    {
+        /**
+         * This field specifies the phys to be contained inside a port.
+         * The bit position in the mask specifies the index of the phy
+         * to be contained in the port.  Multiple bits (i.e. phys)
+        * can be contained in a single port:
+        *      Bit 0 = This controller's PHY index 0     (0x01)
+        *      Bit 1 = This controller's PHY index 1     (0x02)
+        *      Bit 2 = This controller's PHY index 2     (0x04)
+        *      Bit 3 = This controller's PHY index 3     (0x08)
+        *
+        * Refer to the mode_type field for rules regarding APC and MPC mode.
+        * General rule: For APC mode phy_mask = 0
+        */
+        U8 phy_mask;
+
+    } ports[SCI_MAX_PORTS]; // Up to 4 Ports per SCU controller unit
+
+    /**
+     * Per PHY Parameter data.
+     */
+    struct
+    {
+        /**
+         * This field indicates the SAS Address that will be transmitted on
+         * this PHY index.  The field is defined as a union, however, the
+         * OEM should use the U8 array definition when encoding it to ensure
+         * correct byte ordering.
+         *
+         * NOTE: If using APC MODE, along with phy_mask being set to ZERO, the
+         * SAS Addresses for all PHYs within a controller group SHALL be the
+         * same.
+         */
+        union
+        {
+            /**
+             * The array should be stored in little endian order.  For example,
+             * if the desired SAS Address is 0x50010B90_0003538D, then it
+             * should be stored in the following manner:
+             *    array[0] = 0x90
+             *    array[1] = 0x0B
+             *    array[2] = 0x01
+             *    array[3] = 0x50
+             *    array[4] = 0x8D
+             *    array[5] = 0x53
+             *    array[6] = 0x03
+             *    array[7] = 0x00
+             */
+            U8 array[8];
+            /**
+             * This is the typedef'd version of the SAS Address used in
+             * the SCI Library.
+             */
+            SCI_SAS_ADDRESS_T  sci_format;
+
+        } sas_address;
+
+        /**
+         * These are the per PHY equalization settings associated with the the
+         * AFE XCVR Tx Amplitude and Equalization Control Register Set
+         * (0 thru 3).
+         *
+         * Operational Note: The following Look-Up-Table registers are engaged
+         * by the AFE block after the following:
+         *  - Software programs the Link Layer AFE Look Up Table Control
+         *    Registers (AFE_LUTCR).
+         *  - Software sets AFE XCVR Tx Control Register Tx Equalization
+         *    Enable bit.
+         */
+        /**
+         * AFE_TX_AMP_CTRL0.  This register is associated with AFE_LUTCR
+         * LUTSel=00b. It contains the Tx Equalization settings that will be
+         * used if a SATA 1.5Gbs or SATA 3.0Gbs device is direct-attached.
+         */
+        U32 afe_tx_amp_control0;
+
+        /**
+         * AFE_TX_AMP_CTRL1.  This register is associated with AFE_LUTCR
+         * LUTSel=01b. It contains the Tx Equalization settings that will
+         * be used if a SATA 6.0Gbs device is direct-attached.
+         */
+        U32 afe_tx_amp_control1;
+
+        /**
+         * AFE_TX_AMP_CTRL2.  This register is associated with AFE_LUTCR
+         * LUTSel=10b. It contains the Tx Equalization settings that will
+         * be used if a SAS 1.5Gbs or SAS 3.0Gbs device is direct-attached.
+         */
+        U32 afe_tx_amp_control2;
+
+        /**
+         * AFE_TX_AMP_CTRL3.  This register is associated with AFE_LUTCR
+         * LUTSel=11b. It contains the Tx Equalization settings that will
+         * be used if a SAS 6.0Gbs device is direct-attached.
+         */
+        U32 afe_tx_amp_control3;
+
+    } phys[SCI_MAX_PHYS];   // 4 PHYs per SCU controller unit
+
+} SCI_BIOS_OEM_PARAM_ELEMENT_v_1_3_T;
+
+/**
+ *  @struct SCI_BIOS_OEM_PARAM_BLOCK
+ *
+ * @brief This structure defines the OEM Parameter block as it will be stored
+ *  in the last 512 bytes of the PDR region in the SPI flash.  It must be
+ *  unpacked or pack(1).
+ */
+typedef struct SCI_BIOS_OEM_PARAM_BLOCK
+{
+    /**
+     * OEM Parameter Block header.
+     */
+    SCI_BIOS_OEM_PARAM_BLOCK_HDR_T  header;
+
+    /**
+     * Per controller element descriptor containing the controller's
+     * parameter data. The prototype defines just one of these descriptors,
+     * however, the actual runtime number is determined by the num_elements
+     * field in the header.
+     */
+    SCI_BIOS_OEM_PARAM_ELEMENT_T controller_element[1];
+
+} SCI_BIOS_OEM_PARAM_BLOCK_T;
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCU_BIOS_DEFINITIONS_H_
diff --git a/sys/dev/disk/isci/scil/scu_completion_codes.h b/sys/dev/disk/isci/scil/scu_completion_codes.h
new file mode 100644
index 0000000..77ac67d
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scu_completion_codes.h
@@ -0,0 +1,263 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scu_completion_codes.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCU_COMPLETION_CODES_HEADER_
+#define _SCU_COMPLETION_CODES_HEADER_
+
+/**
+ * @file
+ *
+ * @brief This file contains the constants and macros for the SCU hardware
+ *        completion codes.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#define SCU_COMPLETION_TYPE_SHIFT      28
+#define SCU_COMPLETION_TYPE_MASK       0x70000000
+
+/**
+ * This macro constructs an SCU completion type
+ */
+#define SCU_COMPLETION_TYPE(type) \
+   ((U32)(type) << SCU_COMPLETION_TYPE_SHIFT)
+
+/**
+ * These macros contain the SCU completion types
+ *
+ * @name SCU_COMPLETION_TYPE
+ */
+/*@}*/
+#define SCU_COMPLETION_TYPE_TASK       SCU_COMPLETION_TYPE(0)
+#define SCU_COMPLETION_TYPE_SDMA       SCU_COMPLETION_TYPE(1)
+#define SCU_COMPLETION_TYPE_UFI        SCU_COMPLETION_TYPE(2)
+#define SCU_COMPLETION_TYPE_EVENT      SCU_COMPLETION_TYPE(3)
+#define SCU_COMPLETION_TYPE_NOTIFY     SCU_COMPLETION_TYPE(4)
+/*@}*/
+
+/**
+ * These constants provide the shift and mask values for the various parts of
+ * an SCU completion code.
+ */
+#define SCU_COMPLETION_STATUS_MASK       0x0FFC0000
+#define SCU_COMPLETION_TL_STATUS_MASK    0x0FC00000
+#define SCU_COMPLETION_TL_STATUS_SHIFT   22
+#define SCU_COMPLETION_SDMA_STATUS_MASK  0x003C0000
+#define SCU_COMPLETION_PEG_MASK          0x00010000
+#define SCU_COMPLETION_PORT_MASK         0x00007000
+#define SCU_COMPLETION_PE_MASK           SCU_COMPLETION_PORT_MASK
+#define SCU_COMPLETION_PE_SHIFT          12
+#define SCU_COMPLETION_INDEX_MASK        0x00000FFF
+
+/**
+ * This macro returns the SCU completion type.
+ */
+#define SCU_GET_COMPLETION_TYPE(completion_code) \
+   ((completion_code) & SCU_COMPLETION_TYPE_MASK)
+
+/**
+ * This macro returns the SCU completion status.
+ */
+#define SCU_GET_COMPLETION_STATUS(completion_code) \
+   ((completion_code) & SCU_COMPLETION_STATUS_MASK)
+
+/**
+ * This macro returns the transport layer completion status.
+ */
+#define SCU_GET_COMPLETION_TL_STATUS(completion_code) \
+   ((completion_code) & SCU_COMPLETION_TL_STATUS_MASK)
+
+/**
+ * This macro takes a completion code and performs the shift and mask
+ * operations to turn it into a completion code that can be compared to a
+ * SCU_GET_COMPLETION_TL_STATUS.
+ */
+#define SCU_MAKE_COMPLETION_STATUS(completion_code) \
+   ((U32)(completion_code) << SCU_COMPLETION_TL_STATUS_SHIFT)
+
+/**
+ * This macro takes a SCU_GET_COMPLETION_TL_STATUS and normalizes it for a
+ * return code.
+ */
+#define SCU_NORMALIZE_COMPLETION_STATUS(completion_code) \
+   ( \
+      ((U32)((completion_code) & SCU_COMPLETION_TL_STATUS_MASK)) \
+   >> SCU_COMPLETION_TL_STATUS_SHIFT \
+   )
+
+/**
+ * This macro returns the SDMA completion status.
+ */
+#define SCU_GET_COMPLETION_SDMA_STATUS(completion_code) \
+   ((completion_code) & SCU_COMPLETION_SDMA_STATUS_MASK)
+
+/**
+ * This macro returns the Protocol Engine Group from the completion code.
+ */
+#define SCU_GET_COMPLETION_PEG(completion_code) \
+   ((completion_code) & SCU_COMPLETION_PEG_MASK)
+
+/**
+ * This macro reuturns the logical port index from the completion code.
+ */
+#define SCU_GET_COMPLETION_PORT(completion_code) \
+   ((completion_code) & SCU_COMPLETION_PORT_MASK)
+
+/**
+ * This macro returns the PE index from the completion code.
+ */
+#define SCU_GET_PROTOCOL_ENGINE_INDEX(completion_code) \
+   (((U32)((completion_code) & SCU_COMPLETION_PE_MASK)) >> SCU_COMPLETION_PE_SHIFT)
+
+/**
+ * This macro returns the index of the completion which is either a TCi or an
+ * RNi depending on the completion type.
+ */
+#define SCU_GET_COMPLETION_INDEX(completion_code) \
+   ((completion_code) & SCU_COMPLETION_INDEX_MASK)
+
+#define SCU_UNSOLICITED_FRAME_MASK     0x0FFF0000
+#define SCU_UNSOLICITED_FRAME_SHIFT    16
+
+/**
+ * This macro returns a normalized frame index from an unsolicited frame
+ * completion.
+ */
+#define SCU_GET_FRAME_INDEX(completion_code) \
+   ( \
+        ((U32)((completion_code) & SCU_UNSOLICITED_FRAME_MASK)) \
+     >> SCU_UNSOLICITED_FRAME_SHIFT \
+   )
+
+#define SCU_UNSOLICITED_FRAME_ERROR_MASK  0x00008000
+
+/**
+ * This macro returns a zero (0) value if there is no frame error otherwise
+ * it returns non-zero (!0).
+ */
+#define SCU_GET_FRAME_ERROR(completion_code) \
+   ((completion_code) & SCU_UNSOLICITED_FRAME_ERROR_MASK)
+
+/**
+ * These constants represent normalized completion codes which must be shifted
+ * 18 bits to match it with the hardware completion code. In a 16-bit compiler,
+ * immediate constants are 16-bit values (the size of an int). If we shift those
+ * by 18 bits, we completely lose the value. To ensure the value is a 32-bit
+ * value like we want, each immediate value must be cast to a U32.
+ */
+#define SCU_TASK_DONE_GOOD                                  ((U32)0x00)
+#define SCU_TASK_DONE_CRC_ERR                               ((U32)0x14)
+#define SCU_TASK_DONE_CHECK_RESPONSE                        ((U32)0x14)
+#define SCU_TASK_DONE_GEN_RESPONSE                          ((U32)0x15)
+#define SCU_TASK_DONE_NAK_CMD_ERR                           ((U32)0x16)
+#define SCU_TASK_DONE_CMD_LL_R_ERR                          ((U32)0x16)
+#define SCU_TASK_DONE_LL_R_ERR                              ((U32)0x17)
+#define SCU_TASK_DONE_ACK_NAK_TO                            ((U32)0x17)
+#define SCU_TASK_DONE_LL_PERR                               ((U32)0x18)
+#define SCU_TASK_DONE_LL_SY_TERM                            ((U32)0x19)
+#define SCU_TASK_DONE_NAK_ERR                               ((U32)0x19)
+#define SCU_TASK_DONE_LL_LF_TERM                            ((U32)0x1A)
+#define SCU_TASK_DONE_DATA_LEN_ERR                          ((U32)0x1A)
+#define SCU_TASK_DONE_LL_CL_TERM                            ((U32)0x1B)
+#define SCU_TASK_DONE_LL_ABORT_ERR                          ((U32)0x1B)
+#define SCU_TASK_DONE_SEQ_INV_TYPE                          ((U32)0x1C)
+#define SCU_TASK_DONE_UNEXP_XR                              ((U32)0x1C)
+#define SCU_TASK_DONE_INV_FIS_TYPE                          ((U32)0x1D)
+#define SCU_TASK_DONE_XR_IU_LEN_ERR                         ((U32)0x1D)
+#define SCU_TASK_DONE_INV_FIS_LEN                           ((U32)0x1E)
+#define SCU_TASK_DONE_XR_WD_LEN                             ((U32)0x1E)
+#define SCU_TASK_DONE_SDMA_ERR                              ((U32)0x1F)
+#define SCU_TASK_DONE_OFFSET_ERR                            ((U32)0x20)
+#define SCU_TASK_DONE_MAX_PLD_ERR                           ((U32)0x21)
+#define SCU_TASK_DONE_EXCESS_DATA                           ((U32)0x22)
+#define SCU_TASK_DONE_LF_ERR                                ((U32)0x23)
+#define SCU_TASK_DONE_UNEXP_FIS                             ((U32)0x24)
+#define SCU_TASK_DONE_UNEXP_RESP                            ((U32)0x24)
+#define SCU_TASK_DONE_EARLY_RESP                            ((U32)0x25)
+#define SCU_TASK_DONE_SMP_RESP_TO_ERR                       ((U32)0x26)
+#define SCU_TASK_DONE_DMASETUP_DIRERR                       ((U32)0x27)
+#define SCU_TASK_DONE_SMP_UFI_ERR                           ((U32)0x27)
+#define SCU_TASK_DONE_XFERCNT_ERR                           ((U32)0x28)
+#define SCU_TASK_DONE_SMP_FRM_TYPE_ERR                      ((U32)0x28)
+#define SCU_TASK_DONE_SMP_LL_RX_ERR                         ((U32)0x29)
+#define SCU_TASK_DONE_RESP_LEN_ERR                          ((U32)0x2A)
+#define SCU_TASK_DONE_UNEXP_DATA                            ((U32)0x2B)
+#define SCU_TASK_DONE_OPEN_FAIL                             ((U32)0x2C)
+#define SCU_TASK_DONE_UNEXP_SDBFIS                          ((U32)0x2D)
+#define SCU_TASK_DONE_REG_ERR                               ((U32)0x2E)
+#define SCU_TASK_DONE_SDB_ERR                               ((U32)0x2F)
+#define SCU_TASK_DONE_TASK_ABORT                            ((U32)0x30)
+#if defined(PBG_HBA_BETA_BUILD)
+#define SCU_TASK_DONE_CMD_SDMA_ERR                          ((U32)0x32)
+#define SCU_TASK_DONE_CMD_LL_ABORT_ERR                      ((U32)0x33)
+#endif
+#define SCU_TASK_OPEN_REJECT_WRONG_DESTINATION              ((U32)0x34)
+#define SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_1             ((U32)0x35)
+#define SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_2             ((U32)0x36)
+#define SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_3             ((U32)0x37)
+#define SCU_TASK_OPEN_REJECT_BAD_DESTINATION                ((U32)0x38)
+#define SCU_TASK_OPEN_REJECT_ZONE_VIOLATION                 ((U32)0x39)
+#define SCU_TASK_DONE_VIIT_ENTRY_NV                         ((U32)0x3A)
+#define SCU_TASK_DONE_IIT_ENTRY_NV                          ((U32)0x3B)
+#define SCU_TASK_DONE_RNCNV_OUTBOUND                        ((U32)0x3C)
+#define SCU_TASK_OPEN_REJECT_STP_RESOURCES_BUSY             ((U32)0x3D)
+#define SCU_TASK_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED         ((U32)0x3E)
+#define SCU_TASK_OPEN_REJECT_CONNECTION_RATE_NOT_SUPPORTED  ((U32)0x3F)
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCU_COMPLETION_CODES_HEADER_
diff --git a/sys/dev/disk/isci/scil/scu_constants.h b/sys/dev/disk/isci/scil/scu_constants.h
new file mode 100644
index 0000000..42cb6b4
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scu_constants.h
@@ -0,0 +1,154 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scu_constants.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCU_CONSTANTS_H_
+#define _SCU_CONSTANTS_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains the SCU hardware constants.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_controller_constants.h>
+
+/**
+ * 2 indicates the maximum number of UFs that can occur for a given IO
+ * request.  The hardware handles reception of additional unsolicited
+ * frames while all UFs are in use, by holding off the transmitting
+ * device.  This number could be theoretically reduced to 1, but 2
+ * provides for more reliable operation.  During SATA PIO operation,
+ * it is possible under some conditions for there to be 3 separate
+ * FISes received, back to back to back (PIO Setup, Data, D2H Register).
+ * It is unlikely to have all 3 pending all at once without some of
+ * them already being processed.
+ */
+#define SCU_MIN_UNSOLICITED_FRAMES        (8)
+#define SCU_MIN_CRITICAL_NOTIFICATIONS    (19)
+#define SCU_MIN_EVENTS                    (4)
+#define SCU_MIN_COMPLETION_QUEUE_SCRATCH  (0)
+#define SCU_MIN_COMPLETION_QUEUE_ENTRIES  ( SCU_MIN_CRITICAL_NOTIFICATIONS \
+                                          + SCU_MIN_EVENTS \
+                                          + SCU_MIN_UNSOLICITED_FRAMES \
+                                          + SCI_MIN_IO_REQUESTS \
+                                          + SCU_MIN_COMPLETION_QUEUE_SCRATCH )
+
+#define SCU_MAX_CRITICAL_NOTIFICATIONS    (384)
+#define SCU_MAX_EVENTS                    (128)
+#define SCU_MAX_UNSOLICITED_FRAMES        (128)
+#define SCU_MAX_COMPLETION_QUEUE_SCRATCH  (128)
+#define SCU_MAX_COMPLETION_QUEUE_ENTRIES  ( SCU_MAX_CRITICAL_NOTIFICATIONS \
+                                          + SCU_MAX_EVENTS \
+                                          + SCU_MAX_UNSOLICITED_FRAMES \
+                                          + SCI_MAX_IO_REQUESTS \
+                                          + SCU_MAX_COMPLETION_QUEUE_SCRATCH )
+
+#if !defined(ENABLE_MINIMUM_MEMORY_MODE)
+#define SCU_UNSOLICITED_FRAME_COUNT      SCU_MAX_UNSOLICITED_FRAMES
+#define SCU_CRITICAL_NOTIFICATION_COUNT  SCU_MAX_CRITICAL_NOTIFICATIONS
+#define SCU_EVENT_COUNT                  SCU_MAX_EVENTS
+#define SCU_COMPLETION_QUEUE_SCRATCH     SCU_MAX_COMPLETION_QUEUE_SCRATCH
+#define SCU_IO_REQUEST_COUNT             SCI_MAX_IO_REQUESTS
+#define SCU_IO_REQUEST_SGE_COUNT         SCI_MAX_SCATTER_GATHER_ELEMENTS
+#define SCU_COMPLETION_QUEUE_COUNT       SCU_MAX_COMPLETION_QUEUE_ENTRIES
+#else
+#define SCU_UNSOLICITED_FRAME_COUNT      SCU_MIN_UNSOLICITED_FRAMES
+#define SCU_CRITICAL_NOTIFICATION_COUNT  SCU_MIN_CRITICAL_NOTIFICATIONS
+#define SCU_EVENT_COUNT                  SCU_MIN_EVENTS
+#define SCU_COMPLETION_QUEUE_SCRATCH     SCU_MIN_COMPLETION_QUEUE_SCRATCH
+#define SCU_IO_REQUEST_COUNT             SCI_MIN_IO_REQUESTS
+#define SCU_IO_REQUEST_SGE_COUNT         SCI_MIN_SCATTER_GATHER_ELEMENTS
+#define SCU_COMPLETION_QUEUE_COUNT       SCU_MIN_COMPLETION_QUEUE_ENTRIES
+#endif // !defined(ENABLE_MINIMUM_MEMORY_OPERATION)
+
+/**
+ * The SCU_COMPLETION_QUEUE_COUNT constant indicates the size
+ * of the completion queue into which the hardware DMAs 32-bit
+ * quantas (completion entries).
+ */
+
+/**
+ * This queue must be programmed to a power of 2 size (e.g. 32, 64,
+ * 1024, etc.).
+ */
+#if (SCU_COMPLETION_QUEUE_COUNT != 16)  && \
+    (SCU_COMPLETION_QUEUE_COUNT != 32)  && \
+    (SCU_COMPLETION_QUEUE_COUNT != 64)  && \
+    (SCU_COMPLETION_QUEUE_COUNT != 128) && \
+    (SCU_COMPLETION_QUEUE_COUNT != 256) && \
+    (SCU_COMPLETION_QUEUE_COUNT != 512) && \
+    (SCU_COMPLETION_QUEUE_COUNT != 1024)
+#error "SCU_COMPLETION_QUEUE_COUNT must be set to a power of 2."
+#endif
+
+#if SCU_MIN_UNSOLICITED_FRAMES > SCU_MAX_UNSOLICITED_FRAMES
+#error "Invalid configuration of unsolicited frame constants"
+#endif // SCU_MIN_UNSOLICITED_FRAMES > SCU_MAX_UNSOLICITED_FRAMES
+
+#define SCU_MIN_UF_TABLE_ENTRIES            (8)
+#define SCU_ABSOLUTE_MAX_UNSOLICITED_FRAMES (4096)
+#define SCU_UNSOLICITED_FRAME_BUFFER_SIZE   (1024)
+#define SCU_INVALID_FRAME_INDEX             (0xFFFF)
+
+#define SCU_IO_REQUEST_MAX_SGE_SIZE         (0x00FFFFFF)
+#define SCU_IO_REQUEST_MAX_TRANSFER_LENGTH  (0x00FFFFFF)
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCU_CONSTANTS_H_
diff --git a/sys/dev/disk/isci/scil/scu_event_codes.h b/sys/dev/disk/isci/scil/scu_event_codes.h
new file mode 100644
index 0000000..09bfad0
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scu_event_codes.h
@@ -0,0 +1,343 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scu_event_codes.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef __SCU_EVENT_CODES_HEADER__
+#define __SCU_EVENT_CODES_HEADER__
+
+/**
+ * @file
+ *
+ * @brief This file contains the constants and macros for the SCU event codes.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#define SCU_EVENT_TYPE_CODE_SHIFT      24
+#define SCU_EVENT_TYPE_CODE_MASK       0x0F000000
+
+#define SCU_EVENT_SPECIFIC_CODE_SHIFT  18
+#define SCU_EVENT_SPECIFIC_CODE_MASK   0x00FC0000
+
+#define SCU_EVENT_CODE_MASK \
+   (SCU_EVENT_TYPE_CODE_MASK | SCU_EVENT_SPECIFIC_CODE_MASK)
+
+/**
+ * This macro constructs an SCU event type from the type value.
+ */
+#define SCU_EVENT_TYPE(type) \
+   ((U32)(type) << SCU_EVENT_TYPE_CODE_SHIFT)
+
+/**
+ * This macro constructs an SCU event specifier from the code value.
+ */
+#define SCU_EVENT_SPECIFIC(code) \
+   ((U32)(code) << SCU_EVENT_SPECIFIC_CODE_SHIFT)
+
+/**
+ * This macro constructs a combines an SCU event type and SCU event specifier
+ * from the type and code values.
+ */
+#define SCU_EVENT_MESSAGE(type, code) \
+   ((type) | SCU_EVENT_SPECIFIC(code))
+
+/**
+ * @name SCU_EVENT_TYPES
+ */
+/*@{*/
+#define SCU_EVENT_TYPE_SMU_COMMAND_ERROR  SCU_EVENT_TYPE(0x08)
+#define SCU_EVENT_TYPE_SMU_PCQ_ERROR      SCU_EVENT_TYPE(0x09)
+#define SCU_EVENT_TYPE_SMU_ERROR          SCU_EVENT_TYPE(0x00)
+#define SCU_EVENT_TYPE_TRANSPORT_ERROR    SCU_EVENT_TYPE(0x01)
+#define SCU_EVENT_TYPE_BROADCAST_CHANGE   SCU_EVENT_TYPE(0x02)
+#define SCU_EVENT_TYPE_OSSP_EVENT         SCU_EVENT_TYPE(0x03)
+#define SCU_EVENT_TYPE_FATAL_MEMORY_ERROR SCU_EVENT_TYPE(0x0F)
+#define SCU_EVENT_TYPE_RNC_SUSPEND_TX     SCU_EVENT_TYPE(0x04)
+#define SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX  SCU_EVENT_TYPE(0x05)
+#define SCU_EVENT_TYPE_RNC_OPS_MISC       SCU_EVENT_TYPE(0x06)
+#define SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT SCU_EVENT_TYPE(0x07)
+#define SCU_EVENT_TYPE_ERR_CNT_EVENT      SCU_EVENT_TYPE(0x0A)
+/*@}*/
+
+/**
+ * @name SCU_EVENT_SPECIFIERS
+ */
+/*@{*/
+#define SCU_EVENT_SPECIFIER_DRIVER_SUSPEND 0x20
+#define SCU_EVENT_SPECIFIER_RNC_RELEASE    0x00
+/*@}*/
+
+/**
+ * @name SMU_COMMAND_EVENTS
+ */
+/*@{*/
+#define SCU_EVENT_INVALID_CONTEXT_COMMAND \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_COMMAND_ERROR, 0x00)
+/*@}*/
+
+/**
+ * @name SMU_PCQ_EVENTS
+ */
+/*@{*/
+#define SCU_EVENT_UNCORRECTABLE_PCQ_ERROR \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_PCQ_ERROR, 0x00)
+/*@}*/
+
+/**
+ *  @name SMU_EVENTS
+ */
+/*@{*/
+#define SCU_EVENT_UNCORRECTABLE_REGISTER_WRITE \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_ERROR, 0x02)
+#define SCU_EVENT_UNCORRECTABLE_REGISTER_READ \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_ERROR, 0x03)
+#define SCU_EVENT_PCIE_INTERFACE_ERROR \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_ERROR, 0x04)
+#define SCU_EVENT_FUNCTION_LEVEL_RESET \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_ERROR, 0x05)
+/*@}*/
+
+/**
+ * @name TRANSPORT_LEVEL_ERRORS
+ */
+/*@{*/
+#define SCU_EVENT_ACK_NAK_TIMEOUT_ERROR \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_TRANSPORT_ERROR, 0x00)
+/*@}*/
+
+/**
+ * @name BROADCAST_CHANGE_EVENTS
+ */
+/*@{*/
+#define SCU_EVENT_BROADCAST_CHANGE \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x01)
+#define SCU_EVENT_BROADCAST_RESERVED0 \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x02)
+#define SCU_EVENT_BROADCAST_RESERVED1 \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x03)
+#define SCU_EVENT_BROADCAST_SES \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x04)
+#define SCU_EVENT_BROADCAST_EXPANDER \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x05)
+#define SCU_EVENT_BROADCAST_AEN \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x06)
+#define SCU_EVENT_BROADCAST_RESERVED3 \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x07)
+#define SCU_EVENT_BROADCAST_RESERVED4 \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x08)
+#define SCU_EVENT_PE_SUSPENDED \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x09)
+/*@}*/
+
+/**
+ * @name OSSP_EVENTS
+ */
+/*@{*/
+#define SCU_EVENT_PORT_SELECTOR_DETECTED \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x10)
+#define SCU_EVENT_SENT_PORT_SELECTION \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x11)
+#define SCU_EVENT_HARD_RESET_TRANSMITTED \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x12)
+#define SCU_EVENT_HARD_RESET_RECEIVED \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x13)
+#define SCU_EVENT_RECEIVED_IDENTIFY_TIMEOUT \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x15)
+#define SCU_EVENT_LINK_FAILURE \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x16)
+#define SCU_EVENT_SATA_SPINUP_HOLD \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x17)
+#define SCU_EVENT_SAS_15_SSC \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x18)
+#define SCU_EVENT_SAS_15 \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x19)
+#define SCU_EVENT_SAS_30_SSC \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1A)
+#define SCU_EVENT_SAS_30 \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1B)
+#define SCU_EVENT_SAS_60_SSC \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1C)
+#define SCU_EVENT_SAS_60 \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1D)
+#define SCU_EVENT_SATA_15_SSC \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1E)
+#define SCU_EVENT_SATA_15 \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1F)
+#define SCU_EVENT_SATA_30_SSC \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x20)
+#define SCU_EVENT_SATA_30 \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x21)
+#define SCU_EVENT_SATA_60_SSC \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x22)
+#define SCU_EVENT_SATA_60 \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x23)
+#define SCU_EVENT_SAS_PHY_DETECTED \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x24)
+#define SCU_EVENT_SATA_PHY_DETECTED \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x25)
+/*@}*/
+
+/**
+ * @name FATAL_INTERNAL_MEMORY_ERROR_EVENTS
+ */
+/*@{*/
+#define SCU_EVENT_TSC_RNSC_UNCORRECTABLE_ERROR \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_FATAL_MEMORY_ERROR,  0x00)
+#define SCU_EVENT_TC_RNC_UNCORRECTABLE_ERROR \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_FATAL_MEMORY_ERROR,  0x01)
+#define SCU_EVENT_ZPT_UNCORRECTABLE_ERROR \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_FATAL_MEMORY_ERROR,  0x02)
+/*@}*/
+
+/**
+ * @name REMOTE_NODE_SUSPEND_EVENTS
+ */
+/*@{*/
+#define SCU_EVENT_TL_RNC_SUSPEND_TX \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_SUSPEND_TX, 0x00)
+#define SCU_EVENT_TL_RNC_SUSPEND_TX_RX \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX, 0x00)
+#define SCU_EVENT_TL_RNC_SUSPEND_TX_DONE_DATA_LEN_ERR \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_SUSPEND_TX, 0x1A)
+#define SCU_EVENT_TL_RNC_SUSPEND_TX_DONE_OFFSET_ERR \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_SUSPEND_TX, 0x20)
+#define SCU_EVENT_TL_RNC_SUSPEND_TX_DONE_DMASETUP_DIERR \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_SUSPEND_TX, 0x27)
+#define SCU_EVENT_TL_RNC_SUSPEND_TX_DONE_XFERCNT_ERR \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_SUSPEND_TX, 0x28)
+#define SCU_EVENT_TL_RNC_SUSPEND_TX_RX_DONE_PLD_LEN_ERR \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX, 0x21)
+#define SCU_EVENT_DRIVER_POST_RNC_SUSPEND_TX \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_SUSPEND_TX, 0x20)
+#define SCU_EVENT_DRIVER_POST_RNC_SUSPEND_TX_RX \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX, 0x20)
+/*@}*/
+
+/**
+ * @name REMOTE_NODE_MISC_EVENTS
+ */
+/*@{*/
+#define SCU_EVENT_POST_RCN_RELEASE \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC,SCU_EVENT_SPECIFIER_RNC_RELEASE)
+#define SCU_EVENT_POST_IT_NEXUS_LOSS_TIMER_ENABLE \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, 0x01)
+#define SCU_EVENT_POST_IT_NEXUS_LOSS_TIMER_DISABLE \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, 0x02)
+#define SCU_EVENT_POST_RNC_COMPLETE \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, 0x03)
+#define SCU_EVENT_POST_RNC_INVALIDATE_COMPLETE \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, 0x04)
+/*@}*/
+
+/**
+ * @name ERROR_COUNT_EVENT
+ */
+/*@{*/
+#define SCU_ERR_CNT_RX_CREDIT_BLOCKED_RECEIVED_INDEX  0x00
+#define SCU_ERR_CNT_TX_DONE_CREDIT_TIMEOUT_INDEX      0x01
+#define SCU_ERR_CNT_RX_DONE_CREDIT_TIMEOUT_INDEX      0x02
+#define SCU_ERR_CNT_INACTIVITY_TIMER_EXPIRED_INDEX    0x03
+#define SCU_ERR_CNT_TX_DONE_ACK_NAK_TIMEOUT_INDEX     0x04
+#define SCU_ERR_CNT_RX_DONE_ACK_NAK_TIMEOUT_INDEX     0x05
+#define SCU_ERR_CNT_MAX_INDEX                         0x06
+
+#define SCU_EVENT_ERR_CNT(name) \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_ERR_CNT_EVENT, SCU_ERR_CNT_ ## name ## _INDEX)
+/*@}*/
+
+/**
+ * This macro returns the SCU event type from the event code.
+ */
+#define scu_get_event_type(event_code) \
+   ((event_code) & SCU_EVENT_TYPE_CODE_MASK)
+
+/**
+ * This macro returns the SCU event specifier from the event code.
+ */
+#define scu_get_event_specifier(event_code) \
+   ((event_code) & SCU_EVENT_SPECIFIC_CODE_MASK)
+
+/**
+ * This macro returns the combined SCU event type and SCU event specifier from
+ * the event code.
+ */
+#define scu_get_event_code(event_code) \
+   ((event_code) & SCU_EVENT_CODE_MASK)
+
+
+/**
+ * @name PTS_SCHEDULE_EVENT
+ */
+/*@{*/
+#define SCU_EVENT_SMP_RESPONSE_NO_PE \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT, 0x00)
+#define SCU_EVENT_SPECIFIC_SMP_RESPONSE_NO_PE \
+   scu_get_event_specifier(SCU_EVENT_SMP_RESPONSE_NO_PE)
+
+#define SCU_EVENT_TASK_TIMEOUT \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT, 0x01)
+#define SCU_EVENT_SPECIFIC_TASK_TIMEOUT \
+   scu_get_event_specifier(SCU_EVENT_TASK_TIMEOUT)
+
+#define SCU_EVENT_IT_NEXUS_TIMEOUT \
+   SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT, 0x02)
+#define SCU_EVENT_SPECIFIC_IT_NEXUS_TIMEOUT \
+   scu_get_event_specifier(SCU_EVENT_IT_NEXUS_TIMEOUT)
+/*@}*/
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // __SCU_EVENT_CODES_HEADER__
diff --git a/sys/dev/disk/isci/scil/scu_registers.h b/sys/dev/disk/isci/scil/scu_registers.h
new file mode 100644
index 0000000..b967e36
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scu_registers.h
@@ -0,0 +1,2121 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scu_registers.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCU_REGISTERS_H_
+#define _SCU_REGISTERS_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains the constants and structures for the SCU memory
+ * mapped registers.
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <dev/disk/isci/scil/sci_types.h>
+#include <dev/disk/isci/scil/scu_viit_data.h>
+
+
+
+// Generate a value for an SCU register
+#define SCU_GEN_VALUE(name, value) \
+   (((U32)(value) << name ## _SHIFT) & (name ## _MASK))
+
+// Generate a bit value for an SCU register
+// Make sure that the register MASK is just a single bit
+#define SCU_GEN_BIT(name) \
+      SCU_GEN_VALUE(name, ((U32)1))
+
+#define SCU_SET_BIT(name, reg_value) \
+   ((reg_value) | SCU_GEN_BIT(name))
+
+#define SCU_CLEAR_BIT(name, reg_value) \
+   ((reg_value) $ ~(SCU_GEN_BIT(name)))
+
+//*****************************************************************************
+// Unions for bitfield definitions of SCU Registers
+// SMU Post Context Port
+//*****************************************************************************
+#define SMU_POST_CONTEXT_PORT_CONTEXT_INDEX_SHIFT         (0UL)
+#define SMU_POST_CONTEXT_PORT_CONTEXT_INDEX_MASK          (0x00000FFFUL)
+#define SMU_POST_CONTEXT_PORT_LOGICAL_PORT_INDEX_SHIFT    (12UL)
+#define SMU_POST_CONTEXT_PORT_LOGICAL_PORT_INDEX_MASK     (0x0000F000UL)
+#define SMU_POST_CONTEXT_PORT_PROTOCOL_ENGINE_SHIFT       (16UL)
+#define SMU_POST_CONTEXT_PORT_PROTOCOL_ENGINE_MASK        (0x00030000UL)
+#define SMU_POST_CONTEXT_PORT_COMMAND_CONTEXT_SHIFT       (18UL)
+#define SMU_POST_CONTEXT_PORT_COMMAND_CONTEXT_MASK        (0x00FC0000UL)
+#define SMU_POST_CONTEXT_PORT_RESERVED_MASK               (0xFF000000UL)
+
+#define SMU_PCP_GEN_VAL(name, value) \
+    SCU_GEN_VALUE(SMU_POST_CONTEXT_PORT_##name, value)
+
+//*****************************************************************************
+#define SMU_INTERRUPT_STATUS_COMPLETION_SHIFT       (31UL)
+#define SMU_INTERRUPT_STATUS_COMPLETION_MASK        (0x80000000UL)
+#define SMU_INTERRUPT_STATUS_QUEUE_SUSPEND_SHIFT    (1UL)
+#define SMU_INTERRUPT_STATUS_QUEUE_SUSPEND_MASK     (0x00000002UL)
+#define SMU_INTERRUPT_STATUS_QUEUE_ERROR_SHIFT      (0UL)
+#define SMU_INTERRUPT_STATUS_QUEUE_ERROR_MASK       (0x00000001UL)
+#define SMU_INTERRUPT_STATUS_RESERVED_MASK          (0x7FFFFFFCUL)
+
+#define SMU_ISR_GEN_BIT(name) \
+    SCU_GEN_BIT(SMU_INTERRUPT_STATUS_##name)
+
+#define SMU_ISR_QUEUE_ERROR   SMU_ISR_GEN_BIT(QUEUE_ERROR)
+#define SMU_ISR_QUEUE_SUSPEND SMU_ISR_GEN_BIT(QUEUE_SUSPEND)
+#define SMU_ISR_COMPLETION    SMU_ISR_GEN_BIT(COMPLETION)
+
+//*****************************************************************************
+#define SMU_INTERRUPT_MASK_COMPLETION_SHIFT         (31UL)
+#define SMU_INTERRUPT_MASK_COMPLETION_MASK          (0x80000000UL)
+#define SMU_INTERRUPT_MASK_QUEUE_SUSPEND_SHIFT      (1UL)
+#define SMU_INTERRUPT_MASK_QUEUE_SUSPEND_MASK       (0x00000002UL)
+#define SMU_INTERRUPT_MASK_QUEUE_ERROR_SHIFT        (0UL)
+#define SMU_INTERRUPT_MASK_QUEUE_ERROR_MASK         (0x00000001UL)
+#define SMU_INTERRUPT_MASK_RESERVED_MASK            (0x7FFFFFFCUL)
+
+#define SMU_IMR_GEN_BIT(name) \
+    SCU_GEN_BIT(SMU_INTERRUPT_MASK_##name)
+
+#define SMU_IMR_QUEUE_ERROR   SMU_IMR_GEN_BIT(QUEUE_ERROR)
+#define SMU_IMR_QUEUE_SUSPEND SMU_IMR_GEN_BIT(QUEUE_SUSPEND)
+#define SMU_IMR_COMPLETION    SMU_IMR_GEN_BIT(COMPLETION)
+
+//*****************************************************************************
+#define SMU_INTERRUPT_COALESCING_CONTROL_TIMER_SHIFT    (0UL)
+#define SMU_INTERRUPT_COALESCING_CONTROL_TIMER_MASK     (0x0000001FUL)
+#define SMU_INTERRUPT_COALESCING_CONTROL_NUMBER_SHIFT   (8UL)
+#define SMU_INTERRUPT_COALESCING_CONTROL_NUMBER_MASK    (0x0000FF00UL)
+#define SMU_INTERRUPT_COALESCING_CONTROL_RESERVED_MASK  (0xFFFF00E0UL)
+
+#define SMU_ICC_GEN_VAL(name, value) \
+    SCU_GEN_VALUE(SMU_INTERRUPT_COALESCING_CONTROL_##name, value)
+
+//*****************************************************************************
+#define SMU_TASK_CONTEXT_RANGE_START_SHIFT      (0UL)
+#define SMU_TASK_CONTEXT_RANGE_START_MASK       (0x00000FFFUL)
+#define SMU_TASK_CONTEXT_RANGE_ENDING_SHIFT     (16UL)
+#define SMU_TASK_CONTEXT_RANGE_ENDING_MASK      (0x0FFF0000UL)
+#define SMU_TASK_CONTEXT_RANGE_ENABLE_SHIFT     (31UL)
+#define SMU_TASK_CONTEXT_RANGE_ENABLE_MASK      (0x80000000UL)
+#define SMU_TASK_CONTEXT_RANGE_RESERVED_MASK    (0x7000F000UL)
+
+#define SMU_TCR_GEN_VAL(name, value) \
+    SCU_GEN_VALUE(SMU_TASK_CONTEXT_RANGE_##name, value)
+
+#define SMU_TCR_GEN_BIT(name, value) \
+    SCU_GEN_BIT(SMU_TASK_CONTEXT_RANGE_##name)
+
+//*****************************************************************************
+
+#define SMU_COMPLETION_QUEUE_PUT_POINTER_SHIFT          (0UL)
+#define SMU_COMPLETION_QUEUE_PUT_POINTER_MASK           (0x00003FFFUL)
+#define SMU_COMPLETION_QUEUE_PUT_CYCLE_BIT_SHIFT        (15UL)
+#define SMU_COMPLETION_QUEUE_PUT_CYCLE_BIT_MASK         (0x00008000UL)
+#define SMU_COMPLETION_QUEUE_PUT_EVENT_POINTER_SHIFT    (16UL)
+#define SMU_COMPLETION_QUEUE_PUT_EVENT_POINTER_MASK     (0x03FF0000UL)
+#define SMU_COMPLETION_QUEUE_PUT_EVENT_CYCLE_BIT_SHIFT  (26UL)
+#define SMU_COMPLETION_QUEUE_PUT_EVENT_CYCLE_BIT_MASK   (0x04000000UL)
+#define SMU_COMPLETION_QUEUE_PUT_RESERVED_MASK          (0xF8004000UL)
+
+#define SMU_CQPR_GEN_VAL(name, value) \
+    SCU_GEN_VALUE(SMU_COMPLETION_QUEUE_PUT_##name, value)
+
+#define SMU_CQPR_GEN_BIT(name) \
+    SCU_GEN_BIT(SMU_COMPLETION_QUEUE_PUT_##name)
+
+//*****************************************************************************
+
+#define SMU_COMPLETION_QUEUE_GET_POINTER_SHIFT          (0UL)
+#define SMU_COMPLETION_QUEUE_GET_POINTER_MASK           (0x00003FFFUL)
+#define SMU_COMPLETION_QUEUE_GET_CYCLE_BIT_SHIFT        (15UL)
+#define SMU_COMPLETION_QUEUE_GET_CYCLE_BIT_MASK         (0x00008000UL)
+#define SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_SHIFT    (16UL)
+#define SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_MASK     (0x03FF0000UL)
+#define SMU_COMPLETION_QUEUE_GET_EVENT_CYCLE_BIT_SHIFT  (26UL)
+#define SMU_COMPLETION_QUEUE_GET_EVENT_CYCLE_BIT_MASK   (0x04000000UL)
+#define SMU_COMPLETION_QUEUE_GET_ENABLE_SHIFT           (30UL)
+#define SMU_COMPLETION_QUEUE_GET_ENABLE_MASK            (0x40000000UL)
+#define SMU_COMPLETION_QUEUE_GET_EVENT_ENABLE_SHIFT     (31UL)
+#define SMU_COMPLETION_QUEUE_GET_EVENT_ENABLE_MASK      (0x80000000UL)
+#define SMU_COMPLETION_QUEUE_GET_RESERVED_MASK          (0x38004000UL)
+
+#define SMU_CQGR_GEN_VAL(name, value) \
+    SCU_GEN_VALUE(SMU_COMPLETION_QUEUE_GET_##name, value)
+
+#define SMU_CQGR_GEN_BIT(name) \
+    SCU_GEN_BIT(SMU_COMPLETION_QUEUE_GET_##name)
+
+#define SMU_CQGR_CYCLE_BIT \
+    SMU_CQGR_GEN_BIT(CYCLE_BIT)
+
+#define SMU_CQGR_EVENT_CYCLE_BIT \
+    SMU_CQGR_GEN_BIT(EVENT_CYCLE_BIT)
+
+#define SMU_CQGR_GET_POINTER_SET(value) \
+    SMU_CQGR_GEN_VAL(POINTER, value)
+
+
+//*****************************************************************************
+#define SMU_COMPLETION_QUEUE_CONTROL_QUEUE_LIMIT_SHIFT  (0UL)
+#define SMU_COMPLETION_QUEUE_CONTROL_QUEUE_LIMIT_MASK   (0x00003FFFUL)
+#define SMU_COMPLETION_QUEUE_CONTROL_EVENT_LIMIT_SHIFT  (16UL)
+#define SMU_COMPLETION_QUEUE_CONTROL_EVENT_LIMIT_MASK   (0x03FF0000UL)
+#define SMU_COMPLETION_QUEUE_CONTROL_RESERVED_MASK      (0xFC00C000UL)
+
+#define SMU_CQC_GEN_VAL(name, value) \
+    SCU_GEN_VALUE(SMU_COMPLETION_QUEUE_CONTROL_##name, value)
+
+#define SMU_CQC_QUEUE_LIMIT_SET(value) \
+    SMU_CQC_GEN_VAL(QUEUE_LIMIT, value)
+
+#define SMU_CQC_EVENT_LIMIT_SET(value) \
+    SMU_CQC_GEN_VAL(EVENT_LIMIT, value)
+
+
+//*****************************************************************************
+#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_SHIFT    (0UL)
+#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_MASK     (0x00000FFFUL)
+#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_SHIFT    (12UL)
+#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_MASK     (0x00007000UL)
+#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_SHIFT   (15UL)
+#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_MASK    (0x07FF8000UL)
+#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_PEG_SHIFT   (27UL)
+#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_PEG_MASK    (0x08000000UL)
+#define SMU_DEVICE_CONTEXT_CAPACITY_RESERVED_MASK   (0xF0000000UL)
+
+#define SMU_DCC_GEN_VAL(name, value) \
+   SCU_GEN_VALUE(SMU_DEVICE_CONTEXT_CAPACITY_##name, value)
+
+#define SMU_DCC_GET_MAX_PEG(value) \
+   ( \
+         ((U32)((value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_PEG_MASK)) \
+      >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_SHIFT \
+   )
+
+#define SMU_DCC_GET_MAX_LP(value) \
+   ( \
+         ((U32)((value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_MASK)) \
+      >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_SHIFT \
+   )
+
+#define SMU_DCC_GET_MAX_TC(value) \
+   ( \
+         ((U32)((value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_MASK)) \
+      >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_SHIFT \
+   )
+
+#define SMU_DCC_GET_MAX_RNC(value) \
+   ( \
+        ((U32)((value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_MASK)) \
+     >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_SHIFT \
+   )
+
+//*****************************************************************************
+#define SMU_CLOCK_GATING_CONTROL_IDLE_ENABLE_SHIFT    (0UL)
+#define SMU_CLOCK_GATING_CONTROL_IDLE_ENABLE_MASK     (0x00000001UL)
+#define SMU_CLOCK_GATING_CONTROL_XCLK_ENABLE_SHIFT    (1UL)
+#define SMU_CLOCK_GATING_CONTROL_XCLK_ENABLE_MASK     (0x00000002UL)
+#define SMU_CLOCK_GATING_CONTROL_TXCLK_ENABLE_SHIFT   (2UL)
+#define SMU_CLOCK_GATING_CONTROL_TXCLK_ENABLE_MASK    (0x00000004UL)
+#define SMU_CLOCK_GATING_CONTROL_REGCLK_ENABLE_SHIFT  (3UL)
+#define SMU_CLOCK_GATING_CONTROL_REGCLK_ENABLE_MASK   (0x00000008UL)
+#define SMU_CLOCK_GATING_CONTROL_IDLE_TIMEOUT_SHIFT   (16UL)
+#define SMU_CLOCK_GATING_CONTROL_IDLE_TIMEOUT_MASK    (0x000F0000UL)
+#define SMU_CLOCK_GATING_CONTROL_FORCE_IDLE_SHIFT     (31UL)
+#define SMU_CLOCK_GATING_CONTROL_FORCE_IDLE_MASK      (0x80000000UL)
+#define SMU_CLOCK_GATING_CONTROL_RESERVED_MASK        (0x7FF0FFF0UL)
+
+#define SMU_CGUCR_GEN_VAL(name, value) \
+    SCU_GEN_VALUE(SMU_CLOCK_GATING_CONTROL_##name, value)
+
+#define SMU_CGUCR_GEN_BIT(name) \
+    SCU_GEN_BIT(SMU_CLOCK_GATING_CONTROL_##name)
+
+// --------------------------------------------------------------------------
+
+#define SMU_CONTROL_STATUS_TASK_CONTEXT_RANGE_ENABLE_SHIFT      (0UL)
+#define SMU_CONTROL_STATUS_TASK_CONTEXT_RANGE_ENABLE_MASK       (0x00000001UL)
+#define SMU_CONTROL_STATUS_COMPLETION_BYTE_SWAP_ENABLE_SHIFT    (1UL)
+#define SMU_CONTROL_STATUS_COMPLETION_BYTE_SWAP_ENABLE_MASK     (0x00000002UL)
+#define SMU_CONTROL_STATUS_CONTEXT_RAM_INIT_COMPLETED_SHIFT     (16UL)
+#define SMU_CONTROL_STATUS_CONTEXT_RAM_INIT_COMPLETED_MASK      (0x00010000UL)
+#define SMU_CONTROL_STATUS_SCHEDULER_RAM_INIT_COMPLETED_SHIFT   (17UL)
+#define SMU_CONTROL_STATUS_SCHEDULER_RAM_INIT_COMPLETED_MASK    (0x00020000UL)
+#define SMU_CONTROL_STATUS_RESERVED_MASK                        (0xFFFCFFFCUL)
+
+#define SMU_SMUCSR_GEN_BIT(name) \
+   SCU_GEN_BIT(SMU_CONTROL_STATUS_##name)
+
+#define SMU_SMUCSR_SCHEDULER_RAM_INIT_COMPLETED \
+   (SMU_SMUCSR_GEN_BIT(SCHEDULER_RAM_INIT_COMPLETED))
+
+#define SMU_SMUCSR_CONTEXT_RAM_INIT_COMPLETED   \
+   (SMU_SMUCSR_GEN_BIT(CONTEXT_RAM_INIT_COMPLETED))
+
+#define SCU_RAM_INIT_COMPLETED \
+   ( \
+       SMU_SMUCSR_CONTEXT_RAM_INIT_COMPLETED \
+     | SMU_SMUCSR_SCHEDULER_RAM_INIT_COMPLETED \
+   )
+
+// --------------------------------------------------------------------------
+
+#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE0_SHIFT  (0UL)
+#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE0_MASK   (0x00000001UL)
+#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE1_SHIFT  (1UL)
+#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE1_MASK   (0x00000002UL)
+#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE2_SHIFT  (2UL)
+#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE2_MASK   (0x00000004UL)
+#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE3_SHIFT  (3UL)
+#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE3_MASK   (0x00000008UL)
+#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE0_SHIFT  (8UL)
+#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE0_MASK   (0x00000100UL)
+#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE1_SHIFT  (9UL)
+#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE1_MASK   (0x00000200UL)
+#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE2_SHIFT  (10UL)
+#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE2_MASK   (0x00000400UL)
+#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE3_SHIFT  (11UL)
+#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE3_MASK   (0x00000800UL)
+
+#define SMU_RESET_PROTOCOL_ENGINE(peg, pe) \
+    ((1UL << (pe)) << ((peg) * 8UL))
+
+#define SMU_RESET_PEG_PROTOCOL_ENGINES(peg) \
+    ( \
+        SMU_RESET_PROTOCOL_ENGINE(peg, 0) \
+      | SMU_RESET_PROTOCOL_ENGINE(peg, 1) \
+      | SMU_RESET_PROTOCOL_ENGINE(peg, 2) \
+      | SMU_RESET_PROTOCOL_ENGINE(peg, 3) \
+    )
+
+#define SMU_RESET_ALL_PROTOCOL_ENGINES() \
+    ( \
+        SMU_RESET_PEG_PROTOCOL_ENGINES(0) \
+      | SMU_RESET_PEG_PROTOCOL_ENGINES(1) \
+    )
+
+#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG0_LP0_SHIFT  (16UL)
+#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG0_LP0_MASK   (0x00010000UL)
+#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG0_LP2_SHIFT  (17UL)
+#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG0_LP2_MASK   (0x00020000UL)
+#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG1_LP0_SHIFT  (18UL)
+#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG1_LP0_MASK   (0x00040000UL)
+#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG1_LP2_SHIFT  (19UL)
+#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG1_LP2_MASK   (0x00080000UL)
+
+#define SMU_RESET_WIDE_PORT_QUEUE(peg, wide_port) \
+    ((1UL << ((wide_port) / 2)) << ((peg) * 2UL) << 16UL)
+
+#define SMU_SOFTRESET_CONTROL_RESET_PEG0_SHIFT      (20UL)
+#define SMU_SOFTRESET_CONTROL_RESET_PEG0_MASK       (0x00100000UL)
+#define SMU_SOFTRESET_CONTROL_RESET_PEG1_SHIFT      (21UL)
+#define SMU_SOFTRESET_CONTROL_RESET_PEG1_MASK       (0x00200000UL)
+#define SMU_SOFTRESET_CONTROL_RESET_SCU_SHIFT       (22UL)
+#define SMU_SOFTRESET_CONTROL_RESET_SCU_MASK        (0x00400000UL)
+
+// It seems to make sense that if you are going to reset the protocol
+// engine group that you would also reset all of the protocol engines
+#define SMU_RESET_PROTOCOL_ENGINE_GROUP(peg) \
+    ( \
+        (1UL << ((peg) + 20)) \
+      | SMU_RESET_WIDE_PORT_QUEUE(peg, 0) \
+      | SMU_RESET_WIDE_PORT_QUEUE(peg, 1) \
+      | SMU_RESET_PEG_PROTOCOL_ENGINES(peg) \
+    )
+
+#define SMU_RESET_ALL_PROTOCOL_ENGINE_GROUPS() \
+    ( \
+        SMU_RESET_PROTOCOL_ENGINE_GROUP(0) \
+      | SMU_RESET_PROTOCOL_ENGINE_GROUP(1) \
+    )
+
+#define SMU_RESET_SCU()  (0xFFFFFFFF)
+
+
+
+//*****************************************************************************
+#define SMU_TASK_CONTEXT_ASSIGNMENT_STARTING_SHIFT              (0UL)
+#define SMU_TASK_CONTEXT_ASSIGNMENT_STARTING_MASK               (0x00000FFFUL)
+#define SMU_TASK_CONTEXT_ASSIGNMENT_ENDING_SHIFT                (16UL)
+#define SMU_TASK_CONTEXT_ASSIGNMENT_ENDING_MASK                 (0x0FFF0000UL)
+#define SMU_TASK_CONTEXT_ASSIGNMENT_RANGE_CHECK_ENABLE_SHIFT    (31UL)
+#define SMU_TASK_CONTEXT_ASSIGNMENT_RANGE_CHECK_ENABLE_MASK     (0x80000000UL)
+#define SMU_TASK_CONTEXT_ASSIGNMENT_RESERVED_MASK               (0x7000F000UL)
+
+#define SMU_TCA_GEN_VAL(name, value) \
+    SCU_GEN_VALUE(SMU_TASK_CONTEXT_ASSIGNMENT_##name, value)
+
+#define SMU_TCA_GEN_BIT(name) \
+    SCU_GEN_BIT(SMU_TASK_CONTEXT_ASSIGNMENT_##name)
+
+//*****************************************************************************
+#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_CONTROL_QUEUE_SIZE_SHIFT   (0UL)
+#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_CONTROL_QUEUE_SIZE_MASK    (0x00000FFFUL)
+#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_CONTROL_RESERVED_MASK      (0xFFFFF000UL)
+
+#define SCU_UFQC_GEN_VAL(name, value) \
+    SCU_GEN_VALUE(SCU_SDMA_UNSOLICITED_FRAME_QUEUE_CONTROL_##name, value)
+
+#define SCU_UFQC_QUEUE_SIZE_SET(value) \
+    SCU_UFQC_GEN_VAL(QUEUE_SIZE, value)
+
+//*****************************************************************************
+#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_POINTER_SHIFT      (0UL)
+#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_POINTER_MASK       (0x00000FFFUL)
+#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_CYCLE_BIT_SHIFT    (12UL)
+#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_CYCLE_BIT_MASK     (0x00001000UL)
+#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_RESERVED_MASK      (0xFFFFE000UL)
+
+#define SCU_UFQPP_GEN_VAL(name, value) \
+    SCU_GEN_VALUE(SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_##name, value)
+
+#define SCU_UFQPP_GEN_BIT(name) \
+    SCU_GEN_BIT(SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_##name)
+
+//*****************************************************************************
+//* SDMA Registers
+//*****************************************************************************
+#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_POINTER_SHIFT      (0UL)
+#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_POINTER_MASK       (0x00000FFFUL)
+#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_CYCLE_BIT_SHIFT    (12UL)
+#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_CYCLE_BIT_MASK     (12UL)
+#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_ENABLE_BIT_SHIFT   (31UL)
+#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_ENABLE_BIT_MASK    (0x80000000UL)
+#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_RESERVED_MASK      (0x7FFFE000UL)
+
+#define SCU_UFQGP_GEN_VAL(name, value) \
+    SCU_GEN_VALUE(SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_##name, value)
+
+#define SCU_UFQGP_GEN_BIT(name) \
+    SCU_GEN_BIT(SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_##name)
+
+#define SCU_UFQGP_CYCLE_BIT(value) \
+    SCU_UFQGP_GEN_BIT(CYCLE_BIT, value)
+
+#define SCU_UFQGP_GET_POINTER(value) \
+    SCU_UFQGP_GEN_VALUE(POINTER, value)
+
+#define SCU_UFQGP_ENABLE(value) \
+   (SCU_UFQGP_GEN_BIT(ENABLE) | value)
+
+#define SCU_UFQGP_DISABLE(value) \
+   (~SCU_UFQGP_GEN_BIT(ENABLE) & value)
+
+#define SCU_UFQGP_VALUE(bit, value) \
+    (SCU_UFQGP_CYCLE_BIT(bit) | SCU_UFQGP_GET_POINTER(value))
+
+//*****************************************************************************
+#define SCU_PDMA_CONFIGURATION_ADDRESS_MODIFIER_SHIFT                               (0UL)
+#define SCU_PDMA_CONFIGURATION_ADDRESS_MODIFIER_MASK                                (0x0000FFFFUL)
+#define SCU_PDMA_CONFIGURATION_PCI_RELAXED_ORDERING_ENABLE_SHIFT                    (16UL)
+#define SCU_PDMA_CONFIGURATION_PCI_RELAXED_ORDERING_ENABLE_MASK                     (0x00010000UL)
+#define SCU_PDMA_CONFIGURATION_PCI_NO_SNOOP_ENABLE_SHIFT                            (17UL)
+#define SCU_PDMA_CONFIGURATION_PCI_NO_SNOOP_ENABLE_MASK                             (0x00020000UL)
+#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_BYTE_SWAP_SHIFT                   (18UL)
+#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_BYTE_SWAP_MASK                    (0x00040000UL)
+#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_XPI_SGL_FETCH_SHIFT               (19UL)
+#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_XPI_SGL_FETCH_MASK                (0x00080000UL)
+#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_XPI_RX_HEADER_RAM_WRITE_SHIFT     (20UL)
+#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_XPI_RX_HEADER_RAM_WRITE_MASK      (0x00100000UL)
+#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_XPI_UF_ADDRESS_FETCH_SHIFT        (21UL)
+#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_XPI_UF_ADDRESS_FETCH_MASK         (0x00200000UL)
+#define SCU_PDMA_CONFIGURATION_ADDRESS_MODIFIER_SELECT_SHIFT                        (22UL)
+#define SCU_PDMA_CONFIGURATION_ADDRESS_MODIFIER_SELECT_MASK                         (0x00400000UL)
+#define SCU_PDMA_CONFIGURATION_RESERVED_MASK                                        (0xFF800000UL)
+
+#define SCU_PDMACR_GEN_VALUE(name, value) \
+    SCU_GEN_VALUE(SCU_PDMA_CONFIGURATION_##name, value)
+
+#define SCU_PDMACR_GEN_BIT(name) \
+    SCU_GEN_BIT(SCU_PDMA_CONFIGURATION_##name)
+
+#define SCU_PDMACR_BE_GEN_BIT(name) \
+    SCU_PCMACR_GEN_BIT(BIG_ENDIAN_CONTROL_##name)
+
+//*****************************************************************************
+#define SCU_CDMA_CONFIGURATION_PCI_RELAXED_ORDERING_ENABLE_SHIFT                    (8UL)
+#define SCU_CDMA_CONFIGURATION_PCI_RELAXED_ORDERING_ENABLE_MASK                     (0x00000100UL)
+
+#define SCU_CDMACR_GEN_BIT(name) \
+   SCU_GEN_BIT(SCU_CDMA_CONFIGURATION_##name)
+
+//*****************************************************************************
+//* SCU Link Layer Registers
+//*****************************************************************************
+#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_TIMEOUT_SHIFT             (0UL)
+#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_TIMEOUT_MASK              (0x000000FFUL)
+#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_LOCK_TIME_SHIFT           (8UL)
+#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_LOCK_TIME_MASK            (0x0000FF00UL)
+#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_RATE_CHANGE_DELAY_SHIFT   (16UL)
+#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_RATE_CHANGE_DELAY_MASK    (0x00FF0000UL)
+#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_DWORD_SYNC_TIMEOUT_SHIFT  (24UL)
+#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_DWORD_SYNC_TIMEOUT_MASK   (0xFF000000UL)
+#define SCU_LINK_LAYER_SPEED_NECGOIATION_TIMER_VALUES_REQUIRED_MASK             (0x00000000UL)
+#define SCU_LINK_LAYER_SPEED_NECGOIATION_TIMER_VALUES_DEFAULT_MASK              (0x7D00676FUL)
+#define SCU_LINK_LAYER_SPEED_NECGOIATION_TIMER_VALUES_RESERVED_MASK             (0x00FF0000UL)
+
+#define SCU_SAS_SPDTOV_GEN_VALUE(name, value) \
+    SCU_GEN_VALUE(SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_##name, value)
+
+
+#define SCU_LINK_STATUS_DWORD_SYNC_AQUIRED_SHIFT            (2UL)
+#define SCU_LINK_STATUS_DWORD_SYNC_AQUIRED_MASK             (0x00000004UL)
+#define SCU_LINK_STATUS_TRANSMIT_PORT_SELECTION_DONE_SHIFT  (4UL)
+#define SCU_LINK_STATUS_TRANSMIT_PORT_SELECTION_DONE_MASK   (0x00000010UL)
+#define SCU_LINK_STATUS_RECEIVER_CREDIT_EXHAUSTED_SHIFT     (5UL)
+#define SCU_LINK_STATUS_RECEIVER_CREDIT_EXHAUSTED_MASK      (0x00000020UL)
+#define SCU_LINK_STATUS_RESERVED_MASK                       (0xFFFFFFCDUL)
+
+#define SCU_SAS_LLSTA_GEN_BIT(name) \
+    SCU_GEN_BIT(SCU_LINK_STATUS_##name)
+
+
+// TODO: Where is the SATA_PSELTOV register?
+
+//*****************************************************************************
+//* SCU SAS Maximum Arbitration Wait Time Timeout Register
+//*****************************************************************************
+#define SCU_SAS_MAX_ARBITRATION_WAIT_TIME_TIMEOUT_VALUE_SHIFT       (0UL)
+#define SCU_SAS_MAX_ARBITRATION_WAIT_TIME_TIMEOUT_VALUE_MASK        (0x00007FFFUL)
+#define SCU_SAS_MAX_ARBITRATION_WAIT_TIME_TIMEOUT_SCALE_SHIFT       (15UL)
+#define SCU_SAS_MAX_ARBITRATION_WAIT_TIME_TIMEOUT_SCALE_MASK        (0x00008000UL)
+
+#define SCU_SAS_MAWTTOV_GEN_VALUE(name, value) \
+    SCU_GEN_VALUE(SCU_SAS_MAX_ARBITRATION_WAIT_TIME_TIMEOUT_##name, value)
+
+#define SCU_SAS_MAWTTOV_GEN_BIT(name) \
+    SCU_GEN_BIT(SCU_SAS_MAX_ARBITRATION_WAIT_TIME_TIMEOUT_##name)
+
+
+// TODO: Where is the SAS_LNKTOV regsiter?
+// TODO: Where is the SAS_PHYTOV register?
+
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_SMP_TARGET_SHIFT            (1UL)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_SMP_TARGET_MASK             (0x00000002UL)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_STP_TARGET_SHIFT            (2UL)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_STP_TARGET_MASK             (0x00000004UL)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_SSP_TARGET_SHIFT            (3UL)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_SSP_TARGET_MASK             (0x00000008UL)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_DA_SATA_HOST_SHIFT          (8UL)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_DA_SATA_HOST_MASK           (0x00000100UL)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_SMP_INITIATOR_SHIFT         (9UL)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_SMP_INITIATOR_MASK          (0x00000200UL)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_STP_INITIATOR_SHIFT         (10UL)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_STP_INITIATOR_MASK          (0x00000400UL)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_SSP_INITIATOR_SHIFT         (11UL)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_SSP_INITIATOR_MASK          (0x00000800UL)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_REASON_CODE_SHIFT           (16UL)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_REASON_CODE_MASK            (0x000F0000UL)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_ADDRESS_FRAME_TYPE_SHIFT    (24UL)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_ADDRESS_FRAME_TYPE_MASK     (0x0F000000UL)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_DEVICE_TYPE_SHIFT           (28UL)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_DEVICE_TYPE_MASK            (0x70000000UL)
+#define SCU_SAS_TRANSMIT_IDENTIFICATION_RESERVED_MASK               (0x80F0F1F1UL)
+
+#define SCU_SAS_TIID_GEN_VAL(name, value) \
+    SCU_GEN_VALUE(SCU_SAS_TRANSMIT_IDENTIFICATION_##name, value)
+
+#define SCU_SAS_TIID_GEN_BIT(name) \
+    SCU_GEN_BIT(SCU_SAS_TRANSMIT_IDENTIFICATION_##name)
+
+// SAS Identify Frame PHY Identifier Register
+#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_BREAK_REPLY_CAPABLE_SHIFT      (16UL)
+#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_BREAK_REPLY_CAPABLE_MASK       (0x00010000UL)
+#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_REQUESTED_INSIDE_ZPSDS_SHIFT   (17UL)
+#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_REQUESTED_INSIDE_ZPSDS_MASK    (0x00020000UL)
+#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_INSIDE_ZPSDS_PERSISTENT_SHIFT  (18UL)
+#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_INSIDE_ZPSDS_PERSISTENT_MASK   (0x00040000UL)
+#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_ID_SHIFT                       (24UL)
+#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_ID_MASK                        (0xFF000000UL)
+#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_RESERVED_MASK                  (0x00F800FFUL)
+
+#define SCU_SAS_TIPID_GEN_VALUE(name, value) \
+    SCU_GEN_VALUE(SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_##name, value)
+
+#define SCU_SAS_TIPID_GEN_BIT(name) \
+    SCU_GEN_BIT(SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_##name)
+
+
+#define SCU_SAS_PHY_CONFIGURATION_TX_PARITY_CHECK_SHIFT                     (4UL)
+#define SCU_SAS_PHY_CONFIGURATION_TX_PARITY_CHECK_MASK                      (0x00000010UL)
+#define SCU_SAS_PHY_CONFIGURATION_TX_BAD_CRC_SHIFT                          (6UL)
+#define SCU_SAS_PHY_CONFIGURATION_TX_BAD_CRC_MASK                           (0x00000040UL)
+#define SCU_SAS_PHY_CONFIGURATION_DISABLE_SCRAMBLER_SHIFT                   (7UL)
+#define SCU_SAS_PHY_CONFIGURATION_DISABLE_SCRAMBLER_MASK                    (0x00000080UL)
+#define SCU_SAS_PHY_CONFIGURATION_DISABLE_DESCRAMBLER_SHIFT                 (8UL)
+#define SCU_SAS_PHY_CONFIGURATION_DISABLE_DESCRAMBLER_MASK                  (0x00000100UL)
+#define SCU_SAS_PHY_CONFIGURATION_DISABLE_CREDIT_INSERTION_SHIFT            (9UL)
+#define SCU_SAS_PHY_CONFIGURATION_DISABLE_CREDIT_INSERTION_MASK             (0x00000200UL)
+#define SCU_SAS_PHY_CONFIGURATION_SUSPEND_PROTOCOL_ENGINE_SHIFT             (11UL)
+#define SCU_SAS_PHY_CONFIGURATION_SUSPEND_PROTOCOL_ENGINE_MASK              (0x00000800UL)
+#define SCU_SAS_PHY_CONFIGURATION_SATA_SPINUP_HOLD_SHIFT                    (12UL)
+#define SCU_SAS_PHY_CONFIGURATION_SATA_SPINUP_HOLD_MASK                     (0x00001000UL)
+#define SCU_SAS_PHY_CONFIGURATION_TRANSMIT_PORT_SELECTION_SIGNAL_SHIFT      (13UL)
+#define SCU_SAS_PHY_CONFIGURATION_TRANSMIT_PORT_SELECTION_SIGNAL_MASK       (0x00002000UL)
+#define SCU_SAS_PHY_CONFIGURATION_HARD_RESET_SHIFT                          (14UL)
+#define SCU_SAS_PHY_CONFIGURATION_HARD_RESET_MASK                           (0x00004000UL)
+#define SCU_SAS_PHY_CONFIGURATION_OOB_ENABLE_SHIFT                          (15UL)
+#define SCU_SAS_PHY_CONFIGURATION_OOB_ENABLE_MASK                           (0x00008000UL)
+#define SCU_SAS_PHY_CONFIGURATION_ENABLE_FRAME_TX_INSERT_ALIGN_SHIFT        (23UL)
+#define SCU_SAS_PHY_CONFIGURATION_ENABLE_FRAME_TX_INSERT_ALIGN_MASK         (0x00800000UL)
+#define SCU_SAS_PHY_CONFIGURATION_FORWARD_IDENTIFY_FRAME_SHIFT              (27UL)
+#define SCU_SAS_PHY_CONFIGURATION_FORWARD_IDENTIFY_FRAME_MASK               (0x08000000UL)
+#define SCU_SAS_PHY_CONFIGURATION_DISABLE_BYTE_TRANSPOSE_STP_FRAME_SHIFT    (28UL)
+#define SCU_SAS_PHY_CONFIGURATION_DISABLE_BYTE_TRANSPOSE_STP_FRAME_MASK     (0x10000000UL)
+#define SCU_SAS_PHY_CONFIGURATION_OOB_RESET_SHIFT                           (29UL)
+#define SCU_SAS_PHY_CONFIGURATION_OOB_RESET_MASK                            (0x20000000UL)
+#define SCU_SAS_PHY_CONFIGURATION_THREE_IAF_ENABLE_SHIFT                    (30UL)
+#define SCU_SAS_PHY_CONFIGURATION_THREE_IAF_ENABLE_MASK                     (0x40000000UL)
+#define SCU_SAS_PHY_CONFIGURATION_OOB_ALIGN0_ENABLE_SHIFT                   (31UL)
+#define SCU_SAS_PHY_CONFIGURATION_OOB_ALIGN0_ENABLE_MASK                    (0x80000000UL)
+#define SCU_SAS_PHY_CONFIGURATION_REQUIRED_MASK                             (0x0100000FUL)
+#define SCU_SAS_PHY_CONFIGURATION_DEFAULT_MASK                              (0x4180100FUL)
+#define SCU_SAS_PHY_CONFIGURATION_RESERVED_MASK                             (0x00000000UL)
+
+#define SCU_SAS_PCFG_GEN_BIT(name) \
+    SCU_GEN_BIT(SCU_SAS_PHY_CONFIGURATION_##name)
+
+#define SCU_LINK_LAYER_ALIGN_INSERTION_FREQUENCY_GENERAL_SHIFT      (0UL)
+#define SCU_LINK_LAYER_ALIGN_INSERTION_FREQUENCY_GENERAL_MASK       (0x000007FFUL)
+#define SCU_LINK_LAYER_ALIGN_INSERTION_FREQUENCY_CONNECTED_SHIFT    (16UL)
+#define SCU_LINK_LAYER_ALIGN_INSERTION_FREQUENCY_CONNECTED_MASK     (0x00ff0000UL)
+
+#define SCU_ALIGN_INSERTION_FREQUENCY_GEN_VAL(name, value) \
+    SCU_GEN_VALUE(SCU_LINK_LAYER_ALIGN_INSERTION_FREQUENCY_##name, value)
+
+#define SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_COUNT_SHIFT    (0UL)
+#define SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_COUNT_MASK     (0x0003FFFFUL)
+#define SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_ENABLE_SHIFT   (31UL)
+#define SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_ENABLE_MASK    (0x80000000UL)
+#define SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_RESERVED_MASK  (0x7FFC0000UL)
+
+#define SCU_ENSPINUP_GEN_VAL(name, value) \
+    SCU_GEN_VALUE(SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_##name, value)
+
+#define SCU_ENSPINUP_GEN_BIT(name) \
+    SCU_GEN_BIT(SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_##name)
+
+
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_TXSSCTYPE_SHIFT     (1UL)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_TXSSCTYPE_MASK      (0x00000002UL)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_RLLRATE_SHIFT       (4UL)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_RLLRATE_MASK        (0x000000F0UL)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_SWO15GBPS_SHIFT     (8UL)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_SWO15GBPS_MASK      (0x00000100UL)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_SW15GBPS_SHIFT      (9UL)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_SW15GBPS_MASK       (0x00000201UL)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_SWO30GBPS_SHIFT     (10UL)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_SWO30GBPS_MASK      (0x00000401UL)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_SW30GBPS_SHIFT      (11UL)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_SW30GBPS_MASK       (0x00000801UL)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_SWO60GBPS_SHIFT     (12UL)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_SWO60GBPS_MASK      (0x00001001UL)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_SW60GBPS_SHIFT      (13UL)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_SW60GBPS_MASK       (0x00002001UL)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_EVEN_PARITY_SHIFT   (31UL)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_EVEN_PARITY_MASK    (0x80000000UL)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_DEFAULT_MASK        (0x00003F01UL)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_REQUIRED_MASK       (0x00000001UL)
+#define SCU_LINK_LAYER_PHY_CAPABILITIES_RESERVED_MASK       (0x7FFFC00DUL)
+
+#define SCU_SAS_PHYCAP_GEN_VAL(name, value) \
+    SCU_GEN_VALUE(SCU_LINK_LAYER_PHY_CAPABILITIES_##name, value)
+
+#define SCU_SAS_PHYCAP_GEN_BIT(name) \
+    SCU_GEN_BIT(SCU_LINK_LAYER_PHY_CAPABILITIES_##name)
+
+
+#define SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_VIRTUAL_EXPANDER_PHY_ZONE_GROUP_SHIFT  (0UL)
+#define SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_VIRTUAL_EXPANDER_PHY_ZONE_GROUP_MASK   (0x000000FFUL)
+#define SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_INSIDE_SOURCE_ZONE_GROUP_SHIFT         (31UL)
+#define SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_INSIDE_SOURCE_ZONE_GROUP_MASK          (0x80000000UL)
+#define SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_RESERVED_MASK                          (0x7FFFFF00UL)
+
+#define SCU_PSZGCR_GEN_VAL(name, value) \
+    SCU_GEN_VALUE(SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_##name, value)
+
+#define SCU_PSZGCR_GEN_BIT(name) \
+    SCU_GEN_BIT(SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_##name)
+
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE0_LOCKED_SHIFT        (1UL)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE0_LOCKED_MASK         (0x00000002UL)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE0_UPDATING_SHIFT      (2UL)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE0_UPDATING_MASK       (0x00000004UL)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE1_LOCKED_SHIFT        (4UL)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE1_LOCKED_MASK         (0x00000010UL)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE1_UPDATING_SHIFT      (5UL)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE1_UPDATING_MASK       (0x00000020UL)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE0_SHIFT (16UL)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE0_MASK  (0x00030000UL)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE0_SHIFT      (19UL)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE0_MASK       (0x00080000UL)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE1_SHIFT (20UL)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE1_MASK  (0x00300000UL)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE1_SHIFT      (23UL)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE1_MASK       (0x00800000UL)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE2_SHIFT (24UL)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE2_MASK  (0x03000000UL)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE2_SHIFT      (27UL)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE2_MASK       (0x08000000UL)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE3_SHIFT (28UL)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE3_MASK  (0x30000000UL)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE3_SHIFT      (31UL)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE3_MASK       (0x80000000UL)
+#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_RESERVED_MASK             (0x4444FFC9UL)
+
+#define SCU_PEG_SCUVZECR_GEN_VAL(name, val) \
+    SCU_GEN_VALUE(SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_##name, val)
+
+#define SCU_PEG_SCUVZECR_GEN_BIT(name) \
+    SCU_GEN_BIT(SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_##name)
+
+
+//*****************************************************************************
+//* Port Task Scheduler registers shift and mask values
+//*****************************************************************************
+#define SCU_PTSG_CONTROL_IT_NEXUS_TIMEOUT_SHIFT     (0UL)
+#define SCU_PTSG_CONTROL_IT_NEXUS_TIMEOUT_MASK      (0x0000FFFFUL)
+#define SCU_PTSG_CONTROL_TASK_TIMEOUT_SHIFT         (16UL)
+#define SCU_PTSG_CONTROL_TASK_TIMEOUT_MASK          (0x00FF0000UL)
+#define SCU_PTSG_CONTROL_PTSG_ENABLE_SHIFT          (24UL)
+#define SCU_PTSG_CONTROL_PTSG_ENABLE_MASK           (0x01000000UL)
+#define SCU_PTSG_CONTROL_ETM_ENABLE_SHIFT           (25UL)
+#define SCU_PTSG_CONTROL_ETM_ENABLE_MASK            (0x02000000UL)
+#define SCU_PTSG_CONTROL_DEFAULT_MASK               (0x00020002UL)
+#define SCU_PTSG_CONTROL_REQUIRED_MASK              (0x00000000UL)
+#define SCU_PTSG_CONTROL_RESERVED_MASK              (0xFC000000UL)
+
+#define SCU_PTSGCR_GEN_VAL(name, val) \
+    SCU_GEN_VALUE(SCU_PTSG_CONTROL_##name, val)
+
+#define SCU_PTSGCR_GEN_BIT(name) \
+    SCU_GEN_BIT(SCU_PTSG_CONTROL_##name)
+
+
+//*****************************************************************************
+#define SCU_PTSG_REAL_TIME_CLOCK_SHIFT          (0UL)
+#define SCU_PTSG_REAL_TIME_CLOCK_MASK           (0x0000FFFFUL)
+#define SCU_PTSG_REAL_TIME_CLOCK_RESERVED_MASK  (0xFFFF0000UL)
+
+#define SCU_RTCR_GEN_VAL(name, val) \
+    SCU_GEN_VALUE(SCU_PTSG_##name, val)
+
+
+#define SCU_PTSG_REAL_TIME_CLOCK_CONTROL_PRESCALER_VALUE_SHIFT  (0UL)
+#define SCU_PTSG_REAL_TIME_CLOCK_CONTROL_PRESCALER_VALUE_MASK   (0x00FFFFFFUL)
+#define SCU_PTSG_REAL_TIME_CLOCK_CONTROL_RESERVED_MASK          (0xFF000000UL)
+
+#define SCU_RTCCR_GEN_VAL(name, val) \
+   SCU_GEN_VALUE(SCU_PTSG_REAL_TIME_CLOCK_CONTROL_##name, val)
+
+
+#define SCU_PTSG_PORT_TASK_SCHEDULER_CONTROL_SUSPEND_SHIFT  (0UL)
+#define SCU_PTSG_PORT_TASK_SCHEDULER_CONTROL_SUSPEND_MASK   (0x00000001UL)
+#define SCU_PTSG_PORT_TASK_SCHEDULER_CONTROL_ENABLE_SHIFT   (1UL)
+#define SCU_PTSG_PORT_TASK_SCHEDULER_CONTROL_ENABLE_MASK    (0x00000002UL)
+#define SCU_PTSG_PORT_TASK_SCHEDULER_CONTROL_RESERVED_MASK  (0xFFFFFFFCUL)
+
+#define SCU_PTSxCR_GEN_BIT(name) \
+    SCU_GEN_BIT(SCU_PTSG_PORT_TASK_SCHEDULER_CONTROL_##name)
+
+
+#define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_NEXT_RN_VALID_SHIFT             (0UL)
+#define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_NEXT_RN_VALID_MASK              (0x00000001UL)
+#define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_ACTIVE_RNSC_LIST_VALID_SHIFT    (1UL)
+#define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_ACTIVE_RNSC_LIST_VALID_MASK     (0x00000002UL)
+#define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_PTS_SUSPENDED_SHIFT             (2UL)
+#define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_PTS_SUSPENDED_MASK              (0x00000004UL)
+#define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_RESERVED_MASK                   (0xFFFFFFF8UL)
+
+#define SCU_PTSxSR_GEN_BIT(name) \
+    SCU_GEN_BIT(SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_##name)
+
+
+//*****************************************************************************
+//* SGPIO Register shift and mask values
+//*****************************************************************************
+#define SCU_SGPIO_CONTROL_SGPIO_ENABLE_SHIFT                    (0UL)
+#define SCU_SGPIO_CONTROL_SGPIO_ENABLE_MASK                     (0x00000001UL)
+#define SCU_SGPIO_CONTROL_SGPIO_SERIAL_CLOCK_SELECT_SHIFT       (1UL)
+#define SCU_SGPIO_CONTROL_SGPIO_SERIAL_CLOCK_SELECT_MASK        (0x00000002UL)
+#define SCU_SGPIO_CONTROL_SGPIO_SERIAL_SHIFT_WIDTH_SELECT_SHIFT (2UL)
+#define SCU_SGPIO_CONTROL_SGPIO_SERIAL_SHIFT_WIDTH_SELECT_MASK  (0x00000004UL)
+#define SCU_SGPIO_CONTROL_SGPIO_TEST_BIT_SHIFT                  (15UL)
+#define SCU_SGPIO_CONTROL_SGPIO_TEST_BIT_MASK                   (0x00008000UL)
+#define SCU_SGPIO_CONTROL_SGPIO_RESERVED_MASK                   (0xFFFF7FF8UL)
+
+#define SCU_SGICRx_GEN_BIT(name) \
+    SCU_GEN_BIT(SCU_SGPIO_CONTROL_SGPIO_##name)
+
+#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R0_SHIFT      (0UL)
+#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R0_MASK       (0x0000000FUL)
+#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R1_SHIFT      (4UL)
+#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R1_MASK       (0x000000F0UL)
+#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R2_SHIFT      (8UL)
+#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R2_MASK       (0x00000F00UL)
+#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R3_SHIFT      (12UL)
+#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R3_MASK       (0x0000F000UL)
+#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_RESERVED_MASK (0xFFFF0000UL)
+
+#define SCU_SGPBRx_GEN_VAL(name, valueUL) \
+    SCU_GEN_VALUE(SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_##name, value)
+
+#define SCU_SGPIO_START_DRIVE_LOWER_R0_SHIFT        (0UL)
+#define SCU_SGPIO_START_DRIVE_LOWER_R0_MASK         (0x00000003UL)
+#define SCU_SGPIO_START_DRIVE_LOWER_R1_SHIFT        (4UL)
+#define SCU_SGPIO_START_DRIVE_LOWER_R1_MASK         (0x00000030UL)
+#define SCU_SGPIO_START_DRIVE_LOWER_R2_SHIFT        (8UL)
+#define SCU_SGPIO_START_DRIVE_LOWER_R2_MASK         (0x00000300UL)
+#define SCU_SGPIO_START_DRIVE_LOWER_R3_SHIFT        (12UL)
+#define SCU_SGPIO_START_DRIVE_LOWER_R3_MASK         (0x00003000UL)
+#define SCU_SGPIO_START_DRIVE_LOWER_RESERVED_MASK   (0xFFFF8888UL)
+
+#define SCU_SGSDLRx_GEN_VAL(name, value) \
+    SCU_GEN_VALUE(SCU_SGPIO_START_DRIVE_LOWER_##name, value)
+
+#define SCU_SGPIO_START_DRIVE_UPPER_R0_SHIFT        (0UL)
+#define SCU_SGPIO_START_DRIVE_UPPER_R0_MASK         (0x00000003UL)
+#define SCU_SGPIO_START_DRIVE_UPPER_R1_SHIFT        (4UL)
+#define SCU_SGPIO_START_DRIVE_UPPER_R1_MASK         (0x00000030UL)
+#define SCU_SGPIO_START_DRIVE_UPPER_R2_SHIFT        (8UL)
+#define SCU_SGPIO_START_DRIVE_UPPER_R2_MASK         (0x00000300UL)
+#define SCU_SGPIO_START_DRIVE_UPPER_R3_SHIFT        (12UL)
+#define SCU_SGPIO_START_DRIVE_UPPER_R3_MASK         (0x00003000UL)
+#define SCU_SGPIO_START_DRIVE_UPPER_RESERVED_MASK   (0xFFFF8888UL)
+
+#define SCU_SGSDURx_GEN_VAL(name, value) \
+    SCU_GEN_VALUE(SCU_SGPIO_START_DRIVE_LOWER_##name, value)
+
+#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D0_SHIFT      (0UL)
+#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D0_MASK       (0x00000003UL)
+#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D1_SHIFT      (4UL)
+#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D1_MASK       (0x00000030UL)
+#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D2_SHIFT      (8UL)
+#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D2_MASK       (0x00000300UL)
+#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D3_SHIFT      (12UL)
+#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D3_MASK       (0x00003000UL)
+#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_RESERVED_MASK (0xFFFF8888UL)
+
+#define SCU_SGSIDLRx_GEN_VAL(name, valueUL) \
+    SCU_GEN_VALUE(SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_##name, value)
+
+#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D0_SHIFT      (0UL)
+#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D0_MASK       (0x00000003UL)
+#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D1_SHIFT      (4UL)
+#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D1_MASK       (0x00000030UL)
+#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D2_SHIFT      (8UL)
+#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D2_MASK       (0x00000300UL)
+#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D3_SHIFT      (12UL)
+#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D3_MASK       (0x00003000UL)
+#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_RESERVED_MASK (0xFFFF8888UL)
+
+#define SCU_SGSIDURx_GEN_VAL(name, value) \
+    SCU_GEN_VALUE(SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_##name, value)
+
+#define SCU_SGPIO_VENDOR_SPECIFIC_CODE_SHIFT            (0UL)
+#define SCU_SGPIO_VENDOR_SPECIFIC_CODE_MASK             (0x0000000FUL)
+#define SCU_SGPIO_VENDOR_SPECIFIC_CODE_RESERVED_MASK    (0xFFFFFFF0UL)
+
+#define SCU_SGVSCR_GEN_VAL(value) \
+    SCU_GEN_VALUE(SCU_SGPIO_VENDOR_SPECIFIC_CODE##name, value)
+
+#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA0_SHIFT           (0UL)
+#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA0_MASK            (0x00000003UL)
+#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA0_SHIFT    (2UL)
+#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA0_MASK     (0x00000004UL)
+#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA0_SHIFT      (3UL)
+#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA0_MASK       (0x00000008UL)
+#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA1_SHIFT           (4UL)
+#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA1_MASK            (0x00000030UL)
+#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA1_SHIFT    (6UL)
+#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA1_MASK     (0x00000040UL)
+#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA1_SHIFT      (7UL)
+#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA1_MASK       (0x00000080UL)
+#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA2_SHIFT           (8UL)
+#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA2_MASK            (0x00000300UL)
+#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA2_SHIFT    (10UL)
+#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA2_MASK     (0x00000400UL)
+#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA2_SHIFT      (11UL)
+#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA2_MASK       (0x00000800UL)
+#define SCU_SGPIO_OUPUT_DATA_SELECT_RESERVED_MASK               (0xFFFFF000UL)
+
+#define SCU_SGODSR_GEN_VAL(name, value) \
+    SCU_GEN_VALUE(SCU_SGPIO_OUPUT_DATA_SELECT_##name, value)
+
+#define SCU_SGODSR_GEN_BIT(name) \
+    SCU_GEN_BIT(SCU_SGPIO_OUPUT_DATA_SELECT_##name)
+
+#ifdef ARLINGTON_BUILD
+typedef char LEX_REGISTERS_T;
+#endif
+
+//*****************************************************************************
+//* SMU Registers
+//*****************************************************************************
+
+// ----------------------------------------------------------------------------
+// SMU Registers
+// These registers are based off of BAR0
+//
+// To calculate the offset for other functions use
+//       BAR0 + FN# * SystemPageSize * 2
+//
+// The TCA is only accessable from FN#0 (Physical Function) and each
+// is programmed by (BAR0 + SCU_SMU_TCA_OFFSET + (FN# * 0x04)) or
+//    TCA0 for FN#0 is at BAR0 + 0x0400
+//    TCA1 for FN#1 is at BAR0 + 0x0404
+//    etc.
+// ----------------------------------------------------------------------------
+// Accessable to all FN#s
+#define SCU_SMU_PCP_OFFSET          0x0000
+#define SCU_SMU_AMR_OFFSET          0x0004
+#define SCU_SMU_ISR_OFFSET          0x0010
+#define SCU_SMU_IMR_OFFSET          0x0014
+#define SCU_SMU_ICC_OFFSET          0x0018
+#define SCU_SMU_HTTLBAR_OFFSET      0x0020
+#define SCU_SMU_HTTUBAR_OFFSET      0x0024
+#define SCU_SMU_TCR_OFFSET          0x0028
+#define SCU_SMU_CQLBAR_OFFSET       0x0030
+#define SCU_SMU_CQUBAR_OFFSET       0x0034
+#define SCU_SMU_CQPR_OFFSET         0x0040
+#define SCU_SMU_CQGR_OFFSET         0x0044
+#define SCU_SMU_CQC_OFFSET          0x0048
+// Accessable to FN#0 only
+#define SCU_SMU_RNCLBAR_OFFSET      0x0080
+#define SCU_SMU_RNCUBAR_OFFSET      0x0084
+#define SCU_SMU_DCC_OFFSET          0x0090
+#define SCU_SMU_DFC_OFFSET          0x0094
+#define SCU_SMU_SMUCSR_OFFSET       0x0098
+#define SCU_SMU_SCUSRCR_OFFSET      0x009C
+#define SCU_SMU_SMAW_OFFSET         0x00A0
+#define SCU_SMU_SMDW_OFFSET         0x00A4
+// Accessable to FN#0 only
+#define SCU_SMU_TCA_OFFSET          0x0400
+// Accessable to all FN#s
+#define SCU_SMU_MT_MLAR0_OFFSET     0x2000
+#define SCU_SMU_MT_MUAR0_OFFSET     0x2004
+#define SCU_SMU_MT_MDR0_OFFSET      0x2008
+#define SCU_SMU_MT_VCR0_OFFSET      0x200C
+#define SCU_SMU_MT_MLAR1_OFFSET     0x2010
+#define SCU_SMU_MT_MUAR1_OFFSET     0x2014
+#define SCU_SMU_MT_MDR1_OFFSET      0x2018
+#define SCU_SMU_MT_VCR1_OFFSET      0x201C
+#define SCU_SMU_MPBA_OFFSET         0x3000
+
+/**
+ * @struct SMU_REGISTERS
+ *
+ * @brief These are the SMU registers
+ *        See SCU SMU Specification on how this register space is used.
+ */
+typedef struct SMU_REGISTERS
+{
+// 0x0000 PCP
+   U32   post_context_port;
+// 0x0004 AMR
+   U32   address_modifier;
+   U32   reserved_08;
+   U32   reserved_0C;
+// 0x0010 ISR
+   U32   interrupt_status;
+// 0x0014 IMR
+   U32   interrupt_mask;
+// 0x0018 ICC
+   U32   interrupt_coalesce_control;
+   U32   reserved_1C;
+// 0x0020 HTTLBAR
+   U32   host_task_table_lower;
+// 0x0024 HTTUBAR
+   U32   host_task_table_upper;
+// 0x0028 TCR
+   U32   task_context_range;
+   U32   reserved_2C;
+// 0x0030 CQLBAR
+   U32   completion_queue_lower;
+// 0x0034 CQUBAR
+   U32   completion_queue_upper;
+   U32   reserved_38;
+   U32   reserved_3C;
+// 0x0040 CQPR
+   U32   completion_queue_put;
+// 0x0044 CQGR
+   U32   completion_queue_get;
+// 0x0048 CQC
+   U32   completion_queue_control;
+   U32   reserved_4C;
+   U32   reserved_5x[4];
+   U32   reserved_6x[4];
+   U32   reserved_7x[4];
+// Accessable to FN#0 only
+// 0x0080 RNCLBAR
+   U32   remote_node_context_lower;
+// 0x0084 RNCUBAR
+   U32   remote_node_context_upper;
+   U32   reserved_88;
+   U32   reserved_8C;
+// 0x0090 DCC
+   U32   device_context_capacity;
+// 0x0094 DFC
+   U32   device_function_capacity;
+// 0x0098 SMUCSR
+   U32   control_status;
+// 0x009C SCUSRCR
+   U32   soft_reset_control;
+// 0x00A0 SMAW
+   U32   mmr_address_window;
+// 0x00A4 SMDW
+   U32   mmr_data_window;
+// 0x00A8 CGUCR
+   U32   clock_gating_control;
+// 0x00AC CGUPC
+   U32   clock_gating_performance;
+// A whole bunch of reserved space
+   U32   reserved_Bx[4];
+   U32   reserved_Cx[4];
+   U32   reserved_Dx[4];
+   U32   reserved_Ex[4];
+   U32   reserved_Fx[4];
+   U32   reserved_1xx[64];
+   U32   reserved_2xx[64];
+   U32   reserved_3xx[64];
+// Accessable to FN#0 only
+// 0x0400 TCA
+   U32   task_context_assignment[256];
+// MSI-X registers not included
+} SMU_REGISTERS_T;
+
+//*****************************************************************************
+// SDMA Registers
+//*****************************************************************************
+#define SCU_SDMA_BASE               0x6000
+#define SCU_SDMA_PUFATLHAR_OFFSET   0x0000
+#define SCU_SDMA_PUFATUHAR_OFFSET   0x0004
+#define SCU_SDMA_UFLHBAR_OFFSET     0x0008
+#define SCU_SDMA_UFUHBAR_OFFSET     0x000C
+#define SCU_SDMA_UFQC_OFFSET        0x0010
+#define SCU_SDMA_UFQPP_OFFSET       0x0014
+#define SCU_SDMA_UFQGP_OFFSET       0x0018
+#define SCU_SDMA_PDMACR_OFFSET      0x001C
+#define SCU_SDMA_CDMACR_OFFSET      0x0080
+
+/**
+ * @struct SCU_SDMA_REGISTERS
+ *
+ * @brief These are the SCU SDMA Registers
+ *        See SCU SDMA specification on how these registers are used.
+ */
+typedef struct SCU_SDMA_REGISTERS
+{
+// 0x0000 PUFATLHAR
+   U32   uf_address_table_lower;
+// 0x0004 PUFATUHAR
+   U32   uf_address_table_upper;
+// 0x0008 UFLHBAR
+   U32   uf_header_base_address_lower;
+// 0x000C UFUHBAR
+   U32   uf_header_base_address_upper;
+// 0x0010 UFQC
+   U32   unsolicited_frame_queue_control;
+// 0x0014 UFQPP
+   U32   unsolicited_frame_put_pointer;
+// 0x0018 UFQGP
+   U32   unsolicited_frame_get_pointer;
+// 0x001C PDMACR
+   U32   pdma_configuration;
+// Reserved until offset 0x80
+   U32   reserved_0020_007C[0x18];
+// 0x0080 CDMACR
+   U32   cdma_configuration;
+// Remainder SDMA register space
+   U32   reserved_0084_0400[0xDF];
+
+} SCU_SDMA_REGISTERS_T;
+
+//*****************************************************************************
+//* SCU Link Registers
+//*****************************************************************************
+#define SCU_PEG0_OFFSET    0x0000
+#define SCU_PEG1_OFFSET    0x8000
+
+#define SCU_TL0_OFFSET     0x0000
+#define SCU_TL1_OFFSET     0x0400
+#define SCU_TL2_OFFSET     0x0800
+#define SCU_TL3_OFFSET     0x0C00
+
+#define SCU_LL_OFFSET      0x0080
+#define SCU_LL0_OFFSET     (SCU_TL0_OFFSET + SCU_LL_OFFSET)
+#define SCU_LL1_OFFSET     (SCU_TL1_OFFSET + SCU_LL_OFFSET)
+#define SCU_LL2_OFFSET     (SCU_TL2_OFFSET + SCU_LL_OFFSET)
+#define SCU_LL3_OFFSET     (SCU_TL3_OFFSET + SCU_LL_OFFSET)
+
+// Transport Layer Offsets (PEG + TL)
+#define SCU_TLCR_OFFSET         0x0000
+#define SCU_TLADTR_OFFSET       0x0004
+#define SCU_TLTTMR_OFFSET       0x0008
+#define SCU_TLEECR0_OFFSET      0x000C
+#define SCU_STPTLDARNI_OFFSET   0x0010
+
+
+#define SCU_TLCR_HASH_SAS_CHECKING_ENABLE_SHIFT    (0UL)
+#define SCU_TLCR_HASH_SAS_CHECKING_ENABLE_MASK     (0x00000001UL)
+#define SCU_TLCR_CLEAR_TCI_NCQ_MAPPING_TABLE_SHIFT (1UL)
+#define SCU_TLCR_CLEAR_TCI_NCQ_MAPPING_TABLE_MASK  (0x00000002UL)
+#define SCU_TLCR_STP_WRITE_DATA_PREFETCH_SHIFT     (3UL)
+#define SCU_TLCR_STP_WRITE_DATA_PREFETCH_MASK      (0x00000008UL)
+#define SCU_TLCR_CMD_NAK_STATUS_CODE_SHIFT         (4UL)
+#define SCU_TLCR_CMD_NAK_STATUS_CODE_MASK          (0x00000010UL)
+#define SCU_TLCR_RESERVED_MASK                     (0xFFFFFFEBUL)
+
+#define SCU_TLCR_GEN_BIT(name) \
+    SCU_GEN_BIT(SCU_TLCR_##name)
+
+/**
+ * @struct SCU_TRANSPORT_LAYER_REGISTERS
+ *
+ * @brief These are the SCU Transport Layer registers see SSPTL spec for how
+ *        they are used.
+ */
+typedef struct SCU_TRANSPORT_LAYER_REGISTERS
+{
+   // 0x0000 TLCR
+   U32 control;
+   // 0x0004 TLADTR
+   U32 arbitration_delay_timer;
+   // 0x0008 TLTTMR
+   U32 timer_test_mode;
+   // 0x000C reserved
+   U32 reserved_0C;
+   // 0x0010 STPTLDARNI
+   U32   stp_rni;
+   // 0x0014 TLFEWPORCTRL
+   U32 tlfe_wpo_read_control;
+   // 0x0018 TLFEWPORDATA
+   U32 tlfe_wpo_read_data;
+   // 0x001C RXTLSSCSR1
+   U32 rxtl_single_step_control_status_1;
+   // 0x0020 RXTLSSCSR2
+   U32 rxtl_single_step_control_status_2;
+   // 0x0024 AWTRDDCR
+   U32 tlfe_awt_retry_delay_debug_control;
+   // Remainder of TL memory space
+   U32 reserved_0028_007F[0x16];
+
+} SCU_TRANSPORT_LAYER_REGISTERS_T;
+
+// Protocol Engine Group Registers
+#define SCU_SCUVZECRx_OFFSET        0x1080
+
+// Link Layer Offsets (PEG + TL + LL)
+#define SCU_SAS_SPDTOV_OFFSET       0x0000
+#define SCU_SAS_LLSTA_OFFSET        0x0004
+#define SCU_SATA_PSELTOV_OFFSET     0x0008
+#define SCU_SAS_TIMETOV_OFFSET      0x0010
+#define SCU_SAS_LOSTOT_OFFSET       0x0014
+#define SCU_SAS_LNKTOV_OFFSET       0x0018
+#define SCU_SAS_PHYTOV_OFFSET       0x001C
+#define SCU_SAS_AFERCNT_OFFSET      0x0020
+#define SCU_SAS_WERCNT_OFFSET       0x0024
+#define SCU_SAS_TIID_OFFSET         0x0028
+#define SCU_SAS_TIDNH_OFFSET        0x002C
+#define SCU_SAS_TIDNL_OFFSET        0x0030
+#define SCU_SAS_TISSAH_OFFSET       0x0034
+#define SCU_SAS_TISSAL_OFFSET       0x0038
+#define SCU_SAS_TIPID_OFFSET        0x003C
+#define SCU_SAS_TIRES2_OFFSET       0x0040
+#define SCU_SAS_ADRSTA_OFFSET       0x0044
+#define SCU_SAS_MAWTTOV_OFFSET      0x0048
+#define SCU_SAS_ECENCR_OFFSET       0x0050
+#define SCU_SAS_FRPLDFIL_OFFSET     0x0054
+#define SCU_SAS_RFCNT_OFFSET        0x0060
+#define SCU_SAS_TFCNT_OFFSET        0x0064
+#define SCU_SAS_RFDCNT_OFFSET       0x0068
+#define SCU_SAS_TFDCNT_OFFSET       0x006C
+#define SCU_SAS_LERCNT_OFFSET       0x0070
+#define SCU_SAS_RDISERRCNT_OFFSET   0x0074
+#define SCU_SAS_CRERCNT_OFFSET      0x0078
+#define SCU_STPCTL_OFFSET           0x007C
+#define SCU_SAS_PCFG_OFFSET         0x0080
+#define SCU_SAS_CLKSM_OFFSET        0x0084
+#define SCU_SAS_TXCOMWAKE_OFFSET    0x0088
+#define SCU_SAS_TXCOMINIT_OFFSET    0x008C
+#define SCU_SAS_TXCOMSAS_OFFSET     0x0090
+#define SCU_SAS_COMINIT_OFFSET      0x0094
+#define SCU_SAS_COMWAKE_OFFSET      0x0098
+#define SCU_SAS_COMSAS_OFFSET       0x009C
+#define SCU_SAS_SFERCNT_OFFSET      0x00A0
+#define SCU_SAS_CDFERCNT_OFFSET     0x00A4
+#define SCU_SAS_DNFERCNT_OFFSET     0x00A8
+#define SCU_SAS_PRSTERCNT_OFFSET    0x00AC
+#define SCU_SAS_CNTCTL_OFFSET       0x00B0
+#define SCU_SAS_SSPTOV_OFFSET       0x00B4
+#define SCU_FTCTL_OFFSET            0x00B8
+#define SCU_FRCTL_OFFSET            0x00BC
+#define SCU_FTWMRK_OFFSET           0x00C0
+#define SCU_ENSPINUP_OFFSET         0x00C4
+#define SCU_SAS_TRNTOV_OFFSET       0x00C8
+#define SCU_SAS_PHYCAP_OFFSET       0x00CC
+#define SCU_SAS_PHYCTL_OFFSET       0x00D0
+#define SCU_SAS_LLCTL_OFFSET        0x00D8
+#define SCU_AFE_XCVRCR_OFFSET       0x00DC
+#define SCU_AFE_LUTCR_OFFSET        0x00E0
+
+#define SCU_SAS_PHY_TIMER_TIMEOUT_VALUES_ALIGN_DETECTION_SHIFT          (0UL)
+#define SCU_SAS_PHY_TIMER_TIMEOUT_VALUES_ALIGN_DETECTION_MASK           (0x000000FFUL)
+#define SCU_SAS_PHY_TIMER_TIMEOUT_VALUES_HOT_PLUG_SHIFT                 (8UL)
+#define SCU_SAS_PHY_TIMER_TIMEOUT_VALUES_HOT_PLUG_MASK                  (0x0000FF00UL)
+#define SCU_SAS_PHY_TIMER_TIMEOUT_VALUES_COMSAS_DETECTION_SHIFT         (16UL)
+#define SCU_SAS_PHY_TIMER_TIMEOUT_VALUES_COMSAS_DETECTION_MASK          (0x00FF0000UL)
+#define SCU_SAS_PHY_TIMER_TIMEOUT_VALUES_RATE_CHANGE_SHIFT              (24UL)
+#define SCU_SAS_PHY_TIMER_TIMEOUT_VALUES_RATE_CHANGE_MASK               (0xFF000000UL)
+
+#define SCU_SAS_PHYTOV_GEN_VAL(name, value) \
+    SCU_GEN_VALUE(SCU_SAS_PHY_TIMER_TIMEOUT_VALUES_##name, value)
+
+#define SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_SHIFT                  (0UL)
+#define SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_MASK                   (0x00000003UL)
+#define SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN1                   (0UL)
+#define SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN2                   (1UL)
+#define SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN3                   (2UL)
+#define SCU_SAS_LINK_LAYER_CONTROL_BROADCAST_PRIMITIVE_SHIFT            (2UL)
+#define SCU_SAS_LINK_LAYER_CONTROL_BROADCAST_PRIMITIVE_MASK             (0x000003FCUL)
+#define SCU_SAS_LINK_LAYER_CONTROL_CLOSE_NO_ACTIVE_TASK_DISABLE_SHIFT   (16UL)
+#define SCU_SAS_LINK_LAYER_CONTROL_CLOSE_NO_ACTIVE_TASK_DISABLE_MASK    (0x00010000UL)
+#define SCU_SAS_LINK_LAYER_CONTROL_CLOSE_NO_OUTBOUND_TASK_DISABLE_SHIFT (17UL)
+#define SCU_SAS_LINK_LAYER_CONTROL_CLOSE_NO_OUTBOUND_TASK_DISABLE_MASK  (0x00020000UL)
+#define SCU_SAS_LINK_LAYER_CONTROL_NO_OUTBOUND_TASK_TIMEOUT_SHIFT       (24UL)
+#define SCU_SAS_LINK_LAYER_CONTROL_NO_OUTBOUND_TASK_TIMEOUT_MASK        (0xFF000000UL)
+#define SCU_SAS_LINK_LAYER_CONTROL_RESERVED                             (0x00FCFC00UL)
+
+#define SCU_SAS_LLCTL_GEN_VAL(name, value) \
+    SCU_GEN_VALUE(SCU_SAS_LINK_LAYER_CONTROL_##name, value)
+
+#define SCU_SAS_LLCTL_GEN_BIT(name) \
+    SCU_GEN_BIT(SCU_SAS_LINK_LAYER_CONTROL_##name)
+
+//#define SCU_FRXHECR_DCNT_OFFSET      0x00B0
+#define SCU_PSZGCR_OFFSET           0x00E4
+#define SCU_SAS_RECPHYCAP_OFFSET    0x00E8
+//#define SCU_TX_LUTSEL_OFFSET         0x00B8
+
+#define SCU_SAS_PTxC_OFFSET         0x00D4 // Same offset as SAS_TCTSTM
+
+// This macro define the DWORD SYNC ACQUIRED bit in link layer status register.
+#define SCU_SAS_LLSTA_DWORD_SYNCA_BIT   0x4
+
+/**
+ * @struct SCU_LINK_LAYER_REGISTERS
+ *
+ * @brief SCU Link Layer Registers
+ *        See the SCU SSLL Specification on how these registers are used.
+ */
+typedef struct SCU_LINK_LAYER_REGISTERS
+{
+// 0x0000 SAS_SPDTOV
+   U32   speed_negotiation_timers;
+// 0x0004 SAS_LLSTA
+   U32   link_layer_status;
+// 0x0008 SATA_PSELTOV
+   U32   port_selector_timeout;
+   U32   reserved0C;
+// 0x0010 SAS_TIMETOV
+   U32   timeout_unit_value;
+// 0x0014 SAS_RCDTOV
+   U32   rcd_timeout;
+// 0x0018 SAS_LNKTOV
+   U32   link_timer_timeouts;
+// 0x001C SAS_PHYTOV
+   U32   phy_timer_timeout_values;
+// 0x0020 SAS_AFERCNT
+   U32   received_address_frame_error_counter;
+// 0x0024 SAS_WERCNT
+   U32   invalid_dword_counter;
+// 0x0028 SAS_TIID
+   U32   transmit_identification;
+// 0x002C SAS_TIDNH
+   U32   sas_device_name_high;
+// 0x0030 SAS_TIDNL
+   U32   sas_device_name_low;
+// 0x0034 SAS_TISSAH
+   U32   source_sas_address_high;
+// 0x0038 SAS_TISSAL
+   U32   source_sas_address_low;
+// 0x003C SAS_TIPID
+   U32   identify_frame_phy_id;
+// 0x0040 SAS_TIRES2
+   U32   identify_frame_reserved;
+// 0x0044 SAS_ADRSTA
+   U32   received_address_frame;
+// 0x0048 SAS_MAWTTOV
+   U32   maximum_arbitration_wait_timer_timeout;
+// 0x004C SAS_PTxC
+   U32   transmit_primitive;
+// 0x0050 SAS_ECENCR
+   U32   error_counter_event_notification_control;
+// 0x0054 SAS_FRPLDFIL
+   U32   frxq_payload_fill_threshold;
+// 0x0058 SAS_LLHANG_TOT
+   U32   link_layer_hang_detection_timeout;
+   U32   reserved_5C;
+// 0x0060 SAS_RFCNT
+   U32   received_frame_count;
+// 0x0064 SAS_TFCNT
+   U32   transmit_frame_count;
+// 0x0068 SAS_RFDCNT
+   U32   received_dword_count;
+// 0x006C SAS_TFDCNT
+   U32   transmit_dword_count;
+// 0x0070 SAS_LERCNT
+   U32   loss_of_sync_error_count;
+// 0x0074 SAS_RDISERRCNT
+   U32   running_disparity_error_count;
+// 0x0078 SAS_CRERCNT
+   U32   received_frame_crc_error_count;
+// 0x007C STPCTL
+   U32   stp_control;
+// 0x0080 SAS_PCFG
+   U32   phy_configuration;
+// 0x0084 SAS_CLKSM
+   U32   clock_skew_management;
+// 0x0088 SAS_TXCOMWAKE
+   U32   transmit_comwake_signal;
+// 0x008C SAS_TXCOMINIT
+   U32   transmit_cominit_signal;
+// 0x0090 SAS_TXCOMSAS
+   U32   transmit_comsas_signal;
+// 0x0094 SAS_COMINIT
+   U32   cominit_control;
+// 0x0098 SAS_COMWAKE
+   U32   comwake_control;
+// 0x009C SAS_COMSAS
+   U32   comsas_control;
+// 0x00A0 SAS_SFERCNT
+   U32   received_short_frame_count;
+// 0x00A4 SAS_CDFERCNT
+   U32   received_frame_without_credit_count;
+// 0x00A8 SAS_DNFERCNT
+   U32   received_frame_after_done_count;
+// 0x00AC SAS_PRSTERCNT
+   U32   phy_reset_problem_count;
+// 0x00B0 SAS_CNTCTL
+   U32   counter_control;
+// 0x00B4 SAS_SSPTOV
+   U32   ssp_timer_timeout_values;
+// 0x00B8 FTCTL
+   U32   ftx_control;
+// 0x00BC FRCTL
+   U32   frx_control;
+// 0x00C0 FTWMRK
+   U32   ftx_watermark;
+// 0x00C4 ENSPINUP
+   U32   notify_enable_spinup_control;
+// 0x00C8 SAS_TRNTOV
+   U32   sas_training_sequence_timer_values;
+// 0x00CC SAS_PHYCAP
+   U32   phy_capabilities;
+// 0x00D0 SAS_PHYCTL
+   U32   phy_control;
+   U32   reserved_d4;
+// 0x00D8 LLCTL
+   U32   link_layer_control;
+// 0x00DC AFE_XCVRCR
+   U32   afe_xcvr_control;
+// 0x00E0 AFE_LUTCR
+   U32   afe_lookup_table_control;
+// 0x00E4 PSZGCR
+   U32   phy_source_zone_group_control;
+// 0x00E8 SAS_RECPHYCAP
+   U32   receive_phycap;
+   U32   reserved_ec;
+// 0x00F0 SNAFERXRSTCTL
+   U32   speed_negotiation_afe_rx_reset_control;
+// 0x00F4 SAS_SSIPMCTL
+   U32   power_management_control;
+// 0x00F8 SAS_PSPREQ_PRIM
+   U32   sas_pm_partial_request_primitive;
+// 0x00FC SAS_PSSREQ_PRIM
+   U32   sas_pm_slumber_request_primitive;
+// 0x0100 SAS_PPSACK_PRIM
+   U32   sas_pm_ack_primitive_register;
+// 0x0104 SAS_PSNAK_PRIM
+   U32   sas_pm_nak_primitive_register;
+// 0x0108 SAS_SSIPMTOV
+   U32   sas_primitive_timeout;
+   U32   reserved_10c;
+// 0x0110 - 0x011C PLAPRDCTRLxREG
+   U32   pla_product_control[4];
+// 0x0120 PLAPRDSUMREG
+   U32   pla_product_sum;
+// 0x0124 PLACONTROLREG
+   U32   pla_control;
+// Remainder of memory space 896 bytes
+   U32   reserved_0128_037f[0x96];
+
+} SCU_LINK_LAYER_REGISTERS_T;
+
+// 0x00D4 // Same offset as SAS_TCTSTM SAS_PTxC
+//   U32   primitive_transmit_control;
+
+// ----------------------------------------------------------------------------
+// SGPIO
+// ----------------------------------------------------------------------------
+#define SCU_SGPIO_OFFSET         0x1400
+
+//#define SCU_SGPIO_OFFSET         0x6000   // later moves to 0x1400 see HSD 652625
+#define SCU_SGPIO_SGICR_OFFSET   0x0000
+#define SCU_SGPIO_SGPBR_OFFSET   0x0004
+#define SCU_SGPIO_SGSDLR_OFFSET  0x0008
+#define SCU_SGPIO_SGSDUR_OFFSET  0x000C
+#define SCU_SGPIO_SGSIDLR_OFFSET 0x0010
+#define SCU_SGPIO_SGSIDUR_OFFSET 0x0014
+#define SCU_SGPIO_SGVSCR_OFFSET  0x0018
+// Address from 0x0820 to 0x083C
+#define SCU_SGPIO_SGODSR_OFFSET  0x0020
+
+/**
+ * @struct SCU_SGPIO_REGISTERS
+ *
+ * @brief SCU SGPIO Registers
+ *        See the SCU SGPIO Specification on how these registers are used.
+ */
+typedef struct SCU_SGPIO_REGISTERS
+{
+// 0x0000 SGPIO_SGICR
+   U32   interface_control;
+// 0x0004 SGPIO_SGPBR
+   U32   blink_rate;
+// 0x0008 SGPIO_SGSDLR
+   U32   start_drive_lower;
+// 0x000C SGPIO_SGSDUR
+   U32   start_drive_upper;
+// 0x0010 SGPIO_SGSIDLR
+   U32   serial_input_lower;
+// 0x0014 SGPIO_SGSIDUR
+   U32   serial_input_upper;
+// 0x0018 SGPIO_SGVSCR
+   U32   vendor_specific_code;
+// 0x001C Reserved
+   U32   reserved_001C;
+// 0x0020 SGPIO_SGODSR
+   U32   output_data_select[8];
+// Remainder of memory space 256 bytes
+   U32   reserved_1444_14ff[0x30];
+
+} SCU_SGPIO_REGISTERS_T;
+
+//*****************************************************************************
+//* Defines for VIIT entry offsets
+//* Access additional entries by SCU_VIIT_BASE + index * 0x10
+//*****************************************************************************
+#define     SCU_VIIT_BASE     0x1c00
+
+struct SCU_VIIT_REGISTERS
+{
+   U32 registers[256];
+};
+
+//*****************************************************************************
+//* SCU PORT TASK SCHEDULER REGISTERS
+//*****************************************************************************
+
+#define SCU_PTSG_BASE               0x1000
+
+#define SCU_PTSG_PTSGCR_OFFSET      0x0000
+#define SCU_PTSG_RTCR_OFFSET        0x0004
+#define SCU_PTSG_RTCCR_OFFSET       0x0008
+#define SCU_PTSG_PTS0CR_OFFSET      0x0010
+#define SCU_PTSG_PTS0SR_OFFSET      0x0014
+#define SCU_PTSG_PTS1CR_OFFSET      0x0018
+#define SCU_PTSG_PTS1SR_OFFSET      0x001C
+#define SCU_PTSG_PTS2CR_OFFSET      0x0020
+#define SCU_PTSG_PTS2SR_OFFSET      0x0024
+#define SCU_PTSG_PTS3CR_OFFSET      0x0028
+#define SCU_PTSG_PTS3SR_OFFSET      0x002C
+#define SCU_PTSG_PCSPE0CR_OFFSET    0x0030
+#define SCU_PTSG_PCSPE1CR_OFFSET    0x0034
+#define SCU_PTSG_PCSPE2CR_OFFSET    0x0038
+#define SCU_PTSG_PCSPE3CR_OFFSET    0x003C
+#define SCU_PTSG_ETMTSCCR_OFFSET    0x0040
+#define SCU_PTSG_ETMRNSCCR_OFFSET   0x0044
+
+/**
+ * @struct SCU_PORT_TASK_SCHEDULER_REGISTERS
+ *
+ * @brief These are the control/stats pairs for each Port Task Scheduler.
+ *        See the SCU SCHED Specification on how these registers are used.
+ */
+typedef struct SCU_PORT_TASK_SCHEDULER_REGISTERS
+{
+   U32   control;
+   U32   status;
+} SCU_PORT_TASK_SCHEDULER_REGISTERS_T;
+
+typedef U32 SCU_PORT_PE_CONFIGURATION_REGISTER_T;
+
+/**
+ * @struct SCU_PORT_TASK_SCHEDULER_GROUP_REGISTERS
+ *
+ * @brief These are the PORT Task Scheduler registers
+ *        See the SCU SCHED Specification on how these registers are used.
+ */
+typedef struct SCU_PORT_TASK_SCHEDULER_GROUP_REGISTERS
+{
+// 0x0000 PTSGCR
+   U32   control;
+// 0x0004 RTCR
+   U32   real_time_clock;
+// 0x0008 RTCCR
+   U32   real_time_clock_control;
+// 0x000C
+   U32   reserved_0C;
+// 0x0010 PTS0CR
+// 0x0014 PTS0SR
+// 0x0018 PTS1CR
+// 0x001C PTS1SR
+// 0x0020 PTS2CR
+// 0x0024 PTS2SR
+// 0x0028 PTS3CR
+// 0x002C PTS3SR
+   SCU_PORT_TASK_SCHEDULER_REGISTERS_T port[4];
+// 0x0030 PCSPE0CR
+// 0x0034 PCSPE1CR
+// 0x0038 PCSPE2CR
+// 0x003C PCSPE3CR
+   SCU_PORT_PE_CONFIGURATION_REGISTER_T protocol_engine[4];
+// 0x0040 ETMTSCCR
+   U32   tc_scanning_interval_control;
+// 0x0044 ETMRNSCCR
+   U32   rnc_scanning_interval_control;
+// Remainder of memory space 128 bytes
+   U32   reserved_1048_107f[0x0E];
+
+} SCU_PORT_TASK_SCHEDULER_GROUP_REGISTERS_T;
+
+#define SCU_PTSG_SCUVZECR_OFFSET        0x003C
+
+//*****************************************************************************
+//* AFE REGISTERS
+//*****************************************************************************
+#define SCU_AFE_MMR_BASE                  0xE000
+
+#if defined(ARLINGTON_BUILD)
+#define SCU_AFE_PLL_CTL_OFFSET            0x0000
+#define SCU_AFE_RXPI_CTL_OFFSET           0x0004
+#define SCU_AFE_MBIAS_CTL0_OFFSET         0x000C
+#define SCU_AFE_MBIAS_CTL1_OFFSET         0x0010
+#define SCU_AFE_COMM_STA_OFFSET           0x0020
+#define SCU_AFE_RXPI_STA_OFFSET           0x0024
+#define SCU_AFE_XCVR0_CTL0_OFFSET         0x0040
+#define SCU_AFE_XCVR1_CTL0_OFFSET         0x0044
+#define SCU_AFE_XCVR2_CTL0_OFFSET         0x0048
+#define SCU_AFE_XCVR3_CTL0_OFFSET         0x004C
+#define SCU_AFE_XCVR0_CTL1_OFFSET         0x0050
+#define SCU_AFE_XCVR1_CTL1_OFFSET         0x0054
+#define SCU_AFE_XCVR2_CTL1_OFFSET         0x0058
+#define SCU_AFE_XCVR3_CTL1_OFFSET         0x005C
+#define SCU_AFE_XCVR0_RXEQ_CTL_OFFSET     0x0060
+#define SCU_AFE_XCVR1_RXEQ_CTL_OFFSET     0x0064
+#define SCU_AFE_XCVR2_RXEQ_CTL_OFFSET     0x0068
+#define SCU_AFE_XCVR3_RXEQ_CTL_OFFSET     0x006C
+#define SCU_AFE_XCVR0_CDR_STA_OFFSET      0x0080
+#define SCU_AFE_XCVR1_CDR_STA_OFFSET      0x0084
+#define SCU_AFE_XCVR2_CDR_STA_OFFSET      0x0088
+#define SCU_AFE_XCVR3_CDR_STA_OFFSET      0x008C
+#define SCU_AFE_XCVR0_RXEQ_STA0_OFFSET    0x0090
+#define SCU_AFE_XCVR1_RXEQ_STA0_OFFSET    0x0094
+#define SCU_AFE_XCVR2_RXEQ_STA0_OFFSET    0x0098
+#define SCU_AFE_XCVR3_RXEQ_STA0_OFFSET    0x009C
+#define SCU_AFE_XCVR0_RXEQ_STA1_OFFSET    0x00A0
+#define SCU_AFE_XCVR1_RXEQ_STA1_OFFSET    0x00A4
+#define SCU_AFE_XCVR2_RXEQ_STA1_OFFSET    0x00A8
+#define SCU_AFE_XCVR3_RXEQ_STA1_OFFSET    0x00AC
+#define SCU_AFE_DFX_MSTR_CTL_OFFSET       0x0104
+#define SCU_AFE_NTL_CTL_OFFSET            0x010C
+#define SCU_AFE_DFX_XCVR_STA_CLR_OFFSET   0x0120
+#define SCU_AFE_NTL_STA_OFFSET            0x0124
+#define SCU_AFE_DFX_XCVR0_STA0_OFFSET     0x0130
+#define SCU_AFE_DFX_XCVR1_STA0_OFFSET     0x0134
+#define SCU_AFE_DFX_XCVR2_STA0_OFFSET     0x0138
+#define SCU_AFE_DFX_XCVR3_STA0_OFFSET     0x013C
+#define SCU_AFE_DFX_XCVR0_STA1_OFFSET     0x0140
+#define SCU_AFE_DFX_XCVR1_STA1_OFFSET     0x0144
+#define SCU_AFE_DFX_XCVR2_STA1_OFFSET     0x0148
+#define SCU_AFE_DFX_XCVR3_STA1_OFFSET     0x014C
+#define SCU_AFE_DFX_MON_CTL_OFFSET        0x0150
+
+#define SCU_AFE_DFX_RX_CTL0_AFE0_XCVR0_OFFSET       0x0180
+#define SCU_AFE_DFX_RX_CTL0_AFE0_XCVR1_OFFSET       0x0184
+#define SCU_AFE_DFX_RX_CTL0_AFE0_XCVR2_OFFSET       0x0188
+#define SCU_AFE_DFX_RX_CTL0_AFE0_XCVR3_OFFSET       0x018C
+#define SCU_AFE_DFX_RX_CTL0_AFE1_XCVR0_OFFSET       0x0980
+#define SCU_AFE_DFX_RX_CTL0_AFE1_XCVR1_OFFSET       0x0984
+#define SCU_AFE_DFX_RX_CTL0_AFE1_XCVR2_OFFSET       0x0988
+#define SCU_AFE_DFX_RX_CTL0_AFE1_XCVR3_OFFSET       0x098C
+
+#define SCU_AFE_DFX_RX_CTL1_AFE0_XCVR0_OFFSET       0x0190
+#define SCU_AFE_DFX_RX_CTL1_AFE0_XCVR1_OFFSET       0x0194
+#define SCU_AFE_DFX_RX_CTL1_AFE0_XCVR2_OFFSET       0x0198
+#define SCU_AFE_DFX_RX_CTL1_AFE0_XCVR3_OFFSET       0x019C
+#define SCU_AFE_DFX_RX_CTL1_AFE1_XCVR0_OFFSET       0x0990
+#define SCU_AFE_DFX_RX_CTL1_AFE1_XCVR1_OFFSET       0x0994
+#define SCU_AFE_DFX_RX_CTL1_AFE1_XCVR2_OFFSET       0x0998
+#define SCU_AFE_DFX_RX_CTL1_AFE1_XCVR3_OFFSET       0x099C
+
+#define SCU_AFE_PLL_DFX_CTL_OFFSET        0x01C0
+
+#define SCU_AFE_XCVR0_DFX_DATA_OFFSET     0x0200   // [0:0F]
+#define SCU_AFE_XCVR0_CC_OFFSET           0x0240
+#define SCU_AFE_XCVR0_DFX_IR_OFFSET       0x0250   // [0:1F]
+
+#define SCU_AFE_XCVR1_DFX_DATA_OFFSET     0x0300   // [0:0F]
+#define SCU_AFE_XCVR1_CC_OFFSET           0x0340
+#define SCU_AFE_XCVR1_DFX_IR_OFFSET       0x0350   // [0:1F]
+
+#define SCU_AFE_XCVR2_DFX_DATA_OFFSET     0x0400   // [0:0F]
+#define SCU_AFE_XCVR2_CC_OFFSET           0x0440
+#define SCU_AFE_XCVR2_DFX_IR_OFFSET       0x0450   // [0:1F]
+
+#define SCU_AFE_XCVR3_DFX_DATA_OFFSET     0x0500   // [0:0F]
+#define SCU_AFE_XCVR3_CC_OFFSET           0x0540
+#define SCU_AFE_XCVR3_DFX_IR_OFFSET       0x0550   // [0:1F]
+#else // defined(ARLINGTON_BUILD)
+
+#endif // defined(ARLINGTON_BUILD)
+
+/**
+ * @struct SCU_AFE_TRANSCEIVER
+ *
+ * @brief AFE Transceiver Registers
+ *        See SCU AFE Specification for use of these registers.
+ *
+ * @note For ARLINGTON_BUILD see the SCU AFE specification.
+ * @note For PLEASANT_RIDGE_BUILD build see the Uaoa AFE specification.
+ */
+#if defined(ARLINGTON_BUILD)
+   struct SCU_AFE_TRANSCEIVER
+   {
+   // 0x00
+      U32 afe_transceiver_dfx_data[0x10];
+   // 0x40
+      U32 afe_transceiver_dpg_cycle_control;
+   // 0x44 - 0x4c
+      U32 reserved_0044_004c[3];
+   // 0x50
+      U32 afe_transceiver_dfx_instruction[0x20];
+   // 0xd0 - 0xfc
+      U32 reserved_00d0_00fc[0x0C];
+   };
+
+#elif    defined(PLEASANT_RIDGE_BUILD) \
+      || defined(PBG_HBA_A0_BUILD) \
+      || defined(PBG_HBA_A2_BUILD) \
+      || defined(PBG_HBA_BETA_BUILD) \
+      || defined(PBG_BUILD)
+
+   // AFE 0 is at offset 0x0800
+   // AFE 1 is at offset 0x0900
+   // AFE 2 is at offset 0x0a00
+   // AFE 3 is at offset 0x0b00
+   struct SCU_AFE_TRANSCEIVER
+   {
+   // 0x0000 AFE_XCVR_CTRL0
+      U32 afe_xcvr_control0;
+   // 0x0004 AFE_XCVR_CTRL1
+      U32 afe_xcvr_control1;
+   // 0x0008
+      U32 reserved_0008;
+   // 0x000c afe_dfx_rx_control0
+      U32 afe_dfx_rx_control0;
+   // 0x0010 AFE_DFX_RX_CTRL1
+      U32 afe_dfx_rx_control1;
+   // 0x0014
+      U32 reserved_0014;
+   // 0x0018 AFE_DFX_RX_STS0
+      U32 afe_dfx_rx_status0;
+   // 0x001c AFE_DFX_RX_STS1
+      U32 afe_dfx_rx_status1;
+   // 0x0020
+      U32 reserved_0020;
+   // 0x0024 AFE_TX_CTRL
+      U32 afe_tx_control;
+   // 0x0028 AFE_TX_AMP_CTRL0
+      U32 afe_tx_amp_control0;
+   // 0x002c AFE_TX_AMP_CTRL1
+      U32 afe_tx_amp_control1;
+   // 0x0030 AFE_TX_AMP_CTRL2
+      U32 afe_tx_amp_control2;
+   // 0x0034 AFE_TX_AMP_CTRL3
+      U32 afe_tx_amp_control3;
+   // 0x0038 afe_tx_ssc_control
+      U32 afe_tx_ssc_control;
+   // 0x003c
+      U32 reserved_003c;
+   // 0x0040 AFE_RX_SSC_CTRL0
+      U32 afe_rx_ssc_control0;
+   // 0x0044 AFE_RX_SSC_CTRL1
+      U32 afe_rx_ssc_control1;
+   // 0x0048 AFE_RX_SSC_CTRL2
+      U32 afe_rx_ssc_control2;
+   // 0x004c AFE_RX_EQ_STS0
+      U32 afe_rx_eq_status0;
+   // 0x0050 AFE_RX_EQ_STS1
+      U32 afe_rx_eq_status1;
+   // 0x0054 AFE_RX_CDR_STS
+      U32 afe_rx_cdr_status;
+   // 0x0058
+      U32 reserved_0058;
+   // 0x005c AFE_CHAN_CTRL
+      U32 afe_channel_control;
+   // 0x0060-0x006c
+      U32 reserved_0060_006c[0x04];
+   // 0x0070 AFE_XCVR_EC_STS0
+      U32 afe_xcvr_error_capture_status0;
+   // 0x0074 AFE_XCVR_EC_STS1
+      U32 afe_xcvr_error_capture_status1;
+   // 0x0078 AFE_XCVR_EC_STS2
+      U32 afe_xcvr_error_capture_status2;
+   // 0x007c afe_xcvr_ec_status3
+      U32 afe_xcvr_error_capture_status3;
+   // 0x0080 AFE_XCVR_EC_STS4
+      U32 afe_xcvr_error_capture_status4;
+   // 0x0084 AFE_XCVR_EC_STS5
+      U32 afe_xcvr_error_capture_status5;
+   // 0x0088-0x00fc
+      U32 reserved_008c_00fc[0x1e];
+   };
+#else // !defined(PLEASANT_RIDGE_BUILD) && !defined(ARLINGTON_BUILD)
+   #error "Target platform not defined."
+#endif // defined(PLEASANT_RIDGE_BUILD) || defined(ARLINGTON_BUILD)
+
+/**
+ * @struct SCU_AFE_REGISTERS
+ *
+ * @brief AFE Regsiters
+ *        See SCU AFE Specification for use of these registers.
+ */
+#if defined(ARLINGTON_BUILD)
+   typedef struct SCU_AFE_REGISTERS
+   {
+   // 0x0000
+      U32 afe_pll_control;
+   // 0x0004
+      U32 afe_phase_interplator_control;
+   // 0x0008
+      U32 reservd_0008;
+   // 0x000C
+      U32 afe_bias_control[2];
+   // 0x0014 - 0x001c
+      U32 reserved_0014_001c[3];
+   // 0x0020
+      U32 afe_common_status;
+   // 0x0024
+      U32 afe_phase_interpolator_status;
+   // 0x0028 - 0x003C
+      U32 reserved_0028_003c[6];
+   // 0x0040
+      U32 afe_transceiver_control0[4];
+   // 0x0050
+      U32 afe_transceiver_control1[4];
+   // 0x0060
+      U32 afe_transceiver_equalization_control[4];
+   // 0x0070 - 0x007c
+      U32 reserved_0070_007c[4];
+   // 0x0080
+      U32 afe_transceiver_cdr_status[4];
+   // 0x0090
+      U32 afe_transceiver_rx_equaliation_status_register0[4];
+   // 0x00A0
+      U32 afe_transceiver_rx_equaliation_status_register1[4];
+   // 0x00B0 - 0x0100
+      U32 reserved_00b0_0100[0x15];
+   // 0x0104
+      U32 afe_dfx_master_control;
+   // 0x0108
+      U32 reserved_0108;
+   // 0x010c
+      U32 afe_no_touch_leakage_control;
+   // 0x0110 - 0x011C
+      U32 reserved_0110_011c[4];
+   // 0x0120
+      U32 afe_dfx_transceiver_status_clear;
+   // 0x0124
+      U32 afe_no_touch_leakage_status;
+   // 0x0128 - 0x012c
+      U32 reserved_0128_012c[2];
+   // 0x0130
+      U32 afe_dfx_transceiver_status_register0[4];
+   // 0x0140
+      U32 afe_dfx_transceiver_status_register1[4];
+   // 0x0150
+      U32 afe_dfx_transmit_monitor_control;
+   // 0x0154 - 0x017c
+      U32 reserved_0154_017C[0x0B];
+   // 0x0180
+      U32 afe_dfx_receive_control_register0[4];
+   // 0x0190
+      U32 afe_dfx_receive_control_register1[4];
+   // 0x1A0
+      U32 afe_dfx_transmit_control_register[4];
+   // 0x01B0 - 0x01BC
+      U32 reserved_01b0_01bc[4];
+   // 0x01C0
+      U32 afe_pll_dfx_control;
+   // 0x01c4 - 0x01fc
+      U32 reserved_01c4_01fc[0x0F];
+   // 0x0200 - 0x05fc
+      struct SCU_AFE_TRANSCEIVER afe_transceiver[4];
+
+   // 0x0600 - 0x06FC
+      U32 reserved_0600_06FC[0x40];
+
+   // 0x0700
+      struct SCU_AFE_TRANSCEIVER afe_all_transceiver;
+
+      U32 reserved_0800_2000[0x600];
+
+   } SCU_AFE_REGISTERS_T;
+
+#elif    defined(PLEASANT_RIDGE_BUILD) \
+      || defined(PBG_HBA_A0_BUILD) \
+      || defined(PBG_HBA_A2_BUILD) \
+      || defined(PBG_HBA_BETA_BUILD) \
+      || defined(PBG_BUILD)
+
+   /* Uaoa AFE registers */
+   typedef struct SCU_AFE_REGISTERS
+   {
+   // 0Xe000 AFE_BIAS_CTRL
+      U32 afe_bias_control;
+      U32 reserved_0004;
+   // 0x0008 AFE_PLL_CTRL0
+      U32 afe_pll_control0;
+   // 0x000c AFE_PLL_CTRL1
+      U32 afe_pll_control1;
+   // 0x0010 AFE_PLL_CTRL2
+      U32 afe_pll_control2;
+   // 0x0014 AFE_CB_STS
+      U32 afe_common_block_status;
+   // 0x0018-0x007c
+      U32 reserved_18_7c[0x1a];
+   // 0x0080 AFE_PMSN_MCTRL0
+      U32 afe_pmsn_master_control0;
+   // 0x0084 AFE_PMSN_MCTRL1
+      U32 afe_pmsn_master_control1;
+   // 0x0088 AFE_PMSN_MCTRL2
+      U32 afe_pmsn_master_control2;
+   // 0x008C-0x00fc
+      U32 reserved_008c_00fc[0x1D];
+   // 0x0100 AFE_DFX_MST_CTRL0
+      U32 afe_dfx_master_control0;
+   // 0x0104 AFE_DFX_MST_CTRL1
+      U32 afe_dfx_master_control1;
+   // 0x0108 AFE_DFX_DCL_CTRL
+      U32 afe_dfx_dcl_control;
+   // 0x010c AFE_DFX_DMON_CTRL
+      U32 afe_dfx_digital_monitor_control;
+   // 0x0110 AFE_DFX_AMONP_CTRL
+      U32 afe_dfx_analog_p_monitor_control;
+   // 0x0114 AFE_DFX_AMONN_CTRL
+      U32 afe_dfx_analog_n_monitor_control;
+   // 0x0118 AFE_DFX_NTL_STS
+      U32 afe_dfx_ntl_status;
+   // 0x011c AFE_DFX_FIFO_STS0
+      U32 afe_dfx_fifo_status0;
+   // 0x0120 AFE_DFX_FIFO_STS1
+      U32 afe_dfx_fifo_status1;
+   // 0x0124 AFE_DFX_MPAT_CTRL
+      U32 afe_dfx_master_pattern_control;
+   // 0x0128 AFE_DFX_P0_CTRL
+      U32 afe_dfx_p0_control;
+   // 0x012c-0x01a8 AFE_DFX_P0_DRx
+      U32 afe_dfx_p0_data[32];
+   // 0x01ac
+      U32 reserved_01ac;
+   // 0x01b0-0x020c AFE_DFX_P0_IRx
+      U32 afe_dfx_p0_instruction[24];
+   // 0x0210
+      U32 reserved_0210;
+   // 0x0214 AFE_DFX_P1_CTRL
+      U32 afe_dfx_p1_control;
+   // 0x0218-0x245 AFE_DFX_P1_DRx
+      U32 afe_dfx_p1_data[16];
+   // 0x0258-0x029c
+      U32 reserved_0258_029c[0x12];
+   // 0x02a0-0x02bc AFE_DFX_P1_IRx
+      U32 afe_dfx_p1_instruction[8];
+   // 0x02c0-0x2fc
+      U32 reserved_02c0_02fc[0x10];
+   // 0x0300 AFE_DFX_TX_PMSN_CTRL
+      U32 afe_dfx_tx_pmsn_control;
+   // 0x0304 AFE_DFX_RX_PMSN_CTRL
+      U32 afe_dfx_rx_pmsn_control;
+      U32 reserved_0308;
+   // 0x030c AFE_DFX_NOA_CTRL0
+      U32 afe_dfx_noa_control0;
+   // 0x0310 AFE_DFX_NOA_CTRL1
+      U32 afe_dfx_noa_control1;
+   // 0x0314 AFE_DFX_NOA_CTRL2
+      U32 afe_dfx_noa_control2;
+   // 0x0318 AFE_DFX_NOA_CTRL3
+      U32 afe_dfx_noa_control3;
+   // 0x031c AFE_DFX_NOA_CTRL4
+      U32 afe_dfx_noa_control4;
+   // 0x0320 AFE_DFX_NOA_CTRL5
+      U32 afe_dfx_noa_control5;
+   // 0x0324 AFE_DFX_NOA_CTRL6
+      U32 afe_dfx_noa_control6;
+   // 0x0328 AFE_DFX_NOA_CTRL7
+      U32 afe_dfx_noa_control7;
+   // 0x032c-0x07fc
+      U32 reserved_032c_07fc[0x135];
+
+   // 0x0800-0x0bfc
+      struct SCU_AFE_TRANSCEIVER scu_afe_xcvr[4];
+
+   // 0x0c00-0x0ffc
+      U32 reserved_0c00_0ffc[0x0100];
+   } SCU_AFE_REGISTERS_T;
+#else // !defined(PBG_HBA_BUILD) && defined(PLEASANT_RIDGE_BUILD) && !defined(ARLINGTON_BUILD)
+   #error "Target platform not defined."
+#endif // defined(PBG_HBA_BUILD) || defined(PLEASANT_RIDGE_BUILD) || defined(ARLINGTON_BUILD)
+
+
+struct SCU_PROTOCOL_ENGINE_GROUP_REGISTERS
+{
+   U32 table[0xE0];
+};
+
+
+struct SCU_VIIT_IIT
+{
+   U32 table[256];
+};
+
+/**
+ * @brief Placeholder for the ZONE Partition Table information
+ *        ZONING will not be included in the 1.1 release.
+ *
+ */
+struct SCU_ZONE_PARTITION_TABLE
+{
+   U32 table[2048];
+};
+
+/**
+ * @brief CRAM register. MMR base address for CRAMC is 0x6400
+ *        relative to SCUBAR.
+ *
+ */
+struct SCU_COMPLETION_RAM
+{
+   U32 sram_base_address_0;         //0x0000
+   U32 sram_upper_base_address_0;   //0x0004
+   U32 sram_ecc_control_0;          //0x0008
+   U32 sram_ecc_log_0;              //0x000c
+   U32 sram_ecc_addrress_0;         //0x0010
+   U32 sram_ecc_context_address_0;  //0x0014
+   U32 sram_ecc_test_0;             //0x0018
+   U32 sram_parity_control_and_status_0;   //0x001C
+   U32 sram_parity_address_0;              //0x0020
+   U32 sram_parity_upper_address_0;        //0x0024
+   U32 sram_parity_context_0;              //0x0028
+   U32 sram_memory_controller_interrupt_status_0;   //0x002C
+   U32 sram_mcu_read_arbiter_control_0;    //0x0030
+   U32 sram_mcu_write_arbiter_control_0;   //0x0034
+   U32 smcu_error_event_counter_0_0;       //0x0038
+
+   //Remainder CRAM register space
+   U32 reserved_003C_0200[113];
+};
+
+/**
+ * @brief FBRAM registers. MMR base address for FBRAM is
+ *        0x6600 relative to SCUBAR.
+ */
+struct SCU_FRAME_BUFFER_RAM
+{
+   U32 sram_base_address_1;         //0x0000
+   U32 sram_upper_base_address_1;   //0x0004
+   U32 sram_ecc_control_1;          //0x0008
+   U32 sram_ecc_log_1;              //0x000c
+   U32 sram_ecc_addrress_1;         //0x0010
+   U32 sram_ecc_context_address_1;  //0x0014
+   U32 sram_ecc_test_1;             //0x0018
+   U32 sram_parity_control_and_status_1;   //0x001C
+   U32 sram_parity_address_1;              //0x0020
+   U32 sram_parity_upper_address_1;        //0x0024
+   U32 sram_parity_context_1;              //0x0028
+   U32 sram_memory_controller_interrupt_status_1;   //0x002C
+   U32 sram_mcu_read_arbiter_control_1;    //0x0030
+   U32 sram_mcu_write_arbiter_control_1;   //0x0034
+   U32 smcu_error_event_counter_0_1;       //0x0038
+
+   //Remainder of FBRAM register space
+   U32 reserved_003C_0200[113];
+};
+
+#define SCU_SCRATCH_RAM_SIZE_IN_DWORDS  256
+
+/**
+* @brief Placeholder for the scratch RAM registers.
+*
+*/
+struct SCU_SCRATCH_RAM
+{
+    U32 ram[SCU_SCRATCH_RAM_SIZE_IN_DWORDS];
+};
+
+/**
+ * @brief Placeholder since I am not yet sure what these registers are here
+ *        for.
+ *
+ */
+struct NOA_PROTOCOL_ENGINE_PARTITION
+{
+   U32 reserved[64];
+};
+
+/**
+ * @brief Placeholder since I am not yet sure what these registers are here
+ *        for.
+ *
+ */
+struct NOA_HUB_PARTITION
+{
+   U32 reserved[64];
+};
+
+/**
+ * @brief Placeholder since I am not yet sure what these registers are here
+ *        for.
+ *
+ */
+struct NOA_HOST_INTERFACE_PARTITION
+{
+   U32 reserved[64];
+};
+
+/**
+ * @struct TRANSPORT_LINK_LAYER_PAIR
+ *
+ * @brief The SCU Hardware pairs up the TL registers with the LL registers
+ *        so we must place them adjcent to make the array of registers in
+ *        the PEG.
+ *
+ */
+struct TRANSPORT_LINK_LAYER_PAIR
+{
+   struct SCU_TRANSPORT_LAYER_REGISTERS tl;
+   struct SCU_LINK_LAYER_REGISTERS      ll;
+};
+
+/**
+ * @struct SCU_PEG_REGISTERS
+ *
+ * @brief SCU Protocol Engine Memory mapped register space.  These
+ *        registers are unique to each protocol engine group.  There can be
+ *        at most two PEG for a single SCU part.
+ *
+ */
+struct SCU_PEG_REGISTERS
+{
+   struct TRANSPORT_LINK_LAYER_PAIR                pe[4];
+   struct SCU_PORT_TASK_SCHEDULER_GROUP_REGISTERS  ptsg;
+   struct SCU_PROTOCOL_ENGINE_GROUP_REGISTERS      peg;
+   struct SCU_SGPIO_REGISTERS                      sgpio;
+   U32    reserved_01500_1BFF[0x1C0];
+   struct SCU_VIIT_ENTRY                           viit[64];
+   struct SCU_ZONE_PARTITION_TABLE                 zpt0;
+   struct SCU_ZONE_PARTITION_TABLE                 zpt1;
+};
+
+/**
+ * @struct SCU_REGISTERS
+ *
+ * @brief SCU regsiters including both PEG registers if we turn on that
+ *        compile option.
+ *        All of these registers are in the memory mapped space returned
+ *        from BAR1.
+ *        See SCU SMU Specification for how these registers are mapped.
+ *
+ */
+typedef struct SCU_REGISTERS
+{
+   // 0x0000 - PEG 0
+   struct SCU_PEG_REGISTERS              peg0;
+
+   // 0x6000 - SDMA and Miscellaneous
+   struct SCU_SDMA_REGISTERS             sdma;
+   struct SCU_COMPLETION_RAM             cram;
+   struct SCU_FRAME_BUFFER_RAM           fbram;
+   U32    reserved_6800_69FF[0x80];
+   struct NOA_PROTOCOL_ENGINE_PARTITION  noa_pe;
+   struct NOA_HUB_PARTITION              noa_hub;
+   struct NOA_HOST_INTERFACE_PARTITION   noa_if;
+   U32    reserved_6d00_7fff[0x4c0];
+
+   // 0x8000 - PEG 1
+   struct SCU_PEG_REGISTERS              peg1;
+
+   // 0xE000 - AFE Registers
+   struct SCU_AFE_REGISTERS              afe;
+
+} SCU_REGISTERS_T;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif   // _SCU_REGISTERS_HEADER_
diff --git a/sys/dev/disk/isci/scil/scu_remote_node_context.h b/sys/dev/disk/isci/scil/scu_remote_node_context.h
new file mode 100644
index 0000000..0adf7ce
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scu_remote_node_context.h
@@ -0,0 +1,242 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scu_remote_node_context.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef __SCU_REMOTE_NODE_CONTEXT_HEADER__
+#define __SCU_REMOTE_NODE_CONTEXT_HEADER__
+
+/**
+ * @file
+ *
+ * @brief This file contains the structures and constatns used by the SCU
+ * hardware to describe a remote node context.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_types.h>
+
+/**
+ * @struct SSP_REMOTE_NODE_CONTEXT
+ *
+ * @brief This structure contains the SCU hardware definition for an SSP
+ *       remote node.
+ */
+typedef struct SSP_REMOTE_NODE_CONTEXT
+{
+   // WORD 0
+
+   /**
+    * This field is the remote node index assigned for this remote node. All
+    * remote nodes must have a unique remote node index. The value of the remote
+    * node index can not exceed the maximum number of remote nodes reported in
+    * the SCU device context capacity register.
+    */
+   U32 remote_node_index       :12;
+   U32 reserved0_1             : 4;
+
+   /**
+    * This field tells the SCU hardware how many simultaneous connections that
+    * this remote node will support.
+    */
+   U32 remote_node_port_width  : 4;
+
+   /**
+    * This field tells the SCU hardware which logical port to associate with this
+    * remote node.
+    */
+   U32 logical_port_index      : 3;
+   U32 reserved0_2             : 5;
+
+   /**
+    * This field will enable the I_T nexus loss timer for this remote node.
+    */
+   U32 nexus_loss_timer_enable : 1;
+
+   /**
+    * This field is the for driver debug only and is not used.
+    */
+   U32 check_bit               : 1;
+
+   /**
+    * This field must be set to TRUE when the hardware DMAs the remote node
+    * context to the hardware SRAM.  When the remote node is being invalidated
+    * this field must be set to FALSE.
+    */
+   U32 is_valid                : 1;
+
+   /**
+    * This field must be set to TRUE.
+    */
+   U32 is_remote_node_context  : 1;
+
+   // WORD 1 - 2
+
+   /**
+    * This is the low word of the remote device SAS Address
+    */
+   U32 remote_sas_address_lo;
+
+   /**
+    * This field is the high word of the remote device SAS Address
+    */
+   U32 remote_sas_address_hi;
+
+   // WORD 3
+   /**
+    * This field reprensets the function number assigned to this remote device.
+    * This value must match the virtual function number that is being used to
+    * communicate to the device.
+    */
+   U32 function_number         : 8;
+   U32 reserved3_1             : 8;
+
+   /**
+    * This field provides the driver a way to cheat on the arbitration wait time
+    * for this remote node.
+    */
+   U32 arbitration_wait_time   :16;
+
+   // WORD 4
+   /**
+    * This field tells the SCU hardware how long this device may occupy the
+    * connection before it must be closed.
+    */
+   U32 connection_occupancy_timeout  :16;
+
+   /**
+    * This field tells the SCU hardware how long to maintain a connection when
+    * there are no frames being transmitted on the link.
+    */
+   U32 connection_inactivity_timeout :16;
+
+   // WORD  5
+   /**
+    * This field allows the driver to cheat on the arbitration wait time for this
+    * remote node.
+    */
+   U32 initial_arbitration_wait_time :16;
+
+   /**
+    * This field is tells the hardware what to program for the connection rate in
+    * the open address frame.  See the SAS spec for valid values.
+    */
+   U32 oaf_connection_rate           : 4;
+
+   /**
+    * This field tells the SCU hardware what to program for the features in the
+    * open address frame.  See the SAS spec for valid values.
+    */
+   U32 oaf_features                  : 4;
+
+   /**
+    * This field tells the SCU hardware what to use for the source zone group in
+    * the open address frame.  See the SAS spec for more details on zoning.
+    */
+   U32 oaf_source_zone_group         : 8;
+
+   // WORD 6
+   /**
+    * This field tells the SCU hardware what to use as the more capibilities in
+    * the open address frame. See the SAS Spec for details.
+    */
+   U32 oaf_more_compatibility_features;
+
+   // WORD 7
+   U32 reserved7;
+
+} SSP_REMOTE_NODE_CONTEXT_T;
+
+/**
+ * @struct STP_REMOTE_NODE_CONTEXT
+ *
+ * @brief This structure contains the SCU hardware definition for a STP remote
+ *        node.
+ *
+ * @todo STP Targets are not yet supported so this definition is a placeholder
+ *       until we do support them.
+ */
+typedef struct STP_REMOTE_NODE_CONTEXT
+{
+   /**
+    * Placeholder data for the STP remote node.
+    */
+   U32 data[8];
+
+} STP_REMOTE_NODE_CONTEXT_T;
+
+/**
+ * @union SCU_REMOTE_NODE_CONTEXT
+ *
+ * @brief This union combines the SAS and SATA remote node definitions.
+ */
+typedef union SCU_REMOTE_NODE_CONTEXT
+{
+   /**
+    * SSP Remote Node
+    */
+   SSP_REMOTE_NODE_CONTEXT_T ssp;
+
+   /**
+    * STP Remote Node
+    */
+   STP_REMOTE_NODE_CONTEXT_T stp;
+
+} SCU_REMOTE_NODE_CONTEXT_T;
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // __SCU_REMOTE_NODE_CONTEXT_HEADER__
diff --git a/sys/dev/disk/isci/scil/scu_task_context.h b/sys/dev/disk/isci/scil/scu_task_context.h
new file mode 100644
index 0000000..334c8b2
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scu_task_context.h
@@ -0,0 +1,965 @@
+/*-
+ * 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: src/sys/dev/isci/scil/scu_task_context.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCU_TASK_CONTEXT_H_
+#define _SCU_TASK_CONTEXT_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains the structures and constants for the SCU hardware
+ *        task context.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_types.h>
+
+/**
+ * @enum SCU_SSP_TASK_TYPE
+ *
+ * @brief This enumberation defines the various SSP task types the SCU
+ *        hardware will accept.
+ *
+ * The definition for the various task types the SCU hardware will accept can
+ * be found in the DS specification.
+ */
+typedef enum
+{
+    SCU_TASK_TYPE_IOREAD,        ///< IO READ direction or no direction
+    SCU_TASK_TYPE_IOWRITE,       ///< IO Write direction
+    SCU_TASK_TYPE_SMP_REQUEST,   ///< SMP Request type
+    SCU_TASK_TYPE_RESPONSE,      ///< Driver generated response frame (targt mode)
+    SCU_TASK_TYPE_RAW_FRAME,     ///< Raw frame request type
+    SCU_TASK_TYPE_PRIMITIVE      ///< Request for a primitive to be transmitted
+} SCU_SSP_TASK_TYPE;
+
+/**
+ * @enum SCU_SATA_TASK_TYPE
+ *
+ * @brief This enumeration defines the various SATA task types the SCU
+ *        hardware will accept.
+ *
+ * The definition for the various task types the SCU hardware will accept can
+ * be found in the DS specification.
+ */
+typedef enum
+{
+    SCU_TASK_TYPE_DMA_IN,           ///< Read request
+    SCU_TASK_TYPE_FPDMAQ_READ,      ///< NCQ read request
+    SCU_TASK_TYPE_PACKET_DMA_IN,    ///< Packet read request
+    SCU_TASK_TYPE_SATA_RAW_FRAME,   ///< Raw frame request
+    RESERVED_4,
+    RESERVED_5,
+    RESERVED_6,
+    RESERVED_7,
+    SCU_TASK_TYPE_DMA_OUT,          ///< Write request
+    SCU_TASK_TYPE_FPDMAQ_WRITE,     ///< NCQ write Request
+    SCU_TASK_TYPE_PACKET_DMA_OUT    ///< Packet write request
+} SCU_SATA_TASK_TYPE;
+
+
+/**
+ * @name SCU_CONTEXT_TYPE
+ */
+/*@{*/
+#define SCU_TASK_CONTEXT_TYPE  0
+#define SCU_RNC_CONTEXT_TYPE   1
+/*@}*/
+
+/**
+ * @name SCU_TASK_CONTEXT_VALIDITY
+ */
+/*@{*/
+#define SCU_TASK_CONTEXT_INVALID          0
+#define SCU_TASK_CONTEXT_VALID            1
+/*@}*/
+
+/**
+ * @name SCU_COMMAND_CODE
+ */
+/*@{*/
+#define SCU_COMMAND_CODE_INITIATOR_NEW_TASK   0
+#define SCU_COMMAND_CODE_ACTIVE_TASK          1
+#define SCU_COMMAND_CODE_PRIMITIVE_SEQ_TASK   2
+#define SCU_COMMAND_CODE_TARGET_RAW_FRAMES    3
+/*@}*/
+
+/**
+ * @name SCU_TASK_PRIORITY
+ */
+/*@{*/
+/**
+ * This priority is used when there is no priority request for this request.
+ */
+#define SCU_TASK_PRIORITY_NORMAL          0
+
+/**
+ * This priority indicates that the task should be scheduled to the head
+ * of the queue.  The task will NOT be executed if the TX is suspended for
+ * the remote node.
+ */
+#define SCU_TASK_PRIORITY_HEAD_OF_Q       1
+
+/**
+ * This priority indicates that the task will be executed before all
+ * SCU_TASK_PRIORITY_NORMAL and SCU_TASK_PRIORITY_HEAD_OF_Q tasks.
+ * The task WILL be executed if the TX is suspended for the remote node.
+ */
+#define SCU_TASK_PRIORITY_HIGH            2
+
+/**
+ * This task priority is reserved and should not be used.
+ */
+#define SCU_TASK_PRIORITY_RESERVED        3
+/*@}*/
+
+#define SCU_TASK_INITIATOR_MODE           1
+#define SCU_TASK_TARGET_MODE              0
+
+#define SCU_TASK_REGULAR                  0
+#define SCU_TASK_ABORTED                  1
+
+//direction bit defintion
+/**
+ * @name SATA_DIRECTION
+ */
+/*@{*/
+#define SCU_SATA_WRITE_DATA_DIRECTION     0
+#define SCU_SATA_READ_DATA_DIRECTION      1
+/*@}*/
+
+/**
+ * @name SCU_COMMAND_CONTEXT_MACROS
+ *
+ * These macros provide the mask and shift operations to construct the various
+ * SCU commands
+ */
+/*@{*/
+#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_SHIFT           21UL
+#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_MASK            0x00E00000UL
+#define scu_get_command_request_type(x) \
+               ((x) & SCU_CONTEXT_COMMAND_REQUEST_TYPE_MASK)
+
+#define SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_SHIFT        18UL
+#define SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_MASK         0x001C0000UL
+#define scu_get_command_request_subtype(x) \
+               ((x) & SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_MASK)
+
+#define SCU_CONTEXT_COMMAND_REQUEST_FULLTYPE_MASK        \
+   (                                                     \
+       SCU_CONTEXT_COMMAND_REQUEST_TYPE_MASK             \
+     | SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_MASK          \
+   )
+#define scu_get_command_request_full_type(x) \
+               ((x) & SCU_CONTEXT_COMMAND_REQUEST_FULLTYPE_MASK)
+
+#define SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT  16UL
+#define SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_MASK   0x00010000UL
+#define scu_get_command_protocl_engine_group(x) \
+               ((x) & SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_MASK)
+
+#define SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT           12UL
+#define SCU_CONTEXT_COMMAND_LOGICAL_PORT_MASK            0x00007000UL
+#define scu_get_command_reqeust_logical_port(x) \
+               ((x) & SCU_CONTEXT_COMMAND_LOGICAL_PORT_MASK)
+
+
+#define MAKE_SCU_CONTEXT_COMMAND_TYPE(type) \
+   ((U32)(type) << SCU_CONTEXT_COMMAND_REQUEST_TYPE_SHIFT)
+/*@}*/
+
+/**
+ * @name SCU_COMMAND_TYPES
+ *
+ * These constants provide the grouping of the different SCU command types.
+ */
+/*@{*/
+#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC    MAKE_SCU_CONTEXT_COMMAND_TYPE(0UL)
+#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_TC    MAKE_SCU_CONTEXT_COMMAND_TYPE(1UL)
+#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC   MAKE_SCU_CONTEXT_COMMAND_TYPE(2UL)
+#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC   MAKE_SCU_CONTEXT_COMMAND_TYPE(3UL)
+#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC  MAKE_SCU_CONTEXT_COMMAND_TYPE(6UL)
+/*@}*/
+
+#define MAKE_SCU_CONTEXT_COMMAND_REQUEST(type, command) \
+   ((type) | (((U32)(command)) << SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_SHIFT))
+
+/**
+ * @name SCU_REQUEST_TYPES
+ *
+ * These constants are the various request types that can be posted to the SCU
+ * hardware.
+ */
+/*@{*/
+#define SCU_CONTEXT_COMMAND_REQUST_POST_TC \
+   (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC, 0))
+
+#define SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT \
+   (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC, 1))
+
+#define SCU_CONTEXT_COMMAND_REQUST_DUMP_TC \
+   (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_TC, 0))
+
+#define SCU_CONTEXT_COMMAND_POST_RNC_32 \
+   (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC, 0))
+
+#define SCU_CONTEXT_COMMAND_POST_RNC_96 \
+   (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC, 1))
+
+#define SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE \
+   (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC, 2))
+
+#define SCU_CONTEXT_COMMAND_DUMP_RNC_32 \
+   (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC, 0))
+
+#define SCU_CONTEXT_COMMAND_DUMP_RNC_96 \
+   (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC, 1))
+
+#define SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX \
+   (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 0))
+
+#define SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX_RX \
+   (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 1))
+
+#define SCU_CONTEXT_COMMAND_POST_RNC_RESUME \
+   (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 2))
+
+#define SCU_CONTEXT_IT_NEXUS_LOSS_TIMER_ENABLE \
+   (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 3))
+
+#define SCU_CONTEXT_IT_NEXUS_LOSS_TIMER_DISABLE \
+   (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 4))
+/*@}*/
+
+/**
+ * @name SCU_TASK_CONTEXT_PROTOCOL
+ * SCU Task context protocol types this is uesd to program the SCU Task
+ * context protocol field in word 0x00.
+ */
+/*@{*/
+#define SCU_TASK_CONTEXT_PROTOCOL_SMP    0x00
+#define SCU_TASK_CONTEXT_PROTOCOL_SSP    0x01
+#define SCU_TASK_CONTEXT_PROTOCOL_STP    0x02
+#define SCU_TASK_CONTEXT_PROTOCOL_NONE   0x07
+/*@}*/
+
+/**
+ * @struct SSP_TASK_CONTEXT
+ *
+ * @brief This is the SCU hardware definition for an SSP request.
+ */
+struct SSP_TASK_CONTEXT
+{
+   // OFFSET 0x18
+   U32  reserved00              : 24;
+   U32  frame_type              : 8;
+
+   // OFFSET 0x1C
+   U32  reserved01;
+
+   // OFFSET 0x20
+   U32  fill_bytes              : 2;
+   U32  reserved02              : 6;
+   U32  changing_data_pointer   : 1;
+   U32  retransmit              : 1;
+   U32  retry_data_frame        : 1;
+   U32  tlr_control             : 2;
+   U32  reserved03              : 19;
+
+   // OFFSET 0x24
+   U32  uiRsvd4;
+
+   // OFFSET 0x28
+   U32 target_port_transfer_tag : 16;
+   U32 tag                      : 16;
+
+   // OFFSET 0x2C
+   U32 data_offset;
+};
+
+/**
+ * @struct STP_TASK_CONTEXT
+ *
+ * @brief This is the SCU hardware definition for an STP request.
+ */
+struct STP_TASK_CONTEXT
+{
+   // OFFSET 0x18
+   U32 fis_type    : 8;
+   U32 pm_port     : 4;
+   U32 reserved0   : 3;
+   U32 control     : 1;
+   U32 command     : 8;
+   U32 features    : 8;
+
+   // OFFSET 0x1C
+   U32 reserved1;
+
+   // OFFSET 0x20
+   U32 reserved2;
+
+   // OFFSET 0x24
+   U32 reserved3;
+
+   // OFFSET 0x28
+   U32 ncq_tag     : 5;
+   U32 reserved4   : 27;
+
+   // OFFSET 0x2C
+   U32 data_offset;    // TODO: What is this used for?
+};
+
+/**
+ * @struct SMP_TASK_CONTEXT
+ *
+ * @brief This is the SCU hardware definition for an SMP request.
+ */
+struct SMP_TASK_CONTEXT
+{
+   // OFFSET 0x18
+   U32 response_length    : 8;
+   U32 function_result    : 8;
+   U32 function           : 8;
+   U32 frame_type         : 8;
+
+   // OFFSET 0x1C
+   U32 smp_response_ufi   : 12;
+   U32 reserved1          : 20;
+
+   // OFFSET 0x20
+   U32 reserved2;
+
+   // OFFSET 0x24
+   U32 reserved3;
+
+   // OFFSET 0x28
+   U32 reserved4;
+
+   // OFFSET 0x2C
+   U32 reserved5;
+};
+
+/**
+ * @struct PRIMITIVE_TASK_CONTEXT
+ *
+ * @brief This is the SCU hardware definition used when the driver wants to
+ *        send a primitive on the link.
+ */
+struct PRIMITIVE_TASK_CONTEXT
+{
+   // OFFSET 0x18
+   /**
+    * This field is the control word and it must be 0.
+    */
+   U32 control;  ///< must be set to 0
+
+   // OFFSET 0x1C
+   /**
+    * This field specifies the primitive that is to be transmitted.
+    */
+   U32 sequence;
+
+   // OFFSET 0x20
+   U32 reserved0;
+
+   // OFFSET 0x24
+   U32 reserved1;
+
+   // OFFSET 0x28
+   U32 reserved2;
+
+   // OFFSET 0x2C
+   U32 reserved3;
+};
+
+/**
+ * @union PROTOCOL_CONTEXT
+ *
+ * @brief The union of the protocols that can be selected in the SCU task
+ *        context field.
+ */
+union PROTOCOL_CONTEXT
+{
+    struct SSP_TASK_CONTEXT         ssp;
+    struct STP_TASK_CONTEXT         stp;
+    struct SMP_TASK_CONTEXT         smp;
+    struct PRIMITIVE_TASK_CONTEXT   primitive;
+    U32                             words[6];
+};
+
+/**
+ * @struct SCU_SGL_ELEMENT
+ * @typedef SCU_SGL_ELEMENT_T
+ *
+ * @brief This structure represents a single SCU defined SGL element.
+ *
+ * SCU SGLs contain a 64 bit address with the maximum data transfer being 24
+ * bits in size.  The SGL can not cross a 4GB boundary.
+ */
+typedef struct SCU_SGL_ELEMENT
+{
+   /**
+    * This field is the upper 32 bits of the 64 bit physical address.
+    */
+   U32    address_upper;
+
+   /**
+    * This field is the lower 32 bits of the 64 bit physical address.
+    */
+   U32    address_lower;
+
+   /**
+    * This field is the number of bytes to transfer.
+    */
+   U32    length: 24;
+
+   /**
+    * This field is the address modifier to be used when a virtual function is
+    * requesting a data transfer.
+    */
+   U32    address_modifier: 8;
+
+} SCU_SGL_ELEMENT_T;
+
+#define SCU_SGL_ELEMENT_PAIR_A   0
+#define SCU_SGL_ELEMENT_PAIR_B   1
+
+/**
+ * @struct SCU_SGL_ELEMENT_PAIR
+ *
+ * @brief This structure is the SCU hardware definition of a pair of SGL
+ *        elements.
+ *
+ * The SCU hardware always works on SGL pairs.  They are refered to in the DS
+ * specification as SGL A and SGL B.  Each SGL pair is followed by the address
+ * of the next pair.
+ */
+typedef struct SCU_SGL_ELEMENT_PAIR
+{
+   // OFFSET 0x60-0x68
+   /**
+    * This field is the SGL element A of the SGL pair.
+    */
+   SCU_SGL_ELEMENT_T A;
+
+   // OFFSET 0x6C-0x74
+   /**
+    * This field is the SGL element B of the SGL pair.
+    */
+   SCU_SGL_ELEMENT_T B;
+
+   // OFFSET 0x78-0x7C
+   /**
+    * This field is the upper 32 bits of the 64 bit address to the next SGL
+    * element pair.
+    */
+   U32 next_pair_upper;
+
+   /**
+    * This field is the lower 32 bits of the 64 bit address to the next SGL
+    * element pair.
+    */
+   U32 next_pair_lower;
+
+} SCU_SGL_ELEMENT_PAIR_T;
+
+/**
+ * @struct TRANSPORT_SNAPSHOT
+ *
+ * @brief This structure is the SCU hardware scratch area for the task
+ *        context.
+ *
+ * This is set to 0 by the driver but can be read by issuing a dump TC request
+ * to the SCU.
+ */
+struct TRANSPORT_SNAPSHOT
+{
+   // OFFSET 0x48
+   U32  xfer_rdy_write_data_length;
+
+   // OFFSET 0x4C
+   U32  data_offset;
+
+   // OFFSET 0x50
+   U32  data_transfer_size   : 24;
+   U32  reserved_50_0        : 8;
+
+   // OFFSET 0x54
+   U32  next_initiator_write_data_offset;
+
+   // OFFSET 0x58
+   U32  next_initiator_write_data_xfer_size : 24;
+   U32  reserved_58_0                       : 8;
+};
+
+/**
+ * @struct SCU_TASK_CONTEXT
+ *
+ * @brief This structure defines the contents of the SCU silicon task context.
+ *        It lays out all of the fields according to the expected order and
+ *        location for the Storage Controller unit.
+ */
+typedef struct SCU_TASK_CONTEXT
+{
+   // OFFSET 0x00 ------
+   /**
+    * This field must be encoded to one of the valid SCU task priority values
+    *    - SCU_TASK_PRIORITY_NORMAL
+    *    - SCU_TASK_PRIORITY_HEAD_OF_Q
+    *    - SCU_TASK_PRIORITY_HIGH
+    */
+   U32    priority              : 2;
+
+   /**
+    * This field must be set to TRUE if this is an initiator generated request.
+    * Until target mode is supported all task requests are initiator requests.
+    */
+   U32    initiator_request     : 1;
+
+   /**
+    * This field must be set to one of the valid connection rates valid values
+    * are 0x8, 0x9, and 0xA.
+    */
+   U32    connection_rate       : 4;
+
+   /**
+    * This field muse be programed when generating an SMP response since the SMP
+    * connection remains open until the SMP response is generated.
+    */
+   U32    protocol_engine_index : 3;
+
+   /**
+    * This field must contain the logical port for the task request.
+    */
+   U32    logical_port_index    : 3;
+
+   /**
+    * This field must be set to one of the SCU_TASK_CONTEXT_PROTOCOL values
+    *    - SCU_TASK_CONTEXT_PROTOCOL_SMP
+    *    - SCU_TASK_CONTEXT_PROTOCOL_SSP
+    *    - SCU_TASK_CONTEXT_PROTOCOL_STP
+    *    - SCU_TASK_CONTEXT_PROTOCOL_NONE
+    */
+   U32    protocol_type         : 3;
+
+   /**
+    * This filed must be set to the TCi allocated for this task
+    */
+   U32    task_index            : 12;
+
+   /**
+    * This field is reserved and must be set to 0x00
+    */
+   U32    reserved_00_0         : 1;
+
+   /**
+    * For a normal task request this must be set to 0.  If this is an abort of
+    * this task request it must be set to 1.
+    */
+   U32    abort                 : 1;
+
+   /**
+    * This field must be set to TRUE for the SCU hardware to process the task.
+    */
+   U32    valid                 : 1;
+
+   /**
+    * This field must be set to SCU_TASK_CONTEXT_TYPE
+    */
+   U32    context_type          : 1;
+
+   // OFFSET 0x04
+   /**
+    * This field contains the RNi that is the target of this request.
+    */
+   U32    remote_node_index     : 12;
+
+   /**
+    * This field is programmed if this is a mirrored request, which we are not
+    * using, in which case it is the RNi for the mirrored target.
+    */
+   U32    mirrored_node_index   : 12;
+
+   /**
+    * This field is programmed with the direction of the SATA reqeust
+    *    - SCU_SATA_WRITE_DATA_DIRECTION
+    *    - SCU_SATA_READ_DATA_DIRECTION
+    */
+   U32    sata_direction        : 1;
+
+   /**
+    * This field is programmsed with one of the following SCU_COMMAND_CODE
+    *    - SCU_COMMAND_CODE_INITIATOR_NEW_TASK
+    *    - SCU_COMMAND_CODE_ACTIVE_TASK
+    *    - SCU_COMMAND_CODE_PRIMITIVE_SEQ_TASK
+    *    - SCU_COMMAND_CODE_TARGET_RAW_FRAMES
+    */
+   U32    command_code          : 2;
+
+   /**
+    * This field is set to TRUE if the remote node should be suspended.
+    * This bit is only valid for SSP & SMP target devices.
+    */
+   U32    suspend_node          : 1;
+
+   /**
+    * This field is programmed with one of the following command type codes
+    *
+    * For SAS requests use the SCU_SSP_TASK_TYPE
+    *    - SCU_TASK_TYPE_IOREAD
+    *    - SCU_TASK_TYPE_IOWRITE
+    *    - SCU_TASK_TYPE_SMP_REQUEST
+    *    - SCU_TASK_TYPE_RESPONSE
+    *    - SCU_TASK_TYPE_RAW_FRAME
+    *    - SCU_TASK_TYPE_PRIMITIVE
+    *
+    * For SATA requests use the SCU_SATA_TASK_TYPE
+    *    - SCU_TASK_TYPE_DMA_IN
+    *    - SCU_TASK_TYPE_FPDMAQ_READ
+    *    - SCU_TASK_TYPE_PACKET_DMA_IN
+    *    - SCU_TASK_TYPE_SATA_RAW_FRAME
+    *    - SCU_TASK_TYPE_DMA_OUT
+    *    - SCU_TASK_TYPE_FPDMAQ_WRITE
+    *    - SCU_TASK_TYPE_PACKET_DMA_OUT
+    */
+   U32    task_type             : 4;
+
+   // OFFSET 0x08
+   /**
+    * This field is reserved and the must be set to 0x00
+    */
+   U32    link_layer_control          : 8;  // presently all reserved
+
+   /**
+    * This field is set to TRUE when TLR is to be enabled
+    */
+   U32    ssp_tlr_enable              : 1;
+
+   /**
+    * This is field specifies if the SCU DMAs a response frame to host
+    * memory for good response frames when operating in target mode.
+    */
+   U32    dma_ssp_target_good_response : 1;
+
+   /**
+    * This field indicates if the SCU should DMA the response frame to
+    * host memory.
+    */
+   U32    do_not_dma_ssp_good_response : 1;
+
+   /**
+    * This field is set to TRUE when strict ordering is to be enabled
+    */
+   U32    strict_ordering              : 1;
+
+   /**
+    * This field indicates the type of endianess to be utilized for the
+    * frame.  command, task, and response frames utilized control_frame
+    * set to 1.
+    */
+   U32    control_frame               : 1;
+
+   /**
+    * This field is reserved and the driver should set to 0x00
+    */
+   U32    tl_control_reserved         : 3;
+
+   /**
+    * This field is set to TRUE when the SCU hardware task timeout control is to
+    * be enabled
+    */
+   U32    timeout_enable              : 1;
+
+   /**
+    * This field is reserved and the driver should set it to 0x00
+    */
+   U32    pts_control_reserved        : 7;
+
+   /**
+    * This field should be set to TRUE when block guard is to be enabled
+    */
+   U32    block_guard_enable          : 1;
+
+   /**
+    * This field is reserved and the driver should set to 0x00
+    */
+   U32    sdma_control_reserved       : 7;
+
+   // OFFSET 0x0C
+   /**
+    * This field is the address modifier for this io request it should be
+    * programmed with the virtual function that is making the request.
+    */
+   U32    address_modifier            : 16;
+
+   /**
+    * @todo What we support mirrored SMP response frame?
+    */
+   U32    mirrored_protocol_engine    : 3;    // mirrored protocol Engine Index
+
+   /**
+    * If this is a mirrored request the logical port index for the mirrored RNi
+    * must be programmed.
+    */
+   U32    mirrored_logical_port       : 4;    // mirrored local port index
+
+   /**
+    * This field is reserved and the driver must set it to 0x00
+    */
+   U32    reserved_0C_0               : 8;
+
+   /**
+    * This field must be set to TRUE if the mirrored request processing is to be
+    * enabled.
+    */
+   U32    mirror_request_enable       : 1;    // Mirrored request Enable
+
+   // OFFSET 0x10
+   /**
+    * This field is the command iu length in dwords
+    */
+   U32    ssp_command_iu_length       : 8;
+
+   /**
+    * This is the target TLR enable bit it must be set to 0 when creatning the
+    * task context.
+    */
+   U32    xfer_ready_tlr_enable       : 1;
+
+   /**
+    * This field is reserved and the driver must set it to 0x00
+    */
+   U32    reserved_10_0               : 7;
+
+   /**
+    * This is the maximum burst size that the SCU hardware will send in one
+    * connection its value is (N x 512) and N must be a multiple of 2.  If the
+    * value is 0x00 then maximum burst size is disabled.
+    */
+   U32    ssp_max_burst_size          : 16;
+
+   // OFFSET 0x14
+   /**
+    * This filed is set to the number of bytes to be transfered in the request.
+    */
+   U32    transfer_length_bytes       : 24;   // In terms of bytes
+
+   /**
+    * This field is reserved and the driver should set it to 0x00
+    */
+   U32    reserved_14_0               : 8;
+
+   // OFFSET 0x18-0x2C
+   /**
+    * This union provides for the protocol specif part of the SCU Task Context.
+    */
+   union PROTOCOL_CONTEXT  type;
+
+   // OFFSET 0x30-0x34
+   /**
+    * This field is the upper 32 bits of the 64 bit physical address of the
+    * command iu buffer
+    */
+   U32  command_iu_upper;
+
+   /**
+    * This field is the lower 32 bits of the 64 bit physical address of the
+    * command iu buffer
+    */
+   U32  command_iu_lower;
+
+   // OFFSET 0x38-0x3C
+   /**
+    * This field is the upper 32 bits of the 64 bit physical address of the
+    * response iu buffer
+    */
+   U32  response_iu_upper;
+
+   /**
+    * This field is the lower 32 bits of the 64 bit physical address of the
+    * response iu buffer
+    */
+   U32  response_iu_lower;
+
+   // OFFSET 0x40
+   /**
+    * This field is set to the task phase of the SCU hardware. The driver must
+    * set this to 0x01
+    */
+   U32  task_phase            : 8;
+
+   /**
+    * This field is set to the transport layer task status.  The driver must set
+    * this to 0x00
+    */
+   U32  task_status           : 8;
+
+   /**
+    * This field is used during initiator write TLR
+    */
+   U32  previous_extended_tag : 4;
+
+   /**
+    * This field is set the maximum number of retries for a STP non-data FIS
+    */
+   U32  stp_retry_count       : 2;
+
+   /**
+    * This field is reserved and the driver must set it to 0x00
+    */
+   U32  reserved_40_1         : 2;
+
+   /**
+    * This field is used by the SCU TL to determine when to take a snapshot when
+    * tranmitting read data frames.
+    *    - 0x00 The entire IO
+    *    - 0x01 32k
+    *    - 0x02 64k
+    *    - 0x04 128k
+    *    - 0x08 256k
+    */
+   U32  ssp_tlr_threshold     : 4;
+
+   /**
+    * This field is reserved and the driver must set it to 0x00
+    */
+   U32  reserved_40_2         : 4;
+
+   // OFFSET 0x44
+   U32  write_data_length;   // read only set to 0
+
+   // OFFSET 0x48-0x58
+   struct TRANSPORT_SNAPSHOT snapshot;  // read only set to 0
+
+   // OFFSET 0x5C
+   U32  block_protection_enable       : 1;
+   U32  block_size                    : 2;
+   U32  block_protection_function     : 2;
+   U32  reserved_5C_0                 : 9;
+   U32  active_sgl_element            : 2;   // read only set to 0
+   U32  sgl_exhausted                 : 1;   // read only set to 0
+   U32  payload_data_transfer_error   : 4;   // read only set to 0
+   U32  frame_buffer_offset           : 11;  // read only set to 0
+
+   // OFFSET 0x60-0x7C
+   /**
+    * This field is the first SGL element pair found in the TC data structure.
+    */
+   SCU_SGL_ELEMENT_PAIR_T sgl_pair_ab;
+   // OFFSET 0x80-0x9C
+   /**
+    * This field is the second SGL element pair found in the TC data structure.
+    */
+   SCU_SGL_ELEMENT_PAIR_T sgl_pair_cd;
+
+   // OFFSET 0xA0-BC
+   SCU_SGL_ELEMENT_PAIR_T sgl_snapshot_ac;
+
+   // OFFSET 0xC0
+   U32  active_sgl_element_pair; // read only set to 0
+
+   // OFFSET 0xC4-0xCC
+   U32 reserved_C4_CC[3];
+
+   // OFFSET 0xD0
+   U32  intermediate_crc_value : 16;
+   U32  initial_crc_seed       : 16;
+
+   // OFFSET 0xD4
+   U32  application_tag_for_verify    : 16;
+   U32  application_tag_for_generate  : 16;
+
+   // OFFSET 0xD8
+   U32  reference_tag_seed_for_verify_function;
+
+   // OFFSET 0xDC
+   U32  reserved_DC;
+
+   // OFFSET 0xE0
+   U32  reserved_E0_0                    : 16;
+   U32  application_tag_mask_for_generate: 16;
+
+   // OFFSET 0xE4
+   U32  block_protection_control         : 16;
+   U32  application_tag_mask_for_verify  : 16;
+
+   // OFFSET 0xE8
+   U32  block_protection_error  : 8;
+   U32  reserved_E8_0           :24;
+
+   // OFFSET 0xEC
+   U32  reference_tag_seed_for_verify;
+
+   // OFFSET 0xF0
+   U32  intermediate_crc_valid_snapshot  : 16;
+   U32  reserved_F0_0                    : 16;
+
+   // OFFSET 0xF4
+   U32  reference_tag_seed_for_verify_function_snapshot;
+
+   // OFFSET 0xF8
+   U32  snapshot_of_reserved_dword_DC_of_tc;
+
+   // OFFSET 0xFC
+   U32  reference_tag_seed_for_generate_function_snapshot;
+
+} SCU_TASK_CONTEXT_T;
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCU_TASK_CONTEXT_H_
diff --git a/sys/dev/disk/isci/scil/scu_unsolicited_frame.h b/sys/dev/disk/isci/scil/scu_unsolicited_frame.h
new file mode 100644
index 0000000..d202158
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scu_unsolicited_frame.h
@@ -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.
+ *
+ * $FreeBSD: src/sys/dev/isci/scil/scu_unsolicited_frame.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+/**
+ * @file
+ *
+ * @brief This field defines the SCU format of an unsolicited frame (UF).  A
+ *        UF is a frame received by the SCU for which there is no known
+ *        corresponding task context (TC).
+ */
+
+#ifndef _SCU_UNSOLICITED_FRAME_H_
+#define _SCU_UNSOLICITED_FRAME_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_types.h>
+
+/**
+ * This constant defines the number of DWORDS found the unsolicited frame
+ * header data member.
+ */
+#define SCU_UNSOLICITED_FRAME_HEADER_DATA_DWORDS 15
+
+/**
+ * @struct SCU_UNSOLICITED_FRAME_HEADER
+ *
+ * This structure delineates the format of an unsolicited frame header.
+ * The first DWORD are UF attributes defined by the silicon architecture.
+ * The data depicts actual header information received on the link.
+ */
+typedef struct SCU_UNSOLICITED_FRAME_HEADER
+{
+   /**
+    * This field indicates if there is an Initiator Index Table entry with
+    * which this header is associated.
+    */
+   U32 iit_exists : 1;
+
+   /**
+    * This field simply indicates the protocol type (i.e. SSP, STP, SMP).
+    */
+   U32 protocol_type : 3;
+
+   /**
+    * This field indicates if the frame is an address frame (IAF or OAF)
+    * or if it is a information unit frame.
+    */
+   U32 is_address_frame : 1;
+
+   /**
+    * This field simply indicates the connection rate at which the frame
+    * was received.
+    */
+   U32 connection_rate : 4;
+
+   U32 reserved : 23;
+
+   /**
+    * This field represents the actual header data received on the link.
+    */
+   U32 data[SCU_UNSOLICITED_FRAME_HEADER_DATA_DWORDS];
+
+} SCU_UNSOLICITED_FRAME_HEADER_T;
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCU_UNSOLICITED_FRAME_H_
diff --git a/sys/dev/disk/isci/scil/scu_viit_data.h b/sys/dev/disk/isci/scil/scu_viit_data.h
new file mode 100644
index 0000000..caf3c18
--- /dev/null
+++ b/sys/dev/disk/isci/scil/scu_viit_data.h
@@ -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.
+ *
+ * $FreeBSD: src/sys/dev/isci/scil/scu_viit_data.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _SCU_VIIT_DATA_HEADER_
+#define _SCU_VIIT_DATA_HEADER_
+
+/**
+ * @file
+ *
+ * @brief This file contains the constants and structures for the SCU hardware
+ *        VIIT table entries.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <dev/disk/isci/scil/sci_types.h>
+
+#define SCU_VIIT_ENTRY_ID_MASK         (0xC0000000UL)
+#define SCU_VIIT_ENTRY_ID_SHIFT        (30UL)
+
+#define SCU_VIIT_ENTRY_FUNCTION_MASK   (0x0FF00000UL)
+#define SCU_VIIT_ENTRY_FUNCTION_SHIFT  (20UL)
+
+#define SCU_VIIT_ENTRY_IPPTMODE_MASK   (0x0001F800UL)
+#define SCU_VIIT_ENTRY_IPPTMODE_SHIFT  (12UL)
+
+#define SCU_VIIT_ENTRY_LPVIE_MASK      (0x00000F00UL)
+#define SCU_VIIT_ENTRY_LPVIE_SHIFT     (8UL)
+
+#define SCU_VIIT_ENTRY_STATUS_MASK     (0x000000FFUL)
+#define SCU_VIIT_ENTRY_STATUS_SHIFT    (0UL)
+
+#define SCU_VIIT_ENTRY_ID_INVALID   (0UL << SCU_VIIT_ENTRY_ID_SHIFT)
+#define SCU_VIIT_ENTRY_ID_VIIT      (1UL << SCU_VIIT_ENTRY_ID_SHIFT)
+#define SCU_VIIT_ENTRY_ID_IIT       (2UL << SCU_VIIT_ENTRY_ID_SHIFT)
+#define SCU_VIIT_ENTRY_ID_VIRT_EXP  (3UL << SCU_VIIT_ENTRY_ID_SHIFT)
+
+#define SCU_VIIT_IPPT_SSP_INITIATOR (0x01UL << SCU_VIIT_ENTRY_IPPTMODE_SHIFT)
+#define SCU_VIIT_IPPT_SMP_INITIATOR (0x02UL << SCU_VIIT_ENTRY_IPPTMODE_SHIFT)
+#define SCU_VIIT_IPPT_STP_INITIATOR (0x04UL << SCU_VIIT_ENTRY_IPPTMODE_SHIFT)
+#define SCU_VIIT_IPPT_INITIATOR     \
+   (                                \
+       SCU_VIIT_IPPT_SSP_INITIATOR  \
+     | SCU_VIIT_IPPT_SMP_INITIATOR  \
+     | SCU_VIIT_IPPT_STP_INITIATOR  \
+   )
+
+#define SCU_VIIT_STATUS_RNC_VALID      (0x01UL << SCU_VIIT_ENTRY_STATUS_SHIFT)
+#define SCU_VIIT_STATUS_ADDRESS_VALID  (0x02UL << SCU_VIIT_ENTRY_STATUS_SHIFT)
+#define SCU_VIIT_STATUS_RNI_VALID      (0x04UL << SCU_VIIT_ENTRY_STATUS_SHIFT)
+#define SCU_VIIT_STATUS_ALL_VALID      \
+   (                                   \
+       SCU_VIIT_STATUS_RNC_VALID       \
+     | SCU_VIIT_STATUS_ADDRESS_VALID   \
+     | SCU_VIIT_STATUS_RNI_VALID       \
+   )
+
+#define SCU_VIIT_IPPT_SMP_TARGET    (0x10UL << SCU_VIIT_ENTRY_IPPTMODE_SHIFT)
+
+/**
+ * @struct SCU_VIIT_ENTRY
+ *
+ * @brief This is the SCU Virtual Initiator Table Entry
+ */
+typedef struct SCU_VIIT_ENTRY
+{
+   /**
+    * This must be encoded as to the type of initiator that is being constructed
+    * for this port.
+    */
+   U32  status;
+
+   /**
+    * Virtual initiator high SAS Address
+    */
+   U32  initiator_sas_address_hi;
+
+   /**
+    * Virtual initiator low SAS Address
+    */
+   U32  initiator_sas_address_lo;
+
+   /**
+    * This must be 0
+    */
+   U32  reserved;
+
+} SCU_VIIT_ENTRY_T;
+
+
+// IIT Status Defines
+#define SCU_IIT_ENTRY_ID_MASK                (0xC0000000UL)
+#define SCU_IIT_ENTRY_ID_SHIFT               (30UL)
+
+#define SCU_IIT_ENTRY_STATUS_UPDATE_MASK     (0x20000000UL)
+#define SCU_IIT_ENTRY_STATUS_UPDATE_SHIFT    (29UL)
+
+#define SCU_IIT_ENTRY_LPI_MASK               (0x00000F00UL)
+#define SCU_IIT_ENTRY_LPI_SHIFT              (8UL)
+
+#define SCU_IIT_ENTRY_STATUS_MASK            (0x000000FFUL)
+#define SCU_IIT_ENTRY_STATUS_SHIFT           (0UL)
+
+// IIT Remote Initiator Defines
+#define SCU_IIT_ENTRY_REMOTE_TAG_MASK  (0x0000FFFFUL)
+#define SCU_IIT_ENTRY_REMOTE_TAG_SHIFT (0UL)
+
+#define SCU_IIT_ENTRY_REMOTE_RNC_MASK  (0x0FFF0000UL)
+#define SCU_IIT_ENTRY_REMOTE_RNC_SHIFT (16UL)
+
+#define SCU_IIT_ENTRY_ID_INVALID   (0UL << SCU_IIT_ENTRY_ID_SHIFT)
+#define SCU_IIT_ENTRY_ID_VIIT      (1UL << SCU_IIT_ENTRY_ID_SHIFT)
+#define SCU_IIT_ENTRY_ID_IIT       (2UL << SCU_IIT_ENTRY_ID_SHIFT)
+#define SCU_IIT_ENTRY_ID_VIRT_EXP  (3UL << SCU_IIT_ENTRY_ID_SHIFT)
+
+/**
+ * @struct SCU_IIT_ENTRY
+ *
+ * @brief This will be implemented later when we support virtual functions
+ */
+typedef struct SCU_IIT_ENTRY
+{
+   U32  status;
+   U32  remote_initiator_sas_address_hi;
+   U32  remote_initiator_sas_address_lo;
+   U32  remote_initiator;
+
+} SCU_IIT_ENTRY_T;
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _SCU_VIIT_DATA_HEADER_
diff --git a/sys/dev/disk/isci/types.h b/sys/dev/disk/isci/types.h
new file mode 100644
index 0000000..43656b0
--- /dev/null
+++ b/sys/dev/disk/isci/types.h
@@ -0,0 +1,53 @@
+/*-
+ * 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: src/sys/dev/isci/types.h,v 1.1 2012/01/31 19:38:18 jimharris Exp $
+ */
+#ifndef _DRIVER_INCLUDE_TYPES_H_
+#define _DRIVER_INCLUDE_TYPES_H_
+
+#include <dev/disk/isci/environment.h>
+
+typedef uintptr_t POINTER_UINT;
+
+#ifndef NULL
+#define NULL ((void *)0)
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE (!FALSE)
+#endif
+
+typedef uint32_t BOOL;
+
+#endif /* _DRIVER_INCLUDE_TYPES_H_ */
-- 
2.9.2

